javalibgdxbulletphysics

Debug lines not drawing and gravity not setting for player


I am creating a demo game with the book Building a 3d Game with Libgdx. Gravity seems not to be working at all, so I draw debug line with debugDrawer but character's debug lines are also not showing.

Floor's debug lines are showing properly, also character is added to world as I have checked collisionObjects count.

Here is my running game: (can't post picture directly as its my first post ;P)

game demo

My characater creation code is:

private static Entity createCharacter(BulletSystem bulletSystem, float x, float y, float z) {
    Entity entity = new Entity();
    ModelComponent modelComponent = new ModelComponent(playerModel, x, y, z);
    entity.add(modelComponent);

    CharacterComponent characterComponent = new CharacterComponent();
    characterComponent.ghostObject = new btPairCachingGhostObject();
    characterComponent.ghostObject.setWorldTransform(modelComponent.instance.transform);
    characterComponent.ghostShape = new btCapsuleShape(2f, 2f);
    characterComponent.ghostObject.setCollisionShape(characterComponent.ghostShape);
    characterComponent.ghostObject.setCollisionFlags(btCollisionObject.CollisionFlags.CF_CHARACTER_OBJECT);
    characterComponent.characterController = new btKinematicCharacterController(characterComponent.ghostObject,
            characterComponent.ghostShape, .35f);
    characterComponent.ghostObject.userData = entity;
    entity.add(characterComponent);

    // add character to bullet world
    bulletSystem.collisionWorld.addCollisionObject(characterComponent.ghostObject,
                    (short) btBroadphaseProxy.CollisionFilterGroups.CharacterFilter,
                    (short) (btBroadphaseProxy.CollisionFilterGroups.AllFilter));

    // It is showing 2 in console.

    System.out.println(bulletSystem.collisionWorld.getNumCollisionObjects());
    bulletSystem.collisionWorld.addAction(characterComponent.characterController);
    return entity;
}

BulletSystem.java


public class BulletSystem extends EntitySystem implements EntityListener {
    public final btCollisionConfiguration collisionConfiguration;
    public final btCollisionDispatcher dispatcher;
    public final btBroadphaseInterface broadphase;
    public final btConstraintSolver solver;
    public final btDiscreteDynamicsWorld collisionWorld;
    private btGhostPairCallback ghostPairCallback;
    public int maxSubSteps = 5;
    public float fixedTimeStep = 1f / 60f;

    @Override
    public void addedToEngine(Engine engine) {
        engine.addEntityListener(Family.all(BulletComponent.class).get(),
                this);
    }

    public BulletSystem() {
        collisionConfiguration = new
                btDefaultCollisionConfiguration();
        dispatcher = new
                btCollisionDispatcher(collisionConfiguration);

        broadphase = new btAxisSweep3(new Vector3(-1000, -1000,
                -1000), new Vector3(1000, 1000, 1000));
        solver = new btSequentialImpulseConstraintSolver();
        collisionWorld = new btDiscreteDynamicsWorld(dispatcher,
                broadphase, solver, collisionConfiguration);
        ghostPairCallback = new btGhostPairCallback();
        broadphase.getOverlappingPairCache().
                setInternalGhostPairCallback(ghostPairCallback);
        this.collisionWorld.setGravity(new Vector3(0, -9f, 0));
    }

    @Override
    public void update(float deltaTime) {
        collisionWorld.stepSimulation(deltaTime, maxSubSteps,
                fixedTimeStep);
    }


}

My GameScreen is

class GameScreen extends ScreenAdapter {
    private BulletGame game;
    private PerspectiveCamera cam;
    private Environment env;
    private ModelBatch mb;

    private Engine engine;
    private BulletSystem bulletSystem;
    private Model floor;
    private Entity character;

    private DebugDrawer debug;
    GameScreen(BulletGame bulletGame) {
        game = bulletGame;
        Bullet.init();
        initCamera();
        initEnvironemnt();
        mb = new ModelBatch();

        ModelBuilder modelBuilder = new ModelBuilder();
        floor = modelBuilder.createBox(40, 1, 40,
                new Material(ColorAttribute.createDiffuse(Color.YELLOW),
                        ColorAttribute.createSpecular(Color.BLUE),
                        FloatAttribute.createShininess(16f)),
                VertexAttributes.Usage.Position
                        | VertexAttributes.Usage.Normal);

        engine = new Engine();
        engine.addSystem(bulletSystem = new BulletSystem());    // WORLD with entity listener
        engine.addSystem(new RenderSystem(mb, env));    // renders all MODEL_COMPONENTS


        debug = new DebugDrawer();
        debug.setDebugMode(btIDebugDraw.DebugDrawModes.DBG_MAX_DEBUG_DRAW_MODE);
        bulletSystem.collisionWorld.setDebugDrawer(debug);
        addEntities();

    }

    private void addEntities() {
        engine.addEntity(EntityFactory.createStaticEntity(floor,0, 0, 0));
        engine.addEntity(character = EntityFactory.createPlayer(bulletSystem, 0,10,15));
    }

    @Override
    public void render(float delta) {

        mb.begin(cam);
        engine.update(delta);
        mb.end();

        debug.begin(cam);
        bulletSystem.collisionWorld.debugDrawWorld();
        debug.end();
    }


Solution

  • I was disposing off my screen and thus character collision object the wrong way:

    private void setScreen(Screen screen) {
            if (screen != null) {
                screen.hide();
                screen.dispose();
            }
            this.screen = screen;
            if (screen != null) {
                screen.show();
                screen.resize(Gdx.graphics.getWidth(),
                        Gdx.graphics.getHeight());
            }
        }
    

    Dispose method in my screen:

    public void dispose() {
            mb.dispose();
    
            bulletSystem.collisionWorld.removeAction(character.getComponent
                    (CharacterComponent.class).characterController);
            bulletSystem.collisionWorld.removeCollisionObject
                    (character.getComponent(CharacterComponent.class).ghostObject);
            character.getComponent(CharacterComponent.class).characterController.dispose();
            character.getComponent(CharacterComponent.class).ghostObject.dispose();
            character.getComponent(CharacterComponent.class).ghostShape.dispose();
        }
    

    Sticking to the default Game class solved the problem.