瀏覽代碼

SDL.VirtualJoystick. Initial Import.

woollybah 10 年之前
父節點
當前提交
298183c726

+ 74 - 0
virtualjoystick.mod/examples/example_01.bmx

@@ -0,0 +1,74 @@
+SuperStrict
+
+Framework sdl.gl2sdlmax2d
+
+Import sdl.virtualjoystick
+
+
+Local joy:TRenderedJoystick = TRenderedJoystick(New TRenderedJoystick.Create("VJ", 100, 100, 50, 20))
+joy.AddButton(200, 80, 30)
+
+
+Graphics 800, 600, 0
+
+SetBlend alphablend
+
+SetClsColor 255, 255, 255
+SetColor 0, 0, 0
+
+While Not KeyDown(key_escape)
+
+	Cls
+	
+	' draw joystick
+	joy.Render()
+	
+	' get some stats
+	SetColor 0, 0, 0
+	
+	Local x:Float = JoyX()
+	DrawText "JoyX : " + x, 100, 300
+	DrawLine 150, 330, 150, 360, False
+	DrawRect 150, 330, x * 50, 30
+	
+	Local y:Float = JoyY()
+	DrawText "JoyY : " + y, 300, 300
+	DrawLine 260, 310, 290, 310, False
+	DrawRect 260, 310, 30, y * 50
+	
+	If JoyDown(0) Then
+		DrawText "Button 0 : DOWN", 100, 380
+	Else
+		DrawText "Button 0 : UP", 100, 380
+	End If
+	
+	Flip
+
+Wend
+
+
+Type TRenderedJoystick Extends TVirtualJoystick
+
+	Method Render()
+		If touchId <> -1 Then
+			SetColor 200, 200, 100
+		Else
+			SetColor 100, 200, 100
+		End If
+		DrawOval centerX - radius, centerY - radius, radius * 2, radius * 2
+		
+		SetColor 100, 100, 200
+		DrawOval xPos - knobRadius, yPos - knobRadius, knobRadius * 2, knobRadius * 2
+		
+		For Local i:Int = 0 Until buttons.length
+			Local button:TVirtualButton = buttons[i]
+			If JoyDown(i) Then
+				SetColor 255, 100, 100
+			Else
+				SetColor 100, 100, 100 + i * 50
+			End If
+			DrawOval button.centerX - button.radius, button.centerY - button.radius, button.radius * 2, button.radius * 2 
+		Next
+	End Method
+
+End Type

+ 33 - 0
virtualjoystick.mod/examples/post.bmk

@@ -0,0 +1,33 @@
+# post build script
+#
+#
+
+@define copyDLL
+	if bmk.Platform() == "macos" then
+
+		framework = "SDL2.framework"
+
+		# frameworks folder exists?
+		folder = %exepath% .. "/../Frameworks"
+
+		if sys.FileType(folder) == 0 then
+			sys.CreateDir(folder)
+		end
+	
+		# framework exists?
+		if sys.FileType(folder .. "/" .. framework) == 0 then
+
+			# assumes Sparkle.framework.zip is in the module folder.
+			zip = utils.ModulePath("sdl.sdl") .. "/lib/macos/" .. framework .. ".zip"
+		
+			os.execute("unzip -qq " .. zip .. " -d " .. folder)
+	
+		end
+
+	end	
+
+@end
+
+
+#copy the shared objects
+copyDLL

+ 409 - 0
virtualjoystick.mod/virtualjoystick.bmx

@@ -0,0 +1,409 @@
+' Copyright (c) 2015 Bruce A Henderson
+'
+' This software is provided 'as-is', without any express or implied
+' warranty. In no event will the authors be held liable for any damages
+' arising from the use of this software.
+'
+' Permission is granted to anyone to use this software for any purpose,
+' including commercial applications, and to alter it and redistribute it
+' freely, subject to the following restrictions:
+'
+'    1. The origin of this software must not be misrepresented; you must not
+'    claim that you wrote the original software. If you use this software
+'    in a product, an acknowledgment in the product documentation would be
+'    appreciated but is not required.
+'
+'    2. Altered source versions must be plainly marked as such, and must not be
+'    misrepresented as being the original software.
+'
+'    3. This notice may not be removed or altered from any source
+'    distribution.
+'
+SuperStrict
+
+Rem
+bbdoc: Virtual Joystick
+End Rem
+Module SDL.VirtualJoystick
+
+Framework SDL.SDL
+Import BRL.Event
+Import Pub.Joystick
+Import BRL.Math
+
+Private
+Global _driver:TVirtualJoystickDriver
+Public
+
+Type TVirtualJoystickDriver Extends TJoystickDriver
+
+	Field joysticks:TVirtualJoystick[0]
+	Field currentPort:Int = -1
+	Field currentJoystick:TVirtualJoystick
+
+	Method AddJoystick(joystick:TVirtualJoystick)
+		Local port:Int = joysticks.length
+		joysticks = joysticks[..port + 1]
+		joysticks[port] = joystick
+	End Method
+
+	Method GetName:String()
+		Return "Virtual Joystick"
+	End Method
+
+	Method JoyCount:Int()
+		Return joysticks.length
+	End Method
+	
+	Method JoyName:String(port:Int)
+		SampleJoy port
+		If currentJoystick Then
+			Return currentJoystick.name
+		End If
+	End Method
+	
+	Method JoyButtonCaps:Int(port:Int)
+		SampleJoy port
+		If currentJoystick Then
+			Return currentJoystick.buttoncaps
+		End If
+	End Method
+	
+	Method JoyAxisCaps:Int(port:Int)
+		SampleJoy port
+		If currentJoystick Then
+			Return currentJoystick.flags
+		End If
+	End Method
+	
+	Method JoyDown:Int( button:Int, port:Int=0 )
+		SampleJoy port
+		If currentJoystick Then
+			Return currentJoystick.ButtonDown(button)
+		End If
+	End Method
+	
+	Method JoyHit:Int( button:Int, port:Int=0 )
+		SampleJoy port
+		If currentJoystick Then
+			Return currentJoystick.ButtonHit(button)
+		End If
+	End Method
+	
+	Method JoyX#( port:Int=0 )
+		SampleJoy port
+		If currentJoystick Then
+			Return currentJoystick.GetX()
+		End If
+	End Method
+	
+	Method JoyY#( port:Int=0 )
+		SampleJoy port
+		If currentJoystick Then
+			Return currentJoystick.GetY()
+		End If
+	End Method
+	
+	Method JoyZ#( port:Int=0 )
+		Return 0
+	End Method
+	
+	Method JoyR#( port:Int=0 )
+		Return 0
+	End Method
+	
+	Method JoyU#( port:Int=0 )
+		Return 0
+	End Method
+	
+	Method JoyV#( port:Int=0 )
+		Return 0
+	End Method
+	
+	Method JoyYaw#( port:Int=0 )
+		Return 0
+	End Method
+	
+	Method JoyPitch#( port:Int=0 )
+		Return 0
+	End Method
+	
+	Method JoyRoll#( port:Int=0 )
+		Return 0
+	End Method
+	
+	Method JoyHat#( port:Int=0 )
+		Return 0
+	End Method
+	
+	Method JoyWheel#( port:Int=0 )
+		Return 0
+	End Method
+	
+	Method JoyType:Int( port:Int=0 )
+	End Method
+	
+	Method JoyXDir:Int( port:Int=0 )
+		Local t#=JoyX( port )
+		If t<.333333 Return -1
+		If t>.333333 Return 1
+		Return 0
+	End Method
+
+	Method JoyYDir:Int( port:Int=0 )
+		Local t#=JoyY( port )
+		If t<.333333 Return -1
+		If t>.333333 Return 1
+		Return 0
+	End Method
+
+	Method JoyZDir:Int( port:Int=0 )
+		Return 0
+	End Method
+	
+	Method JoyUDir:Int( port:Int=0 )
+		Return 0
+	End Method
+	
+	Method JoyVDir:Int( port:Int=0 )
+		Return 0
+	End Method
+	
+	Method FlushJoy( port_mask:Int=~0 )
+	End Method
+
+	Method SampleJoy(port:Int)
+		If currentPort = port Then
+			Return
+		End If
+		
+		If port >= joysticks.length Then
+			Return
+		End If
+		
+		currentJoystick = joysticks[port]
+		currentPort = port
+	End Method
+
+End Type
+
+Rem
+bbdoc: A virtual touch joystick.
+about: Can be extended to implement your own rendering of it.
+End Rem
+Type TVirtualJoystick
+
+	Field name:String
+	
+	' stick location
+	Field centerX:Int
+	Field centerY:Int
+	Field radius:Int
+	
+	Field radiusSqr:Int
+
+	' current knob location (based on user input) and radius
+	Field xPos:Int
+	Field yPos:Int
+	Field knobRadius:Int
+	Field touchId:Int = - 1
+	
+	Field buttons:TVirtualButton[0]
+	Field buttoncaps:Int
+	
+	' active axis flags - combination of VS_AXIS_X and VS_AXIS_Y
+	Field flags:Int
+	
+	Method New()
+		_driver.AddJoystick(Self)
+	End Method
+	
+	Rem
+	bbdoc: 
+	End Rem
+	Method Create:TVirtualJoystick(name:String, x:Int, y:Int, stickRadius:Int, knobRadius:Int, flags:Int = VS_AXIS_XY)
+		Self.name = name
+		Self.centerX = x
+		Self.centerY = y
+		Self.radius = stickRadius
+		Self.knobRadius = knobRadius
+		Self.flags = flags
+		
+		xPos = x
+		yPos = y
+		
+		radiusSqr = stickRadius * stickRadius
+		
+		AddHook EmitEventHook, Hook, Self, 0
+		Return Self
+	End Method
+	
+	Rem
+	bbdoc: Adds a button at the specified location.
+	End Rem
+	Method AddButton:Int(x:Int, y:Int, radius:Int)
+		Local id:Int = buttons.length
+		buttons = buttons[..id + 1]
+		buttons[id] = New TVirtualButton.Create(x, y, radius)
+		Return id
+	End Method
+
+	Function Hook:Object(id:Int, data:Object, context:Object )
+	
+		Local joystick:TVirtualJoystick = TVirtualJoystick(context)
+		If Not joystick Return data
+	
+		Local ev:TEvent = TEvent(data)
+		If Not ev Return data
+		
+		joystick.OnEvent(ev)
+		
+		Return data
+	End Function
+	
+	Method OnEvent(event:TEvent)
+		Select event.id
+			Case EVENT_TOUCHDOWN
+				' only test stick if we aren't already tracking
+				If touchId = -1 Then
+					Local dist:Int = (centerX - event.x) * (centerX - event.x) + (centerY - event.y) * (centerY - event.y)
+					If dist < radiusSqr Then
+						touchId = event.data
+						xPos = event.x
+						yPos = event.y
+						Return
+					End If
+				End If
+				
+				' test buttons
+				For Local i:Int = 0 Until buttons.length
+					Local button:TVirtualButton = buttons[i]
+					
+					' only test button if we aren't already tracking
+					If button.touchId = -1 Then
+						Local dist:Int = (button.centerX - event.x) * (button.centerX - event.x) + (button.centerY - event.y) * (button.centerY - event.y)
+						If dist < button.radiusSqr Then
+							button.OnDown(event.data)
+							Return
+						End If
+					End If
+					
+				Next
+
+			Case EVENT_TOUCHUP
+				' match tracked touch?
+				If touchId = event.data Then
+					touchId = -1
+					xpos = centerX
+					yPos = centerY
+					Return
+				End If
+			
+				' test buttons
+				For Local i:Int = 0 Until buttons.length
+					Local button:TVirtualButton = buttons[i]
+					
+					' match tracked touch?
+					If button.touchId = event.data Then
+						button.OnUp()
+						Return
+					End If
+					
+				Next
+
+			Case EVENT_TOUCHMOVE
+				' match tracked touch?
+				If touchId = event.data Then
+					Local dist:Int = (centerX - event.x) * (centerX - event.x) + (centerY - event.y) * (centerY - event.y)
+					If dist < radiusSqr Then
+						xPos = event.x
+						yPos = event.y
+					Else
+						Local angle:Float = ATan2(event.y - centerY, event.x - centerX)
+						xPos = centerX + radius * Cos(angle)
+						yPos = centerY + radius * Sin(angle)
+					End If
+				End If
+
+		End Select
+	End Method
+	
+	Method GetX:Float()
+		If flags & VS_AXIS_X Then
+			Return Float(xPos - centerX) / radius
+		End If
+	End Method
+	
+	Method GetY:Float()
+		If flags & VS_AXIS_Y Then
+			Return Float(yPos - centerY) / radius
+		End If
+	End Method
+	
+	Method ButtonDown:Int(button:Int)
+		If button < buttons.length Then
+			Return buttons[button].down
+		End If
+	End Method
+	
+	Method ButtonHit:Int(button:Int)
+		If button < buttons.length Then
+			Return buttons[button].Hit()
+		End If
+	End Method
+	
+	Method Free()
+		RemoveHook EmitEventHook, Hook, Self
+	End Method
+	
+End Type
+
+Type TVirtualButton
+
+	Field centerX:Int
+	Field centerY:Int
+	Field radius:Int
+	
+	Field radiusSqr:Int
+	
+	Field touchId:Int = -1
+	Field down:Int
+	Field hits:Int
+
+	Method Create:TVirtualButton(x:Int, y:Int, radius:Int)
+		centerX = x
+		centerY = y
+		Self.radius = radius
+		radiusSqr = radius * radius
+		Return Self
+	End Method
+	
+	Method OnDown(id:Int)
+		touchId = id
+		down = True
+	End Method
+	
+	Method OnUp()
+		touchId = -1
+		down = False
+		hits :+ 1
+	End Method
+	
+	Method Hit:Int()
+		Local _hits:Int = hits
+		hits = 0
+		Return _hits
+	End Method
+	
+End Type
+
+Const VS_AXIS_X:Int = $001
+Const VS_AXIS_Y:Int = $002
+Const VS_AXIS_XY:Int = VS_AXIS_X | VS_AXIS_Y
+
+
+' init driver
+_driver = New TVirtualJoystickDriver
+
+' make ourself the default
+GetJoystickDriver("Virtual Joystick")