I am trying make create a ContactListener
derived class in Libgdx using Bullet wrapper for collision detection like in this tutorial but in separate classes. It separate classes for rendering and game world. In render()
method of class Render
I pass an Array of model instances to this derived class. But when I run it gives an because Array size is zero. Here is the derived class :
package com.anutrix.brickbreaker3d.Helpers;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g3d.ModelInstance;
import com.badlogic.gdx.physics.bullet.collision.ContactListener;
import com.badlogic.gdx.utils.Array;
public class CollisionListener extends ContactListener {
private Array<ModelInstance> instances;
public CollisionListener() {
this.instances = new Array<ModelInstance>();
}
public void setModelInstances(Array<ModelInstance> instances) {
this.instances = instances;
}
@Override
public boolean onContactAdded(int userValue0, int partId0, int index0, int userValue1, int partId1, int index1) {
//instances.get(colObj1Wrap.getCollisionObject().getUserValue()).collided = false;error
Gdx.app.log("instances.size", Integer.toString(instances.size));//zero
Gdx.app.log("ddhbdfhd", "fhfgjfgj");
return true;
}
}
Here is the Renderer class:
package com.anutrix.brickbreaker3d.gameWorld;
import com.anutrix.brickbreaker3d.gameObjects.Ball;
import com.anutrix.brickbreaker3d.gameObjects.Brick;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.g3d.Environment;
import com.badlogic.gdx.graphics.g3d.ModelBatch;
import com.badlogic.gdx.graphics.g3d.ModelInstance;
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight;
import com.badlogic.gdx.graphics.g3d.utils.CameraInputController;
import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;
import com.badlogic.gdx.physics.bullet.DebugDrawer;
import com.badlogic.gdx.physics.bullet.collision.btCollisionDispatcher;
import com.badlogic.gdx.physics.bullet.collision.btCollisionWorld;
import com.badlogic.gdx.physics.bullet.collision.btDbvtBroadphase;
import com.badlogic.gdx.physics.bullet.collision.btDefaultCollisionConfiguration;
import com.badlogic.gdx.physics.bullet.linearmath.btIDebugDraw;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Disposable;
public class GameRenderer implements Disposable {
private GameWorld gameWorld;
private PerspectiveCamera cam;
public ModelBatch modelBatch;
private CameraInputController camController;
private Environment environment;
public Array<ModelInstance> instances;
ModelBuilder mb = new ModelBuilder();
btCollisionDispatcher dispatcher;
public GameRenderer(GameWorld world) {
this.modelBatch = new ModelBatch();
this.environment = new Environment();
this.instances = new Array<ModelInstance>();
gameWorld = world;
cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
cam.position.set(10f, 10f, 0f);
cam.lookAt(0, 0, 0);
cam.near = 1f;
cam.far = 300f;
cam.update();
camController = new CameraInputController(cam);
Gdx.input.setInputProcessor(camController);
environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f));
environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f));
}
public void render() {
//Gdx.app.log("GameRenderer", "render");
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glClearColor(0f, 0.2f, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
for (Brick b : gameWorld.bricks) {
b.getObject().setUserValue(instances.size);
instances.add(b.getModelInstance());
}
for (Ball b : gameWorld.balls) {
b.getObject().setUserValue(instances.size);
instances.add(b.getModelInstance());
}
gameWorld.collisionListener.setModelInstances(instances);
modelBatch.begin(cam);
modelBatch.render(instances, environment);
modelBatch.end();
instances.clear();
}
@Override
public void dispose() {
modelBatch.dispose();
}
}
What am I doing wrong? Inside setModelInstances()
the instances.size is correct. But after each call to it, the instances.size
is equal to 0 .
Also I wasn't sure of pass by reference(since Java uses pass by value). So is it better(if it works) if I call setInstances()
just once?
Both your CollisionListener#instances
and GameRenderer#instances
point to the same reference after your call to gameWorld.collisionListener.setModelInstances(instances);
inside your GameRenderer#render()
method.
Then, at the end of the method, you are invoking:
instances.clear();
This would be clearing out instances
. So, the size would become 0 when you call render
.
Instead, inside your setModelInstances
method, you could create a new Array instance like this:
public void setModelInstances(Array<ModelInstance> instances) {
this.instances = new Array<>(instances);
}
Hope this helps!