Off screen targert pointer

Blitz3D Forums/Blitz3D Programming/Off screen targert pointer

King Dave(Posted 2005) [#1]
Hey, this isn't easy to explain so bare with me...

If you've played any flight or space sims that allow you to target an objective or player, you hopefully will know what i mean as many have a feature similar to this.

I want to display a arrow on the edge of the screen pointing in the direction the player should turn to get the target into the field of view (the quickest direction).

For example, if the target is outside of the field of view to the right there would be an arrow on the right hand side of the screen.
If the target is outside and to the left, but slightly up too.. the arrow would be on the left side of the screen but near the top.


I've not had much luck getting this to work yet, and can't see anything obvious in the code archieves (if there is one please point it out :))

Does anyone have any ideas or examples on how to do this? Thanks!


GfK(Posted 2005) [#2]
Use a combination of DeltaYaw() and EntityInView()

Pesudo code:

If DeltaYaw < 0 then object is to left of 'straight ahead'
If EntityInView = false then object is off screen so draw an indicator at left edge.

^^repeat for right-hand edge

etc...


King Dave(Posted 2005) [#3]
Hey, thanks for the response.

I've managed to work out if its up down left or right, however i need the arrow to move up or down/left or right on the screen as well to show if they have to turn for example towards the left and up a tad.

I'm just trying to find a screenshot to describe what i mean as its hard in words... i'll post it once I have.


GfK(Posted 2005) [#4]
Yup, I know what you mean. I might have a bit of code somewhere - lemme look.


King Dave(Posted 2005) [#5]
Cheers, just for others reading a similar feature was on FreeSpace (old flight sim), notice the green arrow/distance indicater at the top left:




GfK(Posted 2005) [#6]
Hmm... the code I used uses FONText and it wasn't too clear in what it was doing, so I knocked this little example up for you. You could still incorporate the EntityInView() thing if you didn't want the markers to appear when the target was in view:
Graphics3D 800,600

camera = CreateCamera()
cube = CreateCube()
light = CreateLight()
MoveEntity camera,0,3,-15


While Not KeyDown(1)
	If KeyDown(203) Then TurnEntity camera,0,1,0
	If KeyDown(205) Then TurnEntity camera,0,-1,0
	If KeyDown(200) Then TurnEntity camera,1,0,0
	If KeyDown(208) Then TurnEntity camera,-1,0,0
	RotateEntity camera,EntityPitch(camera),EntityYaw(camera),0
	CameraProject(camera,EntityX(cube),EntityY(cube),EntityZ(cube))
	X# = ProjectedX()
	Y# = ProjectedY()
	RenderWorld
	Oval 8,y,6,6,True
	Oval GraphicsWidth()-8,y,6,6,True
	Oval x,8,6,6,True
	Oval x,GraphicsHeight()-8,6,6,True
	Flip
Wend



King Dave(Posted 2005) [#7]
Not quite what i'm after as it doesn't work when the object goes out of view, and cameraproject will just return 0's if the object is truely behind the camera (more than 90 degrees).
Either that or I'm not following the example properly.

Anyway, I'll keep playing i'm sure i'll work out something sooner or later :)


Ross C(Posted 2005) [#8]
Couldn't you get the angle between the two entities? Using ATan2.

You would need to disregard the Z axis and just use the Y and X co-ords. The only problem i could see there is if your ship rotates on the X axis. Then you would need to translate the other objects co-ords into the ships co-ords. That shouldn't be too hard tho :o) When you have this angle, simple rotate the arrow to that angle and your sorted :o)


King Dave(Posted 2005) [#9]
Hmm, well the closest I have so far is using a combination of EntityInView and DeltaPitch/DeltaYaw as originally suggested (similiar to how I was first trying to get this to work too).

Example:
Const WIDTH=640,HEIGHT=480
Graphics3D WIDTH,HEIGHT,16,2
SetBuffer BackBuffer()

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

light=CreateLight()
RotateEntity light,90,0,0

plane=CreatePlane()

cube=CreateCube()
PositionEntity cube,0,1,0

HidePointer

While Not KeyDown( 1 )
	;Mouse look
	TurnEntity Camera,Float#(MouseYSpeed())/3,-Float#(MouseXSpeed())/3,0
	RotateEntity Camera,EntityPitch#(Camera),EntityYaw#(Camera),0
	
	RenderNeeded=1
	
	MoveMouse WIDTH/2,HEIGHT/2
	
	
	RenderWorld
	
	Color 255,0,0
	a=EntityInView(cube,camera)
	Text 0,5,"EntityInView: "+a
	
	If Not a
		dx#=DeltaPitch#(camera,cube)
		dy#=DeltaYaw#(camera,cube)
		
		If Abs(dx#)>Abs(dy#)
			f#=dy#/90
			If dx#>0
				y=HEIGHT
			Else
				y=0
			EndIf
			x=WIDTH/2-WIDTH*f#
			f#=Abs(dx#/180)
		Else
			f#=0-(dx#/90)
			If dy#>0
				x=0
			Else
				x=WIDTH
			EndIf
			y=HEIGHT/2-HEIGHT*f#
			f#=Abs(dy#/180)
		EndIf
		size=5+f#*15.0
		If x<0 Then x=0
		If x>WIDTH Then x=WIDTH
		If y<0 Then y=0
		If y>HEIGHT Then y=HEIGHT
		
		Color 0,255,0
		Rect x-size/2,y-size/2,size,size,1
		
		
		Color 255,0,0
		Text 0,25,"Delta values: "+dx#+" , "+dy#
		Text 0,45,"Draw coords: "+x+" , "+y+" ("+size+")"
	EndIf
	
	Flip
Wend

End

Its not perfect yet and doesn't work if the camera rolls (which will be a problem as mine does up to about 70 degrees)


Ross C(Posted 2005) [#10]
Ok, i managed to knock together this:

It also works if the camera rolls, as you are translating the targets co-ords to the ships local co-ords. It seems to be pretty robust.

Graphics3D 800,600
SetBuffer BackBuffer()

Global camera = CreateCamera()

Global light = CreateLight()

Global ship = CreateSphere()
EntityParent camera,ship
PositionEntity camera,0,0,-10


Dim cubes(20)

For loop = 0 To 20

	cubes(loop) = CreateSphere(2)
	EntityColor cubes(loop),Rnd(50,255),Rnd(50,255),Rnd(50,255)
	PositionEntity cubes(loop),Rnd(-30,30),Rnd(-30,30),Rnd(-30,30)
	
Next


; set up the target and arrow pointer

Global target = CreateCube()
EntityColor target,200,40,40
PositionEntity target,10,3,20


Global arrow = CreateCone()

Global pivot = CreatePivot()

EntityParent arrow,pivot
PositionEntity arrow,0,4,0
ScaleEntity arrow,0.25,0.25,0.25
EntityColor arrow,40,40,200

EntityParent pivot,ship


While Not KeyHit(1)

	EntityColor target,Rnd(30,230),Rnd(30,230),Rnd(30,230)

	If KeyDown(203) Then RotateEntity ship,EntityPitch(ship,True),EntityYaw(ship,True)+1,EntityRoll(ship,True),True
	If KeyDown(205) Then RotateEntity ship,EntityPitch(ship,True),EntityYaw(ship,True)-1,EntityRoll(ship,True),True
	If KeyDown(200) Then RotateEntity ship,EntityPitch(ship,True)+1,EntityYaw(ship,True),EntityRoll(ship,True),True
	If KeyDown(208) Then RotateEntity ship,EntityPitch(ship,True)-1,EntityYaw(ship,True),EntityRoll(ship,True),True

	If MouseDown(1) Then MoveEntity ship,0,0,0.1
	If MouseDown(2) Then MoveEntity ship,0,0,-0.1
	
	
	; transform the targets X,Y,Z co-ords to the ships local co-ords
	TFormPoint EntityX(target,True),EntityY(target,True),EntityZ(target,True), 0, ship
	
	; work out the angle between the ship's local co-ords (0,0,0) and the targets tranformed co-ords
	angle = ATan2( TFormedY(), TFormedX())
	angle = angle - 90 ; adjust for blitz rotation system

	RotateEntity pivot,0,0,angle ; rotate the arrow pivot to point at the target.

	UpdateWorld
	RenderWorld
	Text 0,0," Arrow Keys to turn. Mouse button left to move forward and mouse button right to move backwards"
	Flip
	
Wend



Ross C(Posted 2005) [#11]
Edited code above to show more clearly :o)


_PJ_(Posted 2005) [#12]
I had an entity that could only translate in Local X and Y space. It was restricted by an Alpha'd bounding box collision which coincided with the edge of the screen. This meant that if pointing directly behind the player, it would show this by being central on screen.


Damien Sturdy(Posted 2005) [#13]
How about:

have an arrow mesh, and TRANSLATEMESH 0,0,forward_a_bit
1)Parent this mesh to the camera/view entity.
2)Point this mesh towards the target
3) Limit the yaw of this mesh to LOCAL >-90 and <90.
4) limit the pitch by the same local amount
5)If the target is onscreen, Hide this mesh, otherwise show it.






This idea is okay, You'll need to play with some code to get it to work :) Hope its w2hat you want.

Oh, and it has the advantage of being in 3d :)

You might want to play with totally limiting some axis for other effects :D


Ross C(Posted 2005) [#14]
Sorry, i mis-read your post :S