使用XNA引擎做3D赛车小游戏..(5)
汽车和道路都画好了,那么下面就是障碍物了,本文只做障碍物的显示,碰撞检测留到下节 - -
- 首先新建障碍物类Obstacle,导入XNA:
-
using Microsoft.Xna.Framework.Graphics;
-
using Microsoft.Xna.Framework.Content;
-
using Microsoft.Xna.Framework;
-
- 在Obstacle类中增加成员:
-
public Vector3 position; //障碍物的位置
-
public BasicEffect basicEffect;
-
VertexDeclaration vertexDeclaration;
-
VertexBuffer vertexBuffer;
-
IndexBuffer triangleListIndexBuffer;
-
- 在Obstacle类中增加方法LoadContentObstacle,用于加载障碍物的顶点信息:
-
public void LoadContentObstacle()
-
{
-
vertexDeclaration = new VertexDeclaration(basicEffect.GraphicsDevice, VertexPositionColor.VertexElements); //GraphicsDevice使用的顶点格式
-
-
verts[0].Color = Color.Aqua; // 顶点0颜色
-
-
verts[1].Color = Color.Brown;
-
-
verts[2].Color = Color.LightPink;
-
-
verts[3].Color = Color.Red;
-
-
verts[4].Color = Color.Green;
-
-
verts[5].Color = Color.Black;
-
-
verts[6].Color = Color.LightPink;
-
-
verts[7].Color = Color.Red;
-
-
VertexPositionColor.SizeInBytes * (verts.Length), BufferUsage.None);
-
vertexBuffer.SetData<VertexPositionColor>(verts);
-
-
// 顶点索引,按顺序分别绘制前面、右面、上面、左面、后面和下面
-
short[] index = { 4, 5, 6, 5, 7, 6, 5, 1, 7, 7, 1, 3, 4, 0, 1, 4, 1, 5, 2, 0, 4, 2, 4, 6, 3, 1, 0, 3, 0, 2, 2, 6, 7, 2, 7, 3 };
-
triangleListIndexBuffer.SetData<short>(index);
-
}
-
- 在Obstacle类中增加DrawObstacle方法,用于绘制障碍物:
-
public void ObstacleDraw()
-
{
-
basicEffect.GraphicsDevice.RenderState.CullMode = CullMode.None;
-
basicEffect.GraphicsDevice.VertexDeclaration = vertexDeclaration;
-
basicEffect.GraphicsDevice.Vertices[0].SetSource(vertexBuffer, 0, VertexPositionColor.SizeInBytes);
-
basicEffect.GraphicsDevice.Indices = triangleListIndexBuffer;
-
basicEffect.Begin();
-
foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
-
{
-
pass.Begin();
-
basicEffect.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, 8, 0, 12);
-
pass.End();
-
}
-
basicEffect.End();
-
}
-
- 在Game1类中增加障碍物对象:
-
public BasicEffect basicEffect;
-
Obstacle obstacle;
-
- 在Game1类的Initialize方法中初始化障碍物对象:
-
在Game1类的LoadContent方法中调用障碍物对象的LoadContentObstacle方法:
-
obstacle.LoadContentObstacle();
-
- 一段公路总是会有多个障碍物,而为了让汽车能够躲避,障碍物的距离应该为2倍车长以上,因此我们在Car类中增加以下属性:
-
public float carDiameter; // 汽车的最大直径
-
public BoundingSphere CarBoundingSphere;// 包含汽车的球,用来检测和障碍物的碰撞
-
- 同时,修改Car类的CarModel的setter方法:
-
public Model CarModel
-
{
-
set
-
{
-
model = value; // 每当素材管道读入car.x文件,重新计算车的最大直径
-
CarBoundingSphere = model.Meshes[0].BoundingSphere; // 得到包含第一个部件的球体
-
for (int i = 1; i < model.Meshes.Count; i++)
-
{
-
//循环后,CarBoundingSphere是包含汽车所有部件的球体
-
CarBoundingSphere = BoundingSphere.CreateMerged(CarBoundingSphere, model.Meshes[i].BoundingSphere); //得到一个球包含参数指定的两个球
-
}
-
-
CarBoundingSphere.Radius *= 0.84f; // CarDraw方法的世界变换中车尺寸放大0.85倍
-
CarBoundingSphere.Center.Z += -3.0f; // CarDraw方法的世界变换中车位置改变
-
carDiameter = CarBoundingSphere.Radius * 2; // 车直径=(2*半径)
-
}
-
}
-
- 在Game1类的Draw方法中绘制多个障碍物:
-
int numberToAdd = (int)((100.0f / car.carDiameter) / 2.0f); // 一段公路放置障碍物的最大数量
-
float depth = 0.0f; // 障碍物Z坐标的偏移值
-
float x = -2.5f; // -2.5表示障碍物在公路的左侧
-
-
for (int i = 0; i < numberToAdd; i++)
-
{
-
depth = 2.0f * i * car.carDiameter; // 障碍物间隔为2倍车长
-
basicEffect.World = Matrix.CreateTranslation(x, 0.7f, RoadDepth0 - depth);
-
obstacle.ObstacleDraw();
-
basicEffect.World = Matrix.CreateTranslation(x, 0.7f, RoadDepth1 - depth);
-
obstacle.ObstacleDraw();
-
-
if (x == 2.5f) // 障碍物左一个,右一个
-
x = -2.5f;
-
else
-
x = 2.5f;
-
}
-
此时界面上已经显示了若干障碍物,但是没有做碰撞检测,因此汽车碰到是没有任何效果的。