游戏暂停的简单实现(2/2)
大家好,距离上一篇说游戏暂停实现机制的文又过去快半个月了,恰好HeartBeast第14集教程也是介绍如何实现游戏暂停,并且就是我们上次提到的将当前场景对象临时禁用的这种方法,今天我们就来介绍一下这一种实现游戏暂停的方式。
不同于我们上次介绍的方式,这个方法是在游戏当前场景中进行暂停,不涉及游戏场景的切换,同时引入了持久化对象的概念,对象属性勾上了持久化(Persistent)以后,该对象一旦创建实例,对应的实例就会存在于后续所有的游戏场景中(除非手动销毁),从而可以用于控制一些所有场景中都需要调用的方法和机制。
本文的具体操作会有别于HB的教程,但思路是一致的
HeartBeast的教程已经传到B站了——简单实现游戏暂停
控制暂停对象
如上文所说,我们需要创建一个新的对象,并把对象的持久化属性打上勾
接着我们创建一个“Create”事件,并在其中定义两个全局变量:
global.paused_ = false ;
global.screen_pic = noone;
这里我们使用全局变量的目的是便于不同的对象都能正确调用和修改这两个值,这两个变量分别是:
- paused_:标识当前是否暂停状态
- screen_pic:用来保存暂停前的游戏画面
因为刚才我们创建的是一个暂停按钮,我希望用户在点击这个按钮时能触发暂停操作,因此可以创建一个点击事件,这里使用“Tap”或“Mouse->Left Down”都可以
然后在这个事件里写暂停相关的代码:
if !global.paused_{
global.paused_ = true
if sprite_exists(global.screen_pic) sprite_delete(global.screen_pic) ;
global.screen_pic = sprite_create_from_surface(application_surface,0,0,room_width,room_height,false,false,0,0)
instance_deactivate_all(all)
instance_create_layer(room_width/2,room_height/2,"pipe",obj_continue)
}
这段代码整体在一个if判断中,第一哈昂的if判断就是判断当玩家点击这个暂停按钮时,当前游戏是否处于“非暂停”即正常游戏状态,注意这里我们前面用了一个感叹号"!"来表示否定,这里也可以使用下面这种写法(HB就是这么写的)
if not global.paused_
当判断条件成立时就直接进入执行暂停的操作,首先是把这个暂停的变量设置为“true”标记将要进入暂停状态
然后我们要给当前画面截屏,在截屏之前我们也做了一个if判断,这个判断是判断当前游戏中是不是已经有相同名称的截屏存在,如果有则要先把之前的截屏删除
这里用了sprite_exists()来判断精灵图像是否存在,然后用sprite_delete()来执行删除操作
if sprite_exists(global.screen_pic) sprite_delete(global.screen_pic) ;
然后我们创建一个新的截屏图像
global.screen_pic = sprite_create_from_surface(application_surface,0,0,room_width,room_height,false,false,0,0)
这里我们使用sprite_create_from_surface()这个方法获取当前应用窗口的界面图像并生成一个精灵图像,然后将其保存到了之前创建的全局变量global.screen_pic中。
这里使用的application_surface是一个默认的surface表面,就是当前整个应用窗口的表层图像窗口。
然后我们用 instance_deactivate_all()这个方法禁用所有的实例,并单独新建了一个用于恢复游戏的按钮"obj_continue"
instance_deactivate_all(all)
instance_create_layer(room_width/2,room_height/2,"pipe",obj_continue)
在HB的教程中因为他使用的是键盘按键来控制暂停事件,因此直接禁用和恢复实例就能实现暂停的效果,而我们这里是通过点击画面中的按钮来实现的,因此恢复游戏的按钮也需要单独创建出来才可以。
恢复游戏对象
好,在刚才我们已经完成了游戏的暂停操作,但是我们要如何解除暂停状态恢复正常游戏呢?
首先同样新建一个对象,由于这个对象也是一个按钮,我们同样创建一个“Tap”事件来执行恢复游戏的操作
在这个“Tap”事件中我们放入的代码如下:
instance_activate_all();
global.paused_ = false;
instance_destroy();
第一行是用instance_activate_all()恢复整个场景中所有的实例,这些实例会保留禁用之前的所有属性,包括坐标、状态等等。
第二行则是重新将暂停状态标记为“未暂停”的状态,表示即将正常恢复游戏
最后则是把自身这个恢复游戏的按钮销毁,因为在正常的游戏过程中这个按钮应该是不会出现的。
到此为止,其实游戏的暂停和恢复基本已经完成了,但是还不够完美。
因为在暂停按钮被按下时所有的实例都被禁用了,因此整个场景中所有的对象实例都会消失不见,整个画面是空的(tiles和背景等还会保留)
希望你还记得我们之前曾经在暂停时单独保存了一张游戏画面的截屏,也希望你在上一张图片中有留意到这个恢复游戏的按钮事件中有一个“draw”事件,我们就要在这个“draw”事件中把之前的截屏绘制到屏幕上,用这张图片来欺骗玩家的眼睛,让他以为因为游戏被“暂停”了所以上面的内容都静止不动了。
draw_sprite(global.screen_pic,0,0,0)
draw_self()
在这个draw事件中,我们首先把刚才截屏画面的精灵图像直接绘制到屏幕上,然后同样不要忘记当我们自定义“draw”事件以后一定要加上一个"draw_self",否则这个按钮本身就不会被绘制出来了。
这里还要注意这两行代码的顺序,因为根据绘制顺序不同的内容的深度也不同,后绘制的内容在上方,如果你先写了"draw_self",那绘制截图的时候就会把按钮给挡住,玩家同样会看不到那个恢复游戏的按钮了。
以上就是通过禁用实例和恢复实例的方式来实现游戏暂停机制的方法。
HB的教学视频中使用了用户事件来封装暂停的操作,而其实也可以用脚本来单独封装,HB没有使用脚本的原因是他的教学视频采用了试用版,对脚本的数量有限制。
而我也没有封装这个暂停操作,是因为感觉没什么必要,好像并没有很多不同的地方会去触发暂停,既然没什么复用的需求也就偷个懒了