Hi,
I'm currently working through Mat Buckland's book "Programming game AI by example", more specifically, chapter 4, creating a simple football game. While the book used C++ I am using C#/XNA.
I'm trying to debug why exactly my agents are behaving like headless chickens instead of world class footballers, and have come up with the possibility that my problems are something to do with a specific function being ported wrong.
Please could someone look over my port and tell me if ive made any mistake along the way:
Mat Buckland's functions
[source language="cpp"]
inline bool MovingEntity::RotateHeadingToFacePosition(Vector2D target)
{
Vector2D toTarget = Vec2DNormalize(target - m_vPosition);
double dot = m_vHeading.Dot(toTarget);
//some compilers lose acurracy so the value is clamped to ensure it
//remains valid for the acos
Clamp(dot, -1, 1);
//first determine the angle between the heading vector and the target
double angle = acos(dot);
//return true if the player is facing the target
if (angle < 0.00001) return true;
//clamp the amount to turn to the max turn rate
if (angle > m_dMaxTurnRate) angle = m_dMaxTurnRate;
//The next few lines use a rotation matrix to rotate the player's heading
//vector accordingly
C2DMatrix RotationMatrix;
//notice how the direction of rotation has to be determined when creating
//the rotation matrix
RotationMatrix.Rotate(angle * m_vHeading.Sign(toTarget));
RotationMatrix.TransformVector2Ds(m_vHeading);
RotationMatrix.TransformVector2Ds(m_vVelocity);
//finally recreate m_vSide
m_vSide = m_vHeading.Perp();
return false;
}
enum {clockwise = 1, anticlockwise = -1};
inline int Vector2D::Sign(const Vector2D& v2)const
{
if (y*v2.x > x*v2.y)
{
return anticlockwise;
}
else
{
return clockwise;
}
}
inline void C2DMatrix::TransformVector2Ds(Vector2D &vPoint)
{
double tempX =(m_Matrix._11*vPoint.x) + (m_Matrix._21*vPoint.y) + (m_Matrix._31);
double tempY = (m_Matrix._12*vPoint.x) + (m_Matrix._22*vPoint.y) + (m_Matrix._32);
vPoint.x = tempX;
vPoint.y = tempY;
}
inline Vector2D Vector2D::Perp()const
{
return Vector2D(-y, x);
}
My port
[source language="C#"]
public bool RotateHeadingToFacePosition(Vector2 target)
{
Vector2 toTarget = Vector2.Normalize(target - Position);
float dot;
Vector2.Dot(ref Heading, ref toTarget, out dot);
// Clamp to ensure we keep accuracy
MathHelper.Clamp(dot, -1.0f, 1.0f);
// Determine the angle between the heading vector and the target
float angle = (float)Math.Acos(dot);
//return true if the player is facing the target
if (angle < 0.00001f) return true;
// clamp the amount to turn to the max turn rate
if (angle > MaxTurnRate) angle = MaxTurnRate;
Matrix rotationMatrix =
Matrix.CreateRotationZ(angle * Heading.Sign(toTarget));
rotationMatrix.TransformVector2(ref Heading);
rotationMatrix.TransformVector2(ref Velocity);
Side = Heading.Perpendicular();
return false;
}
/// <summary>
/// Returns +1 if value is clockwise of this vector, -1 if anticlockwise (Y axis pointing down, X axis to right)
/// </summary>
/// <param name="param"></param>
/// <param name="value"></param>
/// <returns></returns>
public static int Sign(this Vector2 param, Vector2 value)
{
if (param.Y * value.X > param.X * value.Y)
{
return -1;
}
return 1;
}
/// <summary>
/// Transforms a vector by a matrix
/// </summary>
/// <param name="param"></param>
/// <param name="value"></param>
public static void TransformVector2(this Matrix param, ref Vector2 value)
{
value.X = (param.M11 * value.X) + (param.M21 * value.Y) + param.M31;
value.Y = (param.M12 * value.X) + (param.M22 * value.Y) + param.M32;
}
/// <summary>
/// Returns the vector perpendicular to the param
/// </summary>
/// <param name="param"></param>
/// <returns></returns>
public static Vector2 Perpendicular(this Vector2 param)
{
return new Vector2(-param.Y, param.X);
}
I'm aware this is probably a long shot, but eliminating this as a root cause of problems will go a long way to helping me debug this.
Thanks for the help, Scott