1. *** New version of B4J is available ***
    B4J v7.8
    Dismiss Notice

Share My Creation Generic GamePad Support (Source Code)

Discussion in 'Share Your Creations' started by wonder, May 6, 2015.

  1. wonder

    wonder Expert Licensed User

    GENERIC GAMEPAD SUPPORT
    Latest update: 19-05-2015

    Many thanks to thedesolatesoul for his help with the getDeviceName function.


    Fellow gamers and game developers, please test this app with your game controllers.
    It works flawlessly with my PS3 one (using the Sixaxis Controller app), but it should work with any other brand recognized by your android device.

    If like me, you're planning to use a PlayStation controller, please follow this tutorial:
    Using a PlayStation 3 controller with your Android Device

    Note: The Sixaxis app with root access is required only for PS3 / PS4 controllers.

    Download the apk or the full project below (please use the updated GamePad.bas class file), the additional library is included.

    Capture.PNG

    APK:
    Usage:
    As you can see in the source code, the analog sticks and triggers are handled by Activity_OnGenericMotionEvent and the regular buttons by Activity_KeyPress. I've tried the best I could to make the code easier to understand, so everything should be self-explanatory.

    Libraries:

    Class (2016-28-12):
    GamePad.bas (attached)

    Documentation:

    Source:
    Code:
    #Region  Project Attributes
        
    #ApplicationLabel: B4A Generic GamePad Support
        
    #VersionCode: 1
        
    #VersionName:
        
    'SupportedOrientations possible values: unspecified, landscape or portrait.
        #SupportedOrientations: unspecified
        
    #CanInstallToExternalStorage: False
    #End Region

    #Region  Activity Attributes
        
    #FullScreen: True
        
    #IncludeTitle: False
        
    #Extends: anywheresoftware.b4a.objects.ActivityEx
    #End Region

    Sub Process_Globals
        
    'Define the Main Cycle timer
            Dim Main_Cycle As Timer
    End Sub

    Sub Globals
        
    'REQUIRED
            Dim Controller As GamePad

        
    'Used solely for this example
            Dim Mode = "NORMAL" As String

        
    'Designer Variables
            Private Background As ImageView
            
    Private Output As Label
    End Sub

    Sub Activity_Create(FirstTime As Boolean)
        
    'Load the Activity Layout
            Activity.LoadLayout("Layout1")

        
    'Setup the Text and Background
            Background.Width = 100%x
            Background.Height = (
    100%x) * 720 / 1280
            Background.Left = 
    50%x - Background.Width / 2
            Background.Top = 
    50%y - Background.Height / 2

            Output.Left   = Background.Left + (
    0.054 * Background.Width)
            Output.Top    = Background.Top  + (
    0.116 * Background.Height)
            Output.Width  = 
    0.289 * Background.Width
            Output.Height = 
    0.625 * Background.Height

        
    'Initialize the first GamePad with a dead zone of 10%
            Controller.Initialize(00.1)

        
    'Initialize the Main Cycle timer
            Main_Cycle.Initialize("Main_Cycle"1000/60)
            Main_Cycle.Enabled = 
    True
    End Sub

    Sub Activity_Resume
    End Sub

    Sub Activity_Pause (UserClosed As Boolean)
    End Sub


    '========================================================================================================================
    ' MAIN CYCLE
    '========================================================================================================================
        Sub Main_Cycle_Tick
            
    If Controller.Plugged_In Then
                
    If Mode = "NORMAL" Then
                    Output.Text = _
                    Controller.Device_Name & 
    CRLF & _
                    
    CRLF & _
                    
    "Analog LX: " & Round(Controller.L_Analog_X * 100) & "%" & CRLF & _
                    
    "Analog LY: " & Round(Controller.L_Analog_Y * 100) & "%" & CRLF & _
                    
    "Analog RX: " & Round(Controller.R_Analog_X * 100) & "%" & CRLF & _
                    
    "Analog RY: " & Round(Controller.R_Analog_Y * 100) & "%" & CRLF & _
                    
    "L Trigger: " & Round(Controller.L_Trigger  * 100) & "%" & CRLF & _
                    
    "R Trigger: " & Round(Controller.R_Trigger  * 100) & "%" & CRLF & _
                    
    CRLF & _
                    
    "Last KeyCode: " & Controller.Btn_Press & CRLF & _
                    
    CRLF & _
                    
    "Press START for Device Info" & CRLF & _
                    
    "or SELECT To exit."
                
    Else If Mode = "DEVICE_INFO" Then
                    
    If Controller.Device_Info = "" Then
                        Output.Text = 
    "Please move one of the Analog Sticks / Triggers."
                    
    Else
                        Output.Text = Controller.Device_Info & 
    CRLF & _
                        
    CRLF & _
                        
    "Press START to begin" & CRLF & _
                        
    "or SELECT To exit."
                    
    End If
                
    End If
            
    Else
                Output.Text = Controller.Device_Name & 
    CRLF & _
                
    CRLF & _
                
    "Please plug you controller via USB" & CRLF & _
                
    "or pair it via Bluetooth to begin." & CRLF & _
                
    CRLF & _
                
    "Once you have it connected," & CRLF & _
                
    "press START to begin."
            
    End If
        
    End Sub
    '========================================================================================================================




    '========================================================================================================================
    ' BUTTON PRESS (KEYCODE) AND ANALOG AXIS / TRIGGER (GENERIC MOTION EVENT) HANDLING
    '========================================================================================================================
        Sub Activity_KeyPress (KeyCode As Int) As Boolean
            Controller.Btn_Press = KeyCode
            
    If KeyCode = Controller.KEYCODE_BUTTON_START Then
                
    If Controller.Plugged_In Then
                    
    If Mode = "NORMAL" Then
                        Mode = 
    "DEVICE_INFO"
                    
    Else
                        Mode = 
    "NORMAL"
                    
    End If
                
    Else
                    Controller.Initialize(
    00.1)
                
    End If
            
    Else If KeyCode = Controller.KEYCODE_BUTTON_SELECT OR KeyCode = KeyCodes.KEYCODE_BACK Then
                
    ExitApplication
            
    End If
            
    Return True
        
    End Sub


        
    Sub Activity_OnGenericMotionEvent(Event As Object)
            Controller.Input = 
    Event

            Controller.Motion_Detected = 
    True

            Controller.L_Analog_X  = Controller.getAxisValue(Controller.AXIS_X)
            Controller.L_Analog_Y  = Controller.getAxisValue(Controller.AXIS_Y)

            Controller.R_Analog_X  = Controller.getAxisValue(Controller.AXIS_Z)
            Controller.R_Analog_Y  = Controller.getAxisValue(Controller.AXIS_RZ)

            Controller.L_Trigger   = Controller.getAxisValue(Controller.AXIS_LTRIGGER)
            Controller.R_Trigger   = Controller.getAxisValue(Controller.AXIS_RTRIGGER)

            
    If Controller.Device_Info = "" Then Controller.Device_Info = Controller.getDeviceInfo
        
    End Sub
    '========================================================================================================================
     

    Attached Files:

    Last edited: Dec 28, 2016
  2. wonder

    wonder Expert Licensed User

    HOW CAN I IMPLEMENT THIS FRAMEWORK ON MY PROJECT?

    I know the ideal solution is to have a lib which handles everything, but since my java/lib experience is virtually zero, the way to implement my solution is a little bit fragmented.

    Step 1:
    Add both Generic Motion Event and JavaObject libraries to your project.
    Step 2:
    Add the GamePad class to your project.
    Step 3:
    Add the following code to your project:
    Code:
    #Region  Activity Attributes
         
    #Extends: anywheresoftware.b4a.objects.ActivityEx
    #End Region

    Sub Globals
       
    Dim Controller As GamePad
    End Sub

    Sub Activity_Create(FirstTime As Boolean)
       Controller.Initialize(
    00.1'Initializes the first GamePad with a dead zone of 10%
    End Sub

    Step 4:
    Handle the events with Activity_OnGenericMotionEvent for analog sticks and triggers and Activity_KeyPress for the controller buttons.

    Example:
    Code:
    Sub Activity_KeyPress (KeyCode As Int) As Boolean      
        Controller.Btn_Press = KeyCode
        
    If KeyCode = Controller.KEYCODE_BUTTON_START Then
            
    If Controller.Plugged_In Then
                
    If Mode = "NORMAL" Then
                    Mode = 
    "DEVICE_INFO"
                
    Else
                    Mode = 
    "NORMAL"
                
    End If
            
    Else
                Controller.Initialize(
    00.1)
            
    End If
        
    Else If KeyCode = Controller.KEYCODE_BUTTON_SELECT OR KeyCode = KeyCodes.KEYCODE_BACK Then
            
    ExitApplication  
        
    End If      
        
    Return True
    End Sub


    Sub Activity_OnGenericMotionEvent(Event As Object)
        Controller.Input = 
    Event
      
        Controller.Motion_Detected = 
    True
      
        Controller.L_Analog_X  = Controller.getAxisValue(Controller.AXIS_X)
        Controller.L_Analog_Y  = Controller.getAxisValue(Controller.AXIS_Y)

        Controller.R_Analog_X  = Controller.getAxisValue(Controller.AXIS_Z)
        Controller.R_Analog_Y  = Controller.getAxisValue(Controller.AXIS_RZ)
      
        Controller.L_Trigger   = Controller.getAxisValue(Controller.AXIS_LTRIGGER)
        Controller.R_Trigger   = Controller.getAxisValue(Controller.AXIS_RTRIGGER)  

        
    If Controller.Device_Info = "" Then Controller.Device_Info = Controller.getDeviceInfo      
    End Sub
    Feel free to improve my code! If so, don't forget to share your own solution. :)
     
    Last edited: May 19, 2015
  3. andymc

    andymc Well-Known Member Licensed User

    This is awesome, brilliant work! I've got a lot on right now, but will try to integrate this with my space invaders clone and work it into a few games that are currently in the early stages right now.
     
    wonder and Peter Simpson like this.
  4. wonder

    wonder Expert Licensed User

    Thank you so much, andymc!! I'm really glad you find this useful! :)
     
    Last edited: May 19, 2015
  5. wonder

    wonder Expert Licensed User

    Hey guys,

    Check the first and second post again.
    I've cleaned-up and updated the source code, class and apk file.
    The internal functions are now tucked in the GamePad.bas class, including thedesolatesoul's getDeviceName (thanks!).

    Please update your projects accordingly.
     
    Last edited: May 19, 2015
    koaunglay likes this.
  6. freedom2000

    freedom2000 Well-Known Member Licensed User

    Hi,

    Thank you sooo much for this brilliant work.

    I will try to use it on my "RC plane controller" App

    My solution was really poor, so with a generic gamepad it should be great !
     
    wonder likes this.
  7. wonder

    wonder Expert Licensed User

    Thank you for appreciating my work! :)
    I'm really glad you find this useful!
     
  8. freedom2000

    freedom2000 Well-Known Member Licensed User

    HI,

    It's quite a long time since you posted this code...
    I promized to try it and I did it this evening :)

    It WORKs --> simply GREAT

    I have slightly changed the code to discover the "hat buttons".
    Here is the mod I did :

    Code:
    Controller.L_Trigger   = Controller.getAxisValue(Controller.AXIS_HAT_X)
            Controller.R_Trigger   = Controller.getAxisValue(Controller.AXIS_HAT_Y)
    I am not sure to have modified the right thing (What are L_Trigger and R_Trigger ?) but at least it works !

    Again thank you

    I will for sure quote your lib in a few days if I take some time to implement a fully working RC radio with android, B4A, your lib and an ESP8266
     
    JordiCP and wonder like this.
  9. wonder

    wonder Expert Licensed User

    Hello hello!

    I'm really glad to hear that it works fine for you! :)
    Every controller is slightly different so it's only normal we always have to tweak the button assignments here and there.
    The original source code was modeled based on a Playstation 3 controller.

    If I had the time, I'd like to turn this project into a simple (and single) library, but as I said, I'm really glad it works this way!
     
  10. freedom2000

    freedom2000 Well-Known Member Licensed User

    I will for sure quote your lib in a few days if I take some time to implement a fully working RC radio with android, B4A, your lib and an ESP8266
    --> Done for my "Joystick to PPM" solution

    --> Still to be done for the full RC controller with ESP8266...
     
    wonder likes this.
  11. wonder

    wonder Expert Licensed User

    Update:
    - Minor update do GamePad.bas.
     
    freedom2000 likes this.
  12. sorex

    sorex Expert Licensed User

    are many people using these gamepads?

    and are some games limited to use one?
     
  13. wonder

    wonder Expert Licensed User

    Probably not, it a niche part of the market. Nonetheless, we are at least 100,000 around the world, jugging by the download number of the Sixaxis Controller paid app (https://play.google.com/store/apps/details?id=com.dancingpixelstudios.sixaxiscontroller&hl=en).

    Can Android handle more than one controller at the same time?
    I've seen apps that support up to 4 controllers at the same time, so it's up to the developer to implement such feature.
    Docs: https://developer.android.com/training/game-controllers/multiple-controllers.html

    Are there any games which explicitly require a physical controller?
    Yes. Most of NVIDIA Lightspeed Studios games.
    - Portal: https://play.google.com/store/apps/details?id=com.nvidia.valvesoftware.portal&hl=en
    - Doom3: https://play.google.com/store/apps/details?id=com.id.doom3bfg&hl=en
    - Parallax: https://play.google.com/store/apps/details?id=com.nvidia.toastygames.parallax&hl=en
     
    Last edited: Dec 28, 2016
  14. sorex

    sorex Expert Licensed User

    yes, I meant the second one. if there are only games that are playable with such controller.

    Doom3 makes sense, you already need half a keyboard to play such games these days.
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice