FC的习惯是每一个单独的功能都使用一个物体来控制,这次我们也需要一个单独的物体obj_cutscene来控制所有过场动画。但是每一个动画所执行的代码(移动镜头,移动角色,触发对话……)是不同的,所以在实例中我们需要重写create事件,来给每个不同的过场动画初始化不同的代码。
一、初始构想
把过场动画看作一个状态机,每一幕都是一个状态,用switch控制一个状态到下一个状态的切换。
可以看到,每一个状态需要有:1.要执行的代码;2.跳出该状态的条件;3.条件达成后,状态编号加一,进入下一状态。
这样写的逻辑很清晰,但缺点也很明显:每一个过场动画都需要一个单独的物体来控制(因为step事件不同,实例只能重写create事件);如果在中间增减场景时,后面的场景编号全都要跟着变化,场景一多修改起来就会很麻烦。
二、更有普适性的构想
既然只能重写create事件,那实例与实例之间的所有差异只能在create事件里,那就只能是物体变量的初始值不同。
解决方法是把每个场景对应的代码及其参数存入一个数组中:[script, arg0, arg1, ...],然后在step事件中执行。这样用一个物体就可以控制所有过场动画,而且场景数量改变时不需要修改代码。
scene_info = -1; // [代码-参数]数组,在实例代码中赋值 scene = 0; // 当前场景编号,在每个场景脚本代码的末尾加一
在不同的实例中初始化不同的数组即可。一个例子如下:
scene_info = [ [create_box_at_mouse], // 第一个元素是脚本函数ID,其后的元素是其参数 [cutscene_wait, 2], [create_box_at_mouse], [cutscene_wait, 4], [create_box_at_mouse] ]
这种方法下,如果仅仅是想执行GMS2自带的库函数,也需要把它包装进一个脚本函数中,因为库函数无法通过ID形式引用。
而step函数中则只用遍历数组,依次执行代码了。
var crt_scene = scene_info[scene]; // 若有参数 var lenArgs = array_length_1d(crt_scene - 1); // 获得参数数量 if (lenArgs != 0) { var args = array_create(lenArgs, 0); array_copy(args, 0, crt_scene, 1, lenArgs); script_execute_alt(crt_scene[0], args); // 可以传入参数数组 } // 若无参数 else script_execute(crt_scene[0]);
三、一些脚本函数
1. cutscene_end_action()
这个函数在每一个场景的代码末尾执行,负责控制场景间的切换。
scene++; // 防止数组访问越界 if (scene > array_length_1d(scene_info-1)) { instance_destroy(); }
当所有场景执行完毕时,这个实例就销毁了,所以是一次性的过场动画。如果想要可以反复触发的过场动画,还需另设变量控制。
2. cutscene_wait(seconds)
这个函数用于实现场景与场景间的停顿(也就是一个什么也不发生的场景)。
不像播放音效等只用执行一次的函数,这是一个需要连续执行多次、效果会持续一段时间的函数,包括角色的移动也是。所以在物体中加入一个变量来控制时间。
timer = 0;
在函数中对其进行判断:
timer++; // 若达到等待时间,进入下一场景 if (timer >= argument0 * room_speed) { timer = 0; cutscene_end_action(); }
四、触发器
我们不能直接拖一个obj_cutscene到房间里,因为它不负责检测玩家触发过场动画的条件。所以我们还需要一个obj_trigger,在它的create事件中初始化代码数组,在step事件中检测玩家是否触发了过场动画。若触发,则创建一个obj_cutscene(这里需要写一个脚本函数来传入代码数组),然后过场动画开始执行。
一些记录:
1.如果传入脚本函数的参数数量不确定,可以在脚本中先用一个数组循环遍历存储下所有参数(因为此时不能直接用argument0这样的指代),之后就从这个数组中获取参数。
2. 改变指定实例的指定变量:variable_instance_set(instance_id, name, val)
3. 直接获得向量的x分量和y分量:lengthdir_x(len, dir)和lengthdir_y(len, dir)
4. FC制作了角色移动的函数示例,看到这部分时网络卡了……有需要时补上。
————————
这篇分两天完成。(三天……因为我漏看了触发器……)
这样看来,即使是一个一分钟的过场动画,拆分成代码也会是一大串啊……
暂无关于此日志的评论。