2012-10-28 37 views
0

在我的遊戲中,有一個加電使得玩家彈丸彈出遊戲區域的牆壁。我似乎無法讓它起作用,遊戲邊界與平常一樣是水平和垂直的。遊戲邊界的彈跳彈跳不能正常工作

目前我的代碼是這樣的;

public void UpdatePlasma() 
{ 
    Direction = new Vector2((float)Math.Cos(Angle), (float)Math.Sin(Angle)); 
    //Vector2 Velocity = new Vector2(1, 1); 
    Position += Direction * projSpeed; 

    if ((Position.X >= viewport.Width) || (Position.X <= 0)) 
    { 
     Angle = -Angle; 
    } 

    else if ((Position.Y >= viewport.Height) || (Position.Y <= 0)) 
    { 
     Angle = -Angle; 
    } 
} 

這類作品。拋物線有時會反射頂部和底部的邊界(認爲這可能是由於角度變爲0,因此方向在取消和穿過時不會改變),並且根本不在左邊界和右邊界。然後,我嘗試將我的位置乘以註釋掉的速度矢量,然後否定X或Y座標,但是這並不適用於剛剛超出邊界的拋射物。

+1

的拋射角度不會反彈後-angle。有關如何計算它,請參閱http://stackoverflow.com/questions/5830791/find-radians-reflection-angle。 – PHeiberg

回答

4

Radians clockwise (negative)Radians counter-clockwise (positive)

這些圖示出了弧度角爲你周圍的圓移動順時針或逆時針旋轉。我假設,在你的遊戲中,紅色箭頭的方向等同於給定特定角度的球的移動(即0弧度正確,PI/2弧度上升,等等)。

使用這些圖表作爲參考,考慮四種情況的球撞牆:分別向上,向右,向下和向左移動時的頂部,右側,底部和左側。

首先,我將通過使用當前代碼來說明錯誤行爲發生的原因。我將指的是「入射角」是指球在碰撞前(與相應的牆)之間的角度,而「偏轉角」是指球在碰撞後應該具有的角度。


使用deflected_angle = -incidence_angle

案例1:球動起來,打頂壁:

incidence_angle = PI/2 = up 
deflected_angle = -PI/2 = 3PI/2 = down 

好!

案例2:球向下移動,打底壁:

incidence_angle = 3PI/2 = down 
deflected_angle = -3PI/2 = up 

好!

案例3:球向右移動,點擊右側壁:

incidence_angle = 0 = right 
deflected_angle = -0 = 0 = right 

糟糕!

案例4:向左移動球,打左牆:

incidence_angle = PI = left 
deflected_angle = -PI = PI = left 

糟糕!


所以,現在我們有爲什麼目前的代碼是在某些情況下,而不是在其他正常運作的理解,我們必須拿出一些解決方案。應該清楚的是,我們對簡單否定角度不感興趣。相反,(至少在四個樣本情況下),我們希望球在相反的方向上偏轉;我們可以通過將PI添加到我們的角度來做到這一點,這是一個半圈轉彎。

現在讓我們來看看我們的新案例。


使用deflected_angle = incidence_angle + PI

案例1:球動起來,打頂壁:

incidence_angle = PI/2 = up 
deflected_angle = PI/2 + PI = 3PI/2 = down 

好!

案例2:球向下移動,打底壁:

incidence_angle = 3PI/2 = down 
deflected_angle = 3PI/2 + PI = 5PI/2 = PI/2 = up 

好! (需要注意的是5PI/2使得繞了一圈完整的一圈,然後是一些我們可以通過計算5PI/2 - 2PI,這是PI/2得到相同的角度。)

案例3:球向右移動,點擊右側壁:

incidence_angle = 0 = right 
deflected_angle = 0 + PI = PI = left 

不錯!

案例4:向左移動球,打左牆:

incidence_angle = PI = left 
deflected_angle = PI + PI = 2PI = 0 = right 

好!


我推薦嘗試這種解決方案並觀察結果。當球以與我們考慮的四個角度不同的角度擊球時,您仍然應該觀察到奇怪的行爲(特別是,它會朝着它的方向反彈,而不是像我們預期的那樣偏轉)。

要糾正這一點,當我們打一個垂直壁(左或右),我們要計算我們的偏轉角爲deflected_angle = PI - incident_angle,當我們打一個水平壁(頂部或底部),我們要計算的角度deflected_angle = 2PI - incident_angle

爲什麼這種情況如下圖所示。爲了簡潔起見,我們只會看到球擊中頂部牆的情況;其他情況也有類似的說明。

紅色矢量表示入射角,藍色矢量表示偏轉角。每個矢量出現兩次,只是被翻譯過,不會改變它們的含義(唯一的目的是澄清圖)。此外,角度已經被額外地示出爲圓弧ABC(即:紅色矢量和A,並且藍色矢量和C代表相同的事物)。

Deflection example (vertical normal)

從這個圖中,我們可以得出C = PI + BB = PI - A。我們把它們放在一起來達到最終的等式。 (注意,C是我們的偏轉角度,A是入射角度)。

let: 
C = PI + B 
B = PI - A 

then: 
C = PI + (PI - A) 
C = PI + PI - A 
C = 2PI - A 

note: 
2PI = 0 
therefore, C = -A 
(this is why the top and bottom cases worked) 

therefore: 
deflected_angle = 2PI - incidence_angle 

再次,您可以用類似的方法檢查其他情況,併到達其餘方程。你會注意到碰到底部的球用與頂部相同的方程來解決,並且你會發現左邊和右邊的方程deflected_angle = PI - incident_angle是相同的。

如果你想繼續讀下去,你能彎曲你的球掉任何行(即:不只是水平或垂直);這可以通過觀察你偏離的表面的法線來完成。我會避免列出和特定的鏈接,因爲它們可能會被破壞;相反,我會推薦一些谷歌搜索(他們可能會在一段時間;))。


其他注意事項

你必須在遊戲中的物理處理,至少與使用分立物理(而不是連續的方法,其試圖確定碰撞次數發生之前)還有一個問題,是物體會互相滲透。爲了理解這個問題,考慮如果你的球在超出一個更新週期的時候停留在邊界之外會發生什麼(根據你的更新頻率,球的速度,球的加速度和碰撞分辨率,這可能或不可能) 。在第一次更新週期中,假設您檢測到球在邊界之上,所以您正確計算了偏轉角並將其設置爲球的新角度。現在,在你的第二次更新週期中,你根據這個角度移動球,但球仍然在邊界之上(也就是說,由於速度和加速度重新進入邊界,它沒有移動得足夠遠)。您的代碼將再次檢測到球在界限之上並向上偏轉球!結果是,你的球會在短時間內卡在牆上,永久卡在牆上,或者完全離開比賽場地。有很多方法可以解決這個問題,這些問題超出了這個特定問題的範圍。

還有一個缺失的情況下(當然,實際上有四種,但其所有同樣的想法):如果什麼球越過場的一個角落?如果您只將球擊中單個牆壁,您的偏轉角度將不正確,並會導致球飛出界限。因此,您需要額外的邏輯來解釋這種可能性。

+0

乾杯非常感謝,現在就開始工作吧! :) – user1780732

+0

現在更好解釋!非常感謝我的理解。我現在對事物有了更好的理解。 – user1780732