【问题标题】:Trying to make a 2D destructable box in godot试图在 godot 中制作一个 2D 可破坏的盒子
【发布时间】:2022-01-06 18:31:12
【问题描述】:

我不擅长编码。我目前正在尝试制作一个可以在玩家攻击时被破坏的 2D 盒子,但是(就像我之前说的)我不擅长编码。我设法让它工作了一些(我的意思是一点也不)盒子有一个动画,当玩家在范围内攻击时播放,但动画几乎从不播放(有时它会但我不知道为什么)

盒子代码

extends Area2D

var inside = false
var attacking = false
    
func _physics_process(delta):
    pass
func _on_Area2D_body_entered(body):
    if Input.is_action_just_pressed("Attack"):
        $AnimationPlayer.play("box_hit")
        $boxdeathtimer.set_wait_time(0.5)
        $boxdeathtimer.start()

func _on_boxdeathtimer_timeout():
    queue_free()

武器代码(如果需要)

extends RigidBody2D

var picked = false

func _ready(): 
    Global.weapon = self
func _exit_tree():
    Global.weapon = null

var attacking = false

func _physics_process(delta):
    if picked == true:
        self.position = get_node("../player/Position2D").global_position

func _input(event):
    if Input.is_action_just_pressed("e"): #picks up weapon when in range
        var bodies = $detector.get_overlapping_bodies()
        for b in bodies:
            if (b.get_name() == "player"):
                picked = true
                sleeping = true
                rotation_degrees = 90
    if Input.is_action_just_pressed("Attack"):
        
        if picked == true && Global.player.facing_right == true:
            $AnimationPlayer.play("attack")     
            attacking = true
        if picked == true && Global.player.facing_right == false:
            $AnimationPlayer.play("attack2")
            attacking = true
        

【问题讨论】:

  • 假设Global.playerget_node("../player/"),你可以在拾取武器的代码中查看if (b == Global.player)。事实上,您可以查看$detector.overlaps_body(Global.player)。此外,要让武器随玩家移动,您可以这样做:get_parent().remove_child(self); Global.player.get_node("Position2D").add_child(self),并且您不必在每个物理帧都传送武器。编辑:像这样删除它会触发_exit_tree。编辑 2:另见 is_queued_for_deletionis_instance_valid

标签: godot gdscript


【解决方案1】:

当物理体进入该区域时,body_entered 信号会通知您。 is_action_just_pressed 方法告诉您(与该相关的键)操作是否被按下相同的(图形,默认情况下)帧。

因此,在您的代码中,这里的所有内容(假设信号已正确连接):

func _on_Area2D_body_entered(body):
    if Input.is_action_just_pressed("Attack"):
        # CODE HERE

只有当玩家按下(与此相关的键)动作时,才能运行与身体进入区域的相同(图形,默认情况下)帧,这很难管理。


我的建议是给武器一个“攻击范围”区域。然后当玩家攻击时,你可以在它移动时使用该区域的信号。


顺便说一句,避免在_input 中使用is_action_just_pressed。它不是为此而设计的。见Godot - Input.is_action_just_pressed() runs twice。事实上,我认为在_physics_process 中只使用Input,除非你真的需要_input如果您在 _input 工作,请参阅链接以了解替换 is_action_just_pressed 的内容。


所以,它可能看起来像这样:

在玩家方面:

func _physics_process(delta):
    # … some other code …
    if Input.is_action_just_pressed("Attack"):
        if picked == true && Global.player.facing_right == true:
            $AnimationPlayer.play("attack")     
            attacking = true
        if picked == true && Global.player.facing_right == false:
            $AnimationPlayer.play("attack2")
            attacking = true
        if attacking:
            $RangeOfAttack.monitoring = true
            yield($AnimationPlayer, "animation_finished")
            $RangeOfAttack.monitoring = false
            # attacking = false # ?

func _on_RangeOfAttack_area_entered(area):
    if area.has_method("attacked"):
        area.attacked()

地点:

  • yield($AnimationPlayer, "animation_finished") 告诉 Godot 在 $AnimationPlayer 发出 "animation_finished"signal 后继续执行。
  • $RangeOfAttack 指攻击范围。武器的子节点。
  • _on_RangeOfAttack_area_entered 连接到攻击区域范围的"area_entered" 信号。 我使用"area_entered" 而不是"body_entered" 的原因是您将框设置为一个区域。如果盒子不是一个区域而是一个物理体,你可以使用武器的"body_entered"信号(即RigidBody2D),你就不需要$RangeOfAttack了。

在目标端:

func attacked():
   $AnimationPlayer.play("box_hit")
   yield($AnimationPlayer, "animation_finished")
   queue_free()

【讨论】:

  • 对不起,我真的很笨,目标方是什么。
  • 编辑:我假设目标方是我想在攻击时摧毁的盒子。它可以工作,但动画 box_hit 只是循环
  • 编辑:没关系,我只是愚蠢,我让它工作了谢谢!
  • 编辑:没关系,我不能让它工作,我现在就放弃吧
  • @JacobWhisenand 是的,目标方是盒子,或者任何你想要攻击的东西。关于动画,我猜它被设置为在动画播放器中循环。然后你说它不起作用,我不知道你尝试了什么或者你遇到了什么其他问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多