为了回答这些问题,需要扩展向量类,在其中添加基本的向量方法。本章中的示例将以前面章节中的代码为基础。其中的大多数示例都要求创建一个新的游戏状态,并使其成为活动的状态以测试代码。本章所有的示例代码都可以从本书配套光盘中的Code\Chapter 8目录中找到。下面的小节将解释各种向量操作,并列出完成向量类所需添加的代码。游戏引擎中有时候会有Vector2d、Vector3d和Vector4d,但是在这里只创建一个向量结构会更加简单一些,这个向量仍然可以用于任意的2D操作。本书中的内容不会涉及4D向量。
[StructLayout(LayoutKind.Sequential)]
public struct Vector
{
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
public Vector(double x, double y, double z) : this()
{
X = x;
Y = y;
Z = z;
}
}
8.2.2 长度操作
长度操作以一个向量作为参数,返回该向量的大小。对于简单的向量,如[0,1,0],很容易看出长度为1。但是对于复杂一些的向量,如[1.6,-0.99,8],很难一眼看出其长度。如下所示的公式可以计算向量的长度。
v旁边的两条竖线是数学上表示向量长度的一种方法。该公式对于任意维度的向量都是相同的:计算成员的平方值,将这些值相加,然后取其平方根。
用代码表示这个公式很简单。这里使用了两个函数:一个用于计算成员的平方值,然后对这些平方值求和;另一个函数执行求平方根的运算。
public double Length()
{
return Math.Sqrt(LengthSquared());
}
public double LengthSquared()
{
return (X * X + Y * Y + Z * Z);
}
如果想要比较两个向量的长度,可以采用LengthSquared操作,而不是采用Length操作,这样可以省去球平方根的操作,从而使代码更高效一些。
8.2.3 向量的相等性
如果所有的成员值(X、Y和Z)都相等,则认为向量是相等的。向量没有位置,它们只是从某个原点开始的一个方向。图8-3显示了一组向量,可以看到,即使一些向量放到了不同的位置,它们仍然是相等的,因为它们的成员是相等的。不管是从你的房子向北3英里,还是从吉萨金字塔向北3英里,它都一样是向北3英里。
为向量创建一个Equals函数是很简单的。
public bool Equals(Vector v)
{
return (X == v.X) && (Y == v.Y) && (Z == v.Z);
}
在代码中,如果重载了==操作符的话,就更方便了。现在,还不能编写下面的代码。
// Cannot write this
if (vector1 == vector2)
{
System.Console.WriteLine("They're the same")
}
// Instead must write
if (vector1.Equals(vector2))
{
System.Console.WriteLine("They're the same")
}
要使用==操作符,需要重载该操作符,还需要重写其他一些函数或操作符,如GetHashCode、!=和Equals(Object obj)。