为什么我的代码没有使用正确的动画?
Why doesn't my code use the correct animation?
我有一个用 Python 编写的功能正常的格斗游戏,有移动、帧数据、攻击(没有用)但没有重力。我正在尝试用 Godot 重写它,但我真的迷路了。
我有一个在我的攻击中实施帧数据的系统,所以我实际上可以轻松地从空闲状态转换到攻击状态,反之亦然。现在,我的问题是我想攻击并播放那个动画,但它一直在播放空闲动画。在我开始做碰撞盒和碰撞之前,我想让这件事起作用。这是我的代码:
extends KinematicBody2D
export var walking_speed = 100
export var falling_speed = 0
var time = 0
onready var anim = $Sprite
var state = "Idle"
func _ready():
set_physics_process(true)
set_process(true)
$AnimationTree.active = true
func gravity():
pass
func _physics_process(delta):
time += delta
print(time)
# If you press both A and D, you will stop entirely
if Input.is_action_pressed("ui_left") and Input.is_action_pressed("ui_right"):
walking_speed == 0
$AnimationTree.set("parameters/Neutral/current", 0)
#if you press A or D, you will move left or right accordingly
elif Input.is_action_pressed("ui_left"):
move_and_collide(Vector2(-walking_speed * delta, 0))
anim.flip_h = true
$AnimationTree.set("parameters/Neutral/current", 1)
elif Input.is_action_pressed("ui_right"):
move_and_collide(Vector2(walking_speed * delta, 0))
anim.flip_h = false
$AnimationTree.set("parameters/Neutral/current", 1)
else:
walking_speed = walking_speed
if Input.is_action_just_pressed("Horizontal"):
$AnimationTree.set("parameters/Neutral/current", 2)
这段代码基本上只是一堆我被告知要做的事情的教程的混杂(例如,我被告知不要使用 AnimatedSprite
而是使用 AnimationTree
,但是它似乎代码要复杂得多,并且给我带来了与上次相同的问题)。如果你需要我,我也可以 post 我的 Python 代码,但它是一个巨大的混乱,根本没有评论。
您可以使用 AnimatedSprite
制作动画。你有我的祝福。 AnimatedSprite
有没有用。而且“有人告诉我”并不是不这样做的好理由。
此外,AnimatedSprite
与 AnimationPlayer
和 AnimationTree
不是非此即彼。是的,有些东西您需要 AnimationPlayer
和 AnimationTree
,但是您始终可以让 AnimationPlayer
触发 AnimatedSprite
动画。事实上,AnimationPlayer
可以调用任何方法(而 AnimationTree
将控制 AnimationPlayer
)。因此,用 AnimatedSprite
完成的任何工作都不会浪费。
调用 set_physics_process
将启用或禁用 [=31=]。同样,set_process
启用或禁用 [=33=]。但是,如果您有该方法,那么默认情况下它是启用的。因此,只有在禁用它们时才需要启用它们。
我们可以压缩很多你的_physics_process
代码:
func _physics_process(_delta:float) -> void:
var walking_speed := (
Input.get_action_strength("ui_right") -
Input.get_action_strength("ui_left")
)
anim.flip_h = walking_speed < 0
var velocity := Vector2(walking_speed, 0)
move_and_collide(velocity * delta)
当 walking_speed
为负数时,行 anim.flip_h = walking_speed < 0
会将 flip_h
设置为 true
,否则设置为 false
。
我们正在根据 get_action_strength
设置 walking_speed
将 return 一个介于 0
和 1
之间的数字,表示按下动作的力度。这也意味着如果它们被映射到操纵杆或类似物,这将为您提供灵敏度支持。
如果您不想那么敏感,sign
可以:
var walking_speed := sign(
Input.get_action_strength("ui_right") -
Input.get_action_strength("ui_left")
)
使用 KinematicBody2D
你将不得不处理重力。基本上给它一些向下的速度。
var gravitational_acceleration := 100 # pixels per second squared
var falling_speed := 0
func _physics_process(_delta:float) -> void:
falling_speed += gravitational_acceleration * delta
var walking_speed := (
Input.get_action_strength("ui_right") -
Input.get_action_strength("ui_left")
)
anim.flip_h = walking_speed < 0
var velocity := Vector2(walking_speed, falling_speed)
move_and_collide(velocity * delta)
不过,最好用move_and_slide
实现重力:
var gravitational_acceleration := 100 # pixels per second squared
var falling_speed := 0
func _physics_process(_delta:float) -> void:
falling_speed += gravitational_acceleration * delta
var walking_speed := (
Input.get_action_strength("ui_right") -
Input.get_action_strength("ui_left")
)
anim.flip_h = walking_speed < 0
var velocity := Vector2(walking_speed, falling_speed)
velocity = move_and_slide(velocity)
falling_speed = velocity.y
我在末尾删除了与 delta
的乘法,因为 move_and_slide
在内部执行此操作。也就是说,它需要速度而不是位移。
这样 falling_speed
就不会失去控制。
你也可以加上一个向上向量(这样Godot就知道什么是天花板,什么是地板,什么是墙),然后你可以检查is_on_ceiling
,is_on_floor
和is_on_wall
.
另外,你可以告诉move_and_slide
,floor_max_angle
是0
,所以它不会滑动(什么都不算斜坡,只有完全水平的地板是地板),如果这是你想要的。
当然还有动画。
如果您要使用 AnimationTree
,我建议将根设置为 AnimationNodeStateMachine
。然后,从代码中,你可以得到状态机播放对象,像这样:
var state_machine = $AnimationTree.get("parameters/playback")
您可以告诉它您希望它进入不同的状态,如下所示:
state_machine.travel("name_of_some_state")
你可以问它当前状态是什么:
var state:String = state_machine.get_current_node()
例如,你可以在你的状态机中有一个“空闲”状态,在你的状态机中有一个“攻击”状态,从“空闲”到“攻击”的转换,以及从“攻击”的另一个转换”到“空闲”,但那个设置为“最后”过渡。 你当然可以有其他状态。然后使用当前状态(来自get_current_node
)来计算玩家可以做什么。
用AnimationPlayer
你可以检查什么是current_animation
和is_playing
;您还可以连接 "animation_finished"
信号。使用 AnimatedSrite
你可以检查当前的 animation
是什么,是否是 playing
;您还可以连接 "animation_finished"
信号。
我有一个用 Python 编写的功能正常的格斗游戏,有移动、帧数据、攻击(没有用)但没有重力。我正在尝试用 Godot 重写它,但我真的迷路了。
我有一个在我的攻击中实施帧数据的系统,所以我实际上可以轻松地从空闲状态转换到攻击状态,反之亦然。现在,我的问题是我想攻击并播放那个动画,但它一直在播放空闲动画。在我开始做碰撞盒和碰撞之前,我想让这件事起作用。这是我的代码:
extends KinematicBody2D
export var walking_speed = 100
export var falling_speed = 0
var time = 0
onready var anim = $Sprite
var state = "Idle"
func _ready():
set_physics_process(true)
set_process(true)
$AnimationTree.active = true
func gravity():
pass
func _physics_process(delta):
time += delta
print(time)
# If you press both A and D, you will stop entirely
if Input.is_action_pressed("ui_left") and Input.is_action_pressed("ui_right"):
walking_speed == 0
$AnimationTree.set("parameters/Neutral/current", 0)
#if you press A or D, you will move left or right accordingly
elif Input.is_action_pressed("ui_left"):
move_and_collide(Vector2(-walking_speed * delta, 0))
anim.flip_h = true
$AnimationTree.set("parameters/Neutral/current", 1)
elif Input.is_action_pressed("ui_right"):
move_and_collide(Vector2(walking_speed * delta, 0))
anim.flip_h = false
$AnimationTree.set("parameters/Neutral/current", 1)
else:
walking_speed = walking_speed
if Input.is_action_just_pressed("Horizontal"):
$AnimationTree.set("parameters/Neutral/current", 2)
这段代码基本上只是一堆我被告知要做的事情的教程的混杂(例如,我被告知不要使用 AnimatedSprite
而是使用 AnimationTree
,但是它似乎代码要复杂得多,并且给我带来了与上次相同的问题)。如果你需要我,我也可以 post 我的 Python 代码,但它是一个巨大的混乱,根本没有评论。
您可以使用 AnimatedSprite
制作动画。你有我的祝福。 AnimatedSprite
有没有用。而且“有人告诉我”并不是不这样做的好理由。
此外,AnimatedSprite
与 AnimationPlayer
和 AnimationTree
不是非此即彼。是的,有些东西您需要 AnimationPlayer
和 AnimationTree
,但是您始终可以让 AnimationPlayer
触发 AnimatedSprite
动画。事实上,AnimationPlayer
可以调用任何方法(而 AnimationTree
将控制 AnimationPlayer
)。因此,用 AnimatedSprite
完成的任何工作都不会浪费。
调用 set_physics_process
将启用或禁用 [=31=]。同样,set_process
启用或禁用 [=33=]。但是,如果您有该方法,那么默认情况下它是启用的。因此,只有在禁用它们时才需要启用它们。
我们可以压缩很多你的_physics_process
代码:
func _physics_process(_delta:float) -> void:
var walking_speed := (
Input.get_action_strength("ui_right") -
Input.get_action_strength("ui_left")
)
anim.flip_h = walking_speed < 0
var velocity := Vector2(walking_speed, 0)
move_and_collide(velocity * delta)
当 walking_speed
为负数时,行 anim.flip_h = walking_speed < 0
会将 flip_h
设置为 true
,否则设置为 false
。
我们正在根据 get_action_strength
设置 walking_speed
将 return 一个介于 0
和 1
之间的数字,表示按下动作的力度。这也意味着如果它们被映射到操纵杆或类似物,这将为您提供灵敏度支持。
如果您不想那么敏感,sign
可以:
var walking_speed := sign(
Input.get_action_strength("ui_right") -
Input.get_action_strength("ui_left")
)
使用 KinematicBody2D
你将不得不处理重力。基本上给它一些向下的速度。
var gravitational_acceleration := 100 # pixels per second squared
var falling_speed := 0
func _physics_process(_delta:float) -> void:
falling_speed += gravitational_acceleration * delta
var walking_speed := (
Input.get_action_strength("ui_right") -
Input.get_action_strength("ui_left")
)
anim.flip_h = walking_speed < 0
var velocity := Vector2(walking_speed, falling_speed)
move_and_collide(velocity * delta)
不过,最好用move_and_slide
实现重力:
var gravitational_acceleration := 100 # pixels per second squared
var falling_speed := 0
func _physics_process(_delta:float) -> void:
falling_speed += gravitational_acceleration * delta
var walking_speed := (
Input.get_action_strength("ui_right") -
Input.get_action_strength("ui_left")
)
anim.flip_h = walking_speed < 0
var velocity := Vector2(walking_speed, falling_speed)
velocity = move_and_slide(velocity)
falling_speed = velocity.y
我在末尾删除了与 delta
的乘法,因为 move_and_slide
在内部执行此操作。也就是说,它需要速度而不是位移。
这样 falling_speed
就不会失去控制。
你也可以加上一个向上向量(这样Godot就知道什么是天花板,什么是地板,什么是墙),然后你可以检查is_on_ceiling
,is_on_floor
和is_on_wall
.
另外,你可以告诉move_and_slide
,floor_max_angle
是0
,所以它不会滑动(什么都不算斜坡,只有完全水平的地板是地板),如果这是你想要的。
当然还有动画。
如果您要使用 AnimationTree
,我建议将根设置为 AnimationNodeStateMachine
。然后,从代码中,你可以得到状态机播放对象,像这样:
var state_machine = $AnimationTree.get("parameters/playback")
您可以告诉它您希望它进入不同的状态,如下所示:
state_machine.travel("name_of_some_state")
你可以问它当前状态是什么:
var state:String = state_machine.get_current_node()
例如,你可以在你的状态机中有一个“空闲”状态,在你的状态机中有一个“攻击”状态,从“空闲”到“攻击”的转换,以及从“攻击”的另一个转换”到“空闲”,但那个设置为“最后”过渡。 你当然可以有其他状态。然后使用当前状态(来自get_current_node
)来计算玩家可以做什么。
用AnimationPlayer
你可以检查什么是current_animation
和is_playing
;您还可以连接 "animation_finished"
信号。使用 AnimatedSrite
你可以检查当前的 animation
是什么,是否是 playing
;您还可以连接 "animation_finished"
信号。