本帖最后由 guoxiaomi 于 2019-6-16 20:33 编辑
现成的公式在XP的跳跃处理中,XP中有一条事件指令可以让地图上的角色从一个点跳跃到另一个点,在跳跃过程中角色走的路线是抛物线。接下来分析XP是如何实现抛物线的路线的:
我们顺藤摸瓜,首先找到 Game_Character 3 的 jump 方法,在此方法里,执行了以下任务:
1. 调整角色的朝向
2. 将@x和@y设置为目标位置的值
3. 设置跳跃计时@jump_count = @jump_peak * 2
随后找到Game_Character 2 中的 update_jump 方法:
#-------------------------------------------------------------------------- # ● 更新画面 (跳跃) #-------------------------------------------------------------------------- def update_jump # 跳跃计数减 1 @jump_count -= 1 # 计算新坐标 @real_x = (@real_x * @jump_count + @x * 128) / (@jump_count + 1) @real_y = (@real_y * @jump_count + @y * 128) / (@jump_count + 1) end
#--------------------------------------------------------------------------
# ● 更新画面 (跳跃)
#--------------------------------------------------------------------------
def update_jump
# 跳跃计数减 1
@jump_count -= 1
# 计算新坐标
@real_x = (@real_x * @jump_count + @x * 128) / (@jump_count + 1)
@real_y = (@real_y * @jump_count + @y * 128) / (@jump_count + 1)
end
从这里可以看出,每次更新的时候,@jump_count 会减少 1,最终一直减少到 0。同时,角色的@real_x和@real_y会用此递推公式进行更新。
为了庆祝高考结束,现场解一下递推公式,暂不考虑整除的影响:
数列Sn表示角色的@real_x在第 n 帧的值,则有:@jump_count = N - n,其中 N 是 @jump_count 的初始值。代入递推公式:
S[n+1] = (S[n] * (N - n) + X) / (N - n + 1),这里用 X 代替了 @x * 128,在整个跳跃过程中是不变的。同时我们还知道 S[0] = 初始位置的 @real_x。
整理递推公式得:
S[n+1] / (N - n) - S[n] / (N - n + 1) = X / (N - n) - X / (N - n + 1)
取n=0,1,2...a - 1,代入上面的式子,左右两边分别求和消去相同的项:
S[a] / (N - a + 1) - S[0] / N = X / (N - a + 1) - X / N
得到:
S[a] = S[0] - a * (S[0] - X) / N,是一个等差数列。在a = 0的时候,值为S[0],在a = N的时候,值为X。
上面的推导说明了,在跳跃过程中,角色的真实位置@real_x和@real_y是匀速变换到目标位置的。这个和看上去的抛物线路径并不一样,所以找到最后的地方:Game_Character 1 的 screen_y 方法:
#-------------------------------------------------------------------------- # ● 获取画面 Y 坐标 #-------------------------------------------------------------------------- def screen_y # 通过实际坐标和地图的显示位置来求得画面坐标 y = (@real_y - $game_map.display_y + 3) / 4 + 32 # 取跳跃计数小的 Y 坐标 if @jump_count >= @jump_peak n = @jump_count - @jump_peak else n = @jump_peak - @jump_count end return y - (@jump_peak * @jump_peak - n * n) / 2 end
#--------------------------------------------------------------------------
# ● 获取画面 Y 坐标
#--------------------------------------------------------------------------
def screen_y
# 通过实际坐标和地图的显示位置来求得画面坐标
y = (@real_y - $game_map.display_y + 3) / 4 + 32
# 取跳跃计数小的 Y 坐标
if @jump_count >= @jump_peak
n = @jump_count - @jump_peak
else
n = @jump_peak - @jump_count
end
return y - (@jump_peak * @jump_peak - n * n) / 2
end
在跳跃过程中,y值有一个修正项:y = y0 - 1/2 * (N*N - n*n),在这里用 N 表示 @jump_peak。
注意在跳跃过程中,@jump_count 的值从 @jump_peak * 2 逐步减少到 0,对应 n 的变化范围正好是从 -N 到 N,所以 screen_y 增量从 0 逐渐增大最后回落到 0。
实际显示的角色位置,是一个在 y 方向上与时间呈二次方关系的运动,叠加上角色本身的匀速运动,这是一条抛物线。
最终结论是,直接用XP自带的跳跃功能就行了。
|