在 Android studio 上使用 Box2D 与 Libgdx 发生碰撞时,对象并未完全销毁。精灵不能完全穿过被破坏的物体
Object is not fully destroyed upon collision using Box2D with Libgdx on Android studio. Sprite can't go through destroyed object completely
我正在 Android Studio 中使用 Libgdx 开发超级马里奥兄弟游戏,到目前为止我没有遇到任何错误,项目运行良好。然而,当我使用 Box2D 的类别和蒙版过滤器到 "destroy" 一个与精灵碰撞的对象时(当马里奥跳跃并且他的头撞到砖块导致砖块破裂时),尽管砖块得到 "destroyed",马里奥只能跳过曾经是砖块的地方,直到他的头到达砖块的上层(物体方形轮廓的顶部)。以下是一些截图:
正如你所看到的,马里奥不能跳得比上部微弱的绿线更高,这表明被破坏的顶部 brick.The 碰撞检测工作正常,因为我写了一些代码让日志显示 "Brick: Collision" 如果检测到与砖块的碰撞,这是他第一次与砖块碰撞时的结果——这是应该的。于是我的问题就来了,为什么他不跳得比被毁坏的砖块的顶部更高,而他应该能够自由跳跃,就好像根本没有物体一样。目前,他正从广场的顶部弹起,因此他无法走得更高。这是相关代码:
主要class:
public static final short DEFAULT_BIT = 1;
public static final short MARIO_BIT = 2;
public static final short BRICK_BIT = 4;
public static final short COIN_BIT = 8;
public static final short DESTROYED_BIT = 16;
InteractiveTileObject class:
public abstract void onHeadHit();
public void setCategoryFilter(short filterBit){
Filter filter = new Filter();
filter.categoryBits = filterBit;
fixture.setFilterData(filter);
}
public TiledMapTileLayer.Cell getCell(){
TiledMapTileLayer layer = (TiledMapTileLayer) map.getLayers().get(1);
return layer.getCell((int)(body.getPosition().x * SuperMarioBros.PPM / 16),
(int)(body.getPosition().y * SuperMarioBros.PPM / 16));
马里奥精灵 class:
FixtureDef fdef = new FixtureDef();
CircleShape shape = new CircleShape();
shape.setRadius(6 / SuperMarioBros.PPM);
fdef.filter.categoryBits = SuperMarioBros.MARIO_BIT;
fdef.filter.maskBits = SuperMarioBros.DEFAULT_BIT | SuperMarioBros.COIN_BIT | SuperMarioBros.BRICK_BIT ;
fdef.shape = shape;
b2body.createFixture(fdef);
FixtureDef fdef2 = new FixtureDef();
EdgeShape feet = new EdgeShape();
feet.set(new Vector2(-2 / SuperMarioBros.PPM, -6 / SuperMarioBros.PPM), new Vector2(2 / SuperMarioBros.PPM, -6 / SuperMarioBros.PPM));
fdef2.shape = feet;
b2body.createFixture(fdef2);
EdgeShape head = new EdgeShape();
head.set(new Vector2(-2/SuperMarioBros.PPM, 6/SuperMarioBros.PPM), new Vector2(2/SuperMarioBros.PPM, 6/SuperMarioBros.PPM));
fdef.shape = head;
fdef.isSensor = true;
b2body.createFixture(fdef).setUserData("head");
砖块精灵class:
public class Brick extends InteractiveTileObject {
public Brick(World world, TiledMap map, Rectangle bounds) {
super(world, map, bounds);
fixture.setUserData(this);
setCategoryFilter(SuperMarioBros.BRICK_BIT);
}
@Override
public void onHeadHit() {
Gdx.app.log("Brick", "Collision");
setCategoryFilter(SuperMarioBros.DESTROYED_BIT);
getCell().setTile(null);
}
}
请帮助我已经为这个问题苦苦挣扎了很长一段时间,并没有在任何地方找到在线解决方案
我通过将 filter.maskBits 和 filter.categoryBits 过滤器应用于马里奥脚部的 fdef2 来解决这个问题。我直接复制粘贴:
fdef.filter.categoryBits = SuperMarioBros.MARIO_BIT;
fdef.filter.maskBits = SuperMarioBros.DEFAULT_BIT | SuperMarioBros.COIN_BIT | SuperMarioBros.BRICK_BIT ;
并将 fdef 重命名为 fdef2,因此我的代码现在如下所示:
FixtureDef fdef = new FixtureDef();
CircleShape shape = new CircleShape();
shape.setRadius(6 / SuperMarioBros.PPM);
fdef.filter.categoryBits = SuperMarioBros.MARIO_BIT;
fdef.filter.maskBits = SuperMarioBros.DEFAULT_BIT | SuperMarioBros.COIN_BIT | SuperMarioBros.BRICK_BIT ;
fdef.shape = shape;
b2body.createFixture(fdef);
FixtureDef fdef2 = new FixtureDef();
EdgeShape feet = new EdgeShape();
feet.set(new Vector2(-2 / SuperMarioBros.PPM, -6 / SuperMarioBros.PPM), new Vector2(2 / SuperMarioBros.PPM, -6 / SuperMarioBros.PPM));
fdef2.filter.categoryBits = SuperMarioBros.MARIO_BIT;
fdef2.filter.maskBits = SuperMarioBros.DEFAULT_BIT | SuperMarioBros.COIN_BIT | SuperMarioBros.BRICK_BIT ;
fdef2.shape = feet;
b2body.createFixture(fdef2);
EdgeShape head = new EdgeShape();
head.set(new Vector2(-2/SuperMarioBros.PPM, 6/SuperMarioBros.PPM), new Vector2(2/SuperMarioBros.PPM, 6/SuperMarioBros.PPM));
fdef.shape = head;
fdef.isSensor = true;
b2body.createFixture(fdef).setUserData("head");
这似乎有效,但我不太确定为什么?我认为这是因为现在他的脚可以穿过广场的底部,而不是他的头不能穿过广场的顶部。我认为问题的根本原因是他的脚在头部没有检测到物体时,所以马里奥无法让他的脚穿过广场。
---编辑---
我意识到我什至不需要固定他的脚,所以删除所有与 fdef2 相关的代码都可以相应地工作并产生应有的结果。
我正在 Android Studio 中使用 Libgdx 开发超级马里奥兄弟游戏,到目前为止我没有遇到任何错误,项目运行良好。然而,当我使用 Box2D 的类别和蒙版过滤器到 "destroy" 一个与精灵碰撞的对象时(当马里奥跳跃并且他的头撞到砖块导致砖块破裂时),尽管砖块得到 "destroyed",马里奥只能跳过曾经是砖块的地方,直到他的头到达砖块的上层(物体方形轮廓的顶部)。以下是一些截图:
主要class:
public static final short DEFAULT_BIT = 1;
public static final short MARIO_BIT = 2;
public static final short BRICK_BIT = 4;
public static final short COIN_BIT = 8;
public static final short DESTROYED_BIT = 16;
InteractiveTileObject class:
public abstract void onHeadHit();
public void setCategoryFilter(short filterBit){
Filter filter = new Filter();
filter.categoryBits = filterBit;
fixture.setFilterData(filter);
}
public TiledMapTileLayer.Cell getCell(){
TiledMapTileLayer layer = (TiledMapTileLayer) map.getLayers().get(1);
return layer.getCell((int)(body.getPosition().x * SuperMarioBros.PPM / 16),
(int)(body.getPosition().y * SuperMarioBros.PPM / 16));
马里奥精灵 class:
FixtureDef fdef = new FixtureDef();
CircleShape shape = new CircleShape();
shape.setRadius(6 / SuperMarioBros.PPM);
fdef.filter.categoryBits = SuperMarioBros.MARIO_BIT;
fdef.filter.maskBits = SuperMarioBros.DEFAULT_BIT | SuperMarioBros.COIN_BIT | SuperMarioBros.BRICK_BIT ;
fdef.shape = shape;
b2body.createFixture(fdef);
FixtureDef fdef2 = new FixtureDef();
EdgeShape feet = new EdgeShape();
feet.set(new Vector2(-2 / SuperMarioBros.PPM, -6 / SuperMarioBros.PPM), new Vector2(2 / SuperMarioBros.PPM, -6 / SuperMarioBros.PPM));
fdef2.shape = feet;
b2body.createFixture(fdef2);
EdgeShape head = new EdgeShape();
head.set(new Vector2(-2/SuperMarioBros.PPM, 6/SuperMarioBros.PPM), new Vector2(2/SuperMarioBros.PPM, 6/SuperMarioBros.PPM));
fdef.shape = head;
fdef.isSensor = true;
b2body.createFixture(fdef).setUserData("head");
砖块精灵class:
public class Brick extends InteractiveTileObject {
public Brick(World world, TiledMap map, Rectangle bounds) {
super(world, map, bounds);
fixture.setUserData(this);
setCategoryFilter(SuperMarioBros.BRICK_BIT);
}
@Override
public void onHeadHit() {
Gdx.app.log("Brick", "Collision");
setCategoryFilter(SuperMarioBros.DESTROYED_BIT);
getCell().setTile(null);
}
}
请帮助我已经为这个问题苦苦挣扎了很长一段时间,并没有在任何地方找到在线解决方案
我通过将 filter.maskBits 和 filter.categoryBits 过滤器应用于马里奥脚部的 fdef2 来解决这个问题。我直接复制粘贴:
fdef.filter.categoryBits = SuperMarioBros.MARIO_BIT;
fdef.filter.maskBits = SuperMarioBros.DEFAULT_BIT | SuperMarioBros.COIN_BIT | SuperMarioBros.BRICK_BIT ;
并将 fdef 重命名为 fdef2,因此我的代码现在如下所示:
FixtureDef fdef = new FixtureDef();
CircleShape shape = new CircleShape();
shape.setRadius(6 / SuperMarioBros.PPM);
fdef.filter.categoryBits = SuperMarioBros.MARIO_BIT;
fdef.filter.maskBits = SuperMarioBros.DEFAULT_BIT | SuperMarioBros.COIN_BIT | SuperMarioBros.BRICK_BIT ;
fdef.shape = shape;
b2body.createFixture(fdef);
FixtureDef fdef2 = new FixtureDef();
EdgeShape feet = new EdgeShape();
feet.set(new Vector2(-2 / SuperMarioBros.PPM, -6 / SuperMarioBros.PPM), new Vector2(2 / SuperMarioBros.PPM, -6 / SuperMarioBros.PPM));
fdef2.filter.categoryBits = SuperMarioBros.MARIO_BIT;
fdef2.filter.maskBits = SuperMarioBros.DEFAULT_BIT | SuperMarioBros.COIN_BIT | SuperMarioBros.BRICK_BIT ;
fdef2.shape = feet;
b2body.createFixture(fdef2);
EdgeShape head = new EdgeShape();
head.set(new Vector2(-2/SuperMarioBros.PPM, 6/SuperMarioBros.PPM), new Vector2(2/SuperMarioBros.PPM, 6/SuperMarioBros.PPM));
fdef.shape = head;
fdef.isSensor = true;
b2body.createFixture(fdef).setUserData("head");
这似乎有效,但我不太确定为什么?我认为这是因为现在他的脚可以穿过广场的底部,而不是他的头不能穿过广场的顶部。我认为问题的根本原因是他的脚在头部没有检测到物体时,所以马里奥无法让他的脚穿过广场。
---编辑--- 我意识到我什至不需要固定他的脚,所以删除所有与 fdef2 相关的代码都可以相应地工作并产生应有的结果。