Sign in to follow this  
gameXcore

Need someone to check C++ - C#/XNA code port

Recommended Posts

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

Share this post


Link to post
Share on other sites
This doesn't answer your question, but it may help later - avoid arccosine. You correctly clamp it before use, but it's almost always possible to code more efficiently and accurately without arc functions, though it make take a little more algebra. arccosine is fine in a math textbook. In the real world on finite state machines, it usually leads to grief.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this