Libgdx 没有解决冲突

Libgdx not resolving collisions

我对 libgdx 比较陌生,大约一周前才开始使用它。我现在面临 Box2D 动态物体的问题。它们呈现但无法相互交互(尽管它们受到施加于它们的力的影响)。我使用 GitHub 上的免费编辑器创建了这些主体。我一直在为此苦苦挣扎,但我似乎看不出有什么问题。

这是我的全部 类:

public class Bullet {
    float x;
    float y;
    int xDir = 0;
    int yDir = 0;
    boolean isFired = false;
    BodyDef bodyDef;
    Body body;
    Sprite sprite;
    FixtureDef fixtureDef;

    public Bullet(HashMap<String, Sprite> sprites, 
                  World world,Player player, 
                  BodyEditorLoader loader) {
    
        this.x =player.body.getWorldCenter().x;
        this.y =  player.body.getWorldCenter().y;
    
        bodyDef = new BodyDef();
        bodyDef.type = BodyDef.BodyType.DynamicBody;
        bodyDef.position.set(x, y);
        body = world.createBody(bodyDef);
    
        fixtureDef = new FixtureDef();
        fixtureDef.density = 0.5f; 
        fixtureDef.friction = 0.4f;
        fixtureDef.restitution = 0.0f;
    
        sprite = sprites.get("Bullet");
        sprite.setPosition(x, y);

        loader.attachFixture(body, "Bullet", fixtureDef, 20.0f);
    }

    public void setPosition(float x , float y) {
        this.x = x;
        this.y = y;
    }

    public void updateBulletBody() {
        sprite.setPosition(body.getPosition().x,body.getPosition().y);
    }

    public void tick() {
        sprite.translateX(xDir);
        sprite.translateY(yDir);
        x+= xDir;
        y+= yDir;
    }

    public void drawSprite(SpriteBatch batch) {
        sprite.setPosition(x, y);
        sprite.draw(batch);
    }

    public void setXDir(int value) {
        this.xDir = value;
    }

    public void setYDir(int value) {
        this.yDir = value; 
    }

    public float getX() {
        return x;
    }

    public float getY() {
        return y;
    }

    public Sprite getSprite() {
        return this.sprite;
    }
}

子弹管理器:

public class BulletManager {
    ArrayList <Bullet> ll;
    HashMap<String,Sprite> sprites;
    Player player;
    BodyEditorLoader loader;

    public BulletManager(HashMap<String,Sprite> sprites,
                         Player player, World world) {
    
        this.sprites = sprites;
        this.player = player;
    
        loader = new BodyEditorLoader(Gdx.files.internal("BodyColliders.json"));
    
        ll = new ArrayList<Bullet>();
    
        for(int i =0; i<150; i++) {
            ll.add(new Bullet(sprites,world,player,loader));
        }
    }
    
    public void tick() {
        for(Bullet bullet : ll) {
            if(bullet.isFired) bullet.tick();
        }
    }

    public void moveBulletPos(Player player) {
        for(Bullet bullet : ll) {
            if(!bullet.isFired)
                bullet.setPosition(player.body.getWorldCenter().x, player.body.getWorldCenter().y);
        }
    }

    public void renderBullet (Bullet bullet,SpriteBatch batch) {
        bullet.sprite.setScale(player.sprite.getScaleX()/2, player.sprite.getScaleY()/2);
        bullet.drawSprite(batch);
    }

    public void addBullet(Player player,World world) {
        ll.add(new Bullet(sprites,world,player,loader));
    }
}

我的僵尸游戏:

public class MyZombieGame extends ApplicationAdapter implements InputProcessor {
    TextureAtlas textureAtlas;
    SpriteBatch batch;
    OrthographicCamera camera;
    ExtendViewport viewport;

    static final float STEP_TIME = 1f / 60f;
    static final int VELOCITY_ITERATIONS = 6;
    static final int POSITION_ITERATIONS = 2;
    
    final HashMap<String, Sprite> sprites = new HashMap<String, Sprite>();

    Player player;
    Zombie zombie;
    BulletManager magazine;

    int bulletCounter = 0;

    World world;
    BodyEditorLoader loader;
    Box2DDebugRenderer debugRenderer;

    private float accumulator = 0;

    @Override
    public void create () {
        Box2D.init();
        loader = new BodyEditorLoader(Gdx.files.internal("BodyColliders.json"));
        world = new World(new Vector2(0,0),true);
        debugRenderer = new Box2DDebugRenderer();
        textureAtlas = new TextureAtlas("Sprites.txt");
        batch = new SpriteBatch();
        camera = new OrthographicCamera();
        viewport = new ExtendViewport(800, 600, camera);
        Gdx.input.setInputProcessor(this);
        addSprites();
        player = new Player(sprites,world,loader);
        zombie = new Zombie(sprites,world,loader);
        magazine = new BulletManager(sprites,player,world);
    }

    private void stepWorld() {
        float delta = Gdx.graphics.getDeltaTime();
        accumulator += Math.min(delta, 0.25f);

        if (accumulator >= STEP_TIME) {
            accumulator -= STEP_TIME;
            world.step(STEP_TIME, VELOCITY_ITERATIONS, POSITION_ITERATIONS);
        }
    }

    @Override
    public void render () {
        Gdx.gl.glClearColor(0f, 0f, 0f, 1f);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
     
        checkInput();
        debugRenderer.render(world,camera.combined);
     
        world.step(1/60f, 6, 2);
    }


    public void cameraUpdate() {
        Vector3 position = camera.position;
        position.x = player.body.getPosition().x;
        position.y = player.body.getPosition().y;
        camera.position.set(position);
        camera.update();
    }

    public void checkInput() {
        int linearForce =0;
    
        if(Gdx.input.isKeyPressed(Keys.UP)) {
            player.body.applyLinearImpulse(0, -100.0f, player.body.getWorldCenter().x, 
            player.body.getWorldCenter().y, true);
        }
        if(Gdx.input.isKeyPressed(Keys.DOWN)) {
            player.body.applyLinearImpulse(0, 100.0f,  player.body.getWorldCenter().x, 
            player.body.getWorldCenter().y, true);
        }
        if(Gdx.input.isKeyPressed(Keys.LEFT)) {
            player.body.applyLinearImpulse(100.0f, 0,  player.body.getWorldCenter().x, 
            player.body.getWorldCenter().y, true);
        }
        if(Gdx.input.isKeyPressed(Keys.RIGHT)) {
            player.body.applyLinearImpulse(-100.0f, 0, player.body.getWorldCenter().x, 
            player.body.getWorldCenter().y, true);
        }
    }

    public void drawSprite(String name, float x, float y) {
        Sprite sprite = sprites.get(name);
    
        sprite.setPosition(x, y);
        sprite.draw(batch);
    
    }

    public void drawSprite(Sprite sprite) {
        sprite.draw(batch);
    }


    public void addSprites() {
        Array<AtlasRegion> regions = textureAtlas.getRegions();
    
        for(AtlasRegion region : regions) {
            Sprite sprite = textureAtlas.createSprite(region.name);
            sprites.put(region.name, sprite);
        }
    }

    @Override
    public void resize(int width, int height) {
        viewport.update(width, height, true);
        batch.setProjectionMatrix(camera.combined);
    }

    @Override
    public void dispose () {
        textureAtlas.dispose();
        sprites.clear();
        magazine.ll.clear();
        magazine.sprites.clear();
        debugRenderer.dispose();
        world.dispose();
    }


    //KeyBoard Input
    @Override
    public boolean keyDown(int keycode) {

        if(keycode == Keys.C) {
            if(bulletCounter < magazine.ll.size()) {
                for(int i =0; i<magazine.ll.size(); i++) {
                    magazine.ll.get(bulletCounter).isFired = true;
                }
                bulletCounter++;
            }
        }
    
        if(keycode == Keys.UP) { }
    
        if(keycode == Keys.DOWN) { }
    
        if(keycode == Keys.LEFT) { }
    
        if(keycode == Keys.RIGHT) { }
    
        return false;
    }

    @Override
    public boolean keyUp(int keycode) {
        if(keycode == Keys.UP) {
            player.yDir =0;
        
            for(Bullet bullet : magazine.ll) {
                if(!bullet.isFired) {
                    bullet.setXDir(0);
                    bullet.setYDir(1);
                }
            }
        
        }
        if(keycode == Keys.DOWN) {
            player.yDir =0;
        
            for(Bullet bullet : magazine.ll) {
                if(!bullet.isFired) {
                    bullet.setXDir(0);
                    bullet.setYDir(-1);
                }
            }
        
        }
        if(keycode == Keys.LEFT) {
            player.xDir =0;

            for(Bullet bullet : magazine.ll) {
                if(!bullet.isFired) {
                    bullet.setXDir(-1);
                    bullet.setYDir(0);
                }
            }
        
        }
        if(keycode == Keys.RIGHT) {
            player.xDir =0;
        
            for(Bullet bullet : magazine.ll) {
                if(!bullet.isFired) {
                    bullet.setXDir(1);
                    bullet.setYDir(0);
                }
            }
        }
        return false;
    }

    @Override
    public boolean keyTyped(char character) {
        return false;
    }

    @Override
    public boolean touchDown(int screenX, int screenY, int pointer, int button) {
        return false;
    }

    @Override
    public boolean touchUp(int screenX, int screenY, int pointer, int button) {
        return false;
    }

    @Override
    public boolean touchDragged(int screenX, int screenY, int pointer) {
        return false;
    }

    @Override
    public boolean mouseMoved(int screenX, int screenY) {
            return false;
    }

    @Override
    public boolean scrolled(float amountX, float amountY) {
        return false;
    }
}

玩家:

public class Player {

    float x  = 200;
    float y = 200;
    float xCenter = x + 20; // the center is at xCoordinates + half the side
    float yCenter = y + 20; // same
    int xDir = 0;
    int yDir = 5;
    int width = 40;
    int height = 40;
    int dashDirX =0;
    int dashDirY=0;
    int energy = 100;

    Sprite sprite;
    BodyDef bodyDef;
    Body body;
    FixtureDef fixtureDef;

    public Player(HashMap<String, Sprite> sprites, 
                  World world, BodyEditorLoader loader) {
    
    
        sprite = sprites.get("Player");
        sprite.setPosition(x, y);
        sprite.setScale(sprite.getScaleX()/4, sprite.getScaleY()/4);
        bodyDef = new BodyDef();
        bodyDef.type = BodyDef.BodyType.DynamicBody;
        bodyDef.position.set(x, y);
        body = world.createBody(bodyDef);
    
        //body.setUserData(this);
    
        fixtureDef = new FixtureDef();
        fixtureDef.isSensor = true;
        fixtureDef.density = 0.5f; 
        fixtureDef.friction = 0.4f;
        fixtureDef.restitution = 0.4f;

        loader.attachFixture(body, "Player",fixtureDef, 40.0f);
    
    }
 
    public void updatePlayer(SpriteBatch batch) {
        Vector2 position = body.getPosition();
        x= position.x;
        y=position.y;
        sprite.setPosition(position.x, position.y);
        sprite.draw(batch);
    }
}

僵尸:

public class Zombie {

    Random r = new Random();
    float x = 20;
    float y = 300;
    int width = 50;
    int height = 50;
    int xDir;
    int yDir;

    boolean knockedBack = false;
    public Rectangle zombie;
    public boolean alive = true;
    int knockBackForce = 3;
    boolean shouldChase = true;
    int knockBackDir;
    public int Health = 100;
    float xCenter = x + 25;
    float yCenter = y + 25;

    Sprite sprite;
    BodyDef bodyDef;
    Body body;
    FixtureDef fixtureDef;

    public Zombie(HashMap<String, Sprite> sprites, 
                  World world, BodyEditorLoader loader) {

        sprite = sprites.get("Zombie");
        sprite.setPosition(x,y);
        sprite.setScale(sprite.getScaleX()/4, sprite.getScaleY()/4);
    
        bodyDef = new BodyDef();
        bodyDef.type = BodyDef.BodyType.DynamicBody;
        bodyDef.position.set(x, y);
        body = world.createBody(bodyDef);
 
        fixtureDef = new FixtureDef();
        fixtureDef.density = 0.8f; 
        fixtureDef.friction = 0.4f;
        fixtureDef.restitution = 0.7f;
        fixtureDef.isSensor = true;
    
    
        loader.attachFixture(body, "Player",fixtureDef, 40.0f);
    }

    public void updateZombie(SpriteBatch batch) {
        if (alive) {
            Vector2 position = body.getPosition();
            sprite.setPosition(position.x, position.y);
            sprite.draw(batch);
        }
    }

    public void attack () {
        xDir = 0;
        yDir = 0;
    }
    public void setX(int value) {
        x = value;
    }

    public void setY(int value) {
        y = value;
    }

    public void setPos(int x, int y) {
        this.x = x;
        this.y = x;
    }
}

您没有设置碰撞遮罩来指定什么与什么发生碰撞,即

public static final short xZOMBIE       = 0x0001;
public static final short xBULLET       = 0x0002;
public static final short xWALL         = 0x0004;

还有你的面具

public static final short ZOMBIE_MASK = XBULLET | xWALL; //| to add collidables
public static final short BULLET_MASK = xZOMBIE etc

然后在灯具上设置这些

zombieFixtureDef.filter.categoryBits = xZOMBIE;
zombieFixtureDef.filter.maskBits = ZOMBIE_MASK;

看这里 https://www.aurelienribon.com/post/2011-07-box2d-tutorial-collision-filtering