随便写的做耐久小教程——(4)常见bug与debug

本教程是基于umbrella丶2修改果引擎制作的耐久引擎(稍加改动)的教程,该引擎gm版本为Gamemaker8。
一.Gamemaker8的debug模式

在你测试耐久的过程中,应当注意到了除了绿色的运行按钮外,还有一个红色的运行按钮,这就是以debug模式运行游戏的按钮
在debug模式中,除了正常的游戏窗口,还会有一个如下图所示的debug窗口

在这个窗口的上方,有Run,Watch,Tools三个选项和九个按钮
1.Run

点开Run标签后,会发现里面的选项与下方的五个按钮一模一样,现在分别介绍每个按钮的作用

当按下这一按钮后,游戏进程会停止

在游戏进程停止的状态下按下该按钮,游戏将会继续运行

在游戏进程停止的状态下按下该按钮,游戏将会运行1帧后停止

在按下Restart按钮后,游戏将会重置,相当于重新启动游戏
在按下Stop按钮后,游戏进程将会结束
2.Watch
事实上watch作用不大,但为文章完整还是略加叙述

点开Run标签后,会发现里面的选项除了下方的四个按钮,还有Load和Save两个选项,现在分别介绍其作用

按下此按钮后会出现该窗口

填入对应的全局变量/Object变量/函数返回值即可进行变量监视

注:当具有多个相同obj时,只会返回最早创建的obj的变量值


Change按钮用于更改某一变量的名称(也可双击显示某一变量的格子)
Delete按钮用于删除无需监视的变量(也可选中特定变量后按下Delete键)
Clear按钮会清空所有监视的变量值

Save会将你所有进行监视的变量名称存储为一个txt文件,将上文监视的三个变量Save后生成的txt文件如下图所示:

在之后debug的过程中,可以通过Load此txt文件再次对这三个函数进行监视

注:Load的变量不会覆盖Load前添加到监视列表中的变量
(注意:以上所有按钮按下后都不会显示确认界面)
3.Tools

Tools的选项都不以按钮的形式呈现
①上半部分

选中Execute Code选项后,会出现一个窗口

它能够执行一次你输入的代码,但代码必须只有一行,如:
with(player){x=400;y=608}
或
global.DebugNumber=point(400,304,player.x,player.y)
诸如此类
选中Set Speed选项后,会出现一个窗口

里面默认显示目前的游戏帧率,你可以将其更改到其他数值,使游戏运行速度增大/减小,不过对于该耐久引擎的debug并没有什么用处
②中间部分

当点击Show Global Variables选项后,会出现下图界面

其中,第一栏是关于键鼠的变量,第二栏是关于房间设置的变量,第三栏是关于游戏运行状态的变量,这三栏大多数是只能读取,无法更改的
第四栏中,则是用户自行定义的全局变量,即形如global.xxx的变量,其中,与耐久参数和引擎设置相关的全局变量位于第四栏最上方,与Fmod相关的全局变量位于第四栏中部(即前缀为dll_的所有变量,而在耐久进行过程中设置的全局变量一般出现在第四栏最下方
当点击Show Local Variables选项后,会出现下图界面

在框中,我们可以填入某种obj的名称或者某个obj的id
当填入名称时,如果此种obj同时具有多个,那么只会显示最早创建的obj
确认后,会显示以下窗口

其中,第一栏是关于运动状态的变量,第二栏是obj的id与物体、图像变量,第三栏与path相关,但本文并不提及path
与Show Global Variables界面类似,第四栏中为用户自行定义的变量。因此,可以通过该方法对obj的变量进行监视
注:在此界面中,数组变量仅会显示编号为0的数组元素的值,如果要检测某一数组变量的值,可以在Execute Code界面输入形如
global.Test=Variable[i]
的代码,之后在Show Global Variables界面中查看
②下半部分

按下Show Instances选项后,会显示如下界面

在界面中会显示当前房间所有的obj,当游戏运行时,该界面会不断刷新,因此应当在点击暂停按钮之后再查看这一界面
其中,第一列为obj的id编号,第二列为obj的名称,第三列为obj显示的spr图像(<underfined>表示没有spr图像)
Show Messages选项没什么卵用,不用管它
4.其他
①

在debug界面下方有这样一栏,分别显示游戏帧率,房间内Object数量,鼠标指向的obj的id
在暂停状态下,通过mouse id,可以很方便的确定某个出错obj的id编号
②
此引擎在debug模式下,可以通过鼠标左键点击房间内的任意位置的方式,将kid传送到鼠标处。
③
在debug模式下,变量debug_mode等于1

二.常见bug与debug的方法
本文仅提及常见的出现在iw耐久制作中的bug,对于特殊的或者代码逻辑上的错误,本文不予理会。
1.

当游戏弹出这一窗口时,请检查music_init脚本中填写的音乐文件名称是否正确,是否包含后缀名,是否正确按照教程(1)进行参数配置。
2.在时间轴中创建了一个弹幕,但是游戏过程中没有出现
打开debug模式的Show Instances选项,检查这个obj是否存在
如果不存在,可能的原因有:
1.创建函数中的obj名称填写错误
2.obj的销毁代码与需求不符(例如:销毁代码是在离开房间后销毁,但是将obj创建在房间之外)
3.弹幕源创建代码出错
如果确认obj存在,下一步复制这一obj的id,填入Show Local Variables中
在Show Local Variables界面查看以下参数:
1.坐标是否位于房间之外
2.visible(可见参数)是否为0
3.image_alpha(透明度)是否为0
如果正常,第三步打开此obj的界面,检查是否具有绘制事件(当具有绘制事件时,obj不会显示自身图像)
最后,检查此obj是否与背景同色
3.创建的obj/更改的spr等等出错或者与预想不同
若确认名称输入无误,尝试将目标资源名称更改,查看代码是否依然显示浅黄色(一般情况下,GM8中的游戏资源显示为浅黄色,在偏好设置中可以更改为其他颜色)。
若依然显示为浅黄色,则可能是因为游戏中具有同名资源,比如同时具有两个名为bullet的obj之类
4.在耐久进行的过程中,突然一瞬间跳过了好几帧甚至几十帧
基本上,遇见这种情况,可以确定是由于一个image_xscale或者image_yscale为零的物体与另一物体执行碰撞事件,这一类物体参与碰撞事件时,就会产生这一bug,通过其他方式避免即可
5.按下R后耐久bgm不播放,只有第一次进入游戏能运行
如果按下R后kid直接出现在耐久房间中,说明你很可能在耐久房间中存了当,请自行删除存档再次测试,存档在Data\Save文件夹内
6.使用形如player.x=600的代码,但是kid的位置并没有变化
由于GML中独特的固体(solid)特色,如果一个obj具有碰撞另一个obj的事件,并且其中一方是固体,那么这两个obj重叠之后,会回到上一帧所处的位置。
因此,很有可能是因为kid移动到的位置(加上速度位移)上有一个block,正常情况下,控制两个obj不碰撞即可。如果要使两个obj接触成为可能,需要对引擎进行修改,或许在后面的章节中会提及。
7.在创建弹幕的时候写了inst.num=1,在弹幕的create里写了if num=1{……},但是并没有执行大括号里的代码
创建事件是在Object创建的同时执行,因此,形如:
inst=instance_create(x,y,obj)
inst.xxx=xxx
的代码,执行顺序为:
创建obj→执行obj的create事件→为obj的xxx赋值
如果还有其他bug,可在评论区提出

至此,基本上足够制作一个能够称为耐久的iw游戏了
下一章将简要讨论部分与数学相关的弹幕类型