2012-02-28 91 views
2

我有一個玩家可以圍繞2D笛卡爾網格旋轉和移動,我需要計算在屏幕上繪製敵人的位置。圍繞網格旋轉矩形來計算玩家視圖

玩家應該有一個特定的視角,就是玩家面對的方向前面的屏幕尺寸。 (並稍微落後)

我已經嘗試了很多方法來實現這個與雙極座標和Trig混淆的方法,但我還是無法解決計算屏幕上敵人應該在哪裏的問題被畫下來。

問題最好用綠色圖形的形式來表示,它是一個可以圍繞網格旋轉和移動的矩形,以及表示玩家和敵人的點。

Blue is player, Red is Enemy Green represents viewpoint

所以我需要在相對於玩家旋轉和位置的屏幕制定出敵人的位置。

回答

2

如果您打算採用類似Doom的視角,您應該將觀看區域想象爲平行四邊形,而不是矩形。想象一下,你的角色背後是一個擁有自己位置和角度的攝影師。

The camera frustum

敵人的屏幕位置與相機和敵人之間的角度。

//indicates where on the screen an enemy should be drawn. 
//-1 represents the leftmost part of the screen, 
//and 1 is the rightmost. 
//Anything larger or smaller is off the edge of the screen and should not be drawn. 
float calculateXPosition(camera, enemy){ 
    //the camera man can see anything 30 degrees to the left or right of its line of sight. 
    //This number is arbitrary; adjust to your own tastes. 
    frustumWidth = 60; 

    //the angle between the enemy and the camera, in relation to the x axis. 
    angle = atan2(enemy.y - camera.y, enemy.x - camera.x); 

    //the angle of the enemy, in relation to the camera's line of sight. If the enemy is on-camera, this should be less than frustumWidth/2. 
    objectiveAngle = camera.angle - angle; 

    //scale down from [-frustumWidth/2, frustumWidth/2] to [-1, 1] 
    return objectiveAngle/(frustrumWidth/2); 
} 

這些圖表直觀地想象我在這裏使用的變量表示:

depiction of <code>angle</code>

enter image description here

一旦你有了-1的範圍內的 「X位置」, 1],它應該很容易將其轉換爲像素座標。例如,如果你的屏幕是500個像素寬,你可以這樣做((calculateXPosition(camera, enemy) + 1)/2) * 500;

編輯:

你可以做類似的事情,找到一個點,y座標基於點的高度和距離相機。 (我不確定你應該如何定義敵人和相機的高度 - 只要它們與笛卡爾網格的x和y尺寸設置的比例相匹配,任何數字都應該是很好的。)

side view - camera looking at enemy

//this gives you a number between -1 and 1, just as calculateXPosition does. 
//-1 is the bottom of the screen, 1 is the top. 
float getYPosition(pointHeight, cameraHeight, distanceFromCamera){ 
    frustrumWidth = 60; 
    relativeHeight = pointHeight - cameraHeight; 
    angle = atan2(relativeHeight, distanceFromCamera); 
    return angle/(frustrumWidth/2); 
} 

enter image description here

您可以調用該方法兩次,以確定這兩個頂部的y位置和敵人的底部:

distanceFromCamera = sqrt((enemy.x - camera.x)^2 + (enemy.y - camera.y)^2); 
topBoundary = convertToPixels(getYPosition(enemy.height, camera.height, distanceFromCamera)); 
bottomBoundary = convertToPixels(getYPosition(0, camera.height, distanceFromCamera)); 

這應該給你足夠的信息來正確縮放和定位敵人的精靈。 (除此之外:兩種方法中的frustrumWidths不需要相同 - 事實上,如果您正在繪製的屏幕是矩形的,它們應該是不同的。這個比例應該等於屏幕的寬度和高度的比率。)

+0

這真是一個令人難以置信的答案,我當然不會得到像我這樣的東西,所以謝謝你非常。我現在開始工作實現 – Joel 2012-02-28 14:12:47

+0

我已經設法從這個X中獲得X,但是我也在努力獲得Y – Joel 2012-02-28 20:18:22

+0

@Joel,我已經添加了一些關於計算Y座標的信息。 – Kevin 2012-02-28 21:29:59