RM2K3特殊事件-镜子和倒影


写在前面

内容涉及了变量坐标轴

在阅读内容之前,请确认自己已经学习过03的基础指令和变量相关的知识,以及坐标轴的判定原理。

※此教程为个人学习笔记,可能会有很多表述不清楚的地方


初步构思

素材的准备

要做一面镜子,首先得确定镜子的样式面积以及在地图上的位置

为了能让倒影有足够多的测试空间,我选择了3×3的落地镜作为范例,这样一来倒影的活动范围也就固定在了3×3的空间中。

而倒影本质上是一个会跟着主人公走动的NPC,因此倒影事件的图像应当设置成半透明形态的主人公

决定好后就可以开始画对应的素材了。

整理思路

理想状态是:主人公在镜子前走动,倒影能即时作出反应,且没有延迟

那么需要用到的指令一定会有Conditional Branch以及Set Move Route,朝向不需要牵扯到变量,因此可以先在倒影的事件中把四个朝向的条件分歧输入进框架中。

要让倒影做出即时反应,那么必须读取主人公的坐标。当主人公的X值增加,倒影和主人公都会往右走;当主人公的Y值增加,那么倒影应该往上走;而变量可以将XY值转化为可以操作的数值,所以条件分歧除了主人公朝向,大部分应是变量。

主人公走出3×3范围外倒影就会消失,所以还得准备一个开关来控制倒影的有无。

实际操作

首先我们要准备好四个变量,分别是主人公的XY轴和倒影的XY轴。

1
2
3
4
@> Control Variables: [0001:X] = Player's X Coordinate
@> Control Variables: [0002:Y] = Player's Y Coordinate
@> Control Variables: [0003:mirror X] = This Event's X Coordinate
@> Control Variables: [0004:mirror Y] = This Event's Y Coordinate

然后我们进入编辑器,手动确认主人公的活动范围。

X轴在23~25之间,Y轴在19~21之间,在此区间内倒影会显形,反之就会消失。这里就需要用上之前构思的开关了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@> Conditional Branch: Variable [0001:X] > 22
@> Conditional Branch: Variable [0001:X] < 26
@> Conditional Branch: Variable [0002:Y] < 21
@> Control Switches: [0002:transparent] = OFF
@>
: Branch End
@>
: Branch End
@>
: Branch End
@> Conditional Branch: Variable [0001:X] < 22
@> Control Switches: [0002:transparent] = ON
@>
: Branch End
@> Conditional Branch: Variable [0001:X] > 26
@> Control Switches: [0002:transparent] = ON
@>
: Branch End
@> Conditional Branch: Variable [0002:Y] > 21
@> Control Switches: [0002:transparent] = ON
@>
: Branch End

然后比较主人公和倒影的XY值。因为镜子的面积是3×3,所以这里需要把倒影事件设置在底部的中心。这样就可以直接通过比较大小来确认主人公往哪个方向移动了。

当系统读取到主人公往右走时,X值增加,所以当主人公的X值大于倒影的X值时,倒影也应该跟着往右走一格,反之亦然。

1
2
3
4
5
6
7
8
@> Conditional Branch: Variable [0001:X] < V[0003:mirror X]
@> Set Move Route: This Event, Through ON, Move Left
@>
: Branch End
@> Conditional Branch: Variable [0001:X] > V[0003:mirror X]
@> Set Move Route: This Event, Through ON, Move Right
@>
: Branch End

之后是最难的Y轴部分,因为倒影的行走方向和主人公相反,光靠比较大小是没办法的。这里我们要先把每个坐标数值的变化记下来,找到其中的运算规律。

经过计算,最终确定用两个Y变量来代入倒影的Y值。

理论如下(左为主人公,右为倒影)
(24,19)→(24,20) (24,18)→(24,17)

因为最底部中心点的Y值是18,所以两个Y的初始值都应是18

假设主人公往下移动了一格,倒影的理想状态是往上移动一格

第一个Y减去主人公Y坐标 = 18-20 = -2
第二个Y减去镜子Y坐标 = 18-18 = 0

因为主人公不可能和倒影重叠,所以第二个Y必须>主人公的Y值(差值最少为1)所以给第二个Y+1
第一个Y永远比主人公Y轴大,所以得取绝对值才能有条件分歧 ×-1得到2

所以当 第一个Y > 第二个Y 的时候,倒影往上走

相反,如果两者靠近的话

第一个Y减去主人公Y坐标 = 18-19 = -1
第二个Y减去镜子Y坐标 = 18-18 = 0

按照刚才的理论,第二个Y > 第一个Y, 倒影往下走

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@> Control Variables: [0005:mirror Ymove] = 18 
@> Control Variables: [0005:mirror Ymove] -= Variable [0002]
@> Control Variables: [0006:mirror Ymove2] = 18
@> Control Variables: [0006:mirror Ymove2] -= Variable [0004]
@> Control Variables: [0006:mirror Ymove2] += 1
@> Control Variables: [0005:mirror Ymove] *= -1
@> Conditional Branch: Variable [0005:mirror Ymove] < V[0006:mirror Ymove2]
@> Set Move Route: This Event, Through ON, Move Down
@>
: Branch End
@> Conditional Branch: Variable [0005:mirror Ymove] > V[0006:mirror Ymove2]
@> Set Move Route: This Event, Through ON, Move Up
@>
: Branch End

移动决定了,停止时的朝向也得考虑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@> Conditional Branch: Player is facing Up
@> Set Move Route: This Event, Turn Down
@>
: Branch End
@> Conditional Branch: Player is facing Right
@> Set Move Route: This Event, Turn Right
@>
: Branch End
@> Conditional Branch: Player is facing Down
@> Set Move Route: This Event, Turn Up
@>
: Branch End
@> Conditional Branch: Player is facing Left
@> Set Move Route: This Event, Turn Left
@>
: Branch End

之后,我们设置好主人公的半透明图像,并且将这个事件设置为Parallel Process。另:主人公的速度如果保持默认,Movement Speed应当设置成和主人公一样的普通速。

还记得之前的开关吗?我们将这一页直接复制,左上角的触发条件只需要将transparent给打开,图像设置成一个完全透明的图块就OK了。如果不想让主人公碰到倒影,还可以将Priority设置为Below Characters

如果有加速道具或是长按SHIFT加速的需求,再复制一页,触发条件中将加速的开关打开,然后将Movement Speed调整为加速后的速度就没问题了。

最后,我们将主人公放在镜子前,开始debug!

体验实装

延迟完全为零几乎是不存在的,行动稍微有一点点延迟是正常现象。

为了不穿帮,主人公的3×3的外围最好也布置一些不可通行的图块,这样就不会出现倒影乱跑的BUG。

最终结果看起来就会是这样(我还顺带测试了一下SHIFT加速):

mirror.gif


※以上内容仅作为个人观点,如有解释不当的部分欢迎讨论。内容随时会进行更新和补充。

※本文章的内容,包括文字、图片均为本人(Drifter)原创。可将文章提供的内容用于个人学习、研究以及其他非商业用途。转载时请务必注明地址和原作者信息,请勿用于商业性或盈利性用途。