Estoy tratando de crear un sprite jugable en Godot usando GDScript. Mi personaje se mueve hacia la izquierda y hacia la derecha y luego se detiene cuando no se presiona ninguna entrada.

Sin embargo, en lugar de detenerse en seco, quiero que el sprite disminuya la velocidad. ¿Cómo escribiría eso?

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
2
Hearthing 4 feb. 2019 a las 23:50

2 respuestas

La mejor respuesta

Está bien, lo descubrí:

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)

pass
0
Hearthing 4 feb. 2019 a las 21:38

Un método muy simple es reducir la velocidad en cada actualización, un concepto tomado de la resistencia física.

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

Nuevamente, esto es muy simple. Ajustar el valor de arrastre puede ser bastante delicado si desea dar ciertas garantías (como que el jugador debería detenerse por completo después de 6 cuadros), especialmente cuando se trata de fps desbloqueados.

En tales casos, en lugar de tener un solo vector motion, tenga un vector last_motion y un target_motion e interpole entre ellos en consecuencia para obtener el vector motion actual de cada cuadro (puede haga esto también para la aceleración). Esto requiere que piense en transiciones de estado como "cuando un jugador deja de presionar un botón", temporizadores de inicio para rastrear el progreso entre el inicio y el marco de destino para la interpolación, etc. ¿Qué el tipo de función de interpolación que elijas afectará la capacidad de respuesta o lentitud del movimiento para el jugador.

Aquí hay un ejemplo de desaceleración en 0.2 segundos usando interpolación lineal:

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

La desaceleración lineal se sentirá mal, pero puede reemplazarla fácilmente con cualquier otra función, p. Ej. pruebe cúbicos para una desaceleración más rápida y, por lo tanto, una desaceleración más sensible: motion.x = (1 - (t * t * t)) * last_motion.x

0
BeyelerStudios 4 feb. 2019 a las 22:32