用射线投射检查物体碰撞
-
预备知识
介绍
当一辆一车或者一个角色正在移动,它可能会跟其他物体产生碰撞。我们需要确保这个碰撞被真实地模拟出来。举个例子,一个角色不应该能穿透一面墙壁。
除了用距离来计算物体间的碰撞,我们也可以使用一种名为“射线投射”的方式。当场景中有很多你需要检查碰撞的物体时,这个方式会更加方便。
碰撞器
要检查一个玩家物体(一个角色或一辆汽车)是否正在和其他物体碰撞,我们首先需要定义一个玩家的边界。要让这个概念变得简单,我们假设玩家是被一个盒子包裹着的。我们可以把它称之为“碰撞器”。碰撞器的大小是根据玩家物体的大小自动计算的。
https://cdncreaticodecom.b-cdn.net/scratch-gui-projects/forum/7ab7e8b8-4ab3-4245-bb3e-d53b7e1ae664.gif" width="300" style="border-radius: 5px; border: 1px solid #29622d;">
当这个碰撞器盒子和其他物体接触时,我们就会知道碰撞发生了:
https://cdncreaticodecom.b-cdn.net/scratch-gui-projects/forum/a77e60b2-1f91-46e2-bded-d469e8285adc.gif" width="500" style="border-radius: 5px; border: 1px solid #29622d;">
射线投射
要找出碰撞器盒子是否正在接触另一个物体,我们可以使用名为“射线投射”的技巧。
射线投射的基本概念就是我们从碰撞器盒子的中心往所有六个方向(上、下、左、右、前、后)射出线。这些线被称之为“射线”。
https://cdncreaticodecom.b-cdn.net/scratch-gui-projects/forum/052cb6d9-5459-4a0d-9f3e-4b7486594351.gif" width="400" style="border-radius: 5px; border: 1px solid #29622d;">
当一个玩家物体(举例一个角色或一辆汽车)移动时,射线会跟随它一起移动。当玩家物体靠近蓝色墙壁时,玩家物体朝向前方的射线将会先接触到墙壁。射线会报告它与墙壁交互的点,也被称之为“交叉点”。现在我们就可以计算玩家物体前面和交叉点的距离。
https://cdncreaticodecom.b-cdn.net/scratch-gui-projects/forum/5fec3359-1942-42fe-8501-b70c2ff298a7.png" width="700" style="border-radius: 5px; border: 1px solid #29622d;">
这个距离会在玩家逐渐靠经墙壁时被减少,所以当距离减少至0,我们就会知道玩家物体的前面正在触碰墙壁。反之,如果射线没有跟任何物体交互,那我们就假设没有障碍。
https://cdncreaticodecom.b-cdn.net/scratch-gui-projects/forum/9d520ecf-9039-40c2-97de-da9d8a1be5eb.gif" width="950" style="border-radius: 5px; border: 1px solid #29622d;">
同样的方法也可以被使用在其他五个方向。
现在,让我们来看看你可以怎么样在程序中开启碰撞感应。
“打开碰撞”编程积木
https://cdncreaticodecom.b-cdn.net/scratch-gui-projects/forum/9015cef9-0f33-4520-ac13-7f1fcb7389c9.png" width="900" style="">
这个编程积木将会开启玩家物体的碰撞感应。需要注意的是,这个积木只有在你利用三维物体的速度来移动物体的时候才会运作。
需要补充的是,如果你多次运行这个编程积木,最后一个编程积木的参数将会决定碰撞器盒子的参数。
参数
碰撞种类
碰撞有两种类别:“可穿过的”或“不可穿过的”。
- 如果你想要在发生碰撞时让玩家停下,比如当玩家碰到墙壁是,你应该使用不可穿过的类别。需要注意的是,玩家物体只可以在你使用“设置速度”来移动玩家物体时被停下来。换句话说,如果你直接设置玩家物体的x/y/z位置,那么玩家物体将不会在碰撞到物体时停下。
- 如果你要让玩家继续移动,比如当玩家物体为了奖励收集宝石时,你应该使用“可穿过的”类别。
https://cdncreaticodecom.b-cdn.net/scratch-gui-projects/forum/63360e87-9198-4d41-b49f-dfa792ba6e69.png" width="800" style="margin-left: 40px; border-radius: 5px; border: 1px solid #29622d;">
障碍角色
这是你指定哪个角色会跟玩家碰撞的地方。需要注意的是,你不需要一个一个地指定障碍物体。你可以直接指定一个角色,以便所有在那个角色里创建的物体都会时障碍物。
举个例子,如果你在一个游戏里需要很多面墙壁,那么所有的墙壁盒子都可以在一个名为“墙壁”地角色里被创建,然后它们全部都会在你运行这个“打开碰撞”编程积木之后,跟玩家碰撞。
下图展示了一个设立不可穿过的墙和可穿过的宝石的例子。两个“广播”编程积木将会在其他两个角色里创建墙壁盒子并添加宝石,然后你就可以在“墙壁”角色中打开不可穿过的碰撞,并在“宝石”角色中打开可以穿过的碰撞。
https://cdncreaticodecom.b-cdn.net/scratch-gui-projects/forum/b7ae1ad5-7e28-480e-a0f2-312d4ec3d1e3.png" width="800" style="filter: drop-shadow(0.35rem 0.35rem 0.4rem rgba(0, 0, 0, 0.5));">
碰撞器Z位移
这个数值允许你调整碰撞器盒子的Z位置。对于有些物体,比如角色或建筑物来说,他们的位置只说明了他们的最低点,并没有说明他们的中心点,这会导致碰撞器位置太低。所以,我们需要调整碰撞器Z位置的位移。
举个例子,对于一个高度100的角色来说,它的Z位移数值应该是50:
https://cdncreaticodecom.b-cdn.net/scratch-gui-projects/forum/e4b82bf4-f964-462b-88ed-a49cb483db09.gif" width="800" style="border-radius: 5px; border: 1px solid #29622d;">
感应精度
你可以使用这个设置来控制用来感应碰撞的射线数量:
-
低: 这意味着我们只会使用6束射线,每个方向一束。所有的6束射线都来源于玩家盒子的中心,所以如果有个小障碍物没有被射线击中,那么它将不会被感应。
-
高: 这意味着我们会使用26束射线, 左右方向各三束射线,而其他四个方向各五束射线。更多的射线会需要更多的运算,但是它们也会能够检测到更多障碍物。
-
下方和前方: 这意味着我们只会使用2束射线, 下方一束以及前方一束。这是最快的模式,而如果我们正在创建简单的游戏,那它已经足够好用了。
https://cdncreaticodecom.b-cdn.net/scratch-gui-projects/forum/c81ed845-8780-4bf5-b259-d36649076fcf.gif" width="700" style="border-radius: 5px; border: 1px solid #29622d;">
调试模式
这个选项控制了你要隐藏或展示碰撞器盒子和射线。一般情况下,当你正在建立或调试你的程时,你应该把这个选项设置成“是”;当程序完成时,你应该把这个选项设置成“否”。
演示
这是一个你可以尝试的程序例子:
https://play.creaticode.com/projects/151ec87b5f86b37b1bc8154f
检查角色是否被阻挡
你可以使用下列六个编程积木中的一个来找出角色在六个方向中的一个方向是否被阻挡。数值”0“代表角色在该方向没有被阻挡,而数值”1“代表角色在该方向被阻挡。
https://cdncreaticodecom.b-cdn.net/scratch-gui-projects/forum/88d3847b-f325-41ae-bdf3-38f03604ee8f.png" width="800" style="">
演示
在这个演示中,变量“角色物体前面被阻挡”在一开始为0,但是当角色前面被墙壁阻挡时,系统把变量更新成1。
https://cdncreaticodecom.b-cdn.net/scratch-gui-projects/forum/d81e4b3e-578a-4c25-aad1-0fc51d94bd95.gif" width="500" style="border-radius: 5px; border: 1px solid #29622d;">
碰撞事件编程积木
你也可以使用这个帽子编程积木来处理碰撞事件。
https://cdncreaticodecom.b-cdn.net/scratch-gui-projects/forum/cf9dce88-5fd7-421e-a61f-45e1aa1d9e89.png" width="260" style="">
在落下的选项中,你需要选择包含着障碍物体的角色名称,比如添加所有障碍盒子的“墙壁”角色。这之前,你一定需要先开启和该角色的可穿过的和不可穿过的碰撞。
当一个碰撞发生时,这个帽子编程积木将会被触发。而且,正在碰撞的物体就将会成为现有角色的“角色物体”。举个例子,如果你在“墙壁”角色中运行这个帽子编程积木,那么和角色碰撞的那个墙壁盒子将会成为“墙壁”角色的角色物体。
演示
在这个演示中,每当角色跟墙壁盒子碰撞时,我们把角色移到起始点并让他再次向前。需要注意的是,你需要再次设置“前进速度”,因为角色每次被阻挡时,它的前进速度都会被重置成0,以让角色停下。
https://cdncreaticodecom.b-cdn.net/scratch-gui-projects/forum/65b00223-98c7-4345-8e67-c02e2aafef26.gif" width="900" style="border-radius: 5px; border: 1px solid #29622d;">
了解更多
-
I CreatiCode pinned this topic on
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login