如何让 2D 精灵减速停止?
How can I get a 2D sprite to slow to a stop?
我正在尝试使用 GDScript 在 Godot 中创建一个可玩的精灵。我的角色左右移动,然后在没有输入时停止。
但是,我想让精灵减速,而不是完全停下来。我该怎么写?
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
move_and_slide(motion)
pass
好的,我明白了:
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 = motion.x * .9
move_and_slide(motion)
一个非常简单的方法是在每次更新时降低速度 - 一个从物理阻力中借用的概念。
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
向量,而是使用 last_motion
和 target_motion
向量并在它们之间进行相应的插值以获得当前的 motion
向量每一帧(你也可以这样做来加速)。这需要您考虑 "when a player stops pressing a button" 之类的状态转换、启动计时器以跟踪插值的开始帧和目标帧之间的进度等...您选择的 kind of interpolation function 将影响响应速度或迟缓程度运动对玩家有感觉。
下面是使用线性插值在 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
我正在尝试使用 GDScript 在 Godot 中创建一个可玩的精灵。我的角色左右移动,然后在没有输入时停止。
但是,我想让精灵减速,而不是完全停下来。我该怎么写?
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
move_and_slide(motion)
pass
好的,我明白了:
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 = motion.x * .9
move_and_slide(motion)
一个非常简单的方法是在每次更新时降低速度 - 一个从物理阻力中借用的概念。
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
向量,而是使用 last_motion
和 target_motion
向量并在它们之间进行相应的插值以获得当前的 motion
向量每一帧(你也可以这样做来加速)。这需要您考虑 "when a player stops pressing a button" 之类的状态转换、启动计时器以跟踪插值的开始帧和目标帧之间的进度等...您选择的 kind of interpolation function 将影响响应速度或迟缓程度运动对玩家有感觉。
下面是使用线性插值在 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