Processing 3.2.1, Game Control Plus library, java exception

1

Good!

I'm studying Games & Apps Development and in our first half we are making a game in Processing. In my game I'm using a PS4 command with the help of the Game Control Plus library. If I press a button enough times, my game crashes and gives me this in the console: (the 'Uarma' plug is the function that executes the code when pressing the button)

java.lang.reflect.InvocationTargetException
    at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.gamecontrolplus.Plug.call(Unknown Source)
    at org.gamecontrolplus.ControlButton.callPlugs(Unknown Source)
    at org.gamecontrolplus.ControlButton.update(Unknown Source)
    at org.gamecontrolplus.ControlDevice.update(Unknown Source)
    at org.gamecontrolplus.ControlIO.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.AssertionError
    at org.jbox2d.dynamics.World.createBody(World.java:339)
    at shiffman.box2d.Box2DProcessing.createBody(Box2DProcessing.java:203)
    at Meon$Bullet.<init>(Meon.java:202)
    at Meon.Uarma(Meon.java:294)
    ... 9 more
java.lang.RuntimeException: Error on calling plug: Uarma
    at org.gamecontrolplus.Plug.call(Unknown Source)
    at org.gamecontrolplus.ControlButton.callPlugs(Unknown Source)
    at org.gamecontrolplus.ControlButton.update(Unknown Source)
    at org.gamecontrolplus.ControlDevice.update(Unknown Source)
    at org.gamecontrolplus.ControlIO.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:745)

My knowledge of Java is not much, so any help about what might be causing this error is appreciated!

Thanks in advance!

Here's all the code involved in the process:

//Variaveis
ControlIO controlo;
ControlDevice comando;

//inicia o ControlIO (vai ver que comandos estao ligados)
controlo = ControlIO.getInstance(this);

//procura comandos compativeis
comando = controlo.getMatchedDevice("playerControl");

//associa funçoes a botoes (Botão para Função)
BpFp1(); //p1 = player 1

void BpFp1() {

  comando.getButton("jump").plug(this, "salto", ControlIO.ON_PRESS);
  comando.getButton("punch").plug(this, "murro", ControlIO.ON_PRESS);
  comando.getButton("grabWep").plug(this, "Aarma", ControlIO.ON_PRESS);
  comando.getButton("useWep").plug(this, "Uarma", ControlIO.ON_PRESS);
}

void Uarma() {

  println("usar armas? check");  
  bullets.add(new Bullet(player1.playerPos.x + 20, player1.playerPos.y, 5, 5));
}

Bullet Builder:

class Bullet {

  Vec2 bulletPos;
  Body bulletbody;
  float dbulletLarg;
  float dbulletAlt;

  Bullet(float bulletX, float bulletY, float bulletLarg, float bulletAlt) {

    //definir o corpo
    BodyDef bulletbd = new BodyDef();
    bulletbd.type = BodyType.DYNAMIC;
    bulletbd.bullet = true;
    bulletbd.position.set(box2d.coordPixelsToWorld(bulletX, bulletY));

    //criar o corpo
    bulletbody = box2d.createBody(bulletbd);

    //forma
    PolygonShape bulletps = new PolygonShape();
    bulletps.setAsBox(box2d.scalarPixelsToWorld(bulletLarg/2), box2d.scalarPixelsToWorld(bulletAlt/2));


    //o que cola a forma ao corpo
    FixtureDef bulletfd = new FixtureDef();
    bulletfd.shape = bulletps;

    //parametros que afetam a fisica do objeto
    bulletfd.density = 0;

    //colar a forma ao corpo
    bulletbody.createFixture(bulletfd);

    dbulletLarg = bulletLarg;
    dbulletAlt = bulletAlt;

    bulletbody.applyLinearImpulse(new Vec2(100, 0), bulletbody.getWorldCenter(), true);
  }

  void display() {

    bulletPos = box2d.getBodyPixelCoord(bulletbody);

    pushMatrix();
    translate(bulletPos.x, bulletPos.y);
    rectMode(CENTER);
    rect(0, 0, dbulletLarg, dbulletAlt);
    popMatrix();
  }
}

Here's the whole Meon class:

//Sprites: biblioteca de sprites (arte do jogo)
import sprites.*;
import sprites.maths.*;
import sprites.utils.*;

//Box2D for Processing: biblioteca de physX (mais outra)
import shiffman.box2d.*;
import org.jbox2d.collision.shapes.*;
import org.jbox2d.common.*;
import org.jbox2d.dynamics.*;
import org.jbox2d.dynamics.contacts.*;

//Game Control Plus: biblioteca controlo (ps4 neste caso)
import net.java.games.input.*;
import org.gamecontrolplus.*;
import org.gamecontrolplus.gui.*;

//Variaveis
ControlIO controlo;
ControlDevice comando;
ControlDevice comando2;

Box2DProcessing box2d;

float fx1;
float fx2;

Player player1;
Player player2;

Platform floor;
Platform sideRight;
Platform sideLeft;
Platform ceiling;

//s: small, m: medium,  b: big | b: bottom, m: middle, t: top
Platform stleft;
Platform smleft;
Platform sbleft;

Platform stright;
Platform smright;
Platform sbright;

Platform mbleft;
Platform mtleft;

Platform mbright;
Platform mtright;

Platform bbcenter;
Platform btcenter;

ArrayList<Bullet> bullets;

//WeaponPUP weaponpup;

void setup() {

  size(1280, 720);
  frameRate(60);

  //inicia o ControlIO (vai ver que comandos estao ligados)
  controlo = ControlIO.getInstance(this);

  //procura comandos compativeis
  comando = controlo.getMatchedDevice("playerControl");
  //comando2 = controlo.getMatchedDevice("player2Control");

  //associa funçoes a botoes (Botão para Função)
  BpFp1(); //p1 = player 1
  //BpFp2();

  box2d = new Box2DProcessing(this);
  box2d.createWorld();
  box2d.setGravity(0, -90);
  box2d.listenForCollisions();

  player1 = new Player(280, 80, 39, 55);
  player2 = new Player(1000, 80, 39, 55);

  floor = new Platform(640, 720, 1300, 80);
  sideLeft = new Platform(0, 360, 1, 3280);
  sideRight = new Platform(1280, 360, 1, 3280);
  ceiling = new Platform(640, 0, 3280, 1);

  stleft = new Platform(60, 90, 240, 10);
  smleft = new Platform(60, 340, 120, 10);
  sbleft = new Platform(60, 590, 120, 10);

  stright = new Platform(1220, 90, 240, 10);
  smright = new Platform(1220, 340, 120, 10);
  sbright = new Platform(1220, 590, 120, 10);

  mbleft = new Platform(390, 520, 330, 10);
  mtleft = new Platform(390, 270, 330, 10);

  mbright = new Platform(890, 520, 330, 10);
  mtright = new Platform(890, 270, 330, 10);

  bbcenter = new Platform(640, 150, 500, 10);
  btcenter = new Platform(640, 400, 500, 10);


  bullets = new ArrayList<Bullet>();

  //weaponpup = new WeaponPUP(450, 570, 20, 20);
}

void draw() {

  background(0);
  box2d.step();

  fx1 = comando.getSlider("movX").getValue();
  //fx2 = comando2.getSlider("movX").getValue();

  floor.display();
  stleft.display();
  smleft.display();
  sbleft.display();
  stright.display();
  smright.display();
  sbright.display();
  mbleft.display();
  mtleft.display();
  mbright.display();
  mtright.display();
  bbcenter.display();
  btcenter.display();


  player1.display();
  p1Move();

  player2.display();
  p2Move();

  texts();

  //weaponpup.display();

  for (int i = 0; i<bullets.size(); i++) {
    bullets.get(i).display();
  }
}

void texts() {

  fill(255);
  textSize(16);
  textAlign(LEFT);
  text("HP: "+round(player1.hpoints), 10, 20);
  textAlign(LEFT);
  text("HP: "+round(player2.hpoints), 1220, 20);
}
    
asked by anonymous 15.11.2016 / 02:16

1 answer

0

This is a thread problem. ControlIO uses its own thread to receive input, as evidenced by this:

at org.gamecontrolplus.ControlIO.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)

However, Box2D (under Processing) handles your virtual world in its own thread as well. You should not manipulate virtual worlds outside the thread used by Box2D. Doing so is choppy and can cause data corruption problems due to cluttered inter-thread interference.

To protect against this kind of problem, Box2D blocks your virtual worlds to avoid unexpected manipulation. Entrenatnto it uses assert s instead of IllegalArgumentException s or ConcurrentModificationException s that most other frameworks in Java use to check this type of thing. So you have a AssertionError being posted from this point of the Box2D code .

Unfortunately, that's just what you're doing. When you create a Bullet , you do this from the ControlIO thread. The Bullet constructor attempts to add Bullet to the virtual world. Box2D does not like this and throws the error in assert .

The workaround would be to not create Bullet from within the Uarma method. Instead, put an object in some list (with due synchronization) that says Bullet must be created in a certain position. Back to your Meon class that manipulates the virtual world in the Box2D thread, you consume the list and add the corresponding Bullet s in the virtual world when calling the constructor.

    
15.11.2016 / 19:28