為了回答這些問題,需要擴展向量類,在其中添加基本的向量方法。本章中的示例將以前面章節(jié)中的代碼為基礎(chǔ)。其中的大多數(shù)示例都要求創(chuàng)建一個新的游戲狀態(tài),并使其成為活動的狀態(tài)以測試代碼。本章所有的示例代碼都可以從本書配套光盤中的Code\Chapter 8目錄中找到。下面的小節(jié)將解釋各種向量操作,并列出完成向量類所需添加的代碼。游戲引擎中有時候會有Vector2d、Vector3d和Vector4d,但是在這里只創(chuàng)建一個向量結(jié)構(gòu)會更加簡單一些,這個向量仍然可以用于任意的2D操作。本書中的內(nèi)容不會涉及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 長度操作
長度操作以一個向量作為參數(shù),返回該向量的大小。對于簡單的向量,如[0,1,0],很容易看出長度為1。但是對于復(fù)雜一些的向量,如[1.6,-0.99,8],很難一眼看出其長度。如下所示的公式可以計算向量的長度。
v旁邊的兩條豎線是數(shù)學(xué)上表示向量長度的一種方法。該公式對于任意維度的向量都是相同的:計算成員的平方值,將這些值相加,然后取其平方根。
用代碼表示這個公式很簡單。這里使用了兩個函數(shù):一個用于計算成員的平方值,然后對這些平方值求和;另一個函數(shù)執(zhí)行求平方根的運算。
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)都相等,則認(rèn)為向量是相等的。向量沒有位置,它們只是從某個原點開始的一個方向。圖8-3顯示了一組向量,可以看到,即使一些向量放到了不同的位置,它們?nèi)匀皇窍嗟鹊?,因為它們的成員是相等的。不管是從你的房子向北3英里,還是從吉薩金字塔向北3英里,它都一樣是向北3英里。
為向量創(chuàng)建一個Equals函數(shù)是很簡單的。
public bool Equals(Vector v)
{
return (X == v.X) && (Y == v.Y) && (Z == v.Z);
}
在代碼中,如果重載了==操作符的話,就更方便了?,F(xiàn)在,還不能編寫下面的代碼。
// 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")
}
要使用==操作符,需要重載該操作符,還需要重寫其他一些函數(shù)或操作符,如GetHashCode、!=和Equals(Object obj)。