Game Taking too long during render cycles

| | August 11, 2015

Firstly, I’m not asking anyone to read my code. It is only posted as a reference just in case you want to. I am asking for general tips on how to get my game running at higher FPS on android, for people who have had the same problem before.

I’ve been looking all over the web to a specific fix to my problem, but it seems its too generic of a problem to fix, so I thought i’d ask here and see if anyone has experience with this sort of problem. I’m developing a game on android using the native libraries only. my rendering cycle is taking 1/5th of a second to complete, which is ludicrous and drops my frame rate to 5. My game uses very simple PNG graphics i made in GIMP, and i only have a total of 10 images. It doesn’t make sense for the game to be running this slow.

Things that I’ve tried from the web:

-Load each image once and then retrieve them from a cache – done.

-Diagnose using DDMS/MAT to fix memory leaks – there were none.

-Get a sampled size of the image instead of full image – no effect

-Draw onto a off-screen, mutable bitmap, then draw that bitmap onto your main canvas – no effect

-reduce the capped frames/second in my main game loop to around “20” – no effect

The only thing I haven’t done is use completely non-scaled images, which i don’t see as being practical since every android device has different resolutions and screen sizes.

Does anyone have any other things I should try? If i can’t figure this out I’m at a complete loss, because this is crippling the game and making it unplayable. If anyone has steps I can take, please help. In case you’d like to view my code, I’ve posted the relevant code below and my basic loop (a copy of which can be found online under “basic android loops” search term):

My Input/Output Handler Class:

public abstract class FileIO{....

public static synchronized Bitmap getImage(String imageName, Context context){

    for (int i = 0; i < bitmapList.size(); i++){
        if (fileNameList.get(i).equals(imageName)){
            return bitmapList.get(i);
        }
    }
    Bitmap bitmapReturn = null;
    try {
        assetManager = context.getAssets();
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
        inputStream = assetManager.open(imageName);
        bitmapReturn = BitmapFactory.decodeStream(inputStream, null, options);

.......
    }
    fileNameList.add(imageName);
    bitmapList.add(bitmapReturn);
    return bitmapList.get(bitmapList.size()-1);
}

}

My “Drawable Sprite” Base Class:

public class Physical {

public void draw(){ 
        ImageBuffer.bufferCanvas.drawBitmap(FileIO.getImage(imageName, GameLoop.context), null, getRect(), null);
        }
}

My Main Loop:

public class Loop extends Activity{

static Canvas canvas;
public final static int MAX_FPS = 45;
public final static int MAX_FRAME_SKIPS = 5;
public final static int FRAME_PERIOD = 1000 / MAX_FPS;
public final static int GAME_STATE_TITLE_SCREEN = 1;
public static Context context;
public RenderView renderView;

 @Override
    protected void onCreate(Bundle savedInstanceState) {

        context = this;
        super.onCreate(savedInstanceState);
        renderView = new RenderView(this);
        setContentView(renderView);
    }

    public void renderAll(){

        //In this method, I have a call to all my "Physical" objects to draw() themselves.
    }

    public class RenderView extends SurfaceView implements Runnable {

        public Thread renderThread = null;
        public SurfaceHolder holder;
        public volatile boolean running = false;

        public RenderView(Context context) {
            super(context);
            holder = getHolder();
        }

        public void onSizeChanged (int w, int h, int oldw, int oldh){

            if (ImageBuffer.bufferCanvas == null) new ImageBuffer();
        }

        public void resume() {
            running = true;
            renderThread = new Thread(this);
            renderThread.start();
        }


        public void run() {

            long beginTime;
            long timeDiff;
            int sleepTime;
            int framesSkipped = 0;

            sleepTime = 0;

            while (running){

                canvas = holder.lockCanvas();
                canvas.drawRGB(0, 0, 0);

                beginTime = System.nanoTime();
                framesSkipped = 0;

                updateAll();
                renderAll();   

                timeDiff = System.nanoTime() - beginTime;
                sleepTime = (int)(FRAME_PERIOD - (timeDiff/1000));

                if (sleepTime > 0) {
                    try {
                    Thread.sleep(sleepTime);
                }

                while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
                    updateAll();
                    sleepTime += FRAME_PERIOD; 
                    framesSkipped++;
                }

                ImageBuffer.flipBuffer();
                holder.unlockCanvasAndPost(canvas);
            }
        }
    }
}

This code is post-image buffer implementation (which did nothing). I was drawing directly to the main canvas before. In the “renderAll()” method inside the main loop, I just have a call to all of my “Physical” objects to “.draw()” themselves.

Does anyone know what is wrong with my game??

One Response to “Game Taking too long during render cycles”

  1. You seem to be loading the images in memory from the storage every frame when you draw them. This is very slow and is most likely the main reason for the slowdown you are experiencing. You need to reuse the previously loaded image to get the proper draw speed you are looking for. Never load the images on every frame again and again, that will just kill the framerate.

    You currently have the following code:

    public class Physical {
        public void draw(){ 
            ImageBuffer.bufferCanvas.drawBitmap(FileIO.getImage(imageName, GameLoop.context), null, getRect(), null);
        }
    }
    

    You can improve this by storing the bitmap reference, and checking you have loaded it before drawing. Something like this:

    public class Physical {
        Bitmap bitmap = null;
        public void draw(){
            if(bitmap == null) {
                bitmap = FileIO.getImage(imageName, GameLoop.context);
            }
            ImageBuffer.bufferCanvas.drawBitmap(bitmap, null, getRect(), null);
        }
    }
    

Leave a Reply