我试图通过制作一个简单的2D射击游戏来学习Godot,但遇到了一个问题。我不知道如何检测敌人是否被子弹击中。我的项目符号是带有精灵的Area2D节点和附加的CollisionShape2D节点。我的敌人是带有精灵的KinematicBody2D节点和附加的CollisionShape2D节点。敌人也有一个定时器,但这并不重要。
这是敌人的代码:
extends KinematicBody2D
var speed = 200
var velocity = Vector2(-0.5, 1)
var bullet_preload = preload("res://Enemy/EnemyBullet.tscn")
func _ready():
randomize()
velocity.y = [1, -1][randi() % 2]
func _physics_process(delta):
var collision = move_and_collide(velocity * speed * delta)
if collision:
velocity = velocity.bounce(collision.normal)
if position.x < -20:
print("Enemy Despawned")
queue_free()
if $ShootDelay.time_left == 0:
var bullet = bullet_preload.instance()
bullet.position.x = position.x - 18
bullet.position.y = position.y + 6
get_parent().add_child(bullet)
$ShootDelay.start()
这是我的玩家子弹头代码:
extends Area2D
var speed = 600
var velocity = Vector2(1, 0)
func _process(delta):
position.x += speed * delta
if position.x > 1044:
queue_free()
func _on_PlayerBullet_body_entered(body):
queue_free()
需要注意的是,玩家子弹和敌人场景不在同一场景树中,而且(据我所知(无法在它们之间发送信号。它们都被实例化到我的主根节点,该节点通过代码包含整个游戏。
如果我需要包括其他细节,请告诉我。
在您的_on_PlayerBullet_body_entered
上,您有一个body
,它引用了与Area2D
冲突的任何内容,您可以使用它与它通信。
例如,你可以在上面调用一个方法。当然,它可以是queue_free
:
func _on_PlayerBullet_body_entered(body):
body.queue_free()
queue_free()
然而,我建议不要这样做。相反,让我们想出一个方法,你可以实现任何你想要的行为:
func _on_PlayerBullet_body_entered(body):
body.shot()
queue_free()
当然,我们有一个问题,我们不确定它是否有这种方法…所以,让我们检查一下:
func _on_PlayerBullet_body_entered(body):
if body.has_method(shot):
body.shot()
queue_free()
然后将该方法添加到对子弹撞击做出反应的对象上。回到queue_free
,它可能是:
func shot() -> void:
queue_free()
或者你可以让它像这样:
var health := 5
func shot() -> void:
health -= 1
if health <= 0:
queue_free()
或者,你可以让它设置一个标志,并在_physics_process
上处理它,或者在适当的时间和地点处理它:
var was_shot := 5
func _physics_process(_delta) -> void:
if was_shot:
queue_free()
func shot() -> void:
was_shot = true
当然,除了queue_free
之外,你可能还想实例化其他场景(例如尸体或爆炸(或播放动画或类似的东西。