PDA

View Full Version : 2006 PGD Annual: AI for the competition

tux
20-03-2006, 09:30 PM
Im having really big problems with getting AI to work in our entry. My maths is really lacking so here is a plea for help from you smart people.

I'm trying to make my AI look at the player but what ever i try wont work. I have 2 vectors, Player and AI position. currently im 0ing out the Y components (i only want to work in 2D for the steering) and normalizing the 2 vectors.
then i get the cross product between the 2 and then the cross product between that result and the AI. then i get the dot product between the last cross product and the AI. i think im missing something but i dont know what :(

T &#58;= AffineVectorMake&#40;Tank.Matrix&#91;3&#93;&#41;;
T&#91;1&#93; &#58;= 0;
U &#58;= AffineVectorMake&#40;GUserTank.Matrix&#91;3&#93;&#41;;
U&#91;1&#93; &#58;= 0;

VectorNormalize&#40;T&#41;;
VectorNormalize&#40;U&#41;;

Cross &#58;= VectorCrossProduct&#40;T, U&#41;;
Cross &#58;= VectorCrossProduct&#40;Cross, T&#41;;

Dot &#58;= VectorDotProduct&#40;Cross, T&#41;;

if Dot > 0 then
Tank.Steer &#58;= 1 // steer 1 = turn left
else
Tank.Steer &#58;= -1; // steer -1 = turn right

if i cant get this going then the competition entry will just be the player driving around hitting static targets (and how boring will that be!)

aidave
20-03-2006, 11:23 PM
im not sure why you are using cross products etc

what u need to do, is

subtract the two positions
enemy - player
then normalize

and thats your aim at the player

tux
21-03-2006, 06:35 AM
but then how do i turn that into a "turn left" or "turn right"?

i was using cross products to make it into a right angle triangle and then get the angle of it

aidave
21-03-2006, 08:04 AM
ahhh
well, u could:
get the CurrentAim, then calculate the DesiredAim
and get the angle from that triangle.

hope that helps

Huehnerschaender
21-03-2006, 12:31 PM
Hi there,

so if you just need the 2D variant, why don't you use the ArcTan2 function from delphi?

The result contains the angle of the given point. So your point should be PosX-PlayerPosX, PosY-PlayerPosY.

Since your enemy must have an own "looking at"-angle too, you can now consider if the angle is bigger or lower to steer left or right.

EnemyToPlayerAngle := ArcTan2(PosX-PlayerPosX, PosY-PlayerPosY);

if EnemyAngle < EnemyToPlayerAngle then
Steerleft
else
Steerright;

This is not the exact solution, but it should give you a guess how to use ArcTan2 function. Also you may translate the angle to degrees (using radtodeg-function) since the function returns radians as far as I remember, don't know with what you are calculating.

Hope that helps. I use this in my Tanx entry, too. So I know that it works.

tux
22-03-2006, 08:57 PM
hmm. it seems to nearly work. but only between -90 and 90.

if the angle isnt between -90 and 90 then the ai just rotates until it is again...

procedure TEnemyRunAwayState.Update(aGameObject: TObject);
var
Tank: TNPCTank;

Angle: Single;

T: TVector3f;
U: TVector3f;

D: TTransformations;

begin
Tank := aGameObject as TNPCTank;

T := AffineVectorMake(Tank.Matrix[3]);
U := AffineVectorMake(GUserTank.Matrix[3]);

Angle := ArcTan2(U[0] - T[0], U[2] - T[2]);

MatrixDecompose(Tank.Matrix, D);
Angle := D[ttRotateY] - Angle;

if Angle < 0 then
Tank.Steer := 1
else
Tank.Steer := -1;
end;
any idea why?

Huehnerschaender
25-03-2006, 11:56 PM
Hi, I forgot to tell that ArcTan2 function returns values between -Pi and +Pi.

Normally radians are declared between 0 and 2*Pi.

Angle := ArcTan2(U[0] - T[0], U[2] - T[2]) + Pi;

If you don't do that, your comparence with ">" or "<" cannot work correctly.

By the way. Meanwhile I changed my code and apply a virtual segment to my turret. Having this I can calculate if the "targeting point" is on the left or the right side of my "line"using the following code:

function IsPointOnRightSide(const PointX,PointY,SegmentX1,SegmentY1,SegmentX2,Segmen tY2:TFloat):Boolean;
begin
Result := (((SegmentX2 - SegmentX1) * (PointY - SegmentY1)) < ((PointX - SegmentX1) * (SegmentY2 - SegmentY1)));
end;

Then I can say:

if IsPointOnRightSide(TargetPosX,TargetPosY,TurretSeg mentX1,TurretSegmentY1,TurretSegmentX2,TurretSegme ntY2) then
SteerTurretRight
else
SteerTurretLeft;

Hope this helps...

Greetings,
Dirk

Robert Kosek
26-03-2006, 02:49 AM
Thanks Dirk, that answers something I have been wondering about as well. :) (The range of ArcTan2 in particular)