Годот прыгает анимация просто играет первый кадр - PullRequest
0 голосов
/ 04 сентября 2018

В моей простой платформерной игре есть скрипт, который говорит, что если мой игрок находится в земле и нажата «Z», его движение по оси Y возрастет до 600, и если он не в земле он собирается выполнить анимацию прыжка.

Так вот, я знаю, что он воспроизводит только первый кадр анимации прыжка, потому что код постоянно обнаруживает, что игрок находится в воздухе. Я хочу, чтобы код указывал запуск анимации только один раз.

Я пытался использовать функцию с именем input_(event):, но, похоже, у нее нет типа ввода is_action_just_pressed, просто is_action_pressed.

Я довольно новичок в Годо и не знаю, как использовать сигналы. Сигналы могут помочь через animation_finished(), хотя эта функция может не иметь ничего общего с тем, что я на самом деле хочу сделать в своем коде.

Вот мой код:

extends KinematicBody2D
#Variables van aquí 

var movimiento = Vector2();
var gravedad = 20; 
var arriba = Vector2(0, -1);
var velocidadMax = 600;
var fuerza_salto = -600;
var aceleracion = 5;
var saltando = false;
func _ready(): # Esto es void Start()
    pass;

func _physics_process(delta): #Esto es void Update() 

    movimiento.y += gravedad;


    if Input.is_action_pressed("ui_right"):
        $SonicSprite.flip_h = true;
        $SonicSprite.play("Walk");
        movimiento.x = min(movimiento.x +aceleracion, velocidadMax);


    elif Input.is_action_pressed("ui_left"):
        $SonicSprite.flip_h = false;
        $SonicSprite.play("Walk");
        movimiento.x = max(movimiento.x-aceleracion, -velocidadMax);

    else:
        movimiento.x = lerp(movimiento.x, 0, 0.09);
        $SonicSprite.play("Idle");


    if is_on_floor():
        if Input.is_action_just_pressed("z"):
            movimiento.y = fuerza_salto;
    else:
        $SonicSprite.play("Jump");

    movimiento = move_and_slide(movimiento, arriba)

Ответы [ 3 ]

0 голосов
/ 12 сентября 2018

Давайте рассмотрим, что здесь происходит, вы запустите код и попросите своего игрока воспроизвести анимацию в одном кадре, а затем снова в другом и в следующем, пока нажата правильная клавиша или вы находитесь в правильном состоянии.

В чем проблема, проблема в том, что при каждом вызове функции воспроизведения она запускает анимацию снова и снова, поэтому просто перезапускается или выполняется другой вызов отдельно, и это вызывает неожиданное поведение.

Лучшим способом будет одновременное управление состоянием проигрывателя и проигрывателя анимации и использование этого для выполнения вызовов анимации.

enum State { IDLE, WALK, RUN, JUMP, INAIR, GROUNDED } ## This is to manage the player state
var my_state = State.IDLE  ## Start the player with the idle state

Что касается состояния проигрывателя анимации, используйте сигнал, о котором вы говорили, используя графический интерфейс или код, подобный приведенному ниже.

get_node("Animation Player").connect("animation_finished", this, "method_name")
## Here I assume that you have the Animation Player as the Child of the Node you the script on

А также держите логическую переменную, чтобы узнать, воспроизводится ли анимация или нет.

if ( animation_not_playing and (case)):
    animation_player.play("animation")

Поверните это правда или ложь по своему вкусу. На основании анимации закончен сигнал.

В будущем вы можете рассмотреть возможность использования даже простого FSM для сохранения всех этих данных и переменных состояния.

0 голосов
/ 13 ноября 2018

У меня была проблема с smae, и я решил ее, добавив следующее после move_and_slide ():

if velocity.y == 0:
    velocity.y = 10

По-видимому, если скорость равна 0 после move_and_slide (), он больше не обнаруживает is_on_floor () (ошибка?), Поэтому я добавил небольшую скорость в направлении силы тяжести.

Что касается использования input_ (событие), вам не нужно просто just_pressed, потому что он обрабатывается только при наличии ввода ... вы можете сделать что-то вроде этого:

func _input(event):
    if event.is_action_pressed("ui_up") and is_on_floor():
        velocity.y = jump_speed

То, что я назвал скоростью, я думаю, в вашем сценарии называется movimiento. Кроме того, я думаю, что вы смешиваете силы тяжести и скорости в movimiento. Я поделюсь с вами моим scrpit персонажа, чтобы вы могли сравнить и посмотреть, работает ли он лучше:

extends KinematicBody2D

var Bullet = preload("res://Bullet.tscn")

var speed = 200
var jump_speed = -300
var shot_speed = 100
var velocity = Vector2()
var grav = 980
var shooting = false

func _ready():
    $AnimatedSprite.play()
    $AnimatedSprite.connect("animation_finished",self,"on_animation_finished")
func _input(event):
    if event.is_action_pressed("ui_up") and is_on_floor():
        velocity.y = jump_speed
    if event.is_action_pressed("shoot") and !shooting:
        shooting = true
        shot_speed = 20
        velocity.y = -200
        fire_weapon()

func _physics_process(delta):
    velocity.x = 0
    if Input.is_action_pressed("ui_right"):
        velocity.x += speed
    if Input.is_action_pressed("ui_left"):
        velocity.x -= speed
    if velocity.length() > 0:
        if velocity.x < 0:
            $AnimatedSprite.flip_v = true
            $AnimatedSprite.rotation_degrees = 180 
        elif velocity.x > 0:
            $AnimatedSprite.flip_v = false
            $AnimatedSprite.rotation_degrees = 0 
    if shooting:
        $AnimatedSprite.animation = "shot"
        velocity.x = -shot_speed * cos($AnimatedSprite.rotation_degrees)
        shot_speed *= 0.98
    else:
        if is_on_floor():
            if velocity.x == 0:
                $AnimatedSprite.animation = "idle"
            else:
                $AnimatedSprite.animation = "moving"
        else:
            $AnimatedSprite.animation = "jumping"

    velocity.y += grav * delta
    velocity = move_and_slide(velocity, Vector2(0,-1))
    if velocity.y == 0:
        velocity.y = 10

func on_animation_finished():
    if $AnimatedSprite.animation == "shot":
        shooting = false

func fire_weapon():
    var bullet = Bullet.instance()
    get_parent().add_child(bullet)
    if $AnimatedSprite.flip_v :
        bullet.position = $ShotLeft.global_position
    else:
        bullet.position = $ShotRight.global_position
    bullet.rotation_degrees = $AnimatedSprite.rotation_degrees
    bullet.linear_velocity = Vector2(1500 * cos(bullet.rotation),1500*sin(bullet.rotation))

Обратите внимание, что я не использую гравитацию в качестве скорости или фильма; вместо этого y умножьте его на дельту для получения скорости, поскольку ускорение x время дает скорость.

Надеюсь, это поможет.

0 голосов
/ 07 сентября 2018

Эту проблему можно решить с помощью Finite State Machine для управления элементами управления и поведением персонажа. Вы играете анимацию Jump при входе в состояние Jumping из состояния Walking. Использование правильных шаблонов проектирования на ранних этапах предотвращает использование спагетти-кода в будущем.

Это не решение Godot, но определенно стоит вашего внимания.

...