處理模型——使用加速度控制速度

來源:互聯網
上載者:User
問題

你想讓模型能夠漂亮的加速而不是從靜止直接提高到最大速度。圖4-9顯示了你想實現的這種加速過程。

圖4-9 模型的速度時間映像

解決方案

通過添加加速度,你可以定義你的模型的速度變化有多快。加速度就是每幀速度的增加量。

工作原理

你需要儲存模型的位置和旋轉,這是因為你需要知道哪個方向是向前的。在本例中,你只是讓模型繞著它的向上的y軸旋轉並沿著X和Z軸移動。如果你想讓模型只基於X和Z軸沿著一個表面移動可參加教程4-17。

因為模型以後的速度取決於當前速度,所以你需要儲存當前速度。你將儲存速度向量而不是標量。這個速度向量包含模型當前前進的方向,它的長度表示速度的大小。所以在類中添加三個變數:

Vector3 modelPosition = new Vector3(); float modelYRot = 0; Vector3 modelVelocity= new Vector3(); 

你也可以定義模型的最大加速度和轉彎速度:

const float modelMaxAcceleration = 30.0f;const float modelMaxTurnSpeed = 0.002f; 

在Update方法中接受自上一幀以來經過的時間為參數,檢測模型移動的距離:

float elapsedSeconds = (float)gameTime.ElapsedGameTime.Milliseconds / 1000.0f; float forwardReq= 0; float angleReq = 0; if (keyState.IsKeyDown(Keys.Up)) forwardReq += 1.0f; if(keyState.IsKeyDown(Keys.Down)) forwardReq -= 1.0f; if (keyState.IsKeyDown(Keys.Left))angleReq += 1.0f; if (keyState.IsKeyDown(Keys.Right)) angleReq -= 1.0f; 

當模型向前加速時變數forwardReq為正,減速或向後加速時為負。變數angleReq表示模型左轉還是右轉。

在光滑表面上加速

下面的代碼添加基本加速行為:

Matrix rotMatrix = Matrix.CreateRotationY(angle); Vector3 forwardDir = Vector3.Transform(new Vector3(0, 0, -1), rotMatrix); velocity = velocity + elapsedTime * forwardReq *maxAccel *forwardDir; modelPosition += velocity; modelYRot += rotationReq * maxRotSpeed* velocity.Length(); 

前兩行代碼計算模型當前的Forward向量,這個向量用來獲得模型加速的方向。這個Forward向量是在向上y-軸上附加在預設的(0,0,-1) Forward方向上的旋轉獲得的。

注意:本教程中的模型只能繞y軸旋轉,所以Forward向量只是基於繞向上y軸的旋轉。可參加教程2-3和2-4學習計算整個3D空間或四元數的旋轉。

接下來的代碼計算速度。在前一個速度的基礎上基於使用者輸入添加一個新的向量。自上一幀經過的時間越長,越需要調整這個速度向量。另外,加速度越大,越需要調整這個速度向量。最後你還要考慮模型的最大加速度。將這三個因素相乘獲得這一幀需要調整多少速度。因為你需要將一個Vector3添加到速度向量上,要乘以帶有forwardDir的這個值擷取想要添加的向量。

注意:如果沒有旋轉,速度和moveDirection會指向相同的方向,只是簡單使速度向量變大讓模型移動地更快。

最後,這個Vector3添加到模型的位置,模型的旋轉被調整。模型運動得越快,轉向也越快。

當使用這個代碼時,你注意到有兩個缺點。首先,模型將一直加速,它沒有一個最大速度。你想4-9所示增加速度並終止於一個確定的最大速度。使用這個代碼,模型將一直以相同的步進加速。

第二,如果模型在一個方向上的速度很大,在旋轉模型後,它可能仍在相同的方向。如果模型是在一個冰面上當然不錯,但通常這並不是你想要的結果。

添加摩擦力

在真實情況中,模型的速度會因為模型與空氣、表面之間的摩擦等慢慢減小。當你停止加速,摩擦力會讓速度減小直至停止。當持續加速,摩擦力會導致速度增加到一個特定值不在增加。

你可以通過減去前面的速度擷取摩擦力。下面的代碼添加了摩擦力:

velocity = velocity * (1 - friction * elapsedTime) + elapsedTime * forwardReq *maxAccel *forwardDir; 

兩幀之間的時間越長,摩擦力的效果越明顯,所以你要根據流逝時間乘以friction變數。

讓模型保持在向前方向運動

雖然模型現在已經以一個比較自然的方式加速了,但在它旋轉時仍有一點瑕疵(除非是在空間遊戲或冰面滑行遊戲中)。通常,你只想讓模型沿著前進方向移動。

你需要知道沿著Forward 方向上的速度向量是多少。這可以通過點乘得到:它將Velocity (V) 向量投影到Forward (F)上,4-10所示,並返回投影速度的大小。

圖4-10 將速度向量投影到Forward向量上

所以在更新速度後使用下列代碼:

float forwardSpeed = Vector3.Dot(velocity, forwardDir);velocity = forwardSpeed * forwardDir; modelPosition += velocity * elapsedTime; modelYRot+= rotationReq * maxRotSpeed * forwardSpeed; 

forwardSpeed變數表示Velocity向量在Forward方向上分量的大小,然後乘以Forward方向並將結果儲存在一個新的Velocity向量中。通過這個方法,你可以保證模型將沿著向前方向移動。

注意:使用forwardSpeed變數的一個額外好處是當模型向前運動是它為正,向後運動時它為負,而velocity. Length ()總是正的。

代碼 Accelerate方法根據加速度調整模型的位置,速度和旋轉,將它們和最大加速度和旋轉速度相加。你還要擷取使用者輸入和摩擦力變數。

private float Accelerate(ref Vector3 position, ref float angle, ref Vector3 velocity,float forwardReq, float rotationReq, float elapsedTime, float maxAccel, float maxRotSpeed,float friction) {    Matrix rotMatrix = Matrix.CreateRotationY(angle);     Vector3 forwardDir= Vector3.Transform(new Vector3(0, 0, -1), rotMatrix);         velocity = velocity * (1- friction * elapsedTime) + elapsedTime * forwardReq * maxAccel *forwardDir;     loat forwardSpeed = Vector3.Dot(velocity, forwardDir);     velocity = forwardSpeed * forwardDir;        modelPosition += velocity * elapsedTime;     modelYRot += rotationReq * maxRotSpeed* forwardSpeed;         return forwardSpeed; }

這個方法返回forwardSpeed變數,若模型向後運動則為負值。

擴充閱讀

你可以通過允許乘以加速度施加在模型上擴充這個方法,例如,重力加速度,你可以加上這個加速度將總和作為forwardDir。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.