Game Control Plus custom function fails to draw on screen

I’m using the Game Control Plus library to capture inputs from a new NES USB controller. All buttons are mapped correctly and respond to my inputs. I have used .plug() to set up a custom function that is supposed to trigger whenever the A button is released. My chngBgCol() function is correctly triggered and the text “Button A released” appears in the console but any drawing operations (like background() and circle()) fail to do anything on the screen.

I’m sure it’s me being a klutz here and that it’s an easy fix. Anybody able to spot the error? Ping @quark.

(Processing 4.1.2, Mac OS 12.4)

import org.gamecontrolplus.gui.*;
import org.gamecontrolplus.*;
import net.java.games.input.*;

ControlIO control;
ControlDevice stick;

void setup() {
  size(800, 800);
  control = ControlIO.getInstance(this);
  stick = control.getMatchedDevice("joystick");
  stick.getButton("A").plug(this, "chngBgCol", ControlIO.ON_RELEASE);
}

void draw() {
  float px = stick.getSlider("X").getValue();
  float py = stick.getSlider("Y").getValue();
  boolean select = stick.getButton("SELECT").pressed();
  boolean start = stick.getButton("START").pressed();
  boolean a = stick.getButton("A").pressed();
  boolean b = stick.getButton("B").pressed();
  println(px, py, select, start, a, b); // these all work as intended
}

void chngBgCol() {
  println("Button A released"); // this prints in the console
  background(random(255), random(255), random(255)); // background doesn't change?
  circle(random(width), random(height), 200); // circle doesn't appear?
}

As I say on my website, the original code was not created by me I simply updated it for Processing3 (very minor changes) and added the configurator. So I have had to look at the original source code and I believe I have the answer :smile:

I found this method which is used to poll the USB device and as you can see it runs in a separate thread and not on the main event thread.

	/**
	 * Controllers are now polled in a separate thread to get independent from
	 * the framerate of the sketch
	 */
	public void run(){
		while (active){
			for (int i = 0; i < devices.size(); i++)
				devices.get(i).update();
			try {
				Thread.sleep  ( 10 );
			} catch ( InterruptedException e ) { }
		}
	}

All Processing graphics methods must be executed on the main event thread so I suggest that you add a boolean flag (semaphore) to indicate when the button has been released like this

import org.gamecontrolplus.gui.*;
import org.gamecontrolplus.*;
import net.java.games.input.*;

ControlIO control;
ControlDevice stick;
boolean buttonAreleased = false;

void setup() {
  size(800, 800);
  control = ControlIO.getInstance(this);
  stick = control.getMatchedDevice("joystick");
  stick.getButton("A").plug(this, "chngBgCol", ControlIO.ON_RELEASE);
}

void draw() {
  float px = stick.getSlider("X").getValue();
  float py = stick.getSlider("Y").getValue();
  boolean select = stick.getButton("SELECT").pressed();
  boolean start = stick.getButton("START").pressed();
  boolean a = stick.getButton("A").pressed();
  boolean b = stick.getButton("B").pressed();
  println(px, py, select, start, a, b); // these all work as intended

  // Test the semaphore
  if (buttonAreleased) randomCircle();
}

void randomCircle() {
  background(random(255), random(255), random(255));
  circle(random(width), random(height), 200);
  buttonAreleased = false; // clear the semaphore
}

void chngBgCol() {
  println("Button A released");
  buttonAreleased = true;   // set the semaphore
}

I am not promising that this will work but I think it will.

1 Like

Thanks for responding so quickly @quark. I had a hunch it might involve different threads, and your research confirms this. I’ll go with your suggestion for a workaround using a boolean flag.

Please tell us if it worked - might help other Game Control Plus users.