在前文中,我们已经实现了加载复杂的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进行游戏组件的封装,可以在代码的可复用性上取得收益。
好了,我们已经有了更丰富的物体了,多生成几艘飞船试试,看看编队是否够壮观吧。
![](https://box.kancloud.cn/2016-04-08_570727fb56965.gif)
附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](http://blog.csdn.net/caowenbin) ——
- 前言
- Windows Phone 7开发环境初体验
- Windows Phone 7 3D开发中使用纹理贴图
- 在Windows Phone中进行3D开发之一坐标系
- 在Windows Phone中进行3D开发之二摄像机
- 在Windows Phone中进行3D开发之三空间
- 在Windows Phone中进行3D开发之四三角形
- 在Windows Phone中进行3D开发之五平移缩放
- 在Windows Phone中进行3D开发之六旋转
- 在Windows Phone中进行3D开发之七纹理
- 在Windows Phone中进行3D开发之八光照
- 在Windows Phone中进行3D开发之九模型
- 在Windows Phone中进行3D开发之十组件
- 在Windows Phone中进行3D开发之十一天空
- 在Windows Phone中进行3D开发之十二飞行
- 在Windows Phone中进行3D开发之十三阳光
- 在Windows Phone中进行3D开发之后记(附源码)