Unfortunately, b4j does not have a USB Support lib and that is why it's not possible to use any GamePads with our b4j projects, right?? (nahhhhhh....)
Ok it's not a real gamepad support buts a simple workaround until we have something.
so how does it works?
very simple, i create a project in vb 2010 that can listen to the joysticks msgs and then i just use the "sendkeys" function and walla i can now use my joystick with my b4j project.
vb code:
first, we create a class named "joystick.vb"
then we handle all changes on our joystick with a timer in our main form:
and then in our b4j project we catch all keys pressed and do our actions:
we still need to change the code a little if we want to use our Keyboard and not our Joystick but thats should be very simple to solve via if statement.
have fun, ilan
ps: i just noticed how dusty my laptop is. with the light and the cam angle it look really bad so dont worry i cleaned it
Ok it's not a real gamepad support buts a simple workaround until we have something.
so how does it works?
very simple, i create a project in vb 2010 that can listen to the joysticks msgs and then i just use the "sendkeys" function and walla i can now use my joystick with my b4j project.
vb code:
first, we create a class named "joystick.vb"
B4X:
Imports System.ComponentModel
Imports System.Runtime.InteropServices
Public Class Joystick
Inherits NativeWindow
Private parent As Form
Private Const MM_JOY1MOVE As Integer = &H3A0
' Public Event Move(ByVal joystickPosition As Point)
Public btnValue As String
Public yLevel As Integer
Public xLevel As Integer
'Public Event JoyStats()
<StructLayout(LayoutKind.Explicit)> _
Public Structure JoyPosition
<FieldOffset(0)> _
Public Raw As IntPtr
<FieldOffset(0)> _
Public XPos As UShort
<FieldOffset(2)> _
Public YPos As UShort
End Structure
Private Class NativeMethods
Private Sub New()
End Sub
' This is a "Stub" function - it has no code in its body.
' There is a similarly named function inside a dll that comes with windows called
' winmm.dll.
' The .Net framework will route calls to this function, through to the dll file.
<DllImport("winmm", CallingConvention:=CallingConvention.Winapi, EntryPoint:="joySetCapture", SetLastError:=True)> _
Public Shared Function JoySetCapture(ByVal hwnd As IntPtr, ByVal uJoyID As Integer, ByVal uPeriod As Integer, <MarshalAs(UnmanagedType.Bool)> ByVal changed As Boolean) As Integer
End Function
End Class
Public Sub New(ByVal parent As Form, ByVal joyId As Integer)
AddHandler parent.HandleCreated, AddressOf Me.OnHandleCreated
AddHandler parent.HandleDestroyed, AddressOf Me.OnHandleDestroyed
AssignHandle(parent.Handle)
Me.parent = parent
Dim result As Integer = NativeMethods.JoySetCapture(Me.Handle, joyId, 100, True)
End Sub
Private Sub OnHandleCreated(ByVal sender As Object, ByVal e As EventArgs)
AssignHandle(DirectCast(sender, Form).Handle)
End Sub
Private Sub OnHandleDestroyed(ByVal sender As Object, ByVal e As EventArgs)
ReleaseHandle()
End Sub
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = MM_JOY1MOVE Then
' Joystick co-ords.
' (0,0) (32768,0) (65535, 0)
' (0, 32768) (32768, 32768) (65535, 32768)
' (0, 65535) (32768, 65535) (65535, 65535)
Dim p As JoyPosition
p.Raw = m.LParam
yLevel = mapping(p.YPos, 0, 65535, 0, 10)
xLevel = mapping(p.XPos, 0, 65535, 0, 10)
End If
If btnValue <> m.WParam.ToString Then
btnValue = m.WParam.ToString
End If
MyBase.WndProc(m)
End Sub
Function mapping(var As Double, min_real As Double, max_real As Double, min_scaled As Double, max_scaled As Double) As Double
Return (var * ((max_scaled - min_scaled) / (max_real - min_real))) + min_scaled
End Function
End Class
then we handle all changes on our joystick with a timer in our main form:
B4X:
Public Class Form1
Private WithEvents joystick1 As Joystick
Public storedv As String
Public middleOn As Boolean
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
joystick1 = New Joystick(Me, 0)
End Sub
Private Sub joystick_Stats()
Dim midx, midy As Boolean
midx = False
midy = False
Select Case joystick1.xLevel
Case Is < 5
My.Computer.Keyboard.SendKeys("{LEFT}", False)
middleOn = False
Case Is > 5
My.Computer.Keyboard.SendKeys("{RIGHT}", False)
middleOn = False
Case Else
midx = True
End Select
Select Case joystick1.yLevel
Case Is > 5
My.Computer.Keyboard.SendKeys("{DOWN}", False)
middleOn = False
Case Is < 5
My.Computer.Keyboard.SendKeys("{UP}", False)
middleOn = False
Case Else
midy = True
End Select
If midx = True And midy = True And middleOn = False Then
'do nothing
middleOn = True
My.Computer.Keyboard.SendKeys("{M}", False)
End If
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
joystick_Stats()
'Me.Text = joystick1.btnValue
If joystick1.btnValue <> storedv Then
storedv = joystick1.btnValue
If joystick1.btnValue = "256" Then
My.Computer.Keyboard.SendKeys(" ", False)
End If
End If
End Sub
End Class
and then in our b4j project we catch all keys pressed and do our actions:
B4X:
Sub AppStart (Form1 As Form, Args() As String)
'.....
Dim Obj As Reflector
Obj.Target = MainForm.RootPane
Obj.AddEventHandler("RootPaneKeyEvent", "javafx.scene.input.KeyEvent.ANY")
'.....
End Sub
B4X:
Sub RootPaneKeyEvent_Event(e As Event)
' bit hackish to get the code
Dim KE As Reflector
KE.Target = e
Dim KeyCode As String = KE.RunMethod("getCode")
Dim EventType As String = KE.RunMethod("getEventType")
Log(KeyCode)
Select EventType
Case "KEY_PRESSED"
Select KeyCode
Case "RIGHT"
GoForward = True
Gobackward = False
Case "LEFT"
GoForward = False
Gobackward = True
Case "UP"
KaneUp = True
KaneDown = False
Case "DOWN"
KaneUp = False
KaneDown = True
Case "SPACE"
If shotnow Then
shotnow = False
Dim bullet As jbBody = CircleBody.CreateBody(world,kanebody.Position.x+((vpW*0.05)/Scale),kanebody.Position.y+(kanebody.Angle*cPI),0.3,2,0.8,0.2,0.5,False,"bullet",False,Null)
BulletList.Add(bullet)
Dim impulse As jbVec2
impulse.set(10,kanebody.Angle*cPI*2)
bullet.applyLinearImpulse(impulse,bullet.WorldCenter)
End If
End Select
Case "KEY_RELEASED"
Select KeyCode
Case "M"
GoForward = False
Gobackward = False
KaneUp = False
KaneDown = False
Case "SPACE"
shotnow = True
End Select
End Select
End Sub
we still need to change the code a little if we want to use our Keyboard and not our Joystick but thats should be very simple to solve via if statement.
have fun, ilan
ps: i just noticed how dusty my laptop is. with the light and the cam angle it look really bad so dont worry i cleaned it