Search code examples
javalibgdxbox2duser-data

LibGDX box2d detection of specific instance of an Object


I am a little bit confused about beginContact method from box2d.

I have a Runner class which is spawning a single runner into the game. In the game I have a multiple runners and I want to detect a collision between a specific instance of a runner and the obstacle. In beginContact() I want to start hit() method for a runner who has been hit.

public void beginContact(Contact contact) {

    final Body a = contact.getFixtureA().getBody();
    final Body b = contact.getFixtureB().getBody();
    if ((BodyUtils.bodyIsRunner(a) && BodyUtils.bodyIsEnemy(b)) ||
            (BodyUtils.bodyIsEnemy(a) && BodyUtils.bodyIsRunner(b))) {
        Runner c;
        if(BodyUtils.bodyIsRunner(a)) c = (Runner) a.getUserData();
        else c = (Runner) b.getUserData();
        c.hit();

But on this line:

if(BodyUtils.bodyIsRunner(a)) c = (Runner) a.getUserData();

The game crashes with an exception:

com.pl.runner.box2d.RunnerUserData cannot be cast to com.pl.runner.entities.Runner

I don't know how to deal with this right now so if anyone can give an advice or solution I will be really thankfull. I'm propably missing something basic, I'm stuck with this code for a way too long.

Here is RunnerUserData class:

public class RunnerUserData extends UserData {

    private final Vector2 runningPosition = new Vector2(Constants.RUNNER_X, Constants.RUNNER_Y);
    private final Vector2 dodgePosition = new Vector2(Constants.RUNNER_DODGE_X, Constants.RUNNER_DODGE_Y);
    private Vector2 jumpingLinearImpulse;


    public RunnerUserData(float width, float height) {
        super(width,height);
        jumpingLinearImpulse = Constants.RUNNER_JUMPING_LINEAR_IMPULSE;
        userDataType = UserDataType.RUNNER;
    }

    public Vector2 getJumpingLinearImpulse() {
        return jumpingLinearImpulse;
    }

    public void setJumpingLinearImpulse(Vector2 jumpingLinearImpulse) {
        this.jumpingLinearImpulse = jumpingLinearImpulse;
    }

    public float getHitAngularImpulse() {
        return Constants.RUNNER_HIT_ANGULAR_IMPULSE;
    }

    public float getDodgeAngle() {
        // In radians
        return (float) (-90f * (Math.PI / 180f));
    }

    public Vector2 getRunningPosition() {
        return runningPosition;
    }

    public Vector2 getDodgePosition() {
        return dodgePosition;
    }
}

Solution

  • Because my RunnerUserData have a little bit different role in my game I simply can't pass the Runner in body.setUserdata(runner).

    So I have a little workaround and it's working fine, maybe it will help someone someday: in beginContact() method:

                Body c;
                if(a.getUserData() instanceof RunnerUserData) c = a;
                else c = b; //checks which body is a runner
                for (Runner r : runners){
                    if(r.getUserData() == c.getUserData()){
                        runners.remove(r); 
                        break; //do something if you detect proper runner and quit the loop
                    }
                }