双击&长按

年前有朋友在公众号问我——“在游戏中双击跑步怎么实现?”
又想到 QQ 群里也有朋友问过差不多的问题,当时在群里其实也讨论过各种思路,按说觉得这个东西并不困难,但好像确实也没看到有介绍这块的教程,大概是知道的人觉得太简单没必要,让许多新人变得有些苦恼,所以,简单写一下吧。
问题是双击,但因为原理类似,我会顺便说明一下长按的判断机制。

认识 GMS2 自带的按键事件


在 GMS2 中自带就有这样三个按键事件,分别对应了:

  • 按住按键(持续)
  • 按下按键(瞬间)
  • 松开按键(瞬间)

对应的函数则是:

  • keyboard_check()
  • keyboard_check_press()
  • keyboard_check_release()

当我们在需要判断玩家不同的按键事件时,可以简单使用自带的按键事件,也可以在 step 事件中通过函数调用进行判断。

思路

对于普通的按下,单击和松开按键我们都可以简单套用自带的方法,那么双击和长按如何判断?对于缺乏思路的新手而言,首先要学会解构问题来酝酿思路。
双击

通常我们所说的双击是指在极短时间内,玩家连续按下两次相同的按键,重点就是这个间隔时间必须足够短,一旦超出某个阈值,我们会认为玩家可能是进行两次独立的单击操作,而非连续双击

长按

通常我们所说的长按是指玩家按下某个按键以后一段时间不松开,如果在游戏中需要明确区分单击和长按的操作,就需要引入一个时间阈值,当玩家按住按键的时间超过这个值后我们认为玩家是想进行长按操作,而如果在未达到该时间时就松开了按键,我们会认为玩家只是想进行单击操作,只是因为各种原因没有特别及时松开按键

按照上述说明,我们会发现,判断玩家是否进行双击或长按操作,最重要的就是要引入一个时间判断,这个判断可能用于判断按键间隔,也可能用于判断按键的持续时长,而我们可以使用计数器来完成这个目的,计数器可以使用 GMS2 自带的 alarm 事件(有数量限制),也可以自定义一个变量来进行计数。

双击

我们先看双击,首先我们在 create 事件里创建一个变量 press_time 并且默认设为 0

1
press_time = 0 ;    //按键次数

然后当按键的按下事件被触发时,这个数值+1,这里我们以方向键右为例子:

1
if keyboard_check_press(vk_right) press_time ++ ;    //按下按键时,记录变量+1

如果只有以上代码,可以想象得到,我们每次按下按键这个 press_time 都会增加,那这就变成了一个单纯的按键次数统计变量了,这显然不是我们想要的结果,首先我们应当控制这个值不会超过 2(如果你需要 3 连击甚至更多则无视这个)

1
press_time = clamp( press_time , 0 , 2 ) ;        //将 press_time 的值约束在 0-2 之间

然后当玩家松开按键后我们需要判断超过一段时间以后把 press_time 重置为 0 ,这样我们就可以通过这个变量的值来判断玩家是单击还是双击了,因此我们在按键的释放事件里设置一个 alarm

1
if keyboard_check_release(vk_right) alarm[0] = 60 ;    //松开按键时,alarm[0]设为 60

这样每当玩家松开按键后就会进行一个 60 祯的倒计时,根据游戏设置的帧数不同具体的时长可能会不一样,如果 FPS 设为 60 那就是倒计时 1 秒,如果 FPS 设置为 30 则是倒计时 2 秒,下面我们全部以 FPS60 的情况说明。
然后我们创建与之对应的 alarm[0] 事件,并在其中将 press_time 重置为 0

1
press_time = 0 ;    //计时器一旦触发则重置按键计数 

在完成以上所有操作后,当玩家按下按键时,我们自定义的这个变量 press_time 就会变成 1,如果玩家松开按键超过 1 秒则重置为 0,再次按下后又变为 1,如果玩家在 1 秒以内再次按下按键则会变为 2,即便玩家连续不断按键这个值也不会超过 2 。
这时候我们就可以通过 press_time 的值来判断当前是单击操作还是双击操作了

  • press_time = 1 :单击
  • press_time = 2 :双击

把这个变量结合按键是否被按住就可以用于区分走路和跑步的不同状态了

1
2
3
4
5
6
7
8
9
if keyboard_check(vk_right) {
    if  press_time == 1{
        …………
        //向右行走的代码或状态切换
    }else if press_time == 2{
        …………
        //向右跑动的代码或状态切换
    }
}

当然,这里主要提供的还是思路,具体在项目中如何运用要结合自己游戏的机制来权衡。

长按

长按需要判断的就是按下一个按键以后过了多长时间,我们同样可以在 create 事件中设置一个变量 hold_time ,同时设置一个我们确定的时间阈值 hold_max

1
2
hold_time = 0 ;    //默认为 0 即没有按住按键
hold_max  = 60 ;   //默认 60,即按住持续 60 祯认为算长按

每当玩家按下对应的按键时我们就让这个值进行自增长

1
if keyboard_check(vk_right) hold_time ++ ;

然后我们要注意每当玩家松开按键以后我们就应该把 hold_time 重置为 0

1
if keyboard_check_release(vk_right) hold_time = 0 ;

当我们需要判断玩家长按按键并执行对应的操作时就只需要比较 hold_time 跟 hold_max 之间的大小关系就行了

1
2
3
4
if hold_time >= hold_max {
    …………
    //长按以后触发的各种操作
}

以上就是一点关于双击和长按判断的小思路,我相信对于大部分了解编程的朋友而言都是相当基础的东西,只希望能给新手提供一点解题思路,双击使用的是 GMS2 自带的 alarm 计时器,长按则自定义了一个变量充当计时器,其实完全可以根据个人理解随意使用,重点是自己顺手就好,其实那位朋友在提问的时候提了希望知道怎么写最好,我觉得这个最好是没有标准的,也许会有一些精妙的函数和算法可以写出精炼的代码,但是这对于新手而言并不好,因为不易于理解,我觉得写代码这东西,适合自己最好,即便代码不漂亮,但能通过自己的思考写出来更重要,很多优化的问题是可以随着时间和经验的增长得到提高的。

2021-04-28 15:14
Comments
Write a Comment