一个非常简单的方法是在每次更新时降低速度——这个概念是从物理阻力中借来的。
extends KinematicBody2D
var motion = Vector2()
func _physics_process(delta):
if Input.is_action_pressed("ui_right"):
motion.x = 250
elif Input.is_action_pressed("ui_left"):
motion.x = -250
else:
motion.x *= 0.95 # slow down by 5% each frame - play with this value
# i.e. make it dependent on delta to account for different fps
# or slow down faster each frame
# or clamp to zero under a certain threshold
move_and_slide(motion)
pass
同样,这非常简单。如果您想提供某些保证(例如播放器应该在 6 帧后完全停止),尤其是在处理未锁定的 fps 时,调整拖动值可能会非常挑剔。
在这种情况下,不要使用单个motion
向量,而是使用 alast_motion
和 atarget_motion
向量并在它们之间进行相应的插值,以获得每帧的当前motion
向量(您也可以这样做以进行加速)。这需要您考虑状态转换,例如“当玩家停止按下按钮时”,启动计时器以跟踪插值的开始帧和目标帧之间的进度等......您选择什么样的插值函数将影响如何对玩家的运动感觉反应灵敏或迟缓。
这是使用线性插值在 0.2 秒内减速的示例:
enum MotionState {IDLE, MOVING, DECELERATING}
extends KinematicBody2D
var state = IDLE
var last_motion = Vector2()
var time_motion = 0.0
func _physics_process(delta):
var motion = Vector2();
if Input.is_action_pressed("ui_right"):
motion.x = 250
state = MOVING
last_motion = motion
elif Input.is_action_pressed("ui_left"):
motion.x = -250
state = MOVING
last_motion = motion
elif state == IDLE
motion.x = 0
else:
if state == MOVING:
# start a smooth transition from MOVING through DECELERATING to IDLE
state = DECELERATING
# last_motion already holds last motion from latest MOVING state
time_motion = 0.2
# accumulate frame times
time_motion -= delta
if time_motion < 0.0:
# reached last frame of DECELERATING, transitioning to IDLE
state = IDLE
motion.x = 0
else:
var t = (0.2 - time_motion) / 0.2 # t goes from 0 to 1
# we're linearly interpolating between last_motion.x and 0 here
motion.x = (1 - t) * last_motion.x
move_and_slide(motion)
pass
线性减速会感觉不对,但您可以轻松地将其替换为任何其他功能,例如尝试三次以更快地减速,从而更快地响应减速:motion.x = (1 - (t * t * t)) * last_motion.x