2014-09-13 115 views
0

我正在研究Direct3D9空間模擬器遊戲,其中我需要創建一個包含玩家飛船位置和角度的相機。目前,我限制我的代碼只是爲了前後移動,上下移動以及掃射。下面是我的代碼,它有一個問題。除了LocalUp(D3DXVECTOR3(0.0f,1.0f,0.0f))和LocalAhead(D3DXVECTOR3(0.0f,0.0f,0.0f)),構造函數中的所有矢量都被初始化爲D3DXVECTOR3(0.0f, ,0.0f,1.0f)),浮點數設爲0.0f;Direct3D9遊戲:宇宙飛船相機

D3DXVECTOR3 Position, LookAt ,PosDelta, PosDeltaWorld, WorldAhead, WorldUp, LocalUp, 
LocalAhead, Velocity; 
D3DXMATRIX View, CameraRotation; 
float SpeedX, SpeedY, SpeedZ; 

void Update(float ElapsedTime) 
{ 
    SpeedX = 0.0f; 
    SpeedY = 0.0f; 

    if(IsKeyDown('A')) 
    { 
     SpeedX = -0.02f; 
     Velocity.x -= SpeedX; 
    } 
    if(IsKeyDown('D')) 
    { 
     SpeedX = 0.02f; 
     Velocity.x += SpeedX; 
    } 
    if(IsKeyDown('X')) 
    { 
     SpeedZ += 0.01f; 
     Velocity.z += SpeedZ; 
    } 
    if(IsKeyDown('Z')) 
    { 
     SpeedZ -= 0.01f; 
     Velocity.z -= SpeedZ; 
    } 
    if(IsKeyDown('W')) 
    { 
     SpeedY = 0.02f; 
     Velocity.y += SpeedY; 
    } 
    if(IsKeyDown('S')) 
    { 
     SpeedY = -0.02f; 
     Velocity.y -= SpeedY; 
    } 

    D3DXVec3Normalize(&Velocity, &Velocity); 

    PosDelta.x = Velocity.x * SpeedX; 
    PosDelta.y = Velocity.y * SpeedY; 
    PosDelta.z = Velocity.z * SpeedZ; 

    D3DXMatrixRotationYawPitchRoll(&CameraRotation, 0, 0, 0); 
    D3DXVec3TransformCoord(&WorldUp, &LocalUp, &CameraRotation); 
    D3DXVec3TransformCoord(&WorldAhead, &LocalAhead, &CameraRotation); 
    D3DXVec3TransformCoord(&PosDeltaWorld, &PosDelta, &CameraRotation); 

    Position += PosDeltaWorld; 
    LookAt = Position + WorldAhead; 

    D3DXMatrixLookAtLH(&View, &Position, &LookAt, &WorldUp); 
} 

的 「D3DXMatrixPerspectiveFovLH」 和 「的IDirect3DDevice9 ::一個setTransform」 功能被稱爲應用程序的另一部分。由於他們工作正常,我不再談論他們。

問題是,無論Z軸的速度是否相當大,並且我分別或同時橫向移動和橫向移動,相機的Z軸速度都會降低。此外,在速度幾乎爲0之後,我按下增加速度的鍵,矢量的感覺反轉,然後恢復正常。當以相當高的速度改變向量的感覺時(例如,按X然後立即按'Z'),也會發生這種情況。有人可以解釋我爲什麼會發生這種情況,我該如何解決這個問題?

我還會問另一個問題:如果沒有按鍵被按下,我怎樣才能緩慢減少strafe和Y軸的速度?我想在遊戲中實現慣性效果。

如果有人能夠幫助我,請回復!

編輯:NEW CODE:

void NewFrontiers3DEntityPlayer::OnFrameUpdate(float ElapsedTime) 
{ 
State.SpeedX = 0.0f; 
State.SpeedY = 0.0f; 
if(IsKeyDown(State.Keys[CAM_STRAFE_LEFT])) 
    State.SpeedX = -0.02f; 
if(IsKeyDown(State.Keys[CAM_STRAFE_RIGHT])) 
    State.SpeedX = 0.02f; 
if(IsKeyDown(State.Keys[CAM_MOVE_FORWARD])) 
{ 
    State.SpeedZ += 0.01f; 
} 
if(IsKeyDown(State.Keys[CAM_MOVE_BACKWARD])) 
{ 
    State.SpeedZ -= 0.01f; 
} 
if(IsKeyDown(State.Keys[CAM_MOVE_UP])) 
    State.SpeedY = 0.02f; 
if(IsKeyDown(State.Keys[CAM_MOVE_DOWN])) 
    State.SpeedY = -0.02f; 

State.Velocity.x = State.SpeedX; 
State.Velocity.y = State.SpeedY; 
State.Velocity.z = State.SpeedZ; 

D3DXVec3Normalize(&State.Velocity, &State.Velocity); 

State.PosDelta.x = State.Velocity.x * ElapsedTime; 
State.PosDelta.y = State.Velocity.y * ElapsedTime; 
State.PosDelta.z = State.Velocity.z * ElapsedTime; 

D3DXMatrixRotationYawPitchRoll(&State.CameraRotation, 0, 0, 0); 
D3DXVec3TransformCoord(&State.WorldUp, &State.LocalUp, &State.CameraRotation); 
D3DXVec3TransformCoord(&State.WorldAhead, &State.LocalAhead, &State.CameraRotation); 
D3DXVec3TransformCoord(&State.PosDeltaWorld, &State.PosDelta, &State.CameraRotation); 

State.Position += State.PosDeltaWorld; 
State.LookAt = State.Position + State.WorldAhead; 

D3DXMatrixLookAtLH(&State.View, &State.Position, &State.LookAt, &State.WorldUp); 

return; 
} 

「國家」 是保存所有關於相機信息的結構。

+0

由於您使用C++我會推薦你使用類而不是全局變量 – Quest 2014-09-13 16:41:16

+0

我正在使用類,我使用全局變量,因爲在這裏發佈會更容易。 – 2014-09-13 16:52:08

回答

1

我想你的速度會隨着你一次向多個方向移動而改變,因爲你正常化了你的速度。

例如,在Z移動:

Velocity = (0, 0, 0.01) 
Speed = (0,0, 0.01) 
Normalized Velocity = (0, 0, 1) 
PosDelta = (0, 0, 0.01) 

和X + Z移動:

Velocity = (0.02, 0, 0.01) 
Speed = (0.02, 0, 0.01) 
Normalized Velocity = (0.897, 0, 0.435) 
PosDelta = (0.018, 0, 0.0044)  

關於你的方向反轉我猜測它可部分地與您的相對使用速度/速度的奇怪方法(見下面更多內容),也可能是由於浮點數的精度所致。關於最後一點您怎麼看下面的代碼輸出(忽略潛在的編譯器優化):

float test1 = 0f; 

test1 += 0.1f; 
test1 += 0.1f; 
test1 += 0.1f; 
test1 += 0.1f; 
test1 += 0.1f; 

test1 -= 0.1f; 
test1 -= 0.1f; 
test1 -= 0.1f; 
test1 -= 0.1f; 
test1 -= 0.1f; 

printf("%g\n", test1); 

它(?可能)不會輸出,因爲0.10答案顯然不能完全以2爲底的代表。它在我的系統上打印1.49012e-008。可能發生的情況是您可能接近0,但不完全可能導致座標反演出現。你可以通過舍入速度來達到一定的精度。

您處理速度/速度/位置的整體方法有點奇怪,可能是您遇到困難的根源。例如,我認爲Velocity是一個代表玩家速度的向量,而不是像你那樣的歸一化向量。我會做這樣的事情:

SpeedX = 0.0f; 
SpeedY = 0.0f; 
SpeedZ = 0.0f 

if(IsKeyDown('A')) SpeedX += -0.02f; 
if(IsKeyDown('D')) SpeedX += 0.02f; 
... 

Velocity.x += SpeedX; 
Velocity.y += SpeedY; 
Velocity.z += SpeedZ; 

D3DXVECTOR3 NormVelocity; 
D3DXVec3Normalize(&NormVelocity, &Velocity); 

//Round velocity here if you need to 
Velocity.x = floor(Velocity.x * 10000)/10000.0f; 
... 

float FrameTime = 1; //Use last frame time here 

PosDelta.x = Velocity.x * FrameTime; 
PosDelta.y = Velocity.y * FrameTime; 
PosDelta.z = Velocity.z * FrameTime; 

這擺脫了你的速度變化時,在多個方向移動。如果將FrameTime設置爲最後一幀的時間(或從中導出的值),它還可以讓您正確地補償更改的幀速率。當他們試圖一次往兩個相反的方向移動時,它也能正確地阻止玩家移動。

至於你最後一個關於Y速度衰減的問題,有幾種方法可以做到這一點。你可以簡單地做這樣的事情:

Velocity.y *= 0.7f; 

每幀(調整常量,以滿足您的需求)。更準確的模型會做這樣的事情:

if (Velocity.y > 0) { 
    Velocity.y -= 0.001f; //Pick constant to suit 
    if (Velocity.y < 0) Velocity.y = 0; 
} 

一個更好的方法是使用最後一幀的時間來考慮不同的像幀速率:

Velocity.y -= FrameTime * 0.2f; //Pick constant to suit 
+0

感謝您的回覆和幫助,但我仍然有問題。我現在有一段代碼,我將很快通過編輯發佈原始問題。問題是無論我按什麼鍵(我在談論X軸速度),可見速度都將保持不變。你可以幫幫我嗎? – 2014-09-22 17:53:47

+0

沒關係,我忘了在編寫新代碼時添加'+'符號...謝謝您解決我的問題! – 2014-09-29 06:46:18