碰撞

在规划运动或决定某些动作时,查看游戏世界中某些位置是否与其他对象发生碰撞通常很重要,并且通常为工作选择正确的碰撞函数是最重要的任务。GameMaker 具有许多内置函数,可以帮助您根据项目的需要正确处理碰撞。

如何检查碰撞

与物体碰撞

检查对象碰撞的最简单方法是使用 place_meeting

步骤事件

if (!place_meeting(x + 4, y, obj_rock))
{
    x += 4;
}

这仅检查与 obj_rock 实例的碰撞。如果 x + 4 处没有岩石,它会更改 X 位置以将实例移动到那里。

与多个物体的碰撞

您可以通过两种方式检查多个对象的碰撞:

使用传递数组的第二种方法,您的代码将如下所示:

if (!place_meeting(x + 4, y, [obj_rock, obj_bush]))
{
    x += 4;
}

这会检查同一函数调用中 obj_rockobj_bush 实例的冲突。

提示 建议使用父级方法进行多次冲突检查,因为您可以在多个函数调用中使用相同的父级,而无需跟踪数组。

place_meeting 函数仅返回 truefalse。如果您需要访问在碰撞中找到的实例,请使用 instance_place,它会返回实例句柄。

与平铺地图的碰撞

除了对象之外,您还可以将 Tile Map Element ID 传递给碰撞函数。这将检查与该图块地图的碰撞。

使用 layer_tilemap_get_id 获取图层的图块地图 ID,然后将该 ID 传递给碰撞函数。

Create Event

tilemap = layer_tilemap_get_id("TileLayer");

步骤事件

if (!place_meeting(x + 4, y, tilemap))
{
    x += 4;
}

将数组传递给碰撞函数时,您可以组合对象和图块贴图。

记住:

边界框

某些实例将使用矩形边界框来检查碰撞 (除非选择了不同的遮罩形状)。

这些边界框使用包含系统,即它们包括最底部和最右侧的边缘。这意味着 16x16 碰撞掩码的边界框是从 (0.0, 0.0)(16.0, 16.0)( 相对于实例) 生成的。

注意 您可以使用 bbox_leftbbox_topbbox_rightbbox_bottom 变量获取这些值 。

注意 由于边界框是包容性的 (如上所述),因此与精灵的边界框相比,它始终会超出其右下角 1 个像素。例如,16x16 方形精灵的 右边缘偏移 将为 15.0( 从 0 开始时的第 16 个像素),但是使用此精灵的实例将为您提供一个 bbox_right16(+ 其 X 位置)。

为了使两个实例发生碰撞,它们的边界框必须重叠。在像素级别,当该像素的中心被覆盖时,就会计算重叠。

例如, 如果您尝试与覆盖从 (0.0, 0.0)(16.0, 16.0) 区域的边界框发生碰撞, 遮罩的边缘必须接触到 (0.5, 0.5)(15.5, 15.5) 之间的区域才能算作碰撞。

函数 collision_pointcollision_line 是例外,它们不必覆盖像素中心,但可以在像素内的任何位置进行检查。在上面的示例中,(15.99, 15.99) 处的点检查将返回 true,但 (16.0, 16.0) 则不会。

以下函数处理各种方法,通过这些方法可以使实例检查是否与另一个实例发生碰撞:

高级碰撞检查

为此,可以使用以下函数 (以及与 移动实例 相关的部分中详细介绍的其他函数)。这些碰撞函数的工作方式都略有不同,但它们保留了三个共同的参数,我们将在这里进行解释:

基本函数将返回发现有碰撞的实例的Id,或者在没有碰撞时返回特殊关键字noone,而列表函数将返回碰撞的实例数,并用它们的Id填充预制的D列表。请注意,如果与给定对象的这些函数和实例定义的区域存在多个碰撞,则仅返回一个实例Id,并且它可以是碰撞中的任何一个实例。

存在以下处理高级碰撞的函数。

不带遮罩的碰撞检查

以上所有函数都与碰撞检查实例相关,因此依赖于为该实例定义的碰撞遮罩。但是,有许多时刻需要检查与点或区域的"碰撞",尤其是当您的实例没有指定精灵时,或者当您正在使用鼠标等时...因此GameMaker还提供以下函数来帮助您解决这些问题:

物理碰撞

使用内置物理时,不能保证上述碰撞函数适用于启用物理的实例。这主要是由于这些实例不再使用大多数常规内置变量(相反,启用了物理的实例具有自己的组变量),也不使用碰撞遮罩或边界框,因为它们改用了设备。但是,有一个特殊函数可用于在启用了物理函数的情况下测试碰撞,该函数可检查重叠的设备: