Look around using mouse like in most PC FPS games

BlitzMax Modules Forums/MiniB3D/Look around using mouse like in most PC FPS games

Gfx provided me with some very helpful MouseXSpeed and MouseYSpeed substitutes, but I cannot figure out why the following code refuses to budge the camera when I move the mouse:

TurnEntity camera,-mouse.YSpeed()*0.9,mouse.XSpeed()*0.9,mouse.XSpeed()/10.000



Could I please get some help?

Just a guess, but try:
TurnEntity camera,-Float(mouse.YSpeed())*0.9,Float(mouse.XSpeed())*0.9,Float(mouse.XSpeed())/10.000

No, that's not the issue.

For some reason, when I'm calling the function for drawing text, everything goes smoothly ( text 50,50,"MouseYSpeed: "+mouse.YSpeed();text 50,60,"MouseXSpeed: "+mouse.XSpeed() ) but when I assign it to a variable or do anything other than text for that matter, it usually returns 0 but occasionaly returns *something* just to throw me off.

Main program (revised to use RotateEntity rather than TurnEntity because TurnEntity doesn't seem to support roll whereas RotateEntity does)
Import sidesign.minib3d

Global gw=640,gh=480

Graphics3D gw,gh


Include "TMouse.bmx"
Include "TPlayer.bmx"





Global light=CreateLight()

Global player:TPlayer=New TPlayer
player.Create()
PositionEntity player.entity,0,0,0
Global camera=CreateCamera()
PositionEntity camera,0,0.46,-7
RotateEntity camera,-20,0,0
Global cpivot=CreatePivot(player.entity)
'EntityParent(camera,cpivot)



Global p=CreateCube();HideEntity p
For x=1 To 500
	x2=CopyEntity(p)
	PositionEntity x2,Rand(-800,800),Rand(-800,800),Rand(-800,800)
	ScaleEntity x2,Rnd(0.4,8),Rnd(0.4,8),Rnd(0.4,8)
	EntityColor x2,Rand(80,250),Rand(80,250),Rand(80,250)
Next




Global fpstimer=CreateTimer(60)



Repeat


	Local mys=mouse.YSpeed()
	Local mxs=mouse.XSpeed()	
	Print mys+" , "+mxs

	If KeyDown(KEY_W) player.spd:+0.9
	If KeyDown(KEY_S) player.spd:-0.9
	If KeyDown(KEY_A) player.y:-0.2
	If KeyDown(KEY_D) player.y:+0.2
	player.p:-Float(mouse.YSpeed())
	player.y:+Float(mouse.XSpeed())
	player.r:+Float(mouse.XSpeed())
	player.update()
	MoveMouse gw/2,gh/2
	If MouseHit(1)
		
	EndIf

	UpdateWorld
	RenderWorld
	

	text 50,50,"MouseYSpeed: "+mouse.YSpeed()
	text 50,60,"MouseXSpeed: "+mouse.XSpeed()

	Flip
	WaitTimer(fpstimer)
	If KeyDown(KEY_ESCAPE) End
	mouse.update()
	
Forever



TMouse.bmx (thanks to Gfx):
Global mouse:tMouse = New tMouse

Type tMouse
	Field lastX:Int
	Field lastY:Int
	Method XSpeed:Int()
		Return MouseX() - lastX
	End Method
	Method YSpeed:Int()
		Return MouseY() - lastY
	End Method
	Method update()
		lastx = MouseX()
		lasty = MouseY()
	End Method
End Type


And TPlayer.bmx:
Global PlayerMesh=CreateCone(4)
ScaleEntity PlayerMesh,5,2,0.6
TurnEntity PlayerMesh,90,0,0
HideEntity PlayerMesh

Global players=0

Type TPlayer
	Global list:TList=CreateList() 'in the case of more than 1 player (online play would be awesome)
	
	Global decellerate#=0.001
	
	Field spd#,maxspd#,p#,y#,r#
	
	Field entity
	
	Field hits=100
	
	Method Create(x#=0,y#=0)
		spd#=0
		maxspd=40
		p#=0;y#=0;r#=0
		entity=CopyEntity(PlayerMesh)
		list.AddLast(Self)
		players:+1
	End Method
	
	Method Kill()
		FreeEntity entity
		players:-1
		list.remove(Self)
	End Method
	
	Method Update()
		If spd>0 spd:-decellerate ElseIf spd<0 spd:+decellerate
		If Abs(spd)=<decellerate spd=0
		If spd>maxspd spd=maxspd
		If spd<-maxspd spd=-maxspd
		MoveEntity entity,0,spd/40,0
		RotateEntity entity,p,y,r
	End Method
	
End Type


I'd probably encapsulate the mouselook capability within the mouse class itself, to make things a little tidier.

Your code structure is somewhat unkind to my way of thinking, so I can't help you directly, but here's a simple example that hopefully will help:

SuperStrict

Import sidesign.minib3d

Local ScreenWidth:Int = 800
Local ScreenHeight:Int = 600
Local ScreenWidthC:Int = (ScreenWidth / 2)
Local ScreenHeightC:Int = (ScreenHeight / 2)

Graphics3D 800, 600

AmbientLight 255, 255, 255

Local Camera:TCamera = CreateCamera()
PositionEntity Camera, 0.0, 0.0, -10.0

Local Cube:TMesh = CreateCube()
PositionEntity Cube, 0.0, 0.0, 0.0

PointEntity Camera, Cube

Local Mouse:TMouseSystem = TMouseSystem.Create()

Local MoveSpeed:Float = 0.5

HideMouse

While Not KeyHit(KEY_ESCAPE)
	
	If KeyDown(KEY_W) Then MoveEntity Camera, 0.0, 0.0, MoveSpeed
	If KeyDown(KEY_S) Then MoveEntity Camera, 0.0, 0.0, -MoveSpeed
	If KeyDown(KEY_A) Then MoveEntity Camera, -MoveSpeed, 0.0, 0.0
	If KeyDown(KEY_D) Then MoveEntity Camera, MoveSpeed, 0.0, 0.0
	
	Mouse.Look Camera, ScreenWidthC, ScreenHeightC
	
	Mouse.Update
	
	RenderWorld
	
	Flip True

Wend

End


'************* MOUSE CLASS *************


Type TMouseSystem


	Function Create:TMouseSystem(pointer_url:String = "")
	
		Local msys:TMouseSystem = New TMouseSystem
		
		msys.Pointer = LoadImage(pointer_url)
		
		Return msys
	
	EndFunction


	Field MX:Int, MY:Int, OldMX:Int, OldMY:Int
	Field MXS:Int, MYS:Int
	Field Pointer:TImage

	
	Method MovePointer(x:Int, y:Int)
	
		MoveMouse x, y
		
		MX = x
		MY = y
	
	EndMethod


	Method Look(cam:TEntity, x:Int, y:Int, quickness:Float = 3.0)
	
		MXS :+ (XSpeed() / quickness)
		MYS :+ (YSpeed() / quickness)

		If cam Then RotateEntity cam, MYS, -MXS, 0.0

		MovePointer x, y
		
		XSpeed()
		YSpeed()
	
	EndMethod 
	
	
	Method Update()

		MX = MouseX()
		MY = MouseY()
		
		If Pointer Then DrawImage Pointer, MX, MY
	
	EndMethod
		

	Method XSpeed:Int()
	
		Local mxs:Int = MX - OldMX
		
		OldMX = MX
		
		Return mxs
		
	EndMethod
	
	
	Method YSpeed:Int()
	
		Local mys:Int = MY - OldMY
		
		OldMY = MY
		
		Return mys
		
	EndMethod


EndType



Your code was a bit.. jumpy.. for me, but this code works wonderfully:
Type T_MouseLook
	Field resetX%
	Field resetY%
	Field speedX%  'not needed externally but may be useful for other things
	Field speedY%  
        Field pitch:Float  'smoother inverse value for rotation
        Field yaw:Float

	Method Init(rX% , rY%)
		resetX = rx
		resetY = ry
	End Method
	
	Method Pollmouse()
		speedX = resetX - MouseX()
		speedY = resetY - MouseY()
              	yaw :- Float(-speedX) / 15
         	pitch :+ Float(-speedY) / 15
		MoveMouse(resetX,resetY)	
	End Method
	
	Method flush()
		speedX = 0
		speedY = 0
		MoveMouse(resetX,resetY)
	End Method	
End Type

'Initialise mouselook
Local mlook:T_MouseLook=New t_mouselook
mlook.init(512,350) ' or width/height*.5 etc
mlook.flush() 'kills any initial movements

While Not KeyDown(KEY_ESCAPE)		

	'Poll mouse And adjust rotation values.
	mlook.pollmouse()
	RotateEntity cam, mlook.pitch, mlook.yaw, 0
     '   (......rest of main loop)
Wend




Can't remeber where I found it XD I thought I copied your code but apparently this remained on the clipboard. Thanks all for the help.

I have unfortunately learned that making mouse move code that works well on a lot of different computers is tough in OpenGL. The results with the various drivers are pretty inconsistent. At least, that has been my experience. :(

I have unfortunately learned that making mouse move code that works well on a lot of different computers is tough in OpenGL.


I have also noticed this. I've yet to find an acceptable solution in Mac OS 10.5. It is annoying the hell out of me...

Here's a partial framework that functions reasonably well on MacOS 10.5, but still isn't entirely smooth:

EDIT: Removed code. Works crap on Windows... Back to the drawing board...