Mouse movement woes

BlitzMax Forums/BlitzMax Beginners Area/Mouse movement woes

Zolyx(Posted 2006) [#1]
I'm trying to create a system of moving the player by mouse, although not in the standard way. I am aiming for a method that is similar to the one used in games like XQuest (PC) and Crystal Quest (Mac) whereby you essentially control the player's inertia within a frictionless environment. Moving the mouse right would begin sliding the player in that direction until you moved left to come to a stop.

The basic code I have for this at the moment looks like this...
SuperStrict

Framework BRL.GLMax2D
Import BRL.FileSystem
Import BRL.FreeTypeFont
Import BRL.PNGLoader
Import BRL.Retro

'Create graphics interface
SetGraphicsDriver GLMax2DDriver()
Graphics 800, 600
SetBlend ALPHABLEND
SeedRnd MilliSecs()

'Types
Global MEngine:XQ_MouseEngine   'Engine to control mouse movement of the player
Global Player:XQ_Player         'The player ship

'Lists
Global lstEntities:TList = New TList

'Types
Type XQ_MouseEngine
' ----------------------------------------------------------------------------------
' DESCRIPTION - Centralises all of the mouse-related functions into one engine.
' ----------------------------------------------------------------------------------

	Field M1:Short, M2:Short        'Counter for mouse button actions
	Field tmx:Short, tmy:Short      'Mouse position on this tick
	Field pmx:Short, pmy:Short      'Mouse position on previous tick
	Field offx:Float, offy:Float    'Offset of last tick
	Field focx:Float, focy:Float    'Current X and Y movement focus
	Field sensitivity:Float         'How sensitive is movement?


	Method Destroy()
		Destroy()
	End Method

	Method Update()
	' -----------------------------------------------------------------------------
	' DESCRIPTION - Every game tick, this function is called to compare the mouse's
	'               current position with it's last position. The values are used
	'               to manipulate the direction focus of the player. Also handles
	'               mouse click counters.
	' -----------------------------------------------------------------------------
		pmx = tmx
		pmy = tmy
	
		tmx = MouseX()
		tmy = MouseY()
		
		offx = (tmx - pmx) * sensitivity
		offy = (tmy - pmy) * sensitivity
		
		If MouseDown(1) Then M1 :+ 1 Else M1 = 0
		If MouseDown(2) Then M2 :+ 1 Else M2 = 0
	End Method
	
	
	Function Create:XQ_MouseEngine(sense:Float = 0.1)
		Local me:XQ_MouseEngine = New XQ_MouseEngine
		me.sensitivity = sense
		Return me
	End Function

End Type


Type XQ_Entity
' ----------------------------------------------------------------------------------
' DESCRIPTION - All entities in the game - such as the player, the enemies and any
'               and any bullets - as well some that don't move are created from this
'               base type.
' ----------------------------------------------------------------------------------

	Field x:Float       'X position
	Field y:Float       'Y position
	Field velx:Float    'X velocity
	Field vely:Float    'Y velocity
	Field ang!          'Angle
	Field speed!        'Directional speed



	Method New()
		lstEntities.AddLast Self
	End Method

	Method Destroy()
		lstEntities.Remove Self
	End Method

	Method Update()
		UpdatePositions()
		CheckCollisions()
	End Method

	Method UpdatePositions()
		x :+ velx
		y :+ vely
	End Method

	Method UpdateVelocities(ang!, speed!)
	    	velx = Sin(ang) * speed
     	vely = Cos(ang) * speed
	End Method

	Method CheckCollisions()
		If x < 0 Or x > (GraphicsWidth() - 16) Then
			ang = 360 - ang
			If ang < 0 Then ang :+ 360
			UpdateVelocities(ang, speed)
		EndIf

		If y < 0 Or y > (GraphicsHeight() - 16) Then
			ang = 180 - ang
			If ang < 0 Then ang :+ 360
			UpdateVelocities(ang, speed)
		EndIf
	End Method
	
	Method Draw()
		DrawOval x-10, y-10, 20, 20
	End Method



	Function UpdateAll()
		For Local e:XQ_Entity = EachIn lstEntities
			e.Update()
			e.Draw()
		Next
     End Function

	Function DestroyAll()
		For Local e:XQ_Entity = EachIn lstEntities
			e.Destroy()
		Next
	End Function

End Type


Type XQ_Player Extends XQ_Entity
' ----------------------------------------------------------------------------------
' DESCRIPTION - The player entity.
' ----------------------------------------------------------------------------------

	Function Create:XQ_Player(xpos:Short, ypos:Short)
		Local te:XQ_Player = New XQ_Player

		te.x = xpos
		te.y = ypos
		te.ang   = 0
		te.speed = 0

		te.UpdateVelocities(te.ang, te.speed)

		Return te
	End Function

End Type










MEngine = XQ_MouseEngine.Create()
Player = XQ_Player.Create(400, 300)

'Main program loop
Repeat
	Cls
	MEngine.Update()
		
	DrawText "Entity count: " + lstEntities.Count(), 200, 10
	DrawText "Offset X:     " + MEngine.offx, 200, 25
	DrawText "Offset Y:     " + MEngine.offy, 200, 40

	Player.velx :+ MEngine.offx
	Player.vely :+ MEngine.offy
	
	XQ_Entity.UpdateAll()
	'MoveMouse 400, 300
	
	Flip
Until KeyDown(KEY_ESCAPE)



XQ_Entity.DestroyAll()
End


That code sort of works, but you have to move the mouse up-left a bit at the start to see the oval you're moving about. Also, because the mouse itself is unconstrained, when it hits the edge of the window, player control is lost, so there needs to be some way of resetting the mouse position cleanly without affecting the updates. If you uncomment the MoveMouse line within the main loop to do this, weirdness starts happening, and maybe I've just been looking at it too long today to see why... :(

Any advice gratefully received.


TomToad(Posted 2006) [#2]
Are you trying to do something like this?



Zolyx(Posted 2006) [#3]
Yes... that's exactly it :) Thanks very much!