1
\$\begingroup\$

I am making a 2d platformer where the character has a melee attack. To achieve this, I created a new arm body which I attached to the player's torso body (comprised of two circles). However, this interferes with the player's y-axis, which now jumps around between 0, 1.4901161E-8 and -1.4901161E-8 unless the player stays still for a few seconds. This interferes with the sprite generation and jumping, the player keeps flipping back and forth between facing left and facing right and when jumping sometimes the player's fall slows down and they gently float to the ground. Can anyone explain why this is happening? Is it something to do with the physics simulation?

My code is a bit of a mess right now, but I will include it in case it's relevant. So, at the moment, I have a definePlayer() and redefinePlayer() method where the player body and the arm body are created. The definePlayer() is called on construction and redefinePlayer() is called when necessary. They're not fully polished yet to say the least, but here they are.

public void definePlayer(){
    BodyDef bdef = new BodyDef();
    bdef.position.set(24 / GameName.PPM, 32 / GameName.PPM);
    bdef.type = BodyDef.BodyType.DynamicBody;
    b2body = world.createBody(bdef);

    FixtureDef fdef = new FixtureDef();
    CircleShape shape = new CircleShape();
    shape.setRadius(6 / GameName.PPM);
    fdef.filter.categoryBits = GameName.PLAYER_BIT;
    fdef.filter.maskBits = GameName.PLAYER_BIT |
            GameName.COIN_BIT |
            GameName.BRICK_BIT |
            GameName.ENEMY_BIT |
            GameName.OBJECT_BIT |
            GameName.ENEMY_HEAD_BIT |
            GameName.ITEM_BIT;

    //create player's 'torso' (lower circle)
    fdef.shape = shape;
    b2body.createFixture(fdef).setUserData(this);
    shape.setPosition(new Vector2(0, -10 / GameName.PPM));
    shape.setRadius(3 / GameName.PPM);
    b2body.createFixture(fdef).setUserData(this);

    //create player head (upper circle)
    EdgeShape head = new EdgeShape();
    head.set(new Vector2(-2 / GameName.PPM, 6 / GameName.PPM), new Vector2(2 / GameName.PPM, 6 / GameName.PPM));
    fdef.filter.categoryBits = GameName.PLAYER_HEAD_BIT;
    fdef.shape = head;
    fdef.isSensor = true;
    b2body.createFixture(fdef).setUserData(this);

    //define right Arm
    PolygonShape rightArm = new PolygonShape();
    rightArm.set(armRVertices);
    fdef.shape = rightArm;
    fdef.isSensor = true;

    //set armR
    bdef.type = BodyDef.BodyType.DynamicBody;
    armR = world.createBody(bdef);
    armR.createFixture(fdef).setUserData(this);

    //define joint connecting right arm to body
    RevoluteJointDef rightArmDef = new RevoluteJointDef();
    rightArmDef.bodyA = b2body;
    rightArmDef.bodyB = armR;
    rightArmDef.collideConnected = false;

    rightArmDef.localAnchorA.set(0, 0);
    rightArmDef.localAnchorB.set(0, 0);

    rightArmJoint = (RevoluteJoint)world.createJoint(rightArmDef);
}

public void redefinePlayer(){
    Vector2 position = b2body.getPosition();
    world.destroyBody(b2body);

    BodyDef bdef = new BodyDef();
    bdef.position.set(position);
    bdef.type = BodyDef.BodyType.DynamicBody;
    b2body = world.createBody(bdef);

    FixtureDef fdef = new FixtureDef();
    CircleShape shape = new CircleShape();
    shape.setRadius(6 / GameName.PPM);
    fdef.filter.categoryBits = GameName.PLAYER_BIT;
    fdef.filter.maskBits = GameName.GROUND_BIT |
            GameName.COIN_BIT |
            GameName.BRICK_BIT |
            GameName.ENEMY_BIT |
            GameName.OBJECT_BIT |
            GameName.ENEMY_HEAD_BIT |
            GameName.ITEM_BIT;

    fdef.shape = shape;
    b2body.createFixture(fdef).setUserData(this);

    EdgeShape head = new EdgeShape();
    head.set(new Vector2(-2 / GameName.PPM, 6 / GameName.PPM), new Vector2(2 / GameName.PPM, 6 / GameName.PPM));
    fdef.filter.categoryBits = GameName.PLAYER_HEAD_BIT;
    fdef.shape = head;
    fdef.isSensor = true;

    b2body.createFixture(fdef).setUserData(this);

    world.destroyBody(armR);
    PolygonShape rightArm = new PolygonShape();
    rightArm.set(armRVertices);
    fdef.shape = rightArm;
    fdef.isSensor = true;

    //set armR
    bdef.type = BodyDef.BodyType.DynamicBody;
    armR = world.createBody(bdef);
    armR.createFixture(fdef).setUserData(this);

    //define joint connecting right arm to body
    RevoluteJointDef rightArmDef = new RevoluteJointDef();
    rightArmDef.bodyA = b2body;
    rightArmDef.bodyB = armR;
    rightArmDef.collideConnected = false;

    rightArmDef.localAnchorA.set(0, 0);
    rightArmDef.localAnchorB.set(0, 0);
    rightArmJoint = (RevoluteJoint)world.createJoint(rightArmDef);

    timeToRedefinePlayer = false;
}
\$\endgroup\$
0
\$\begingroup\$

If I understand your question correctly, this is indeed most likely the physics simulation. Any two objects that are attached will influence each other.

If you don't want the arm to influence the body so much, try playing around with density of the different objects. In the extreme you could have an arm with a density of 0 and make it a sensor. You can then still implement yourself what happens when the arm collides with other objects. The best way to do this would be through a listener class.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ This didn't seem to work, unless I'm setting the density wrong somehow. I put armR.createFixture.setDensity(0); before the armR.createFixture.setUserData(this); line in both methods, but got no change, I tried commenting out the second line and still not change. Is there some way to make two bodies not interfere with each other? \$\endgroup\$ – foopydoop Oct 3 '16 at 23:58
  • \$\begingroup\$ Ok, I figured out how to change the density, but it still has the flipping sprite issue. \$\endgroup\$ – foopydoop Oct 4 '16 at 2:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.