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
我对 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