Joystick wrapper (for GLFW and XNA)

Monkey Forums/Monkey Code/Joystick wrapper (for GLFW and XNA)

dopeyrulz(Posted 2011) [#1]
DO NOT USE - SUPERSEEDED BY MONKEY v37 OR BETTER

I've created a wrapper so we can have some joystick control in GLFW. This code also wraps the standard Joy controls so this should also work for XNA.

Currently I have a wireless Xbox controller which I cannot test with (anyone who has an Xbox controller and would be kind enough to try), so have used my USB Joypad to create this. There could be some issues with mapping and currently the JoyZ component is unknown.

The only difference between the current monkey module and this one is you will need to call joypad.UpdateJoyState() in the OnUpdate() method to validate the stick - this will be hidden eventually once added into the monkey framework.

Oh - JOY_LEFT, JOY_RIGHT, JOY_UP, JOY_DOWN not yet implemented.

Anyway,

1. In the modules folder, create a folder called 'joypad'

2. In the modules/joypad folder, create a file called 'joypad.monkey' and add the following:
Import "native/joypad.glfw.cpp"
import mojo

Extern Private

#If TARGET="glfw" Then
    Function UpdateJoypadState:Void()="UpdateJoypadState"
    Function JoypadX:Float(index:Int)="JoypadX"
    Function JoypadY:Float(index:Int)="JoypadY"
    Function JoypadZ:Float(index:Int)="JoypadZ"
#EndIf

Public

Function JoyDown( button )
   Return mojo.input.JoyDown( button )
End

Function JoyHit( button )
   Return mojo.input.JoyHit( button )
End

Function UpdateJoyState:Void()
#If TARGET="glfw" Then
   UpdateJoypadState()
#EndIf
End

Function JoyX:Float(index:Int)
#If TARGET="glfw" Then
    Return JoypadX( index )
#Else
    Return mojo.input.JoyX( index )
#EndIf
End

Function JoyY:Float(index:Int)
#If TARGET="glfw" Then
    Return JoypadY( index )
#Else
    Return mojo.input.JoyY( index )
#EndIf
End

Function JoyZ:Float(index:Int)
#If TARGET="glfw" Then
    Return JoypadZ( index )
#Else
    Return mojo.input.JoyZ( index )
#EndIf
End


3. In the modules/joypad folder, create a folder called 'native'

4. In the modules/joypad/native folder, create a file called 'joypad.glfw.cpp' and add the following:
#define JOY_MAX_AXES	10
#define JOY_MAX_BUTTONS	30

void UpdateJoypadState();
void OnKeyJoypad( int key, int action );
float JoypadX( int index );
float JoypadY( int index );
float JoypadZ( int index );

struct JoypadState{
	bool present;
	int num_axes;
	int num_buttons;
	float axes[ JOY_MAX_AXES ];
	unsigned char buttons[ JOY_MAX_BUTTONS ];
};

struct JoypadState states[ GLFW_JOYSTICK_1 + 1 ];

void UpdateJoypadState(){
	//Read one joystick only (but more can be read - see the GLFW samples)
	states[GLFW_JOYSTICK_1].num_axes = glfwGetJoystickPos( GLFW_JOYSTICK_1,states[GLFW_JOYSTICK_1].axes,JOY_MAX_AXES );
	states[GLFW_JOYSTICK_1].num_buttons = glfwGetJoystickButtons ( GLFW_JOYSTICK_1,states[GLFW_JOYSTICK_1].buttons,JOY_MAX_BUTTONS );

	//Process buttons into key changes
	OnKeyJoypad( 0x100,states[GLFW_JOYSTICK_1].buttons[2] );  //A
	OnKeyJoypad( 0x101,states[GLFW_JOYSTICK_1].buttons[1] );  //B
	OnKeyJoypad( 0x102,states[GLFW_JOYSTICK_1].buttons[3] );  //X
	OnKeyJoypad( 0x103,states[GLFW_JOYSTICK_1].buttons[0] );  //Y
	OnKeyJoypad( 0x104,states[GLFW_JOYSTICK_1].buttons[6] );  //LB
	OnKeyJoypad( 0x105,states[GLFW_JOYSTICK_1].buttons[7] );  //RB
	OnKeyJoypad( 0x106,states[GLFW_JOYSTICK_1].buttons[8] );  //Back
	OnKeyJoypad( 0x107,states[GLFW_JOYSTICK_1].buttons[9] );  //Start
}

void OnKeyJoypad ( int key, int action ){
	switch ( action ){
		case GLFW_PRESS:
			app->input->OnKeyDown( key );

			if ( int chr=KeyToChar( key ) ){
				app->input->PutChar( chr );
			}
			break;
		case GLFW_RELEASE:
			app->input->OnKeyUp( key );
			break;
	}

}

float JoypadX( int index ){
	switch ( index ){
	case 0:
		return states[GLFW_JOYSTICK_1].axes[0];
	case 1:
		return states[GLFW_JOYSTICK_1].axes[2];
	}
	return 0;
}

float JoypadY( int index ){
	switch ( index ){
	case 0:
		return states[GLFW_JOYSTICK_1].axes[1];
	case 1:
		return states[GLFW_JOYSTICK_1].axes[3];
	}
	return 0;
}

float JoypadZ( int index ){
	//switch ( index ){
	//case 0:
	//	return states[GLFW_JOYSTICK_1].axes[4];
	//case 1:
	//	return states[GLFW_JOYSTICK_1].axes[5];
	//}
	return 0;
}


Here is an example of it's use:
Import mojo
Import joypad

Class TestApp Extends App	
	Method OnCreate()
		SetUpdateRate 60

	End Method
	
	Method OnUpdate()
		joypad.UpdateJoyState()
		
	End Method
	
	Method OnRender()
		'Clear screen
		Cls(0, 0, 0)
	    
		'Buttons
		For Local i:Int = 0 to 9
			SetColor(255, 255, 255)
			If (joypad.JoyDown(i)) Then SetColor(255, 0, 0)
			DrawOval(i * 16, 80, 14, 14)
		Next
		
		'Sticks
		SetColor(255,255,0)
		DrawProp("JoyXL:",joypad.JoyX(0), 100)
		DrawProp("JoyYL:",joypad.JoyY(0), 120)
		DrawProp("JoyZL:",joypad.JoyZ(0), 140)
		DrawProp("JoyXR:",joypad.JoyX(1), 160)
		DrawProp("JoyYR:",joypad.JoyY(1), 180)
		DrawProp("JoyZR:",joypad.JoyZ(1), 200)		
		
	End Method

	Method DrawProp(name:String, p:Float, y:Int)
		DrawText name, 0, y
		
		Local w:Int = Abs(p) * 256
		If (p < 0) Then
			DrawRect(320 - w, y, w, 16)
		Else
			DrawRect(320, y, w, 16)
		EndIf
		
	End Method
	
End Class

Function Main()
	New TestApp()
	
End Function



xzess(Posted 2011) [#2]
cool, thanks!


dopeyrulz(Posted 2011) [#3]
xzess,

You shouldn't need to use this anymore - Mark has provided this in Monkey now. (except the D-Pad which is currently not implemented in GLFW).


dopeyrulz(Posted 2014) [#4]
DPad functionality (Windows) is now implemented to v77c