一段时间后,libgdx游戏开始冻结

时间:2016-01-29 09:50:57

标签: java android libgdx

我的游戏在一段时间后开始冻结(占用太多ram),我想尝试使用循环方法绘制3(后来更多)字符串。我的代码是这样的:

    public class Simple implements ApplicationListener {
        private OrthographicCamera camera;
        private SpriteBatch batch;
        private BitmapFont font;
        private GlyphLayout layout;
        String a1 = "aa";
        String a2 = "bb";
        String a3 = "cc";
        int a = 0;

        @Override
        public void create() {
            camera = new OrthographicCamera();
            camera.setToOrtho(false, 800, 480);
            batch = new SpriteBatch();
        }

        @Override
        public void render() {
            Gdx.gl.glClearColor(0, 0, 0.2f, 1);
            Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
            camera.update();
            batch.setProjectionMatrix(camera.combined);
            batch.begin();
            for (int i = 1; i < 4; i++) {
                layout = new GlyphLayout();
                font = new BitmapFont();
                layout.setText(font, "a" + i);
                font.draw(batch, layout, 200 + (15 * i), 200);
            }
            batch.end();
        }
    }

2 个答案:

答案 0 :(得分:2)

想象一下EpicPandaForce在评论中提到的内容:

public class Simple implements ApplicationListener {
    private OrthographicCamera camera;
    private SpriteBatch batch;
    private BitmapFont font;
    private GlyphLayout layout;
    String a1 = "aa";
    String a2 = "bb";
    String a3 = "cc";
    int a = 0;

    @Override
    public void create() {
        camera = new OrthographicCamera();
        camera.setToOrtho(false, 800, 480);
        batch = new SpriteBatch();
        //Initialize the fields in create()           
        layout = new GlyphLayout();
        font = new BitmapFont();

    }

    @Override
    public void render() {
        Gdx.gl.glClearColor(0, 0, 0.2f, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        camera.update();
        batch.setProjectionMatrix(camera.combined);
        batch.begin();
        for (int i = 1; i < 4; i++) {
            //Use them like you do.
            layout.setText(font, "a" + i);
            font.draw(batch, layout, 200 + (15 * i), 200);
        }
        batch.end();
    }
}

我不确定这是否会起作用。你没有在任何地方指定bitmapfont所以当你使用布局绘制它时,你可能得到nullPointerException。在create方法中,您可能希望使用font = new BitmapFont(Gdx.files.internal("Path to bitmapfont"));初始化字体。

使用new是一项昂贵的操作。每个帧都调用update()方法,并且每次调用时都要创建新对象。最重要的是BitmapFont()不是一个小对象。每次为字体和布局创建一个新对象时,它所拥有的上一个对象都需要由垃圾收集器收集。一个基本规则是永远不要在new方法中使用update()关键字,而是改变它和/或像我刚才那样使用它。以一种非常简单的方式可视化:

Object o; // <-- a simple container
new Object(); // <-- a object stored in memory in all it's glory

Object o = new Object(); // <-- container o is now pointing to the memory address of new Object()

Object o = new Object(); // container 0 is now pointing to a different object in memory
//But the old one is still chilling at it's own address and needs to be collected

答案 1 :(得分:2)

问题不一定是你在每次渲染调用时创建一个新字体(尽管出于性能原因你当然不应该这样做),但更多的是你没有通过{{从内存中释放字体'。 1}}。

通常垃圾收集会在您之后清理,但在某些情况下您需要自行清理。 Libgdx出于性能原因使用了一些非托管代码,因此需要您手动释放它。该文件清楚地说明了这一点,并阐述了原因。

  

管理从文件加载的BitmapFont的纹理。处置()   必须调用以在不再需要时释放纹理。一个BitmapFont   如果区域的纹理是,则使用TextureRegion加载   管理。处理BitmapFont会处理区域的纹理   如果纹理仍在其他地方使用,则可能不合适。

因此,在完成字体操作后调用dispose,并在构造函数中初始化字体。否则你的程序将使用越来越多的内存,性能将会非常糟糕。