Giter Site home page Giter Site logo

libgdx / jamepad Goto Github PK

View Code? Open in Web Editor NEW

This project forked from mrstahlfelge/jamepad

16.0 5.0 11.0 78.44 MB

A better way to use gamepads in Java

License: Apache License 2.0

Java 81.98% Roff 18.02%
sdl2 gamepad gamecontroller-framework java

jamepad's Introduction

Jamepad Fork

A better way to use gamepads in Java.

This is a fork of and based on the original work by William Hartman.

Jamepad is a library for using gamepads in Java. It's based on SDL2 (here) and uses jnigen (more info here). We also use this really nice database of gamepad mappings.

Jamepad has:

  • One library that supports all platforms (Windows, OSX, and Linux)
  • XInput support on Windows for full Xbox 360 controller support.
  • Support for plugging/unplugging controllers at runtime.
  • Support for rumble
  • Button/Axis mappings for popular controllers.
  • A permissive license (see below).

This fork improved the following points compared to last real Jamepad version 1.3.2:

  • This fork builts the native library on Github Actions. You can see all the magic happen there. Moreover, if you fork this repo and adjust settings, you are immediately ready to go with your own build! We are open for PRs though.
  • New features added, newer SDL version used
  • Natives are smaller in size
  • Natives for arm architecture included

Stuff You Should Know About Jamepad

  • On Windows (only 7 and up were tested), no special dependencies are needed.
  • On Linux, runtime dependencies are: libevdev, libudev (normally included)
  • On OS X, no special dependencies are needed

Current Limitations

  • The order of gamepads on Windows is not necessarily the order they were plugged in. XInput controllers will always appear before DirectInput controllers, regardless of when they were plugged in. This means that the player numbers associated with each controller can change unexpectedly if XInput controllers are plugged in or disconnected while DirectInput controllers are present.
  • If using getState() in ControllerManager, a new ControllerState is instantiated on each call. For some games, this could pose a problem.

Using Jamepad

For usage within libgdx project, take a look at gdx-controllers. The following information is only needed for non-gdx Java projects.

Getting Jamepad

Sonatype Nexus (Releases) Sonatype Nexus (Snapshots)

gradle

If you use gradle, you can pull this package in from Maven Central. Add this line to your dependencies section. Update the version number to whatever the latest release is.

dependencies {
  ...
  compile 'com.badlogicgames.jamepad:jamepad:2.0.14.0'
}
maven

If you use gradle, you can pull this package in from Maven Central. Add this line to your dependencies section. Update the version number to whatever the latest release is.

<dependencies>
    ...
    <dependency>
        <groupId>com.badlogicgames.jamepad</groupId>
        <artifactId>jamepad</artifactId>
        <version>2.0.14.0</version>
    </dependency>
</dependencies>

Using Jamepad

There are two main ways to use Jamepad. Both rely on a ControllerManager Object.

ControllerManager controllers = new ControllerManager();
controllers.initSDLGamepad();

For most applications, using the getState() method in ControllerManager is best. This method returns an immutable ControllerState object that describes the state of the controller at the instant the method is called. Using this method, you don't need to litter code with a bunch of exceoption handling or handle the possiblity of controller disconnections at weird times.

If a controller is disconnected, the returned ControllerState object has the isConnected field set to false. All other fields are either false (for buttons) or 0 (for axes).

Here's a simple example:

//Print a message when the "A" button is pressed. Exit if the "B" button is pressed 
//or the controller disconnects.
while(true) {
  ControllerState currState = controllers.getState(0);
  
  if(!currState.isConnected || currState.b) {
    break;
  }
  if(currState.a) {
    System.out.println("\"A\" on \"" + currState.controllerType + "\" is pressed");
  }
}

For a select few applications, getState() might not be the best decision. Since ControllerState is immutable, a new one is instantiated on each call to getState(). This should be fine for normal desktop JVMs; both Oracle's JVM and the OpenJDK one should absolutely be able to handle this. What problems do come up could probably be solved with some GC tuning.

If these allocations do end up being an actual problem, you can access the internal representation of the controllers. This is more complicated to use, and you might need to deal with some exceptions.

Here's a pretty barebones example:

//Print a message when the "A" button is pressed. Exit if the "B" button is pressed 
//or the controller disconnects.
ControllerIndex currController = controllers.getControllerIndex(0);

while(true) {
  controllers.update(); //If using ControllerIndex, you should call update() to check if a new controller
                        //was plugged in or unplugged at this index.
  try {
    if(currController.isButtonPressed(ControllerButton.A)) {
      System.out.println("\"A\" on \"" + currController.getName() + "\" is pressed");
    }
    if(currController.isButtonPressed(ControllerButton.B)) {
      break;
    }
  } catch (ControllerUnpluggedException e) {   
    break;
  }
}

When you're finished with your gamepad stuff, you should call quitSDLGamepad() to free the native library.

controllers.quitSDLGamepad();

Building Jamepad

See BUILDING

License

The original work by William Hartman is licensed under the permissive zLib license. You can include this use this library in proprietary projects without sharing source, and you are allowed to alter the project. The original license is kept here.

libSDL 2.0 is zLib licensed, too.

Every work done in this fork is licensed under Apache 2 License conditions, see LICENSE file.

jamepad's People

Contributors

actions-user avatar breiler avatar code-disaster avatar electronstudio avatar gamebuster19901 avatar javmarina avatar mrstahlfelge avatar pokemmo avatar scotthamper avatar simonit avatar tom-ski avatar williamahartman avatar xenoamess avatar yontipon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

jamepad's Issues

Upgrade to SDL 2.0.14

Changelog:

2.0.14:
---------------------------------------------------------------------------
General:
* Added support for PS5 DualSense and Xbox Series X controllers to the HIDAPI controller driver
* Added game controller button constants for paddles and new buttons
* Added game controller functions to get additional information:
	* SDL_GameControllerGetSerial()
	* SDL_GameControllerHasAxis()
	* SDL_GameControllerHasButton()
	* SDL_GameControllerGetNumTouchpads()
	* SDL_GameControllerGetNumTouchpadFingers()
	* SDL_GameControllerGetTouchpadFinger()
	* SDL_GameControllerHasSensor()
	* SDL_GameControllerSetSensorEnabled()
	* SDL_GameControllerIsSensorEnabled()
	* SDL_GameControllerGetSensorData()
	* SDL_GameControllerRumbleTriggers()
	* SDL_GameControllerHasLED()
	* SDL_GameControllerSetLED()
* Added the hint SDL_HINT_JOYSTICK_HIDAPI_PS5 to control whether the HIDAPI driver for PS5 controllers should be used.
* Added joystick functions to get additional information:
	* SDL_JoystickGetSerial()
	* SDL_JoystickRumbleTriggers()
	* SDL_JoystickHasLED()
	* SDL_JoystickSetLED()
* Added an API to allow the application to create virtual joysticks:
	* SDL_JoystickAttachVirtual()
	* SDL_JoystickDetachVirtual()
	* SDL_JoystickIsVirtual()
	* SDL_JoystickSetVirtualAxis()
	* SDL_JoystickSetVirtualButton()
	* SDL_JoystickSetVirtualHat()
  • check new button constants
  • check hasLED/setLED
  • update game controller db

Implementation on sdl/2_0_14 branch

Excessive use of user objects on Windows

When using the library (version 2.26.5.0, 2.26.4.0 and 2.0.20.0) on Windows it seems that it will start allocating "User Objects" which will finally make the application unresponsive. On Mac and Linux this works without problems.

The interesting thing is that if the window of the related process is not in focus it will not create new user objects even though the example is a console application:

2024-02-29.10-03-52.mp4

Example program:

package com.willwinder.ugs.nbp.joystick;

import com.studiohartman.jamepad.Configuration;
import com.studiohartman.jamepad.ControllerManager;
import com.studiohartman.jamepad.ControllerState;


public class TestMain {
    public static void main(String[] args) {
        Configuration configuration = new Configuration();
        ControllerManager controllerManager = new ControllerManager(configuration, "/com/willwinder/ugs/nbp/joystick/gamecontrollerdb.txt");
        controllerManager.initSDLGamepad();
        
        // Print a message when the "A" button is pressed. Exit if the "B" button is pressed
        // or the controller disconnects.
        while (true) {
            ControllerState currState = controllerManager.getState(0);

            if (!currState.isConnected || currState.b) {
                break;
            }
            if (currState.a) {
                System.out.println("\"A\" on \"" + currState.controllerType + "\" is pressed");
            }
        }
    }
}

Tried with JDK Temurin 17.0.9 and Temuring 21.0.2.

libjamepad64.so: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.27' not found

The current Jamepad version on maven seems to require glibc minimum 2.27. Is this intentional and really necessary? I thought libgdx was meant to be more portable across linux distrubutions, including slightly outdated ones. Never had any such troubles with other native libraries coming with libgdx, such as libgdx64.so, liblwjgl64.so or libopenal64.so.

Doesn't react to controller being turned on

When the app is turned on before the controller, it will never start working (unless perhaps quitSDLGamepad and initSDLGamepad will be called). Calling ControllerManager.update does nothing.

Question about DualSense features

I saw that there was a pull request 2 years ago

#1

I know that SDL2 can access the motion data and touchpad data but I guess these APIs are not (yet) accessible via Jamepad? Is this correct? For my application it's necassary to support this.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.