如何检查两个 KinematicBody2D 在 Godot 中是否重叠?

How do I check if two KinematicBody2D's are overlapping in Godot?

我刚刚开始编码,我正在尝试在 Godot 3.0 中制作一个简单的鸭子射击游戏。我有一个十字准线(Kinematicbody2D)和飞过屏幕的鸭子(也是 KinematicBody2D)。有没有一种方法可以检测鸭子和十字准线是否重叠?比如 if 语句?
如果有人好奇,这是我目前得到的代码(这是鸭子脚本,注释是我需要在该行添加的内容)。

 func _physics_process(delta: float) -> void:
    position.x += 4
    if (position.x > 1600):
        Score -= 1
        position.x = rand_range(-250, -1000)
    
    if Input.is_action_just_pressed("shoot"):
        #check if overlapping with crosshair
            Score += 1
            #bird explodes in feathers
            position.x = rand_range(-250, -1000)
        else:
            Score -= 0.25

我认为把准星做成物理学没有意义body。 它 collide/push/bounce 能避开障碍物吗? 更不用说 KinematicBody2D 了。 你需要 move_and_slide 或者你可以写 position 吗? 所以在我回答发布的问题之前,这里有一些替代方法可以解决这个问题。


输入可拾取

如果你想知道指针是否与物理相互作用body,你可以启用input_pickable,当它发生时你会得到一个"input_event"信号。


模拟输入 Pickable

否则,您可以在 _input 事件中获取定点设备的位置,并查询那里有什么物理 objects。像这样:

if (
        event is InputEventScreenDrag
        or event is InputEventScreenTouch
        or event is InputEventMouse
    ):
        var viewport := get_viewport()
        var position:Vector2 = viewport.get_canvas_transform().affine_inverse().xform(event.position)
        var objects := get_world_2d().direct_space_state.intersect_point(position)
        for object in objects:
            print(object.collider)

然后看看有没有你想要的。


Area2D

另一种方法是把十字准线做成Area2D,然后你可以向Area2D要它的overlapping_bodies,看看有没有你想要的。或者调用 overlaps_body 传递你的物理 body 作为参数,它 returns truefalse 分别与 Area2D 重叠或不重叠。


KinematicBody2D 碰撞

然后回答标题上的问题,如果你有两个运动机构,如果你用 move_and_* 方法移动它们(这就是它的意图)。你可以像这样列出他们碰撞的东西:

for i in get_slide_count():
    var collision = get_slide_collision(i)
    print("Collided with: ", collision.collider.name)

否则,你可以这样做:

var parameters := Physics2DShapeQueryParameters.new()
parameters.transform = global_transform
parameters.set_shape($CollisionShape2D.shape)
var results = get_world_2d().direct_space_state.intersect_shape(parameters)
for result in results:
    print(result.collider)