我用过的一种方法:
当移动一个(玩家、其他精灵……)时,将它通过的所有图块确定为一个矩形。
举例:
on tick:
player-box = (player.x, player.y) - (player.x + player.width, player.y + player.height)
player-delta.x = (player-speed.x × (now - last-updated))
player-delta.y = (player-speed.y × (now - last-updated))
player-end-box = player-box + player-delta
{ i.e. player-end-box = ( player-box.top-left.x + player-delta.x,
player-box.top-left.y + player-delta.y ) -
( player-box.bottom-right.x + player-delta.x,
player-box.bottom-right.y + player-delta.y ) }
player-collided = ( min (player-box.top-left.x, player-end-box.top-left.x),
min (player-box.top-left.y, player-end-box.top-left.y) ) -
( max (player-box.bottom-right.x, player-end-box.bottom-right.x),
max (player-box.bottom-right.y, player-end-box.bottom-right.y) )
然后您可以使用player-collided 的每个角的modulo 32 来确定玩家(或任何精灵)已经(试图)遮挡的图块。
通常,您可能希望在播放器的实际尺寸上放置一个小的“边距”,以避免 1px 或 2px 重叠......(即,将起始框设置为比实际精灵小几个 px),具体取决于如何准确的玩家控制,以及精灵和一个瓷砖之间的大小差异。
请注意,非常快的(每次更新许多图块)对角线移动会使此设置无效,但它适用于非常快速的线性(水平或垂直)移动。如果您在对角线上移动“太快”,对于这种方法,请考虑将开始和结束矩形连接成一个多边形(不规则六边形)并测试每个图块是否包含该六边形的任何部分。
for each tile in (big rectangular area):
if tile is inside polygon (hexagon of movement):
add tile to list of collisions
这本质上是对常见 2D 情况的完整边界几何检查的优化。