Code archives/Algorithms/Homing physics ( 2D )

This code has been declared by its author to be Public Domain code.

Download source code

Homing physics ( 2D ) by Jeppe Nielsen
(Posted 24 years ago)
Allow enemies to chase player, with velocity and acceleration.
;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

Comments

TWH
(Posted 18 years ago)
'Blitzmax:
Strict
'Homing example, by Jeppe Nielsen 2003
'mouse position:
Global playerx# 
Global playery#
Global distance#=100
Global enemylist:TList = CreateList()

Type enemy
	Field x#,y#
	Field vx#,vy#
	Field ax#,ay#
	Field vmax#
	Field amax#
	
	Function enemynew:enemy(x,y,vmax#,amax#)
	Local e:enemy=New enemy
	enemylist.addlast(e)
	e.x#=x
	e.y#=y
	e.vmax#=vmax#
	e.amax#=amax#
	Return e
	End Function

	Function enemydraw()
	For Local e:enemy=EachIn enemylist
		SetColor 0,0,255
		DrawRect e.x-3,e.y-3,6,6
	Next
	End Function
	
	Function enemyupdate()
		For Local e:enemy=EachIn enemylist
	
		Local dx#=(playerx-e.x)
		Local dy#=(playery-e.y)	
		Local 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
		Local dxx#=0
		Local dyy#=0
		Local co=0
		For Local otherEnemy:enemy=EachIn enemylist
			If otherEnemy<>e
				Local dex#=(e.x-otherEnemy.x)
				Local dey#=(e.y-otherEnemy.y)
				
				'Avoid other enemies. Comment out these 3 lines to remove avoidance.
				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#
		
		Local 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#
		
		Local 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
End Type

'SetGraphicsDriver GLMax2DDriver()
Graphics 640,480

'Create ten enemies at random locations
Local n:Int
For n=1 To 10				
	'play with last number
	'enemynew(x,y,vmax,amax)
	enemy.enemynew(Rnd(800),Rnd(600),Rnd(5,5), 10)'Rnd(0.08,0.1))
Next

Local click:Int = 0
Local clickx:Int = 0
Local clicky:Int = 0
Repeat
	Cls
	DrawText "Move player with mouse",10,10
	DrawText "LMB - Resize allowed distance to player",10,30
	DrawText "RMB - Add enemies",10,50
	
	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
		Local dx:Int=(MouseX()-clickx)
		Local dy:Int=(MouseY()-clicky)
		distance#=Sqr(dx*dx+dy*dy)
	EndIf
	
	If MouseDown(1)=False And click=1
		click=0
	EndIf
	
	If MouseDown(2)>0
		enemy.enemynew(Rnd(800),Rnd(600),Rnd(2.5,2.5),Rnd(0.08,0.1))
	EndIf
	
	
	enemy.enemyupdate()
	enemy.enemydraw()
	
	'DrawRect playerx-5,playery-5,10,10
	
	SetAlpha 0.8
	SetColor 255,0,0
	SetBlend(LIGHTBLEND)
	DrawOval playerx-distance#,playery-distance#,distance#*2,distance#*2
	SetAlpha 1
	
	Flip
Until KeyDown(KEY_ESCAPE) Or AppTerminate()
End


markcw
(Posted 18 years ago)
http://www.blitzbasic.com/faq/faq_entry.php?id=2

Jesse
(Posted 18 years ago)
Dud! I've been here many time and I had not seen the original code. Nice.

Code Archives Forum