Limiting the crosshair

Blitz3D Forums/Blitz3D Programming/Limiting the crosshair

Well I'm working on a 3d shooter, in my game the crosshair is independent from the player spaceship and it's mouse controlled so as it's the mouse icon you can move it anywhere on screen.

The problem is, the crosshair is a quad in 3d space which has a pivot, controlled with mousexspeed and mouseyspeed and it's also parented to spaceship so when the spaceship moves it moves too as it's 2d.

I can't limit it's movement by viewport limits and it goes out of sight.Any ideas to limit it's movement by screen edges? Thanks!

I'm not sure if this would be the best way. The idea is that if you parent the crosshair to the camera, it should allways have coordinates that are relative to the camera.
Then, on initializing your program, you could create a temp. Plane, move it at the same z-distance from the camera as the crosshair, set it's picking mode to 2 and use CameraPick to pick the 3d coordinates in each corner of the screen.
At runtime, you could use these the x and y of these 3d coordinates to limit the crosshairs movement.

Thanks b32 I'll keep it in my mind, anyone else with a more practical idea?

:) funny ..
	;setup graphics
	Graphics3D 800, 600, 0, 2
	SetBuffer BackBuffer()
	
	;create camera
	cam = CreateCamera()
	
	;position camera
	MoveEntity cam, 0, 0, -15
	
	;create cube
	cube = CreateCube(cam)
	PositionEntity cube, 0, 0, 0, 1
	ScaleEntity cube, 1, 1, 0.01
	
	;init bounds
	GetLimits(cam, cube, 100, 100, 700, 500)
	EntityOrder cube, -1
			
	z# = 0
	
	For i = 0 To 100
		c = CreateCube()
		ScaleEntity c, 0.1, 0.1, 0.1
		EntityColor c,Rand(255),Rand(255),Rand(255)
		PositionEntity c, Rnd(-10, 10), Rnd(-10, 10), Rnd(-10, 10) - 15
   Next
	
	;main loop
	Repeat
	
		TurnEntity cam, 0, 1, 0
	
		;move cube	
		x# = x# + (MouseXSpeed() * 0.01)
		y# = y# - (MouseYSpeed() * 0.01)
		PositionEntity cube, x, y, EntityZ(cube)
		MoveMouse 400, 300
	
		;limit cube's position
		LimitPosition cam, cube
	
		RenderWorld()
	
		;draw bounds (100,100)-(700,500)
		Color 0, 0, 255
		Rect 100, 100, 600, 400, 0
			
		Flip
	
	Until KeyHit(1)
	
	End

Global minx#, miny#, maxx#, maxy#
Function GetLimits(cam, ent, x1, y1, x2, y2)

	;determine distance entity->camera
	TFormPoint EntityX(ent, 1), EntityY(ent, 1), EntityZ(ent, 1), 0, cam

	;create temp. plane	
	plane = CreatePlane(1, cam)
	;move away from camera
	PositionEntity plane, 0, 0, TFormedZ()
	;turn towards camera
	RotateEntity plane, -90, 0, 0

	;make plane pickable	
	EntityPickMode plane, 2
	
	;pick upperleft coords
	CameraPick cam, x1, y1
	TFormPoint PickedX(), PickedY(), PickedZ(), 0, cam

	;store upperleft coords	
	minx# = TFormedX()
	miny# = TFormedY()

	;pick bottomright coords
	CameraPick cam, x2, y2
	TFormPoint PickedX(), PickedY(), PickedZ(), 0, cam
	
	;store bottomright coords
	maxx# = TFormedX()
	maxy# = TFormedY()	

	;free temp. plane	
	FreeEntity plane

	;swap coords if needed	
	If maxx < minx Then 
		t# = maxx
		maxx = minx
		minx = t#
	End If
	
	;swap coords if needed	
	If maxy < miny Then
		t# = maxy
		maxy = miny
		miny = t
	End If
	
End Function

;apply limits
Function LimitPosition(cam, ent)

	;convert current coords to camera coords
	TFormPoint EntityX(ent, 1), EntityY(ent, 1), EntityZ(ent, 1), 0, cam
	x# = TFormedX()
	y# = TFormedY()
	z# = TFormedZ()

	;limit coords	
	If x < minx Then x = minx
	If x > maxx Then x = maxx
	If y < miny Then y = miny
	If y > maxy Then y = maxy

	;convert coords back to world coords	
	TFormPoint x, y, z, cam, 0
	;reposition object
	PositionEntity ent, TFormedX(), TFormedY(), TFormedZ(), 1

End Function


However, instead of using MouseXSpeed/MouseYSpeed, you could also create the plane, make it invisible using EntityAlpha and pickable, and use CameraPick to determine where the crosshair should be:

	;setup graphics
	Graphics3D 800, 600, 0, 2
	SetBuffer BackBuffer()
	
	;create camera
	cam = CreateCamera()
	
	;position camera
	MoveEntity cam, 0, 0, -15
	
	;create cube
	cube = CreateCube()
	ScaleEntity cube, 1, 1, 0.01
	
	plane = CreatePlane()
	TurnEntity plane, -90, 0, 0
	EntityPickMode plane, 2
	EntityAlpha plane, 0.1
	
	;main loop
	Repeat
		
		mx = mx + MouseXSpeed()
		my = my + MouseYSpeed()
		MoveMouse 400, 300
		If mx < 0 Then mx = 0
		If my < 0 Then my = 0
		If mx > 800 Then mx = 800
		If my > 600 Then my = 600
		
		CameraPick cam, mx, my
		PositionEntity cube, PickedX(), PickedY(), PickedZ()	
	
		RenderWorld()
				
		Flip
	
	Until KeyHit(1)
	
	End


Something like this?

[EDIT] Brams solution is better.


Graphics3D 800,600,16,1

camera = CreateCamera()
cursor = CreateCube( camera ) : ScaleMesh cursor, 1,1,.1

While Not KeyDown(1)

	x# = LIMIT( EntityX( cursor ) + MouseXSpeed()*.01 , -10.0 , 10.0 )
	y# = LIMIT( EntityY( cursor ) - MouseYSpeed()*.01 , -7.5, 7.5 )
	MoveMouse 400,300
	PositionEntity cursor, x, y, 10

	RenderWorld()
	Flip
	
Wend


Function  LIMIT# ( q#, lo#, hi# )

	If q < lo q = lo
	If q > hi q = hi
	Return q
	
End Function


@b32:Thank you so much! I thought it was harder to code what you mentioned that's why I asked for something more practical but it's the easiest way.Thanks...

@Stevie G:Thanks, I'll stick with b32's anyway.Thank you...

One more problem, in the game there are some objects like asteroids pickable for AI to evade them while chasing the player.

When crosshair moves on those pickable objects, it changes the Y position and moves closer to the top-down camera. It looks bad and the launched rockets and fired weapons move to false coordinates.

Don't use PickedY() to set your crosshair position if you already know what it is going to be. Just hard-coded it to the same height as your ship, or just above the ground.