2011-09-02 153 views
2

我正在做一個簡單的2D遊戲(鳥瞰圖)。我有射彈,它們是圓圈。圍繞遊戲關卡存在障礙,這些都是矩形(軸對齊)。我希望彈丸在碰撞時能夠從障礙物上彈開。我不知道如何在我的遊戲循環中實現這一點。猜測它會是這樣的:遊戲循環中的碰撞檢測?

void gameLoop() { 

    Projectile p = ..; 

    p.updateLocation(p.getVelocity(), p.getDirection()); 

    Barrier intersected = p.intersects(barriers); 
    if (intersected != null) { 
     // We hit a barrier after moving on this time tick. 
     // Figure out where our reflected location off the 
     // barrier should be now. 
     Point ptNew = intersected.reflect(p.getLastPoint(), p.getVelocity(), 
      p.getDirection()); 

     // Our new location after getting bounced off the barrier. 
     ptNew.setLocation(ptNew); 
    } 
} 

所以當我們移動彈丸,我們可以檢查,如果我們相交(或完全內)的障礙之一。如果是這樣,做一個計算,找出我們的反射位置應該離開我們的起點和速度/方向的障礙。

感謝

----------更新------------------------

小更具體一點 - 考慮到Erik的評論,我確實需要確保彈丸正常彈跳,如果它們的速度恰好如此之快,我們就不能讓它們通過障礙,它們會在單個遊戲循環迭代中順利完成。在這種情況下,我想我需要測試一個起點,速度,方向,對所有障礙(可能反覆),直到不再有可能的速度交點。例如:

void gameLoop() { 
    Projectile p = ...; 

    Barrier barrier = moveProjectile(p, barriers); 
    while (barrier != null && p.stillHasVelocityThisFrame()) { 
     barrier = moveProjectile(p, barriers); 
    } 

    // at this point, the projectile is done moving/bouncing around. 
} 

void moveProjectile(Projectile projectile, 
        List<Barrier> barriers) 
{ 
    for (Barrier barrier : barriers) { 
     // tbd 
     Barrier intersected = test2dVectorAgainstRectangle(
      projectile.getPosition(), 
      projectile.get2dVector()); 
     // the above would test the projectile's vector 
     // to see if it intersects any barrier, reflect 
     // off of it if necessary, modify the projectile's 
     // position, and reduce the available distance it 
     // can still travel for this frame. 
     if (intersected) { 
      return intersected; 
     } 
    } 

    // no intersections. 
    return null; 
} 

是的,這已經變得棘手。

感謝

+0

其中的這部分,你需要幫助的?碰撞本身還是反射?或者兩者兼得? – MGZero

+0

嗯,我不知道該怎麼做(代碼示例或鏈接會很棒),但是如果這是如何完成的話,更多的是尋找一般性的yes/no。 – user291701

+0

這是一個非常開放的問題 – Erik

回答

2

您希望使用矢量數學您的反射和碰撞檢測。這是非常直接的檢測,如果你是在一條線(世界矩形邊緣)的一側,並在該線的另一側接下來。同樣的支票也會讓你碰到更多的數學碰撞點。然後你有一個點來反思,再次使用矢量。繪製與其他物體的碰撞有點詭計,但仍然可以完成。列出一個循環中的所有碰撞列表,並嘗試找到沿着它們的移動路徑出現的第一個 - 再次使用某些點積魔術。或者,如果您檢測到多次碰撞,則可以始終備份每個對象,使其位於之前的位置,並從那裏應用碰撞。你永遠要做到

一件事是讓物體停留另一個對象內。它可能會導致它們彼此卡住,並且行爲非常不穩定 - 取決於您如何執行碰撞代碼。

2

碰撞檢測是很難得到的權利。這真的取決於你想要的東西是多麼「完美」。

需要思考的幾件事:
1)如果p移動得太快,直接通過一個更新而不經過一次更新就會發生什麼?你真的需要檢查p的路徑是否與屏障相交。

2)如果p在穿過更新刻度的中途與屏障相交,但是在新的刻度結束之前如果與另一個屏障(或另一個p)相交,則會發生什麼?您必須在單個更新記錄中多次更新p的速度。

或者你可以忽略這些案件,希望事情工作了/不經常發生;)

+0

是的完美的這些是我需要警告的問題! – user291701

1

對於碰撞...... 什麼你要找的是的中心之間的距離圓和矩形上的任意點。如果任何給定點之間的距離小於圓的半徑,則發生碰撞。你可以使用畢達哥拉斯定理。

If (sqrt((circle.x - rect.x)² + (circle.y - rect.y)²) <= circle.radius) 
    circle.reflect(); 

至於反射... 這是很好的瞭解一些事情是入射角等於反射角,但負。因此,以45度的角度撞擊表面的拋射體將以-45度反彈。這將要求你知道拋射體正在移動的方向(角度)以及表面的角度。如果你總結這些,你會得到你的角度。把它乘以-1,然後重新計算彈頭的方向。

circle.velocity.x = cos(angleInc); circle.velocity。y = sin(angleInc);

+1

很多,只是使用矢量數學更好... –

+0

@Michael Dorgan好點,同意。我假設你只是指反射本身而不是碰撞檢測? – MGZero

1

如果障礙的位置是固定的,你可以使用它的速度計算球下一個gameloop的位置,如果它的位置將超越下一次循環的障礙,你可以設置一個布爾值來設置球在下一個循環開始時緊挨着其中一個障礙物,並在檢查到它們有效碰撞後相應地進行計算。

我不會賭這是做的最有效的方法,但它不應該妨礙你的遊戲在所有如果它是一個2D遊戲。

而且,總是試圖設置限制在球上的最高速度,如果他們變得越來越快,每過gameloop,你是在自找麻煩。