8.2.8 关于向量结构的最后一点内容
现在已经完成了一个很不错的、功能完善的向量结构,但是稍加一些处理,还可以使这个结构更加容易使用。首先,可以重写ToString方法,使其输出一些有用的内容。在Visual Studio中使用调试器时,将自动调用ToString方法。重写这个方法后,可以立刻了解向量,而不需要仔细分析向量的定义并查看它可以取的各个值。
public override string ToString()
{
return string.Format("X:{0}, Y:{1}, Z:{2}", X, Y, Z);
}
0向量是一个特殊的向量,它没有单位向量。0向量不代表方向,也没有大小。它有些类似于向量中的null。因此,把它定义为一个常量是很有帮助的。
[StructLayout(LayoutKind.Sequential)]
public struct Vector
{
public static Vector Zero = new Vector(0, 0, 0);
这是所需的全部向量操作。通过这个简单的结构,可以构建并操作一个完整的3D世界。如果现在还不能完全理解向量的所有特性,也不用担心,这是一个熟能生巧的过程。
8.3 二维相交
相交用于判断两个形状何时重叠或相交。在所有的图形编程(包括游戏)中这都很重要。检测鼠标指针是否在一个按钮上就是一种相交测试。在游戏中,检测一个导弹是否击中飞船也是一种相交性测试。2D相交十分简单,可以作为一个不错的起点。
8.3.1 圆
圆通过位置和弧度定义。相交以图形化方式显示最容易理解。接下来就创建一个游戏状态CircleIntersectionState,使其成为默认加载的状态。
class CircleIntersectionState : IGameObject
{
public CircleIntersectionState()
{
Gl.glLineWidth(3);
Gl.glDisable(Gl.GL_TEXTURE_2D);
}
#region IGameObject Members
public void Update(double elapsedTime)
{
}
public void Render()
{
}
#endregion
}
现在状态只是准备好OpenGL,使其可以画线。接下来需要创建Circle类。
public class Circle
{
Vector Position { get; set; }
double Radius { get; set; }
public Circle()
{
Position = Vector.Zero;
Radius = 1;
}
public Circle(Vector position, double radius)
{
Position = position;
Radius = radius;
}
public void Draw()
{
// Determines how round the circle will appear.
int vertexAmount = 10;
double twoPI = 2.0 * Math.PI;
// A line loop connects all the vertices with lines
// The last vertex is connected to the first vertex
// to make a loop.
Gl.glBegin(Gl.GL_LINE_LOOP);
{
for (int i = 0; i <= vertexAmount; i++)
{
double xPos = Position.X + Radius * Math.Cos(i * twoPI /
vertexAmount);
double yPos = Position.Y + Radius * Math.Sin(i * twoPI /
vertexAmount);
Gl.glVertex2d(xPos, yPos);
}
}
Gl.glEnd();
}
}
默认情况下,在原点位置定义一个圆,其半径为1个单位。现在还没有编写绘制圆的代码。绘制圆时,将使用OpenGL的立即模式,即只绘制圆的轮廓。正弦和余弦函数用于确定在什么位置绘制组成圆周的各个顶点。
为了在CircleIntersectionState内测试绘图函数,应在类中添加一个成员_circle。
Circle _circle = new Circle(Vector.Zero, 200);
现在以原点为圆心、创建一个半径为200的圆。为了看到圆,需要修改渲染方法。
public void Render()
{
_circle.Draw();
}