LibGDX阻止主体获取先前删除的主体的属性 [英] LibGDX Stop body from taking properties of previously deleted body

查看:49
本文介绍了LibGDX阻止主体获取先前删除的主体的属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

清晰度视频: https://www .youtube.com/watch?v = 3Mrro8sjcqo#t = 25

我正在制作我的第一个LibGDX游戏,但是我在销毁和创建尸体方面遇到困难.我一直在使用此代码段(因为似乎无处不在)来删除正文:

I'm making my first LibGDX game, and I'm having trouble destroying and creating bodies. I've been using this snippet (because it seems to be everywhere) to remove bodies:

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;
            }
        }
    }
}

这按预期效果很好,但是运行之后不久,它崩溃了.我得到了整个" AL lib:(EE)alc_cleanup:1设备未关闭"的信息.我进行了一些调试,得出的结论是,当一个对象被销毁后,当我的一个实体发射弹丸时,它崩溃了.这是一个非常特殊的问题.被摧毁的实体正在缓慢地运转着.销毁后,当发射下一个弹丸时,它会照常显示,但不会移动,并以与被摧毁实体相同的缓慢圆周运动.如果播放器再次射击,则会崩溃.我很困惑有什么想法吗?

That works great, just as intended, but shortly after running it, it crashes. I get the whole "AL lib: (EE) alc_cleanup: 1 device not closed" thing. I did some debugging and came to the conclusion that it was crashing when one of my entities fires a projectile, after an object is destroyed. Its a very peculiar problem. The entity that was destroyed was continuously going in a slow circle. After being destroyed, when the next projectile is fired, it will appear as normal, but not move, and take on that same slow circular movement of the entity it destroyed. If the player fires again, it crashes. I'm stumped. Any thoughts?

这里是有问题的源代码

/*Render Loop in screen:*/    

public void render(float delta) {
    Gdx.gl.glClearColor(0, 0, 0, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);



    // Update World, Camera, and State Time
    world.step(TIMESTEP, VELOCITYITERATIONS, POSITIONITERATIONS);
    sweepDeadBodies();
    camera.update();
    stateTime += delta;

    // Get Fire Buttons
    System.out.println(player.stateTime % 2);
    if (aButton.isPressed() && player.stateTime / 0.25 >= 1) {
        player.stateTime = 0f;
        //Projectile in question
        Laser laser = new Laser(world, player.getBody().getPosition()); 
    }

    // Update the player
    player.update(joyStick.getKnobPercentX(), joyStick.getKnobPercentY(),
            delta);
    enemy.update(delta);

    // Order the bodies
    world.getBodies(tmpBodies);
    Iterator<Body> iterator = tmpBodies.iterator();
    int j;
    boolean flag = true; // set flag to true to begin first pass

    while (flag) {
        flag = false; // set flag to false awaiting a possible swap
        for (j = 0; j < tmpBodies.size - 1; j++) {
            if (tmpBodies.get(j).getType() == BodyType.DynamicBody
                && tmpBodies.get(j + 1).getType() == BodyType.StaticBody) {

                tmpBodies.swap(j, j + 1);
                flag = true;

            }
        }
    }

    /*ADDED THIS, FORGOT TO LEAVE WHEN TRIMMING CODE FOR POST*/
    for (Body body : tmpBodies) {

        // Entity
        if (body.getUserData() instanceof Entity) {
            Entity entity = (Entity) body.getUserData();

            if (entity.sprite != null) {
                entity.sprite.setPosition(body.getPosition().x
                        - entity.sprite.getWidth() / 2,
                        body.getPosition().y - entity.sprite.getHeight()
                                / 2);
                entity.sprite.setRotation(body.getAngle()
                        * MathUtils.radiansToDegrees);
                entity.sprite.draw(batch);
            }

            // Damage
            if (entity.health <= 0) {
                // entity.isFlaggedForDelete = true;
                entity.die();
            }
        }
    }

    // Render Box2D World
    debugRenderer.render(world, camera.combined);

    // Render Stage
    stage.draw();

}


/*Laser Class:*/  
public class Laser {

    private Body    body;
    private Fixture fixture;
    private Vector2 velocity    = new Vector2();
    private float   speed       = 4800;
    private World   world;

    public Laser(World world, Vector2 pos) {
        this.world = world;

        // Body Definition
        BodyDef bodyDef = new BodyDef();
        bodyDef.type = BodyType.DynamicBody;
        bodyDef.position.set(pos);
        bodyDef.fixedRotation = true;
        bodyDef.gravityScale = 0;
        bodyDef.linearVelocity.x = 100f;

        // Shape
        PolygonShape shape = new PolygonShape();
        shape.setAsBox(2, 0.25f);

        // Fixture Definition
        FixtureDef fixtureDef = new FixtureDef();
        fixtureDef.shape = shape;
        fixtureDef.restitution = 0f;
        fixtureDef.friction = .8f;
        fixtureDef.density = 0f;
        fixtureDef.filter.categoryBits = Entities.CATEGORY_PLAYER_PROJECTILE;
        fixtureDef.filter.maskBits = Entities.MASK_PLAYER_PROJECTILE;

        // Create Body
        body = world.createBody(bodyDef);
        fixture = body.createFixture(fixtureDef);

        // Assign Entity to Body
        Sprite sprite = new Sprite(new Texture("sprites/projectiles/laser.png"));
        sprite.setSize(2, 0.25f);
        Entity entity = new Entity();
        entity.sprite = sprite;
        entity.speed = 100f;
        entity.damage = 20f;
        entity.type = Entities.CATEGORY_PLAYER_PROJECTILE;
        body.setUserData(entity);
        body.setBullet(true);
    }

    public float getRestitution() {
        return fixture.getRestitution();
    }

    public void setRestitution(float restitution) {
        fixture.setRestitution(restitution);
    }

    public Body getBody() {
        return body;
    }

    public Fixture getFixture() {
        return fixture;
    }

}

崩溃时抛出错误:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000066bcbd0d, pid=63044, tid=52440
#
# JRE version: Java(TM) SE Runtime Environment (7.0_45-b18) (build 1.7.0_45-b18)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (24.45-b08 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C  [gdx-box2d64.dll+0xbd0d]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\Programming\Eclipse Projects\#######\desktop\hs_err_pid63044.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
AL lib: (EE) alc_cleanup: 1 device not closed

记录了错误(仅堆栈跟踪,如我能找到的东西) (TestControls是我们正在使用的屏幕)

Error logged (only stack trace like thing I could find) (TestControls is the screen we are working in)

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  com.badlogic.gdx.physics.box2d.World.jniCreateBody(JIFFFFFFFFZZZZZF)J+0
j  com.badlogic.gdx.physics.box2d.World.createBody(Lcom/badlogic/gdx/physics/box2d/BodyDef;)Lcom/badlogic/gdx/physics/box2d/Body;+80
J  ####.###########.########.screens.levels.TestControls.render(F)V
j  com.badlogic.gdx.Game.render()V+19
j  com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop()V+619
j  com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run()V+27
v  ~StubRoutines::call_stub

设置删除标记的世界联系人侦听器:

World contact listener that sets flag for delete:

    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) {
        }
    });

推荐答案

最近2天,我遇到了完全相同的问题.

I had exactly the same problem happen to me the last 2 days.

这是一个简单的错误,其中显示了当前显示的实体的ArrayList.如果发生碰撞,我会像您一样设置一个标志.稍后,我遍历Entity ArrayList并删除了所有已标记的Entities主体-但未删除Entity本身!

It was a simple bug where I had an ArrayList of Entities which are displayed at the moment. If a collision happened, I set a flag just as you did. Later, I run through my Entity ArrayList and deleted every Entities body which was flagged - but not the Entity itself!

这是我的删除代码.它对我有用,我希望它也对您有用.

Here's my deletion code. It works for me, I hope it works for you as well.

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;                    
            }
        }
    }
}

另外,请确保不要过早处理dispose()!也可能是个问题.

Additionally make sure you dont dispose() too early! Could be a problem as well.

我希望这会有所帮助:-)

I hope this was helpful :-)

这篇关于LibGDX阻止主体获取先前删除的主体的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆