3D驾驶模拟游戏开发教程

本教程系列的目标是制作一款3D驾驶模拟游戏。随着每个教程的深入,将通过添加新的图形、物理和游戏玩法特性,使游戏变得更加炫酷。本教程的目的是模拟一辆汽车在无限大的平面上行驶。虽然这与现实世界并不完全相同,但会在后面的教程中逐步增加现实感。目前,请想象这个世界是一个没有障碍物的完美平面。

本文不是针对绝对初学者的。需要对XNA Game Studio 2.0有基本的了解。如果是初学者,建议如下:

  • 下载并安装Microsoft Visual C# 2005 Express Edition及其SP1更新和XNAGame Studio 2.0。所有这些都可以免费从www.microsoft.com下载。
  • 阅读'XNA Game Studio文档',特别是文章'Your First Game: Microsoft XNA Game Studio in 2D'和'Going Beyond: XNA Game Studio in 3D'。这些教程相当容易理解。
  • 阅读Riemer的XNA教程。阅读所有3个教程将给一个很好的XNA理解。但目前,前2个教程就足够了。应该清楚理解四元数的概念。

理解公式需要对牛顿力学和几何学有合理的了解。

使用代码

应用程序被分为三个类:Game1、Stuff、Car。类Stuff代表可以在屏幕上渲染的任何物质体。类Car是类Stuff的专业化,代表汽车。类Game1是主应用程序,使用Stuff和Car的对象。

首先让理解类Stuff。如果查看代码,会看到试图封装存储任何物质体信息并在屏幕上渲染所需的一切。由于代码相当直接,仅提供成员变量和函数的概述。

成员viewMatrix和projectionMatrix是静态的,因为它们对所有可渲染对象都是相同的。成员position和rotation分别代表物体在3D空间中的位置和方向。成员cameraRotation代表相机的方向。存储这个是必要的,以实现相机延迟的效果。成员model代表物体的3D模型。函数UpdateCamera根据汽车的位置和方向更新viewMatrix。函数Draw在屏幕上渲染3D模型。

现在来理解最困难的部分——理解类Car。这里有两个概念在起作用。第一个是踩油门、松开油门和刹车对汽车运动的影响。第二个是当方向盘向左或向右转动时汽车如何转弯。

第一个概念。在任何瞬间,汽车都处于某个档位,由变量gear表示。车辆的速度决定了gear。在变量topSpeeds中存储了每个档位的最高速度。档位x的最高速度也是档位x+1的最低速度。每个档位的加速度是不同的。

public void Accelerate() { free = false; if ((gear < 7) && (speed > topSpeeds[gear])) { gear++; } if (gear == 0) { acceleration = accelerations[1]; } else if (gear < 7) acceleration = accelerations[gear]; else { gear = 6; acceleration = 0; speed = topSpeeds[6]; } }

当刹车被应用时,效果是负加速度,其大小是该档位的加速度加上一个常数。这里还需要考虑倒车档和倒车的最高速度。

public void Brake() { free = false; if ((gear > 0) && speed <= topSpeeds[gear - 1]) { gear--; } if ((gear == 0) && (speed < -maxReverseSpeed)) { acceleration = 0; speed = -maxReverseSpeed; } else { acceleration = -accelerations[gear] - 6.7f; } }

当油门被释放时,即使这样,也需要应用一个负加速度,其大小与该档位的加速度相同。最终汽车会停下来。

public void Free() { free = true; if ((gear > 0) && (speed < topSpeeds[gear - 1])) { gear--; } acceleration = -accelerations[gear]; }

为了确定汽车在每个瞬间的新位置,以下代码放置在Update方法中。

float speed = speed + acceleration * time; float dist = speed * time; Vector3 addVector = Vector3.Transform(new Vector3(0, 0, -1), rotation); position += addVector * dist;

为了确保当油门和刹车都没有被按下时汽车最终停下来,使用以下代码:

float newSpeed = speed + acceleration * time; if ((free == true) && (newSpeed * speed <= 0.0f)) { gear = 1; acceleration = accelerations[gear]; speed = 0.0f; } else speed = newSpeed;

现在让理解汽车是如何转弯的。当驾驶员向左或向右转动方向盘时,平面表面与汽车车身形成一个角度theta,如图示。Theta应该均匀地从0增加到一个最大值。同时,当方向盘被释放时,theta最终应该变为零。代码如下:

if (turn == 0) { float newAngle = steerAngle; if (steerAngle < 0.0f) { newAngle = steerAngle + time * steerSpeed; } else if (steerAngle > 0.0f) { newAngle = steerAngle - time * steerSpeed; } if (newAngle * steerAngle < 0.0f) { steerAngle = 0.0f; } else steerAngle = newAngle; } else { if (turn == -1) { float newAngle = steerAngle - time * steerSpeed; if (newAngle < -maxSteerAngle) { steerAngle = -maxSteerAngle; } else { steerAngle = newAngle; } } else { float newAngle = steerAngle + time * steerSpeed; if (newAngle > maxSteerAngle) { steerAngle = maxSteerAngle; } else { steerAngle = newAngle; } } }

现在已经理解了轮胎是如何转动的,让弄清楚汽车是如何转弯的。仔细看看图:

会立刻明白常数HD、VD和L代表什么。O是3D模型的原点。假设汽车将围绕标记为“转弯中心”的点旋转,半径为r。可以使用三角学计算r的值:

float x = (VD / Math.Abs((float)Math.Tan(steerAngle)) + HD / 2); float r = (float)Math.Sqrt(x * x + L * L);

现在有了半径。汽车旋转的角度可以计算出来,并相应地创建Quaternion。

float theta = speed * time / r; if (steerAngle < 0.0f) theta = -theta; rotation = rotation * Quaternion.CreateFromAxisAngle(new Vector3(0, -1, 0), theta);

现在可以确定汽车的位置如下:

speed = speed + acceleration * time; float dist = speed * time; Vector3 addVector = Vector3.Transform(new Vector3(0, 0, -1), rotation); position += addVector * dist;

其余的代码相当直接。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485