Off screen targert pointer
Blitz3D Forums/Blitz3D Programming/Off screen targert pointer
| ||
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! |
| ||
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... |
| ||
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. |
| ||
Yup, I know what you mean. I might have a bit of code somewhere - lemme look. |
| ||
Cheers, just for others reading a similar feature was on FreeSpace (old flight sim), notice the green arrow/distance indicater at the top left: |
| ||
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 |
| ||
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 :) |
| ||
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) |
| ||
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) |
| ||
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 |
| ||
Edited code above to show more clearly :o) |
| ||
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. |
| ||
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 |
| ||
Sorry, i mis-read your post :S |