简体   繁体   中英

Box2D recreating a body

In my game I have a Bullet class, which is in charge of making a new bullet every time the gun is fired. Upon creation the bullet is added to the Bullets class, which is in charge of keeping track of said bullet, along with the rest of the bullets. I have come across a strange behavior:
After killing an enemy, and then shooting once more, the new bullet has the following traits:

  1. The bullet is the same one (as in the same code id) as the bullet that killed the enemy. (IE if the id was: com.badlogic.gdx.physics.box2d.Body@fc7157f , then it will be the exact same id.)
  2. The bullet will appear stuck in place, it's sprite not moving, but according to the game it will have a velocity, but the position remains the same. The only visible movement is when you enable the Box2DDebugRenderer , you can see the body move downwards until hitting the ground at which point he "teleports" back up and slowly falls back down.
  3. The number of stuck bullets are equal to the number of enemies killed.

This is the bullet class:

public class Bullet {

private Body bullet;

public Bullet(final float force, final int bulletDmg, final Weapon weapon,
        final World world) {
    System.out.println("Position " + weapon.getPosition() + ", Angle: "
            + weapon.getAngle());
    final BodyDef bulletDef = new BodyDef();
    bulletDef.type = BodyDef.BodyType.DynamicBody;
    bulletDef.angle = weapon.getAngle();
    bulletDef.position.set(
            weapon.getPosition().x
                    + (float) (2.5 * MathUtils.cos(weapon.getAngle())),
            weapon.getPosition().y
                    + (float) (2.5 * MathUtils.sin(weapon.getAngle())));
    bulletDef.angle = weapon.getAngle();
    PolygonShape bulletShape_1 = new PolygonShape();
    bulletShape_1.setAsBox(0.34375f, 0.34375f);
    CircleShape bulletShape_2 = new CircleShape();
    bulletShape_2.setPosition(new Vector2(0.34375f, 0));
    bulletShape_2.setRadius(0.34375f);
    final FixtureDef bulletFixture_1 = new FixtureDef();
    bulletFixture_1.density = 1f;
    bulletFixture_1.shape = bulletShape_1;
    bulletFixture_1.friction = 0.25f;
    bulletFixture_1.restitution = 0.75f;
    final FixtureDef bulletFixture_2 = new FixtureDef();
    bulletFixture_2.density = 1;
    bulletFixture_2.shape = bulletShape_2;
    bulletFixture_2.friction = 0.25f;
    bulletFixture_2.restitution = 0.75f;
    final Timer creationTimer = new Timer();
    creationTimer.scheduleTask(new Task() {

        @Override
        public void run() {
            if (!world.isLocked()) {
                System.out.println(bullet);
                bullet = world.createBody(bulletDef);
                bullet.createFixture(bulletFixture_1);
                bullet.createFixture(bulletFixture_2);
                System.out.println(bullet);
                bullet.applyForceToCenter(
                        force * MathUtils.cos(weapon.getAngle()), force
                                * MathUtils.sin(weapon.getAngle()), true);
                Sprite sprite = new Sprite(new Texture(
                        "sprites\\Weapon\\bullet_standard.png"));
                sprite.setSize(1.03125f, 0.6875f);
                sprite.setOrigin((float) (sprite.getWidth() / 2 - 0.12f),
                        (float) (sprite.getHeight() / 2));
                bullet.setUserData(sprite);
                Bullets bullets = Bullets.getInstance(world);
                bullets.addBullet(bullet);
                bullets.setDmg(bulletDmg);
                System.out.println("Create bullet number: " + bullet);
                creationTimer.stop();
            }
        }

    }, 0, 1);
    creationTimer.start();
}

}

I have been facing this for quite some time now and can't figure out the problem, I would love some assistance with this. Thanks in advance!



I do not reuse any of the bullets created.
This is the code that handles collision with the enemy:

public void onCollision(final Body collidedBody, final String bodyHit,
        final int index) {
    assert instance != null;
    final Timer timer = new Timer();
    timer.scheduleTask(new Task() {
        @Override
        public void run() {
            if (!world.isLocked()) {
                Circles circles = Circles.getInstance();
                if (bodyHit.equalsIgnoreCase("ground")) {
                    if (bulletGroundCollision.get(index) == 5) {
                        if (bullets.get(index) != null) {
                            world.destroyBody(bullets.get(index));
                            bullets.removeIndex(index);
                            bulletGroundCollision.removeIndex(index);
                        }
                    } else
                        bulletGroundCollision.set(index,
                                (bulletGroundCollision.get(index) + 1));
                } else if (bodyHit.equalsIgnoreCase("enemy")) {
                    Circle enemy = circles
                            .findAccordingToCode(collidedBody);
                    enemy.damaged(bulletDmg);
                    System.out.println("Hit at: "
                            + bullets.get(index).getPosition());
                    if (bullets.get(index) != null) {
                        world.destroyBody(bullets.get(index));
                        bullets.removeIndex(index);
                        bulletGroundCollision.removeIndex(index);
                    }
                } else if (bodyHit.equalsIgnoreCase("player")) {
                    if (bullets.get(index) != null) {
                        world.destroyBody(bullets.get(index));
                        bullets.removeIndex(index);
                        bulletGroundCollision.removeIndex(index);
                    }
                    Square square = Square.getInstance(world);
                    square.damaged(bulletDmg);
                }
                timer.stop();
            }
        }

    }, 0, 1);
    timer.start();
}

The code for the bullet creation is already posted as the bullet class.
bullets - is an Array of bodies that are the bullets.
bulletGroundCollision - is an Array of ints which keeps track of how many times a bullet at i position (ie index), hit the ground.


I had noticed that after the bullet gets stuck, the collision with the bullet does not happen according to the body, instead it is only when there is a collision with the sprite that a collision is triggered.

Your code is somewhat hard to read. However you need to make sure that after your enemy is dead, you need to update your bullet class again with the update method in your bullet class.

boolean enemyDead;

if(damage<=0)
{
 bulletClass.updateBulletLocation();
}

I doesn't look like it to me that you are updating your bullet class after you kill the enemy, and because of this, the bullet stays where it is.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM