【问题标题】:How can I get a 2D sprite to slow to a stop?如何让 2D 精灵减速停止?
【发布时间】:2019-02-04 20:50:59
【问题描述】:

我正在尝试使用 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

【问题讨论】:

    标签: sprite godot gdscript


    【解决方案1】:

    好的,我想通了:

    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)
    

    【讨论】:

      【解决方案2】:

      一个非常简单的方法是在每次更新时降低速度——这个概念是从物理阻力中借来的。

      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 向量(您也可以这样做以加速)。这需要您考虑状态转换,例如“当玩家停止按下按钮时”,启动计时器以跟踪开始和目标帧之间的进度以进行插值等...您选择的 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

      【讨论】:

        猜你喜欢
        • 2021-08-29
        • 1970-01-01
        • 2012-01-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-03
        • 1970-01-01
        相关资源
        最近更新 更多