2

I'm currently working on a project that includes a short demo game, we've decided to use LibGDX as the java library and we're required to use an arduino and/or raspberry pi as a controller input. My assumption was to make an inputprocessor that uses the serial monitor input sent by the arduino. We're currently stumped on how to accomplish this and aren't even sure if you can use the inputprocessor in this way.

#define left 2
#define right 3
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  if(digitalRead(left))
  {
   

 goLeft();
  }
  if(digitalRead(right))
  {
    goRight();
  }
  delay(100);
}
void goLeft()
{
  Serial.println(1000);
}
void goRight()
{
  Serial.println(500);
}

This is the code running on the Arduino it's a simple setup that just serial prints 2 different numbers depending on what button is pressed to be later used as a left or right direction in the game.

port = SerialPort.getCommPort("COM4");
        if(port.openPort()) {
            System.out.println("Successfully opened the port.");
        } else {
            System.out.println("Unable to open the port.");
            return;
        }
        port.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING, 0, 0);
        data = new Scanner(port.getInputStream());
        if(data.hasNextLine())
        {
            int number = 0;
            try{number = Integer.parseInt(data.nextLine());}catch(Exception e){}
            if(number == 500)
            {
                bucket.x += 200 * Gdx.graphics.getDeltaTime();
            }
            if(number == 1000)
            {
                bucket.x -= 200 * Gdx.graphics.getDeltaTime();
            }
        }

This is the code currently used during the render() function in our game. However what happens is that the game will only continue to render when there is a nextLine in the serial monitor and will not render at any other times. We're currently using the java library jserial comm in order to facilitate the connection between the ardiono and java application. For this reason we believed we would require an inputprocessor however as we're currently student developers we're unable to figure out if this is the case and how we could accomplish it.

2 Answers2

2

I would suggest moving your serial listener to a separate dedicated thread, which calls back to your game when it reads something.

This way your GDX Game thread can continue to run as you expect, with a parallel thread listening for inputs, only notifying the game when it receives them.

To achieve this, package your listener into a Runnable interface:

    // Runnable class, listens for serial input
    public class serialListener implements Runnable {
        
        @Override
        public void run() {
            // Listen for input, and calls corresponding methods in your game
        }
    }

Then dispatch it in a new thread from your game upon creation :

    public class myGame extends GameAdapter {
        
        private serialListener listener = new serialListener();
        private Thread ListenerThread;
        
        @Override
        public void Create(){
            ListenerThread = new Thread(listener);
            ListenerThread.setDaemon(true);
            ListenerThread.start();
        }
    }
Shinkson47
  • 120
  • 8
  • 1
    You should change the thread to a [daemon thread](https://stackoverflow.com/questions/2213340/what-is-a-daemon-thread-in-java) before starting it using `listenerThread.setDaemon(true)`. Otherwise the game might not be able to exit, because there is still a thread, that is running. The daemon thread will be killed by the JVM when there are no non-daemon threads alive anymore. – Tobias Apr 21 '21 at 17:35
  • @Tobias Made the change - Just tested with the game of my own and saw that exact behaviour, thanks for informing me! – Shinkson47 Apr 21 '21 at 17:41
0

I'm not shure if this is answers your question, but I think there is an easier solution for what you are trying to achieve:
Instead of using the Serial Port like this, you could use an Arduino as a keyboard and use the normal libGDX input library to controll the game (just like you would with a normal keyboard). You can use an Arduino Leonardo or an Arduino Pro Micro (and also any cheap copy of it), to register it as a Keyboard on your computer. This way you can use the Arduino to send key inputs to the computer, that are recognized by libGDX (and any other program) just like a normal keyboard would be recognized.

The Keyboard library can be used like this:

#include "Keyboard.h"

#define left 2
#define right 3

void setup() {
  //start a serial connection, because the keyboard uses this connection
  Serial.begin(9600);
  //create a keyboard
  Keyboard.begin();
}
 
void loop() {
  if(digitalRead(left))
  {
    Keyboard.write(KEY_LEFT_ARROW);// the KEY_LEFT_ARROW is defined in Keyboard.h
  }
  if(digitalRead(right))
  {
    Keyboard.write(KEY_RIGHT_ARROW);
  }
  // ...other keys...

  delay(100);//debounce button
}

On the libGDX side of the project you would not need any serial port handling, but just the usual libGDX input handling.

I've used something similar to build a presenter. The code is on GitHub. Maybe it helps.

Tobias
  • 2,547
  • 3
  • 14
  • 29
  • Sadly I'm currently using an arduino uno and had no plans on getting a different one and the keyboard library can not be used on it. I should've said this in the question but I didn't realize that different arduino's could use different arduino libraries. Thank you for the solution that I might use in the future though. – Cordell Stirling Apr 26 '21 at 13:08