Letterbox code + Alien Space Beetles Test

BlitzMax Forums/BlitzMax Programming/Letterbox code + Alien Space Beetles Test

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

As for:

How are you handling getting MouseX() and MouseY() that correspond to your virtual width and height?


I'm not. I didn't even consider whether there would be issues with MouseX() and MouseY(). My code just worked when I plugged this in, because I simply subtract the last mouse position from the current position to get the mouse speed, and then use the mouse speed to adjust the velocity of my ship in each direction. (The ship's controlled with physics, not directly by the mouse, so it has a little bit of inertia. It would feel like a mouse pointer otherwise.)

Which does answer something I'd been wondering about... Whether the mouse moved faster on higher resolution screens so that the distance it moved on the screen was constant regardless of the resolution. Apparently it does not, and instead moves at a constant rate in pixels... controlled only by the mouse cursor speed slider in windows. So identical mouse cursor speeds would move the mouse a shorter distance on the screen on identically sized screens with one being set to a higher resolution than the other. For me, that works out great, but for some kinds of games, I guess that could be an issue, but I can't think of which sorts.

Anyway... You're probably wondering how I'd fix the problem of moving the mouse about on the screen if I wanted a mouse pointer.

This is how I handle the mouse in my code:

' -----------------------------------------------------------------------------------------------------------------------------------------------------------
' These functions override the standard mouse visibility functions so that we can keep track of the mouse visible state.
'
' For ShowMouse:
'
' If Force% is False, then the mouse will not be shown if the current state indicates it is visible.  This is to avoid mouse flicker which is caused by
' showing the mouse over and over.
'
' If Force% is True, the mouse is shown regardless of what state MouseVisible indicates it is in.  This is used during fullscreen/window mode switches where
' the mouse is hidden by the system automatically.
' -----------------------------------------------------------------------------------------------------------------------------------------------------------

	Global MouseDown_Left%, MouseDown_Right%, MouseDown_Middle%
	Global MouseHit_Left%, MouseHit_Right%, MouseHit_Middle%
	Global Mouse_X#, Mouse_Y#
	Global Old_Mouse_X# = MouseX()
	Global Old_Mouse_Y# = MouseY()
	Global Mouse_Speed_X#, Mouse_Speed_Y#
	Global MouseVisible% = True
	Global Mouse_ForceRecenter% 


	Function ShowMouse(Force%=False)
		If (MouseVisible = False) Or (Force = True)
			MouseVisible = True
			Brl.System.ShowMouse()
		EndIf
	End Function

	
	Function HideMouse()
		MouseVisible = False
		Brl.System.HideMouse()	
	End Function
	
	
	Function AutoRecenterMouse(Recenter%=False) 
		
		Mouse_ForceRecenter = Recenter
		
		Select Recenter
		
			Case True  
				HideMouse()
				MoveMouse App.Width/2, App.Height/2
				
			Case False 
				ShowMouse()
			
		End Select
		
	End Function
	
	
' -----------------------------------------------------------------------------------------------------------------------------------------------------------
' This function gets the mouse input for this frame.
' -----------------------------------------------------------------------------------------------------------------------------------------------------------

	Function UpdateMouse()								
		
		Const SAFEZONE_RADIUS# = 100		
				
		Mouse_X# = MouseX()
		Mouse_Y# = MouseY()
			
		Mouse_Speed_X# = Mouse_X# - Old_Mouse_X#
		Mouse_Speed_Y# = Mouse_Y# - Old_Mouse_Y#

		MouseDown_Left   = MouseDown(1)
		MouseDown_Right  = MouseDown(2)
		MouseDown_Middle = MouseDown(3)	
				
		MouseHit_Left    = MouseHit(1)
		MouseHit_Right   = MouseHit(2)
		MouseHit_Middle  = MouseHit(3)
		
		' Recenter mouse if desired.
		' Recentering the mouse allows Mouse_Speed to work consistently.

			If Mouse_ForceRecenter 
				
				If (Abs(App.Width/2 - Mouse_X#) > SAFEZONE_RADIUS#) Or (Abs(App.Height/2 - Mouse_Y#) > SAFEZONE_RADIUS#)
			
					MoveMouse App.Width/2, App.Height/2
				
					Old_Mouse_X# = App.Width/2  - Mouse_Speed_X#
					Old_Mouse_Y# = App.Height/2 - Mouse_Speed_Y#
					
				Else
				
					Old_Mouse_X# = Mouse_X#
					Old_Mouse_Y# = Mouse_Y#
									
				EndIf			
				
			EndIf
	
	End Function


' -----------------------------------------------------------------------------------------------------------------------------------------------------------
' This function checks for events in the event queue and acts upon them.
' -----------------------------------------------------------------------------------------------------------------------------------------------------------

	Function EventHandler()

		MouseHit_Left   = False
		MouseHit_Right  = False
		MouseHit_Middle = False

		While PollEvent() <> 0
		
			'DebugLog("EventID: " + EventID())
			'If Scoreboard.TEXT_AngerMeter <> Null 
			'	If EventID() <= 258 Then Scoreboard.TEXT_AngerMeter.Set(EventID()) 
			'EndIf
			
			Select EventID()
					
				Case EVENT_APPSUSPEND 		' Application suspended. Triggered when window is minimized.
					
					' Pause music.
						If Sound.MusicChannel <> Null Then Sound.MusicChannel.SetPaused(True)
				
				
				Case EVENT_APPRESUME  		' Application resumed.
				
					' Resume music.
						If Sound.MusicChannel <> Null Then Sound.MusicChannel.SetPaused(False)
				
				 
				Case EVENT_APPTERMINATE 	' Application wants to terminate. 
				Case EVENT_KEYDOWN 			' Key pressed. Event data contains keycode. 
				Case EVENT_KEYUP 			' Key released. Event data contains keycode. 
				Case EVENT_KEYCHAR 			' Key character. Event data contains unicode value. 
				
				Case EVENT_MOUSEDOWN 		' Mouse button pressed. Event data contains mouse button code.
				
					Select EventData()
					
						Case 1 
							MouseDown_Left   = True
							MouseHit_Left    = True
							
						Case 2 
							MouseDown_Right  = True
							MouseHit_Right   = True
							
						Case 3 
							MouseDown_Middle = True
							MouseHit_Right   = True
							
					End Select
					
					
				Case EVENT_MOUSEUP 			' Mouse button released. Event data contains mouse button code. 
				
					Select EventData()
						Case 1 	MouseDown_Left   = False
						Case 2 	MouseDown_Right  = False
						Case 3 	MouseDown_Middle = False
					End Select
				
				
				Case EVENT_MOUSEMOVE 		' Mouse moved. Event x and y contain mouse coordinates.
				
					Mouse_X = EventX()
					Mouse_Y = EventY()
				
						 
				Case EVENT_MOUSEWHEEL 		' Mouse wheel spun. Event data contains delta clicks. 
				Case EVENT_MOUSEENTER 		' Mouse entered gadget area. 
				Case EVENT_MOUSELEAVE 		' Mouse left gadget area. 
				Case EVENT_TIMERTICK 		' Timer ticked. Event source contains timer object. 
				Case EVENT_HOTKEYHIT 		' Hot key hit. Event data and mods contains hotkey keycode and modifier.
				Case EVENT_MENUACTION 		' Menu has been selected. 
				Case EVENT_WINDOWMOVE 		' Window has been moved. 
				Case EVENT_WINDOWSIZE 		' Window has been resized.
				 
				Case EVENT_WINDOWCLOSE 		' Window close icon clicked. 
					End
					
				Case EVENT_WINDOWACTIVATE	' Window activated. 
				Case EVENT_WINDOWACCEPT 	' Drag and drop operation was attempted. 
				Case EVENT_GADGETACTION 	' Gadget state has been updated. 
				Case EVENT_GADGETPAINT 		' A canvas gadget needs to be redrawn. 
				Case EVENT_GADGETSELECT		' A treeview node has been selected. 
				Case EVENT_GADGETMENU 		' User has right clicked a treeview node or textarea gadget. 
				Case EVENT_GADGETOPEN 		' A treeview node has been expanded. 
				Case EVENT_GADGETCLOSE 		' A treeview node has been collapsed. 
				Case EVENT_GADGETDONE 		' An HTMLview has completed loading a page. 

			End Select

		Wend

	End Function



As you can see the Mouse_X and Mouse_Y variables I grab are just the raw coordinates. But to solve this issue, what you could do is change where the Mouse_X and Y are being stored, and then use the mouse speed calculated each frame to output a virtualizedMouse_X and Mouse_Y. In other words, change all the Mouse_X and Mouse_Y references in that code to New_Mouse_X, New_Mouse_Y and then add Mouse_Speed_X to Mouse_X each frame to calculate that instead of returning the true coordinate, making sure to truncate Mouse_X if it goes below 0 or above the virtual graphics width.

Not a particularly pretty solution, but if just scaling MouseX() and MouseY() doesn't give you the results you were looking for, then this will. The only issue might be that the user's mouse might move faster than they're used to if your virtual coordinates are less than the real resolution, because now you move the mouse 5 pixels in virtual space, and it moves 10 pixels on the screen, whereas before the mouse was 1:1 with the onscreen pixels.

So, if the user has 1600x1200 res, and the game has 800x600 virtual res, then moving the mouse 0.5 pixels in virtual space for every 1 pixel it actually moves would be a good thing if you want to keep the mouse speed consistent with what the user expects. And to do this you just scale the mouse coordinates. But if you want the mouse to move pixel perfect on an 800x600 virtual screen, then make those modifcations to my code I suggested, but keep in mind the mouse will move at half the speed the user expects.

I reccomend just scaling the position personally, and drawing stuff at floating point coordinates.