在前文中,我們已經實現了載入複雜的3D模型並在空間中進行控制,通常在一個遊戲程式中,這樣的3D模型有很多,如果每一個都在情境中去繪製,那麼Draw()方法就會很複雜了,而且也不利於代碼的複用。更好的方式是把這艘飛船實現為GameComponent,而且是DrawableGameComponent。接下來我們就來構造飛船組件。
首先為項目中添加一個新元素,使用XNA中的GameComponent,在產生的程式碼中做如下修改:
public class Ship :Microsoft.Xna.Framework.DrawableGameComponent
即將GameComponent改為DrawableGameComponent,然後加入Draw()方法。
public override void Draw(GameTimegameTime)
同樣使用Model model;和Matrix[] modelTransforms;兩個成員變數用於儲存模型和骨骼資料。並在Initialize()方法中完成載入,代碼見下:
public override void Initialize() { model = Game.Content.Load<Model>(@"Models/wedge_player1"); modelTransforms = new Matrix[model.Bones.Count]; base.Initialize(); }
但是經過這樣的封裝以後,使用者無法進行座標變換的控制了,因此,還需要提供三個用於座標變換的矩陣。加入成員變數:
public Matrix worldMatrix {set;get;} public Matrix viewMatrix { set; get; } public Matrix projectionMatrix { set; get; }
最後完成Draw()方法,代碼如下:
public override void Draw(GameTime gameTime) { //GraphicsDevice.Clear(Color.CornflowerBlue); model.CopyAbsoluteBoneTransformsTo(modelTransforms); foreach (ModelMesh mesh in model.Meshes) { foreach (BasicEffect effect in mesh.Effects) { effect.EnableDefaultLighting(); effect.World = modelTransforms[mesh.ParentBone.Index] * worldMatrix; effect.View = viewMatrix; effect.Projection = projectionMatrix; } mesh.Draw(); } base.Draw(gameTime); }
這樣,這個Ship類就封裝完成了,當在情境中使用時,需要建立一個ship對象:
ship = new Ship(this);
然後將其加到Components中去:
Components.Add(ship);
並在LoadContent()方法中為其指定變換參數:
ship.projectionMatrix = camera.projection; ship.viewMatrix = camera.view * Matrix.CreateTranslation(new Vector3(4, 0, 10)); ship.worldMatrix = Matrix.CreateScale(-0.02f) * Matrix.CreateRotationZ(MathHelper.ToRadians(180))*Matrix.CreateTranslation(new Vector3(20,0,0));
當然也可以同樣在Update()方法中更新ship.worldMatrix以對其進行旋轉、平移、縮放的操作。如果需要有多艘飛船的編隊,只要多建立幾個ship對象,分別為其設定到不同的座標即可。這樣一來,通過繼承自GameCompenent進行遊戲組件的封裝,可以在代碼的可複用性上取得收益。
好了,我們已經有了更豐富的物體了,多產生幾艘飛船試試,看看編隊是否夠壯觀吧。
附Ship類的原始碼:
public class Ship : Microsoft.Xna.Framework.DrawableGameComponent { public Matrix worldMatrix {set;get;} public Matrix viewMatrix { set; get; } public Matrix projectionMatrix { set; get; } Model model; Matrix[] modelTransforms; public Ship(Game game) : base(game) { worldMatrix = Matrix.Identity; viewMatrix = Matrix.Identity; projectionMatrix = Matrix.Identity; } /// <summary> /// Allows the game component to perform any initialization it needs to before starting /// to run. This is where it can query for any required services and load content. /// </summary> public override void Initialize() { model = Game.Content.Load<Model>(@"Models/wedge_player1"); modelTransforms = new Matrix[model.Bones.Count]; base.Initialize(); } /// <summary> /// Allows the game component to update itself. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> public override void Update(GameTime gameTime) { base.Update(gameTime); } public override void Draw(GameTime gameTime) { //GraphicsDevice.Clear(Color.CornflowerBlue); model.CopyAbsoluteBoneTransformsTo(modelTransforms); foreach (ModelMesh mesh in model.Meshes) { foreach (BasicEffect effect in mesh.Effects) { effect.EnableDefaultLighting(); effect.World = modelTransforms[mesh.ParentBone.Index] * worldMatrix; effect.View = viewMatrix; effect.Projection = projectionMatrix; } mesh.Draw(); } base.Draw(gameTime); } }
——歡迎轉載,請註明出處 http://blog.csdn.net/caowenbin ——