引子

        在一些游戏中,如果击中敌人,会跳出敌人车内的内构损伤情况

        这种伤害机制让“血条”隐藏在了不易被玩家发现的更深处,同时也增强了游戏的可玩性、真实性,对玩家的操作精度做出了更高的要求,增加了许多魔法的场面


我们能否在Scratch中实现这种效果?

原理详解

        我们以坦克为例,其内部主要结构大概有:发动机,弹药架,成员,炮闩(还有更多)

先从判定原理入手

        一般来说,想到纯数据碰撞,我们会想到计算两点距离来构造圆形碰撞箱:

image.png"

        当然也可以把两边同时平方后进行距离平方大小比较,省去开方运算

        如果使用曼哈顿距离会形成一个相对于x轴旋转45度的,对角线长为2d的正方形碰撞箱

image.png"

        这样可以省去乘法运算

        那么接下来,如果按照这种思路,我们可以创建一个列表来存储各个部件相对于车体的xy坐标

        此时,当炮弹射中车体后进行毁伤计算,代码流程大概如下:

重复执行(炮弹移动步数)次{

]遍历模块列表,每个元素设为a[n]{

]]判断炮弹是否命中a[n]

]}移动(步长)

}

''

        显然,这种方法的时间复杂度为O(n²),不够快

        那么更好的方法是什么?

        接下来切入正题!


网格法

        Scratch 的算力有限,我们可以把坦克内部结构抽象模糊成一个网格,每个网格中填充一种模块

例如:

车体:
装甲 装甲 装甲
履带 驾驶员 履带
履带 弹药架 履带
履带 发动机 履带
 
履带 发动机 履带
炮塔:
装甲 炮闩 装甲
车长 炮闩 炮手
弹药架 炮闩 弹药架
这样,我们可以对于炮弹相对于车体的坐标进行简单的运算计算出它在网格的哪一格中

(具体代码可以自己摸索)

那么此时毁伤计算代码如下:

'''

重复执行(炮弹移动步数)次{
]计算炮弹所在的网格
]判断炮弹命中的模块
]移动(步长)
}

'''

        当然,这种方法需要合适的步长(一般来说约等于网格边长)

        显然,这种方法的时间复杂度为O(n),且提高网格总数对代码运行速度影响不大

        那么,判定方法的问题已经解决,接下来的问题是如何将炮弹的绝对坐标转化为相对于车体的坐标

        可以用转轴公式解决:

image.png"

        (注意,这里的θ为从x轴正方向开始逆时针旋转的角度,sc中方向为从y轴正方向开始顺时针旋转的角度,即:公式角度=90°-sc方向)

        当然如果你会三角变换公式可以化简,这里不具体说明

        最后,你只需要将它们组合起来,再加上一些图形界面来反映毁伤结果,就可以制作出了!

更多推荐