Turret Targeting

Blitz3D Forums/Blitz3D Programming/Turret Targeting

GIB3D(Posted 2008) [#1]
How do you make one Entity target another Entity, like on Sheep Defence?

Edit
Or could someone at least tell me how to find the closest entity to another entity.


mtnhome3d(Posted 2008) [#2]
pointentity or aligntovector on the z axis.
to find the closest entity i would check to see if the enemy is in range with entitydistance and then if it is in range check its distance aganst the othe entitysin range.


GIB3D(Posted 2008) [#3]
Well I'm using types and it doesn't work out the same way.
I'm checking one entities distance, and then another one's distance(whether it even exists or not which I probably shouldn't do), and whichever one is closer is the target.

I could do it like this, checking all the entities that I know exist...
Graphics3D 800,600,0,2
SetBuffer BackBuffer()

cam = CreateCamera()
	PositionEntity cam,0,2,-10

light = CreateLight()


a2.Unit = Unit(CreateCube(),2,0,0,"a")
b2.Unit = Unit(CreateSphere(32),-2,-1,0,"b")
c2.Unit =  Unit(CreateSphere(32),7,-1,0,"c")

While Not KeyDown(1)
	
	If KeyDown(200) a2\y = a2\y + .1
	If KeyDown(208) a2\y = a2\y - .1
	
	If KeyDown(205) a2\x = a2\x + .1
	If KeyDown(203) a2\x = a2\x - .1
	
	UpdateUnit
	
				If EntityDistance(a2\mdl,b2\mdl) < EntityDistance(a2\mdl,c2\mdl)
					a2\target = EntityName(b2\mdl)
					
						ElseIf EntityDistance(a2\mdl,c2\mdl) < EntityDistance(a2\mdl,b2\mdl)
							a2\target = EntityName(c2\mdl)
								
						Else
							a2\target = 0
				EndIf
	
	UpdateWorld
	RenderWorld

	Text 0,0,"Target = " + a2\target
	Text 0,20,EntityDistance(a2\mdl,b2\mdl)
	Text 0,40,EntityDistance(a2\mdl,c2\mdl)
	
	Flip
Wend
End

Type Unit
	Field mdl
	Field x#,y#,z#
	Field target$
	Field name$
End Type

Function Unit.Unit(mdl,x#,y#,z#,name$)
	a.Unit = New Unit
		
		a\mdl = mdl
		
		a\x = x
		a\y = y
		a\z = z
		
		a\name = name
		
		NameEntity a\mdl,a\name
		
		PositionEntity a\mdl,a\x,a\y,a\z
	Return a
End Function

Function UpdateUnit()
	For a.Unit = Each Unit
		
		PositionEntity a\mdl,a\x,a\y,a\z
	Next
End Function


But I want it updating for ALL of that Type...
Graphics3D 800,600,0,2
SetBuffer BackBuffer()

cam = CreateCamera()
	PositionEntity cam,0,2,-10

light = CreateLight()


a2.Unit = Unit(CreateCube(),2,0,0,"a")
b2.Unit = Unit(CreateSphere(32),-2,-1,0,"b")
c2.Unit =  Unit(CreateSphere(32),7,-1,0,"c")

While Not KeyDown(1)
	
	If KeyDown(200) a2\y = a2\y + .1
	If KeyDown(208) a2\y = a2\y - .1
	
	If KeyDown(205) a2\x = a2\x + .1
	If KeyDown(203) a2\x = a2\x - .1
	
	UpdateUnit
	
	UpdateWorld
	RenderWorld

	Text 0,0,"Target = " + a2\target
	Text 0,20,EntityDistance(a2\mdl,b2\mdl)
	Text 0,40,EntityDistance(a2\mdl,c2\mdl)
	
	Flip
Wend
End

Type Unit
	Field mdl
	Field x#,y#,z#
	Field target$
	Field name$
End Type

Function Unit.Unit(mdl,x#,y#,z#,name$)
	a.Unit = New Unit
		
		a\mdl = mdl
		
		a\x = x
		a\y = y
		a\z = z
		
		a\name = name
		
		NameEntity a\mdl,a\name
		
		PositionEntity a\mdl,a\x,a\y,a\z
	Return a
End Function

Function UpdateUnit()
	For a.Unit = Each Unit
		For b.Unit = Each Unit
			For c.Unit = Each Unit
				
				If EntityDistance(a\mdl,b\mdl) < EntityDistance(a\mdl,c\mdl)
					a\target = EntityName(b\mdl)
					
						ElseIf EntityDistance(a\mdl,c\mdl) < EntityDistance(a\mdl,b\mdl)
							a\target = EntityName(c\mdl)
								
						Else
							a\target = 0
				EndIf
				
			Next
		Next
		
		PositionEntity a\mdl,a\x,a\y,a\z
	Next
End Function



Buggy(Posted 2008) [#4]
Why not just have two nested for loops?

Have a local variable, smallestDistance.

For a.Unit = each Unit

     For b.Unit = each Unit

          If EntityDistance(a\mdl, b\mdl) < smallestDistance

               smallestDistance = EntityDistance(a\mdl, b\mdl)
               a\target = EntityName(b\mdl)

          Endif

     Next

Next


It's hard to write code, because I usually do things differently, but I've used this general implementation many times to great success.


GIB3D(Posted 2008) [#5]
Because what if two entities are under the
smallestDistance
, it would target both of them... somehow... it just wouldn't turn out right.

Edit
Oh wait a minute here... you put
smallestDistance = EntityDistance...


I'll go ahead and try that one out


GIB3D(Posted 2008) [#6]
HA HA Thank you! Man y'all are really helpful... this is what I came up with..

Graphics3D 800,600,0,2
SetBuffer BackBuffer()

cam = CreateCamera()
	PositionEntity cam,0,2,-10

light = CreateLight()


a2.Unit = Unit(CreateCube(),2,0,0,"A2")
b2.Unit = Unit(CreateSphere(32),-2,-1,0,"B2")
c2.Unit =  Unit(CreateSphere(32),7,-1,0,"C2")



While Not KeyDown(1)
	
	If KeyDown(200) a2\y = a2\y + .1
	If KeyDown(208) a2\y = a2\y - .1
	
	If KeyDown(205) a2\x = a2\x + .1
	If KeyDown(203) a2\x = a2\x - .1
	
	
	
	
	
	If KeyDown(17) c2\y = c2\y + .1
	If KeyDown(31) c2\y = c2\y - .1
	
	If KeyDown(32) c2\x = c2\x + .1
	If KeyDown(30) c2\x = c2\x - .1
	
	
	
	
	UpdateUnit()
	
	UpdateWorld
	RenderWorld
	
	Text 0,0,"Target = " + a2\target
	Text 0,20,"B2 Distance= " + EntityDistance(a2\mdl,b2\mdl)
	Text 0,40,"C2 Distance= " + EntityDistance(a2\mdl,c2\mdl)
	
	Text 0,80,"A2 Smallest Distance = " + a2\sD
	Text 0,100,"B2 Smallest Distance = " + c2\sD
	Text 0,120,"C2 Smallest Distance = " + b2\sD
	
	Flip
Wend
End

Type Unit
	Field mdl
	Field x#,y#,z#
	Field target$
	Field name$
	Field sD#
End Type

Function Unit.Unit(mdl,x#,y#,z#,name$)
	a.Unit = New Unit
		
		a\mdl = mdl
		
		a\x = x
		a\y = y
		a\z = z
		
		a\sD#=5
		
		a\name = name
		
		NameEntity a\mdl,a\name
		
		PositionEntity a\mdl,a\x,a\y,a\z
	Return a
End Function

Function UpdateUnit()
	For ua.Unit = Each Unit
		For ub.Unit = Each Unit
			If EntityDistance(ua\mdl,ub\mdl) < ua\sD
				If EntityDistance(ua\mdl,ub\mdl) > 0
					ua\sD = EntityDistance(ua\mdl,ub\mdl)
					ua\target = EntityName(ub\mdl)		
						Else
							ua\sD=5
							ua\target = 0
				EndIf
			EndIf
		Next
		
		PositionEntity ua\mdl,ua\x,ua\y,ua\z
	Next
End Function


I didn't know before that I had to check if the distance was above 0

Should I put it in the code archives?


Stevie G(Posted 2008) [#7]
You don't have to check if distance > 0, just make sure ua<>ub so that a unit doesn't try and target itself. Normally you would have a TEAM field so the check would be ua\Team <> ub\Team so that you don't target your own units. You should hold a unit maximum range so that it doesn't target units which it has no chance of hitting. The code below is slightly more efficient as you only call entitydistance once.

I'd also recommend not changing the target every frame, only when the target is dead or out of range or your ai decides to do a runner etc..

Function UpdateUnit()

	For ua.Unit = Each Unit
	
		ua\sD = ua\MaxRange
		ua\Target = 0
	
		For ub.Unit = Each Unit
			
			If ua <> ub
				Distance# = EntityDistance(ua\mdl,ub\mdl)
				If Distance < ua\sD
					ua\sD = Distance
					ua\target = EntityName(ub\mdl)		
				EndIf
			EndIf
			
		Next
		
		PositionEntity ua\mdl,ua\x,ua\y,ua\z
	Next

End Function



srcoder(Posted 2008) [#8]
Thats funny!
The biggest problem is predicting where the target will be when the bullet gets there.
Bullets have finite speed and direction as do targets.
So how far ahead do you have to "lead" the target?

I know because I wrote sheep defence.

Bring on the solutions!


GIB3D(Posted 2008) [#9]
Ello there mister srcoder..

Couldnt you somehow add the objects current velocity to determie which way to shoot the bulet? It pretty much what you already do in FPS games, and if I'm not mistaken, the best way to figure out how to do code certain things (like ai) is to figure out how a human would do it.


Ross C(Posted 2008) [#10]
I would:

1. calculate the time the bullet would take to get to the enemy.
2. calculate the speed the enemy is travelling at
3. figure out how much ground the enemy could make up, based on the time the bullet would take to hit it
4. extend the target in front of the enemy (using some sort of TFormPoint), using the distance worked out in step 3.

That should work. At least it does in my head :o)


srcoder(Posted 2008) [#11]
Ah yes......
However
1. Once you predict how long it will take for the bullet to get to the target
2. You can work how where the target will be after that length of time
3. But the target could be moving towards or away from the turret
4. therefore the bullet will take slightly more/or less time to get to the predicted position of the player....

Work that puppy out!!! Kep it up and I will give you the Sheep Defence Source Code!

(;o#


Ross C(Posted 2008) [#12]
Yes, that's where a vector comes into it. It points the direction in which the entity is travelling.

So, work out the angle the entity is travelling. Once you have the distance, project it along that angle, from the entity position, along the angle :o)


srcoder(Posted 2008) [#13]
Think of a fast moving obect. Now you calculate the time the bullet will take to get to the target and use a vector to calculate the target's position after that length of time (and therefore predict where to aim).

Problem.....

Well the distance the bullet will have to travel to get the targets predicted position is now different....

therefore it will take more/less time to get there.....

therefore you need to predict a new vector for the target's position after the new length of time.....

oh nuts........

Keep trying......You're nearly there......


srcoder(Posted 2008) [#14]
I got bored waiting!!!
Here is my code for the machine gun turrets. I have not included the vector library but it's simple enought to find those.
I might be persuaded to make the test code available to download if you want to use it.
Have fun!!