Java LibGDX阻止body获取以前删除的body的属性
为清晰起见,请观看视频: 我正在制作我的第一个LibGDX游戏,我在销毁和创建尸体方面遇到了困难。我一直在使用这个片段(因为它似乎无处不在)来移除尸体:Java LibGDX阻止body获取以前删除的body的属性,java,libgdx,box2d,Java,Libgdx,Box2d,为清晰起见,请观看视频: 我正在制作我的第一个LibGDX游戏,我在销毁和创建尸体方面遇到了困难。我一直在使用这个片段(因为它似乎无处不在)来移除尸体: private void sweepDeadBodies() { for (Iterator<Body> iter = tmpBodies.iterator(); iter.hasNext();) { Body body = iter.next(); if (body != null) {
private void sweepDeadBodies() {
for (Iterator<Body> iter = tmpBodies.iterator(); iter.hasNext();) {
Body body = iter.next();
if (body != null) {
Entity data = (Entity) body.getUserData(); //Just the bodies data
if (data.isFlaggedForDelete) {
iter.remove();
world.destroyBody(body);
body.setUserData(null);
body = null;
}
}
}
}
记录错误(我只能找到类似堆栈跟踪的东西)
(TestControls是我们正在使用的屏幕)
设置删除标志的世界联系人侦听器:
world.setContactListener(new ContactListener() {
@Override
public void beginContact(Contact contact) {
}
@Override
public void endContact(Contact contact) {
if (contact.getFixtureA().getFilterData().categoryBits == Entities.CATEGORY_PLAYER_PROJECTILE
&& contact.getFixtureB().getFilterData().categoryBits == Entities.CATEGORY_ENEMY) {
((Entity) contact.getFixtureA().getBody().getUserData()).isFlaggedForDelete = true;
((Entity) contact.getFixtureB().getBody().getUserData())
.damage(((Entity) contact.getFixtureA().getBody()
.getUserData()).damage);
}
if (contact.getFixtureA().getFilterData().categoryBits == Entities.CATEGORY_ENEMY
&& contact.getFixtureB().getFilterData().categoryBits == Entities.CATEGORY_PLAYER_PROJECTILE) {
((Entity) contact.getFixtureB().getBody().getUserData()).isFlaggedForDelete = true;
((Entity) contact.getFixtureA().getBody().getUserData())
.damage(((Entity) contact.getFixtureB().getBody()
.getUserData()).damage);
}
}
@Override
public void preSolve(Contact contact, Manifold oldManifold) {
}
@Override
public void postSolve(Contact contact, ContactImpulse impulse) {
}
});
你必须把激光器排成一排。他们正在离开范围并被摧毁,但尸体仍然活着。box2d回收车身,因此可能会导致问题。像那样在渲染中创建它们也很糟糕。对于生命周期短的任何东西,都应该使用池 以任何方式触摸弃置的尸体都会炸毁游戏,所以最好不要在游戏中弃置尸体 我最近发布了libgdx/box2d游戏,该游戏广泛使用池。您可以在查看代码 还有endContact(),请将其清理干净。它不可能被阅读。大概是这样吧
@Override
public void endContact(Contact contact) {
Fixture fA = contact.getFixtureA();
Fixture fB = contact.getFixtureB();
if (isPlayerProjectile(fA) && isEnemy(fB)) {
Entity projectile = (Entity) contact.getFixtureA().getBody().getUserData();
Entity enemy = (Entity) contact.getFixtureB().getBody().getUserData();
solveProjectileEnemyContact(projectile, enemy);
} else if (isPlayerProjectile(fB) && isEnemy(fA)) {
Entity projectile = (Entity) contact.getFixtureB().getBody().getUserData();
Entity enemy = (Entity) contact.getFixtureA().getBody().getUserData();
solveProjectileEnemyContact(projectile, enemy);
}
}
private boolean isPlayerProjectile(Fixture fixture){
return fixture.getFilterData().categoryBits == Entities.CATEGORY_PLAYER_PROJECTILE;
}
private boolean isEnemy(Fixture fixture){
return fixture.getFilterData().categoryBits == Entities.CATEGORY_ENEMY;
}
private void solveProjectileEnemyContact(Entity projectile, Entity enemy){
projectile.isFlaggedForDelete = true;
enemy.damage(projectile.damage);
}
在过去的两天里,我也遇到了同样的问题 这是一个简单的bug,我有一个当前显示的实体的ArrayList。如果发生碰撞,我会像你一样设置一面旗帜。后来,我运行了我的实体ArrayList并删除了每个被标记的实体体——但不是实体本身 这是我的删除代码。它对我有效,我希望它对你也有效
CopyOnWriteArrayList<Entity> entities = new CopyOnWriteArrayList<Entity>();
public void deleteEntities() {
for(Entity entity: entities){
Body body = entity.getBody();
if (body != null) {
EntityData data = (EntityData) body.getUserData();
if (data.isFlaggedForDelete()) {
final Array<JointEdge> list = body.getJointList();
//delete all joints attached
while (list.size > 0) {
myWorld.getWorld().destroyJoint(list.get(0).joint);
}
//nullify everything, remove the entity from entities and destroy the body
body.setUserData(null);
myWorld.getWorld().destroyBody(body);
entities.remove(entity);
body = null;
}
}
}
}
CopyOnWriteArrayList实体=新建CopyOnWriteArrayList();
公共实体(){
for(实体:实体){
Body=entity.getBody();
if(body!=null){
EntityData data=(EntityData)body.getUserData();
if(data.isFlaggedForDelete()){
最终数组列表=body.getJointList();
//删除所有附着的关节
而(list.size>0){
myWorld.getWorld().destroyJoint(list.get(0.joint));
}
//取消所有内容,从实体中移除实体并销毁实体
body.setUserData(空);
myWorld.getWorld().destroyBody(body);
实体。移除(实体);
body=null;
}
}
}
}
另外,请确保不要过早处理()!也可能是个问题
我希望这是有帮助的:-)我知道这个问题已经很老了,但我想分享一下我的经验,这个错误与选择的答案没有帮助 因此,对于仍在经历此问题的任何人,我就是这样解决的: 我没有随机创建和删除我的身体,而是用两种方法创建和删除了所有创建和删除:
//CREATE ALL
public void createAll(){
if(!world.isLocked()){ //KEY FACTOR
if(createEnemy){
createEnemy();
}
if(createBullet){
createBullet();
}
}
}
删除:
//get rid of all bodies (toBeDeleted is an Array<Body>)
public void sweepDeadBodies() {
if(!world.isLocked()){ // KEY FACTOR
Array<Body> wB = getBodies();
for (Body body : wB) {
if(body!=null && toBeDeleted.contains(body, false)) {
body.setUserData(null);
world.destroyBody(body);
toBeDeleted.removeValue(body, false);
}
}
}
}
最后,我的敌人()
还有我的createBullet():
在我标记删除后,所有待删除的实体都在那里,如下所示:
((UserData) enemy.getBody().getUserData()).isFlaggedForDelete = true;
并添加如下内容:
if(((UserData)body.getUserData()).isFlaggedForDelete){
toBeDeleted.add(body);
}
在我的更新方法
我希望这对某人有帮助。基本上,我的错误是在没有检查世界是否被锁定的情况下创建/销毁尸体,我通过调用!世界。已锁定() 首先,除了设备非关闭的堆栈跟踪之外,是否还有另一个堆栈跟踪被输出?这通常是当你运行游戏的窗口突然崩溃时出现的。其次,在销毁主体的userData之前,应该尝试将其设置为null。最后,您能给出为要销毁的实体集设置markedForDelete的代码吗?谢谢您的回复。我添加了请求的代码。我事先将用户数据设置为null,但仍然得到相同的错误。哇。你的比赛(显然)比我现在的水平有了飞跃。您能告诉我开始查看哪些文件的正确方向吗?请注意,destroyBody也会自动销毁所有关联的关节,因此无需手动执行此操作
//get rid of all bodies (toBeDeleted is an Array<Body>)
public void sweepDeadBodies() {
if(!world.isLocked()){ // KEY FACTOR
Array<Body> wB = getBodies();
for (Body body : wB) {
if(body!=null && toBeDeleted.contains(body, false)) {
body.setUserData(null);
world.destroyBody(body);
toBeDeleted.removeValue(body, false);
}
}
}
}
@Override
public void draw() {
super.draw();
glyphLayout.setText(scoreFont, score);
//Do all my deleting and creating after the world.step !!! VERY IMPORTANT!!!
sweepDeadBodies();
removeEmtpyActors(); //I use actors as containers for the body, so here i loop though them all and nullify them
createAll();
renderer.render(world, camera.combined);
}
private void createEnemy() {
Enemy enemy= new Enemy(WorldUtils.createEnemy(world));
((UserData) enemy.getBody().getUserData()).isFlaggedForDelete = false;
addActor(enemy);
addGameActor(enemy); //again this is just for me, you might be using entities or something else
createEnemy = false;
}
public void createBullet(){
Bullet bullet = new Bullet(WorldUtils.createBullet(world));
((UserData) bullet.getBody().getUserData()).isFlaggedForDelete = false;
addActor(bullet);
addGameActor(bullet);
bullet.fire(); //just adds a linear impulse
createBullet= false;
}
((UserData) enemy.getBody().getUserData()).isFlaggedForDelete = true;
if(((UserData)body.getUserData()).isFlaggedForDelete){
toBeDeleted.add(body);
}