Dogfight AI

Blitz3D Forums/Blitz3D Beginners Area/Dogfight AI

earok(Posted 2005) [#1]
Hi there,

Recently i've started programming an action-flight simulator, however i've hit a major snag with programming the AI.

The most effective way to 'dogfight' another fighter is to roll to the point where your enemy is 'infront and above' you relative to your current orientation, and then pitch upwards until the enemy fighter is in your sights. For instance: there is an enemy fighter approaching from your right, so instead of yawing right with the rudder (which would take too long to turn on an aircraft) you should roll right 90 degrees and then pitch upwards 90 degrees so you'll be facing your enemy and lined up for a shot.

Problem is I cant seem to get the enemy to 'think' like that. I've tried Deltayaw, deltapitch, pointentity and align to vector in different combinations to try to create a function which works but i've had no success, laregly because of the functions i've mentioned deal in yaw and pitch but not roll angles.

I need to be able to allow AI fighters to roll to the correct angle needed to be able to pitch to face the players figher and also allow the AI fighters to work out the delta-pitch in relation to its roll angle.

Any help would be very appreciated!


Many thanks,
Erik Hogan


Andy(Posted 2005) [#2]
You need to build a finite state machine.

attach a pivot to the aircraft. point entity the pivot to the enemy every logic frame.

You need a counter that keeps the state of the manouver. It will start at 0.

State 0 will mean that the enemy is within +- 5 degrees pitch and yaw, so roll will not be nessesary. the aircraft will manouver using pitch and yaw alone. If the enemy is not within the pitch limit, then the counter is set to 2, if it is not within the yaw limit, then the counter will be set to 1.

state 1 will roll the aircraft 90 degrees towards left or right as appropriate, one degree at a time. When the aircraft is at 90 degrees, the function will increase the counter to 2.

State 2 will pitch the aircraft until it is pointing at the pivot yaw +- 5 degrees, one degree at a time. When it does, the counter is set to 0.

It is actually better to make counters for both pitch and yaw, but this will work.

Don't use global angles, only use the difference between the aircraft orientation and the pivot orientation.


Andy


earok(Posted 2005) [#3]
Hi Andy,

I think, with a bit of testing and tweaking, that would work awesomely for basic AI.

Although its still not as 'optimised' as it could be. For instance, if your enemy was 45 degrees to the left and 45 degrees above, the machine would roll the craft 90 degrees left, pitch up 45 degrees, roll 90 degrees right and then pitch up 45 degrees (four movements), when all it needed to do was roll left 45 degrees and then pitch up 45 degrees (two movements, manuever done in half the time).


Many thanks,


Andy(Posted 2005) [#4]
>Although its still not as 'optimised' as it could be.

Well, I didn't want to write it for you, just give you som inspiration.

Andy


Viperfish(Posted 2005) [#5]
Below is a snippet of code from my current space shooter project. The enemy calculates how far to aim infront of the players craft by positioning TargetLeader depending on distance, speed and bullet speed. TargetLeader becomes the target rather than the player.

Basically the code rolls the craft so the target is near the vertical axis then pitchs up or down. The total AI code is about 15 times longer than this but it should give you a starting point.

You can see the code in action here http://www.blitzbasic.com/Community/posts.php?topic=49902

;Move targetleader to position relevent for current enemy
			PositionEntity TargetLeader,0,0,e\leader
			e\leader = (e\leader/((e\leader/acceleration)-(EntityDistance(e\entity,TargetLeader)/EnemyBulletSpeed)+(EntityDistance(e\entity,pvt)/EnemyBulletSpeed)))*(EntityDistance(e\entity,pvt)/EnemyBulletSpeed)
			PositionEntity targetleader,0,0,e\leader
			;--------------------------
			;Determine targetleaders x,y,z location relative to the enemy ship
			TFormPoint 0,0,0,TargetLeader,e\entity
			TargetX# = TFormedX()
			TargetY# = TFormedY()
			TargetZ# = TFormedZ()
			
			TFormPoint 0,0,0,e\entity, TargetLeader
			EnX# = TFormedX()
			EnY# = TFormedY()
			EnZ# = TFormedZ()
			;--------------------------
			;Calculate Steering factor. The further away an entity is the higher the factor
			SteeringFactor# = EntityDistance(TargetLeader,e\entity)/1000
			
			;--------------------------
			;Rotate z based on x position 
			;If target is in front, roll the ship so target is near vertical axis
			
				If targetX < -30*(SteeringFactor#-RandomFactor#) 
					If TargetY < 0 ;Below and to the left, turn right
						e\roll# = e\roll# -(e\spz/TurningFactor%)
					Else
					 	e\roll# = e\roll# +(e\spz/TurningFactor%);Above and to the left, roll left
					End If
				End If
				If TargetX > 30*SteeringFactor# 
					If TargetY > 0;Above And To the Right, turn Right
						e\roll# = e\roll# -(e\spz/TurningFactor%)
					Else 
						e\roll# = e\roll# +(e\spz/TurningFactor%);Below and to the right, turn left
					End If
				End If
					
			;--------------------------
			;Rotate x based on y (Climb or dive to face the target only if the target is near the 
			;vertical axis). Climb is the target is behind.
			If TargetZ < 0 And Enz>0 Then 
				e\pitch# = e\pitch# - (e\spx/TurningFactor%)
			Else
				If Abs(TargetX) <(100* (SteeringFactor#-RandomFactor#)) Then
					If TargetY > 20*SteeringFactor# Then
						e\pitch# = e\pitch# - (e\spx/TurningFactor%)
					End If
					If TargetY < -20*SteeringFactor# Then
						e\pitch# = e\pitch# + (e\spx/TurningFactor%)
					End If				
				End If
			End If
			;--------------------------
			;If the enemy is close to the player and is behind the player then slow down to avoid overtaking
			If EntityDistance(e\entity,targetLeader)<(500*(e\spd/10)) And targetz >20 And e\spd>3 Then
				e\spd = e\spd * .98^FL\SpeedFactor
			End If	
			;If Enemy is behind the player and the player is behind the enemy. Then slow down to reduce turn circle.
			TFormPoint 0,0,0,e\entity,TargetLeader
			enemyZ# = TFormedZ()
 			If (enemyz < 0) And (targetz <0) And (e\spd>(e\maxspd/1.66)) Then e\spd= e\spd * .99^FL\SpeedFactor
			;--------------------------



earok(Posted 2005) [#6]
Hi guys,

Thanks for your help, but after much mucking around i've found a really simple formula which does the job perfectly. It uses the DeltaPitch and DeltaYaw functions to calculate the how far in which direction the fighter has to roll to for it to have its X axis perfectly aligned with the target entity.

ATan2(DeltaPitch(src_entity,dest_entity),DeltaYaw(src_entity, dest_entity)) + 90 - EntityRoll(src_entity)

Xiraya is an awesome game. Brings back memories of Wing Commander..