seek&destroy enemies

BlitzPlus Forums/BlitzPlus Programming/seek&destroy enemies

Bremer(Posted 2003) [#1]
Hi, I'm well on my way with my Defender/horizontal shooter, but I'm having problems with an enemy type that should hunt down the player and shoot at him. The problem is that I have managed to have the enemy find the player and move to where he is, but it moves in a more or less straight line and I would like to have it moving around the player in circles when it gets there. Any ideas are welcome.


Foppy(Posted 2003) [#2]
A relatively simple way of doing that would be to pick a (random) point *nearby* the player to fly to. Then when you get there, pick another point close to the player. (In the meanwhile you keep shooting at the player.) This will not give you circles but the enemy will fly close to the player in an annoying way! ;)

To get circles you could first fly towards the player, then when you are close (as close as the size of the circle) start flying in a circle. For a circle you would need to adjust the flying angle a little bit each time, or do things with sinus and cosinus, I am not sure right away.

Or, as an approximation of a circle, you could pick points in sequence that are on a circle. So, when you are close enough to the player, first take a point directly above the player (North), fly there, then take the next point (North-East), then the next (East) and so on. (Assuming you want to circle clockwise.) The enemy would need to keep track of these directions (like "current point is East") and using if-then or a select statement decide where to fly next. This way the enemy will fly in something that resembles a circle (a hexagon if I am not mistaken, 8 corners). If the ship turns in a realistic way (by changing the directional angle) this may result in it flying a circle. This depends on how you have programmed movement (8 directional movement, or 360 degree movement, or another method).

Well I hope that made some sense! ;)


Rob Farley(Posted 2003) [#3]
for indeed just use sine and cosine to determine where to fly to...

x - x position of target
y - y position of target
r - distance away from target
counter - starts at 0 and counts round to 359 before looping back again

So... You just make you're guy aim at:

x+(sin(counter)*r)
y+(cos(counter)*r)

Job done...

Increase the increments of counter to make it circle it faster.
Increase R to make it circle further away.


Jeppe Nielsen(Posted 2003) [#4]
Little example :)


;Homing example, by Jeppe Nielsen 2003

Global playerx#
Global playery#
Global distance#=100

Type enemy

Field x#,y#
Field vx#,vy#
Field ax#,ay#

Field vmax#
Field amax#

End Type


Graphics3D 800,600,16,2


;create ten enemies at random locations
For n=1 To 10				
;play with last number
;enemynew(x,y,vmax,amax)
enemynew(Rnd(800),Rnd(600),Rnd(0.5,4.5),Rnd(0.08,0.1))
Next


Repeat
Cls

Text 10,10,"Move player with mouse"
Text 10,30,"LMB - Resize allowed distance to player"
Text 10,50,"RMB - Add enemies"

If click=0
	
	playerx=MouseX()
	playery=MouseY()
	
EndIf

If MouseDown(1) And click=0
	
	click=1
	clickx=MouseX()
	clicky=MouseY()
	
EndIf

If MouseDown(1) And click=1
	
	dx=(MouseX()-clickx)
	dy=(MouseY()-clicky)
	
	distance#=Sqr(dx*dx+dy*dy)
		
EndIf

If MouseDown(1)=False And click=1
	click=0
EndIf

If MouseDown(2)>0
	enemynew(Rnd(800),Rnd(600),Rnd(2.5,2.5),Rnd(0.08,0.1))
EndIf


enemyupdate()
enemydraw()


Rect playerx-5,playery-5,10,10,0

Oval playerx-distance#,playery-distance#,distance#*2,distance#*2,0

Flip


Until KeyDown(1)
End

Function enemynew.enemy(x,y,vmax#,amax#)

e.enemy=New enemy

e\x#=x
e\y#=y

e\vmax#=vmax#
e\amax#=amax#

Return e

End Function

Function enemyupdate()

For e.enemy=Each enemy

dx#=(playerx-e\x)
dy#=(playery-e\y)

l#=Sqr(dx#*dx#+dy#*dy#)

dx#=(dx#/l#)*e\amax#
dy#=(dy#/l#)*e\amax#

;if close enough escape target
If l#<=distance#
dx#=-dx#
dy#=-dy#
EndIf

;check against all other enemies, to avoid them
dxx#=0
dyy#=0
co=0
For ee.enemy=Each enemy
	
	If ee<>e
		
		dex#=(e\x-ee\x)
		dey#=(e\y-ee\y)
		
		l#=Sqr(dex#*dex#+dey#*dey#)
		
		dxx#=dxx#+(dex#/l#)*e\amax#
		dyy#=dyy#+(dey#/l#)*e\amax#
		
		co=co+1
	EndIf
Next

dxx#=dxx#/Float(co)
dyy#=dyy#/Float(co)

dx#=(dx#+dxx#)/2
dy#=(dy#+dyy#)/2

e\ax#=e\ax#+dx#
e\ay#=e\ay#+dy#

acc#=Sqr(e\ax#*e\ax#+e\ay#*e\ay#)

;Check if current acceleration is more than allowed
If acc#>e\amax#
	
	e\ax#=(e\ax#/acc#)*e\amax
	e\ay#=(e\ay#/acc#)*e\amax
	
EndIf

e\vx#=e\vx#+e\ax#
e\vy#=e\vy#+e\ay#

vel#=Sqr(e\vx#*e\vx#+e\vy#*e\vy#)

;Check if current velocity is more than allowed
If vel#>e\vmax#
	
	e\vx#=(e\vx#/vel#)*e\vmax
	e\vy#=(e\vy#/vel#)*e\vmax
	
EndIf

; add velocity to position
e\x#=e\x#+e\vx#
e\y#=e\y#+e\vy#

Next

End Function


Function enemydraw()

For e.enemy=Each enemy

	Rect e\x-3,e\y-3,6,6,0

Next

End Function


Hope it is of use :-)


Dr Derek Doctors(Posted 2003) [#5]
Personally I'd just give the alien a velocity which it adds to it's co-ordinates each frame and make it so it can only alter it's velocity by a small amount each frame. That way it'll aim at the player and overshoot, but then decellerate and effectively buzz around the player like a bee.


Bremer(Posted 2003) [#6]
Thank you all for the answers so far. I like your example Jeppe, I'm not that great with math, which might be why I have trouble with stuff like this. But I tried it out and it looks very interesting. I'll try and see if I can incorporate the idea into my game.

Your AlphaGUI looks interesting too, I'm downloading it now to look at it further.

Jeppe: Tak for svaret.


Jeppe Nielsen(Posted 2003) [#7]
Velbekommen