Enemy turn arround player position

BlitzMax Forums/BlitzMax Programming/Enemy turn arround player position

Hi !
how to code this :
When distance between the player and the enemy is less than 300 pixels the enemy start turn arround the player. When the player move, it continue to turn arround it ! Thanks for your help and yours ideas !

Just a code to begin
Strict

Graphics 1024,768


Global Enemy_x# = 300
Global Enemy_y# = 400

Global Player_x# = GraphicsWidth() / 2
Global Player_y# = GraphicsHeight() / 2
Global d#
Global angle# = 0.0

MoveMouse Player_x#, Player_y#

While Not KeyDown(KEY_ESCAPE)

	Cls

	SetColor 255,255,255
	DrawOval Player_x#-2, Player_y#-2,4,4
	SetColor 0,255,0
	DrawOval Enemy_x#-2, Enemy_y#-2,4,4
	
	Player_x# = MouseX()
	Player_y# = MouseY()
	
	SetColor 255,0,0
	
	d# = Float ( (Player_x# - Enemy_x#) * (Player_x# - Enemy_x#) + (Player_y# - Enemy_y#) * (Player_y# - Enemy_y#) )
	If d < 300 * 300 Then
		
		If angle# < 360 Then 
			angle# = angle# + 1.0
		Else
			angle# = 0.0
		End If
		
		Local xmov# = Cos (Angle#) * 2.0
		Local ymov# = Sin (Angle#) * 2.0
		
		Enemy_x# = Enemy_x# + xmov#	
		Enemy_y# = Enemy_y# + ymov#		
		
	End If

	SetColor 255,255,255
	DrawText "d=" + Sqr(d),0,0
	
	Flip

Wend


another try. No very smooth and realistic ! How to fix the rotation speed (the same for any distance) ?
Strict

Graphics 1024,768


Global Enemy_x# = 200
Global Enemy_y# = 400

Global Player_x# = GraphicsWidth() / 2
Global Player_y# = GraphicsHeight() / 2
Global d#
Global angle# = 0.0

MoveMouse Player_x#, Player_y#

Local bStartTurn = False

While Not KeyDown(KEY_ESCAPE)

	Cls

	SetColor 255,255,255
	DrawOval Player_x#-2, Player_y#-2,4,4
	SetColor 0,255,0
	DrawOval Enemy_x#-2, Enemy_y#-2,4,4
	
	Player_x# = MouseX()
	Player_y# = MouseY()
	
	SetColor 255,0,0
	
	d# = Float ( (Player_x# - Enemy_x#) * (Player_x# - Enemy_x#) + (Player_y# - Enemy_y#) * (Player_y# - Enemy_y#) )
	If d < 300 * 300 Then
		bStartTurn = True
	End If
	
	If bStartTurn = True
		
		If angle# < 360 Then 
			angle# = angle# + 1.0
		Else
			angle# = 0.0
		End If
		
		Local xmov# = Cos (Angle#) * Sqr(d)
		Local ymov# = Sin (Angle#) * Sqr(d)
		
		Enemy_x# = Player_x# + xmov#	
		Enemy_y# = Player_y# + ymov#		
		
	End If

	SetColor 255,255,255
	DrawText "d=" + Sqr(d),0,0
	
	Flip

Wend



You can use atan2 to get the angle to the player.

why use atan2 ?

This might explain or this or this .
There's quite a few others as well.
<edit> Might even be this

do you mean something like this:
SuperStrict
Framework BRL.GLMax2D
Import BRL.Random



Const Acceleration# 	= 00.5
Const TopSpeed# 		= 05.0
Const TurnAcceleration#	= 01.0
Const TurnMax# 			= 10.0
Const MaxPoints#		= 30.0
Const MissileSpeed%		= 3
Local Missiles% = 1
Local Missile:TMisile[Missiles] ' create missiles
Local streak:tstreak[Missiles]  ' create streak for missiles


Graphics 800,600,32,60
Global width% = GraphicsWidth()
Global height% = GraphicsHeight()
Local ship#[] = [0#,0#,0#,-4#,10#,0#,0#,4#,0#,0#]
SetBlend alphablend
glEnable(GL_LINE_SMOOTH)	'Quick antaliasing hack
glHint(GL_LINE_SMOOTH_HINT,GL_NICEST)
glLineWidth(3.0)

' create missiles and streaks.

For Local i% = 0 To Missiles-1
	Missile[i] = TMisile.Create(Rand(700)+50,Rand(500)+50,Rand(360))
	streak[i] =tstreak.Create(Missile[i].x,Missile[i].y,Rand(255),Rand(255),Rand(255))
Next

SeedRnd MilliSecs()

Repeat
	SetColor 20,200,40
	DrawText "Press (esc) to exit",300,30
	For Local i% = 0 To Missiles-1
		For Local s% = 1 To MissileSpeed
			Missile[i].update(MouseX(),MouseY())
			streak[i].add(Missile[i].x,Missile[i].y)
		Next
		streak[i].draw()
		missile[i].draw(ship) 
	Next
	Flip()
	Cls 
Until KeyHit(key_escape)


'
'				Resources
'-----------------------------------------------------------------------------------
'

Type Tpoint
	Field x#
	Field y#
End Type

' used to draw a streak. 
'Note:  does become jugged If points are separated Too far And
'		angles are set sharp.

Type Tstreak
	Field PointList:TList 
	Field lastpoint:tpoint
	Field active%
	Field Red%,Green%,Blue%
	Function Create:tstreak(x#,y#,Red%,Green%,Blue%)
		Local s:tstreak = New tstreak
		Local p:tpoint  = New tpoint
		If Not s.PointList Then 
			s.PointList      = CreateList()
			s.lastpoint = New tpoint
			s.active    = True
		EndIf
		p.x = x
		p.y = y
		s.PointList.addlast(p)
		s.lastpoint.x = p.x
		s.lastpoint.y = p.y
		s.Red    = Red
		s.Green  = Green
		s.Blue   = Blue
		Return s
	End Function
	' adds a segment to a streak.
	
	Method add(x#,y#)
		If PointList.count()<MaxPoints 
			Local p:tpoint = New tpoint
			p.x = x
			p.y = y
			PointList.addlast(p)
			lastpoint.x = p.x
			lastpoint.y = p.y 
		Else
			PointList.remove(PointList.first())
		EndIf
	End Method
	
	'
	
	Method draw()
		Local tint# = 1.0/MaxPoints
		If Not PointList.count() Return 	
		If PointList.count() > 1 Then 
			Local Alpha# = 0.0
			Local p1:Tpoint = Tpoint(PointList.first())
			SetColor Red,Green,Blue
			For Local p2:tpoint = EachIn PointList
				If p2<>p1 Then 
					SetAlpha alpha
					DrawLine(p1.x,p1.y,p2.x,p2.y,False)
					p1 = p2	
				EndIf
				alpha :+Tint
			Next		
		EndIf 
	End Method
End Type


Type TMisile 	
	Field Red%
	Field Green%
	Field Blue%
	Field x#,y#
	Field DirectionX#,DirectionY#
	Field XS#,YS#
	Field Done:Int
	Field OldDirection#
	Field Direction#
	Field TurnSpeed#
	Field CurrentSpeed#
	Field Difference#
	Field TargetAngle#
	
	Function Create:TMisile(x#,y#,dir#)
	
		Local s:TMisile = New TMisile
		s.x = x
		s.y = y
		s.Direction = Dir 
		s.Done = False
		s.CurrentSpeed = 0
		Return s
		
	End Function
	
	'Draw Missile

	Method draw(s#[]) ' used to draw missile
		SetOrigin(x,y)
		SetRotation(direction)
		SetColor(0,0,180)
		DrawPoly s
		SetOrigin 0,0
		SetRotation 0
	' use from field in type
	' x, y -- is the current missile position also used for head of streak
	'direction -- is the angle the missile is facing in degrees. 
	End Method
	
	' Target chassing logic
	
	Method Update%(nx%,ny%)
		'Set Rotation
								
		'turn toward target

		If TargetAngle < (Direction-TurnAcceleration)				
			If difference > 180.0 
				TurnSpeed:+TurnAcceleration 
			Else 
				TurnSpeed:-TurnAcceleration
				
			EndIf
		ElseIf TargetAngle > (Direction+TurnAcceleration)
			If difference > 180.0 
				TurnSpeed:-TurnAcceleration 
			Else 
				TurnSpeed:+TurnAcceleration
			EndIf
		EndIf
		
		
		'If found stop turning
		
		If difference < 3.0 Or  difference >357.0 
			TurnSpeed = 0.0;
			 
		EndIf			
				
		'Limit TurnSpeed
		If TurnSpeed >  TurnMax TurnSpeed =  TurnMax
		If TurnSpeed < -TurnMax TurnSpeed = -TurnMax
		Direction = (Direction+TurnSpeed+360) Mod 360.0
		'Set acceleration
		XS:+ Cos(Direction)*Acceleration
		YS:+ Sin(Direction)*Acceleration
	
		If CurrentSpeed > TopSpeed 
			XS:+ (XS/CurrentSpeed)*(TopSpeed - CurrentSpeed)
			YS:+ (YS/CurrentSpeed)*(TopSpeed - CurrentSpeed)
		EndIf
		
		X:+ XS 
		Y:+ YS 
		TargetAngle# = (ATan2(y-ny,x-nx)+180.0) Mod 360.0		
		difference# = Abs(TargetAngle-Direction)
		CurrentSpeed = Sqr(XS^2 + YS^2)
		 	
	EndMethod
End Type

adopted from my guided misile code.

many thanks for this tonyg and jesse.

just need help now to set the speed enemy the same for any enemy-player distance ! please help !

Strict

Graphics 1024,768


Global Enemy_x# = 200
Global Enemy_y# = 400

Global Player_x# = GraphicsWidth() / 2
Global Player_y# = GraphicsHeight() / 2
Global d#
Global angle# = 0.0
Global Speed# = 1.0

Const Pi_div_180# = Pi / 180.00

MoveMouse Player_x#, Player_y#

Local bStartTurn = False

While Not KeyDown(KEY_ESCAPE)

	Cls

	SetColor 255,255,255
	DrawOval Player_x#-2, Player_y#-2,4,4
	SetColor 0,255,0
	DrawOval Enemy_x#-2, Enemy_y#-2,4,4
	
	Player_x# = MouseX()
	Player_y# = MouseY()
	
	SetColor 255,0,0
	
	d# = Float ( (Player_x# - Enemy_x#) * (Player_x# - Enemy_x#) + (Player_y# - Enemy_y#) * (Player_y# - Enemy_y#) )
	If d < 300 * 300 Then
		bStartTurn = True
		angle# = ATan2 (Enemy_y#-player_y#, Enemy_x#-Player_x#)
	End If
	
	If bStartTurn = True
		
		If angle# < 360 Then 
			angle# = angle# + Speed#*360.0/60.0 '60 is FPS
		Else
			angle# = 0.0
		End If
		
		d = Sqr(d)
		If d < 3.0 Then d = 3.0
		
		Local xmov# = Cos (Angle# + Pi_div_180#) * d
		Local ymov# = Sin (Angle# + Pi_div_180#) * d
		
		Enemy_x# = Player_x# + xmov#	
		Enemy_y# = Player_y# + ymov#		
		
	End If

	SetColor 255,255,255
	DrawText "d=" + Sqr(d),0,0
	
	Flip

Wend


My pb is now to set a constant speed (same speed if the enemy is near or far the player position). Have you an idea to do this ?

to get the angle movement. you do it like this:
angle = arc/radius (in your case arc being the speed and radius half D)
note: the result will be in radians so you need to convert it back to degrees by multiplying the result by 57.2957.

if i understand this :
angle = angle + speed# / (0.5 * sqr(d)) * 57.2957 ?

when i test, this is not the same speed. Where is my error ?
Strict

Graphics 1024,768


Global Enemy_x# = 200
Global Enemy_y# = 400

Global Player_x# = GraphicsWidth() / 2
Global Player_y# = GraphicsHeight() / 2
Global d#
Global angle# = 0.0
Global Speed# = 4.0

Const Pi_div_180# = Pi / 180.00

MoveMouse Player_x#, Player_y#

Local bStartTurn = False

While Not KeyDown(KEY_ESCAPE)

	Cls

	SetColor 255,255,255
	DrawOval Player_x#-2, Player_y#-2,4,4
	SetColor 0,255,0
	DrawOval Enemy_x#-2, Enemy_y#-2,4,4
	
	Player_x# = MouseX()
	Player_y# = MouseY()
	
	SetColor 255,0,0
	
	d# = Float ( (Player_x# - Enemy_x#) * (Player_x# - Enemy_x#) + (Player_y# - Enemy_y#) * (Player_y# - Enemy_y#) )
	If d < 300 * 300 Then
		bStartTurn = True
		angle# = ATan2 (Enemy_y#-player_y#, Enemy_x#-Player_x#)
	End If
	
	If bStartTurn = True
		
		If angle# < 360 Then 
			angle# = angle# + speed# / (0.5 * Sqr(d)) * 57.2957
		Else
			angle# = 0.0
		End If
		
		d = Sqr(d)
		If d < 3.0 Then d = 3.0
		
		Local xmov# = Cos (Angle# + Pi_div_180#) * d
		Local ymov# = Sin (Angle# + Pi_div_180#) * d
		
		Enemy_x# = Player_x# + xmov#	
		Enemy_y# = Player_y# + ymov#		
		
	End If

	SetColor 255,255,255
	DrawText "d=" + Sqr(d),0,0
	
	Flip

Wend


I don't know what you are trying to acomplish but it is a consistent speed. it is doing what is supposed to do. What I am thinking is that you want it to go slower the smaller the radius is. am I correct? remove the cls from your sample and see. All of the steps are about 4 pixels apart. whether a small radius or large. if you want it to go slower/faster you need to find a factor by which to decrease/increase the speed depending on the size of the radius.

I googled the formula just to make shure I remembered it correctly:
http://www.themathpage.com/aTrig/arc-length.htm

you are correct. to go slower the smaller the radius is. But the code produce the contrary for me !

i want that the enemy take the same time to accomplish the circle, this for any radius ! ... hope that this is this that i want ;-) if you have a formulae ... i'm interested !

Same time for any radius means that

2 * Radius * Pi / Desired Time = Speed gives you the actual speed your object needs to have.

with dreamora code, this is not that i want. try it, i'm tired need to sleep ! Time to go to bed for me ! Thanks for your help :!

Strict

Graphics 1024,768


Global Enemy_x# = 200
Global Enemy_y# = 400

Global Player_x# = GraphicsWidth() / 2
Global Player_y# = GraphicsHeight() / 2
Global d#
Global angle# = 0.0
Global Speed# = 4.0

Const Pi_div_180# = Pi / 180.00

MoveMouse Player_x#, Player_y#

Local bStartTurn = False

While Not KeyDown(KEY_ESCAPE)

	Cls

	SetColor 255,255,255
	DrawOval Player_x#-2, Player_y#-2,4,4
	SetColor 0,255,0
	DrawOval Enemy_x#-2, Enemy_y#-2,4,4
	
	Player_x# = MouseX()
	Player_y# = MouseY()
	
	SetColor 255,0,0
	
	d# = Float ( (Player_x# - Enemy_x#) * (Player_x# - Enemy_x#) + (Player_y# - Enemy_y#) * (Player_y# - Enemy_y#) )
	If d < 300 * 300 Then
		bStartTurn = True
		angle# = ATan2 (Enemy_y#-player_y#, Enemy_x#-Player_x#)
	End If
	
	If bStartTurn = True
		
		If angle# < 360 Then 
'			angle# = angle# + (speed# / (Sqr(d)/2.0)) * 57.2957
			angle  = angle# + (2 * Sqr(d) * Pi) / 2000
		Else
			angle# = 0.0
		End If
		
		d = Sqr(d)
		
		Local xmov# = Cos (Angle# + Pi_div_180#) * d
		Local ymov# = Sin (Angle# + Pi_div_180#) * d
		
		Enemy_x# = Player_x# + xmov#	
		Enemy_y# = Player_y# + ymov#		
		
	End If

	SetColor 255,255,255
	DrawText "d=" + Sqr(d),0,0
	
	Flip

Wend