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.
|