我在一个简单的平台游戏中有一个脚本,其中说如果我的玩家在地面上并且按下“ Z”,则他在Y轴上的移动将上升到600,而如果他不在地面上,他将执行跳转动画。
这就是问题,我知道它仅播放跳跃动画的第一帧,因为代码不断检测到播放器处于空中。 我想要一种告诉代码仅触发一次动画的方法。
我尝试使用名为input_(event):
的函数,但似乎没有is_action_just_pressed
类型的is_action_pressed
输入。
我对Godot还是很陌生,不知道如何使用信号。信号可能通过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)
答案 0 :(得分:2)
我遇到了smae问题,它为我解决了,在move_and_slide()之后添加了下一个:
if velocity.y == 0:
velocity.y = 10
显然,如果在move_and_slide()之后速度为0,则不再检测到is_on_floor()(错误?),所以我在重力方向上添加了较小的速度。
关于usinginput_(event),您不需要just_pressed,因为它只在有输入时才处理。您可以执行以下操作:
func _input(event):
if event.is_action_pressed("ui_up") and is_on_floor():
velocity.y = jump_speed
我所说的速度,我认为在您的脚本中称为movimiento。另外,我认为您在movimiento中混合重力和速度。我正在与您分享我的角色故事,以便您进行比较并查看效果是否更好:
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乘以delta以获得速度,因为加速度x时间给出速度。
我希望这会有所帮助。
答案 1 :(得分:0)
可以使用Finite State Machine来解决角色控制和行为的问题。从“行走”状态进入“跳跃”状态时,将播放“跳跃”动画。尽早使用正确的设计模式可以防止将来出现意粉代码。
这不是Godot专用的解决方案,但是绝对值得您关注。
答案 2 :(得分:0)
让我们剖析一下这里发生的事情,您启动代码并要求您的播放器在一帧中播放动画,然后在另一帧中播放动画,只要按下正确的键或您处于正确的状态即可。
问题是,问题在于每次调用该函数时,它会一次又一次触发动画,因此它只是重新启动,或者另一个调用单独运行,这会导致意外的行为。
更好的方法是同时管理播放器和动画播放器的状态,并使用它们来执行动画调用。
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
对于动画播放器状态,请使用您正在谈论的信号,使用GUI或以下代码。
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")
根据自己的喜好将其设置为true或false。基于动画完成信号。
将来,您甚至可能要考虑使用简单的FSM来维护所有这些状态数据和变量。