在一個3D的遊戲當中,除了靜態的物件以外,再來就是讓模型動起來產生互動性,以一個動作型的角色扮演的遊戲來說,可能你扮演著某一個角色,拿著一個武器,砍殺邪惡的角色等,或是盡情的在世界地圖上面奔跑著。

本篇就是要說明,如何在一個3D的遊戲場景中,讓模型動起來!

讓模型動起來的方式有兩個:

1.       Simple Animation 簡易的模型動作方式

2.       SkinnedSample 骨架模型移動方式

XNA所提供的3D物件操作方式,並沒有提供如何讓物件實體動起來的方法(例如,現在你下一個RUN,你不會看到3D模型自己就在跑步)XNA只提供基本的針對模型的操作方式,像是讓模型針對某個轉軸,轉某個角度等,而如果你想要讓模型有動作的話,只能用這種比較簡單的方式,讓模型運作,而首先讓模型動起來這個部分,就先介紹簡單的方法。

 

所謂簡單的方法,就是用旋轉角度,控制模型的動作,而這個範例建議使用在像是馬車的移動,賽開移動等,較有規律性的模型上面因為如果你要讓這個範例,可以做出打鬥的動作,你會有很多考量,也許你可以在看完這篇以後,你就知道,事實上,用這個範例做打鬥,是個很折磨人的事情。

 

先來看看這個模型的截圖部分吧~!

(圖片是動不起來的,當然我沒有用GIF)

 

上面這張圖片就是SimpleAnimation編譯過後的結果,可以看到一台戰車的轉動。

 

接下來讓我們來看一下主程式的地方,也就是SimpleAnimation.cs

這邊宣告了一個Tank的類別,至於Tank這個類別,稍後在介紹,他有很特殊的存在

接下來可能有些人會覺得很奇怪,怎麼看到建構子沒有看到XNA五大函數的初始化這個函數呢?因為,大部分初始化這個函數能做的事情,建構子都可以做得到。

所謂的XNA五大函數,初始化、載入內文,更新、繪出、卸除內文,這些只是XNA所提供的概觀,也就是所謂的,一個遊戲會先初始化一些變數函數等,在來載入需要呈現的文件,更新現在的畫面或是事件,在來呈現出畫面,最後結束遊戲的時候,需要釋放掉資源等。(可能我之前有說過,只是我大概又癡呆,如果有重複就原諒我這個老人家吧)

在建構子這邊設定了視窗大小(如果沒有用全螢幕的話,又不想又預設的解析度,就可以自己設定一下)

graphics.PreferredBackBufferWidth = 853;

graphics.PreferredBackBufferHeight = 480;

這邊我們將解析度設定為853*480,解析度可以隨意調整,當然你也可以調成1080p,隨意~~

在來時做一個Tank的類別,剛剛只有做宣告的動作,現在就需要實作這個類別囉(你可以在宣告的時候順便實作,可是這邊的話就配合建構子的功能囉。

LoadContent這個函數部分,呼叫了tank.Load(content),因為Tank類別,提供載入的部分,所以就用TANK的類別作載入。這邊就將Content傳入進去,你可以用甚麼方式,只要讓XNA可以讀到檔案就好。

UnloadContent這個函數就保持不變,不需要設定甚麼特殊的功能。

Update的函數部分,首先我們先更新一下鍵盤資訊(這邊做的事情就是當按下ESC以後,就會關閉式窗)

         float time = (float)gameTime.TotalGameTime.TotalSeconds;

這一行程式碼,就是為了解決在每台電腦有不相同的CLOCK的問題,免得有些電腦CPU夠強,處理指令速度夠快,而有些電腦處理速度較慢的問題。

tank.WheelRotation = time * 5;

tank.SteerRotation = (float)Math.Sin(time * 0.75f) * 0.5f;

tank.TurretRotation = (float)Math.Sin(time * 0.333f) * 1.25f;

tank.CannonRotation = (float)Math.Sin(time * 0.25f) * 0.333f - 0.333f;

tank.HatchRotation = MathHelper.Clamp((float)Math.Sin(time * 2) * 2, -1, 0);

以上程式碼,都是使用Tank類別中的set設定,針對於模型的WheelSteerTurretHatch,等數值做更改,而上面的函數(sin函數)可以看到有一個time的變數,也就是讓模型能夠動的原因,隨著時間的改變,每次呈現連續的轉動設定,SIN是周期函數,所以在這個範例中,就可以看到輪子一直在重覆轉動。在Clamp這個函數部分,他的功能就是對SIN這個函數做範圍的設定,像是讓他的直只能落在[-1,0]之間。

 

Draw的部分先計算螢幕的比例大小

float aspectRatio = (float)viewport.Width / (float)viewport.Height;

在來設定對於Y軸的轉動,所以你可以發現,模型是跟著Y軸隨著時間轉動

         Matrix rotation = Matrix.CreateRotationY(time * 0.1f);

上面程式碼同時也代表著World Matrix(世界矩陣)的部分,只是我只針對3D模型做旋轉的部分,像是比例大小位置,都不做調整。

在來針對View Matrix做設定

Matrix view = Matrix.CreateLookAt(new Vector3(1000, 500, 0),new Vector3(0, 150, 0), Vector3.Up);

CreateLookAt函數,設定視野矩陣,第一個參數也就是觀察者的位置,第二個參數設定觀看的點,在來設定上方。

在來對Projection Matrix設定

Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, aspectRatio, 10, 10000);

運用CreatePerspectiveFieldOfView函數設定即可,第一個函數設定視角,第二個參數設定螢幕比例,第三個參數設定進平面,第四個參數設定遠平面。

在來將剛剛設定的資訊丟到Tank的類別中去處理

tank.Draw(rotation, view, projection);

上面的函數,就會將模型繪出。

以上就是針對於主程式SimpleAnimation.cs的部分

在下一篇就會開始針對Tank這個類別做說明,我想大家對於這個專案如何讓3D模型動起來,也有大概的概念吧~!

 

創作者介紹
創作者 teexit1224 的頭像
teexit1224

StreamWhite

teexit1224 發表在 痞客邦 留言(0) 人氣()