java - Android 游戏中的卡顿(垃圾收集?)

标签 java android

为了优化我的游戏,我让它基于网格。物体位于网格正方形中。因此,为了进行渲染,我收集了相机可见区域中的所有对象,并将它们逐层放入列表中:

public ArrayList<Entity> queryRect(OBB2D rect)
{
    neighbourQueryObjs.clear();
    ArrayList<Region> reg = determineNeighbourRegions(rect);
    for(int i = 0; i < Entity.MAX_LAYERS; ++i)
    {
        for(Region r : reg)
        {
            for(Entity e : r.getStatic(i))
            {
                if(!neighbourQueryObjs.contains(e) && e.getRect().overlaps(rect))
                {
                    neighbourQueryObjs.add(e);
                }
            }

            for(Entity e : r.getDynamic(i))
            {
                if(!neighbourQueryObjs.contains(e) && e.getRect().overlaps(rect))
                {
                    neighbourQueryObjs.add(e);
                }
            }
        }
    }

    return neighbourQueryObjs;

}

这很好用。游戏速度非常快。我称这个为每一帧 问题是每隔 1 或 2 秒左右,游戏就会卡住大约 2-300 毫秒。

我怀疑是垃圾回收。会不会是这样?

有没有一种方法可以预先分配这些东西,让它永远不必使用 GC?我不介意浪费内存,内存没问题。

这是我的游戏循环,可以这样吗:

public void run() {
        Canvas canvas;

        long beginTime;     // the time when the cycle begun
        long timeDiff;      // the time it took for the cycle to execute
        int sleepTime;      // ms to sleep (<0 if we're behind)
        int framesSkipped;  // number of frames being skipped 

        sleepTime = 0;

        while (running) 
        {
            canvas = null;
            // try locking the canvas for exclusive pixel editing
            // in the surface
            try 
            {

                // we have to make sure that the surface has been created
                // if not we wait until it gets created
                if (!holder.getSurface ().isValid())
                    continue;
                canvas = this.holder.lockCanvas();
            synchronized (holder) 
            {
                    beginTime = System.currentTimeMillis();
                    framesSkipped = 0;  // resetting the frames skipped
                    // update game state
                    update();
                    // render state to the screen
                    // draws the canvas on the panel
                    display(canvas);
                    // calculate how long did the cycle take
                    timeDiff = System.currentTimeMillis() - beginTime;
                    // calculate sleep time
                    sleepTime = (int)(FRAME_PERIOD - timeDiff);

                    if (sleepTime > 0) 
                    {
                        // if sleepTime > 0 we're OK
                        try 
                        {
                            // send the thread to sleep for a short period
                            // very useful for battery saving
                            Thread.sleep(sleepTime);
                        } catch (InterruptedException e) {}
                    }

                    while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) 
                    {
                        // we need to catch up
                        // update without rendering
                        update();
                        // add frame period to check if in next frame
                        sleepTime += FRAME_PERIOD;
                        framesSkipped++;
                    }
                }
            } 
            finally 
            {
                // in case of an exception the surface is not left in
                // an inconsistent state
                if (canvas != null) 
                {
                    holder.unlockCanvasAndPost(canvas);
                }
            }   // end finally
        }
    }
    protected void onDrawTransformed(GraphicsContext g)
    {   
        OBB2D view = g.getCamera().getCamRect(getWidth(), getHeight());

        ArrayList<Entity> ents = world.queryRect(view);
        for(Entity e : ents)
        {
            e.draw(g);
        }
        //city.draw(g);
        //vehicle.draw(g);
    }

我该怎么做才能停止口吃?

谢谢

最佳答案

在你的public ArrayList<Entity> queryRect(OBB2D rect)你一直在打电话neighbourQueryObjs.clear();neighbourQueryObjs.add(e); ,分配和释放内存。

要确定这是否真的是问题所在,您可以暂时注释掉 clear()/add()部分和返回始终相同(预先计算?)neighbourQueryObjs看看口吃是否消失了。沿线的东西:

if( neighbourQueryObjs.length() == 0 ) {
    // calculate the neighbourQueryObjs
}
return neighbourQueryObjs;

关于java - Android 游戏中的卡顿(垃圾收集?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13300939/

相关文章:

java - 将文件添加到可执行 jar 文件

java - 如何获取存储在 HashMap 中的列表中的对象,以创建新列表

java - 适配器中的 viewHolder.getAdapterPosition() 返回 -1 位置并导致 IndexOutOfBoundException

android - 图标未显示在操作栏中

android - 可绘制图像给出 'No resource found..' 但它在文件夹中

java - 使用嵌入式 tomcat 7 获取 EOFException

java - "if (int == 1)"不起作用

java - 连接到数据库,但我只获得默认模式,而不是我在原始系统上创建的模式。有任何想法吗?

android - 如何防止LRU缓存android中的内存不足错误

android - 在 Gradle 中定义为每个构建类型运行的任务