Some famous game developer whose name I cannot remember (sorry about that whoever you are), said recently at a conference; that the AI of your game “enemies” can be a major part of the success and differentiation of a game. I don’t think you can instantly create great AI, it takes a lot of work, and for me its still “work in progress”.
So, I’ve been working on AI lately with the help of this excellent book as a reference.
This book is really good, not only for AI but also for anything to do with game movement.
Reading this book, suddenly made vector and matrix calculations make sense. And once they make sense its hard to use normal trigonometry again.
Below are some macro’s I’ve built with the help of the book.
(Note1: most of these require GLKit, and that the input vectors are sometimes respective to a sprite not to the game space geometry)
(Note2: currently the GLKVector methods are not necessarily faster than using plane old trigonometry functions, but they certainly abstract things much more nicely)
(Note3: depending on how you do angles you may need to adjust the input angle – for me I have to often add 90 degrees)
//Below 2 courtesy of Michael Daley #define RANDOM_MINUS_1_TO_1() ((random() / (GLfloat)0x3fffffff )-1.0f) #define RANDOM_0_TO_1() ((random() / (GLfloat)0x7fffffff )) //gets the distance squared - avoids the need to use sqrt and is significantly faster than GLKVector2Distance #define DISTSQ(A,B) (A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y) //quick check to see if something is behind /facing away or toward. A is facing out vector of one sprite, B is the vector from another sprite to the first #define BEHIND(A,B) GLKVector2DotProduct(A, B) > 0.0 ? YES : NO //gets the actual angular difference between two vectors #define ANGLEV(A,B) GLKMathRadiansToDegrees(acosf(GLKVector2DotProduct(GLKVector2Normalize(A), GLKVector2Normalize(B)))) //finds out whether one vector is clockwise or not (so that you know which direction to turn - assuming that the angle drives the direction of travel not the travel vector turns the angle) #define CLOCK(A,B) A.y * B.x < A.x * B.y ? YES : NO //random vector #define RANDOM_CLAMPED() GLKVector2Make(RANDOM_MINUS_1_TO_1(),RANDOM_MINUS_1_TO_1()) //keeps to a certain velocity - might be better if this was based on magnitude #define TRUNCATEV(A) GLKVector2Minimum(A, MAX_MONSTER_VEL_VECTOR) //below returns vector given angle, radius of circle and point of origin - really useful #define POSITION_ON_CIRCLE(A,R,P) GLKVector2Make(R * cosf(A) + P.x, R * sinf(A) + P.y) //cgpoint to vector #define PTV(A) GLKVector2Make(A.x, A.y) // vector to cgpoint #define VTP(A) CGPointMake(A.x, A.y) //2D perpendicular in one direction #define PERP1(A) GLKVector2Make(-A.y, A.x) //2D perpendicular in the other #define PERP2(A) GLKVector2Make(A.y, -A.x) #define VEC0 GLKVector2Make(0,0) #define RECTFV(A, S) CGRectMake(A.x-S *0.5, A.y - S * 0.5, S * 0.5, S * 0.5) // CGRect from a vector #define ROTATE_VECTOR2_AROUND_Z(V) GLKMatrix3MultiplyVector3(GLKMatrix3MakeRotation(-M_PI_4, 0, 0, 1), GLKVector3Make(V.x, V.y, V.z)) // on an ipad2 if you can't precalculate the matrix its currently quicker to use something like: //CGPoint rotatedPoint = CGPointMake(cosf(theta) * point.x -sinf(theta) * point.y, sinf(theta) * point.x + cosf(theta) * point.y); //especially if you can pre-calculate the sin or the cos