一種方法:
當移動一個(播放器,其他精靈...),確定所有其所穿過的矩形瓦片。
舉例來說:
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
確定磚的播放器(或任何Sprite)的(試圖)封閉。
通常情況下,您可能希望在播放器的實際尺寸中放置一個小的「邊距」以避免1px或2px重疊...(即,將起始框設置爲小於實際精靈幾個像素),具體取決於玩家的控制有多精確,以及精靈和一個圖塊之間的大小差異。
請注意,非常快速(每更新多個瓷磚)的對角線移動使其無效,但對於非常快速的線性(水平或垂直)移動,它可以很好地工作。如果您在對角線上移動速度太快,對於此方法,請考慮將起始矩形和結束矩形連接成多邊形(不規則六邊形),然後測試每個小塊是否包含該六邊形的任何部分。
for each tile in (big rectangular area):
if tile is inside polygon (hexagon of movement):
add tile to list of collisions
這實質上是對常見2D情況的全邊界幾何檢查的優化。
因此,您認爲在檢查之前不是移動框,而是在碰撞檢查期間更新位置時,只有在檢查碰撞結果爲假時才更新位置? –
如果您的包裝箱/掃描箱檢查爲假,那麼您可以將其移動到所需的位置。如果這是真的,你需要弄清楚在dt期間它是否成真。我建議您在二進制搜索中改變掃描箱第二個點(位置+速度* alpha),其中alpha在0.0和1.0之間變化。當你發現你的碰撞發生時,你只需將你的盒子的最終位置設置爲(position + velocity * alpha)。 – genpfault
非常感謝您的回答。我已經應用這種方法並且工作得非常好。 –