如何让 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_motiontarget_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