How to draw lots of bitmaps on screen in an Android game without slow performance

前端 未结 6 1959
一个人的身影
一个人的身影 2020-12-28 20:32

I want to make a tile based game for android. At the moment I am drawing each tile as a separate bitmap. I have a big for loop that reads from a string and draws different

相关标签:
6条回答
  • 2020-12-28 20:38

    It looks like you are creating a new instance of each bitmap image for every tile rendered. Maybe instead of doing that, you could create one instance for each tile type? ex:

    private Bitmap wallTile = BitmapFactory.decodeResource(getResources(), R.drawable.walla);
    private Bitmap floorTile = BitmapFactory.decodeResource(getResources(), R.drawable.floore);
    

    Then reuse the same tile instance each time the tile is drawn. If this doesn't work, you should put in some kind of performance measurement to see what part of the code is taking the longest time, and minimize the amount of times that code is run, or try to slim it down.

    Disclaimer: I am not an Android programmer

    0 讨论(0)
  • 2020-12-28 20:38
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.util.AttributeSet;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    
    public class MapLoader extends SurfaceView implements SurfaceHolder.Callback,
        Runnable {
    
    SurfaceHolder holder;
    Thread thread;
    
    Bitmap grass = BitmapFactory.decodeResource(getResources(),
            R.drawable.tilemapdemo);
    boolean running = false;
    
    int[][] grassCoords = new int[][] { { 0, 16, 32, 48, 64 },
            { 0, 16, 32, 48, 64 }, { 0, 16, 32, 48, 64 },
            { 0, 16, 32, 48, 64 }, { 0, 16, 32, 48, 64 } };
    
    public MapLoader(Context context, int width, int height) {
        super(context);
    
        holder = getHolder();
        holder.addCallback(this);
    }
    
    public MapLoader(Context context, AttributeSet attrs) {
        super(context, attrs);
    
        holder = getHolder();
        holder.addCallback(this);
    }
    
    public MapLoader(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    
        holder = getHolder();
        holder.addCallback(this);
    }
    
    public void pause() {
        running = false;
    
        while (running) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            break;
        }
        thread = null;
    }
    
    public void resume() {
        running = true;
        thread = new Thread(this);
        thread.start();
    
    }
    
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
    
        running = true;
        thread = new Thread(this);
        thread.start();
    
    }
    
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        Canvas c = holder.lockCanvas();
        draw(c);
        holder.unlockCanvasAndPost(c);
    
    }
    
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
    
    }
    
    @Override
    public void run() {
    
        while (running == true) {
    
            // performs drawing to the canvas
            if (!holder.getSurface().isValid()) {
    
                continue;
            }
    
            Canvas c = holder.lockCanvas();
    
            int x = 0;
            int y = 0;
    
            for (x = 0; x < grassCoords.length; x += grass.getWidth()) {
    
                for (y = 0; y < grassCoords.length; y += grass.getHeight()) {
    
                    c.drawBitmap(grass, x, y, null);
                }
    
            }
    
            holder.unlockCanvasAndPost(c);
    
        }
    
    }
    

    }

    0 讨论(0)
  • 2020-12-28 20:44

    The problem is pretty obvious. You are just leaking a hell lot of memory. Take a look in the LogCat and you'll see what I mean. 1. NEVER allocate strings each frame. They are immutable so every operation with a strings equals memory leaking. Use instead a simple char[] object that you modify. 2. Stop creating bitmap objects over and over again. I suppose that the DecodeBitmap method internally allocates a bitmap object for each call. It's bad to do that every frame.

    As a rule of thumb -> leaking memory and it's buddy the GC are very expensive operations that be avoided when drawing.

    0 讨论(0)
  • 2020-12-28 20:44

    I've never programmed for Android before, so I'm not 100% sure about what's going on underneath the covers there, but assuming that:

    BitmapFactory.decodeResource(getResources(), R.drawable.walla);
    

    this bit of code goes and loads up a bitmap into memory, it would appear that you're reloading each bitmap as you draw it.

    What I've done when developing small games in the past, is when you go to load a level, work out all of the resources that you'll need then load them up into memory once, then reuse them.

    0 讨论(0)
  • 2020-12-28 20:49

    How about moving the whole view when the user scrolls. When you scroll in windows, you actually move the window in the opposite direction that you perceive. You scroll down, the windows moves up..

    I am quite sure you could collect all the elements in a view (grid) and move the whole view.. Render images off screen (faster) and move them up as needed..

    There are examples available.. I know you can get all the code for the home screen, and it scrolls left to right. Might be something to look into. I'm quite sure they did that app right.

    0 讨论(0)
  • 2020-12-28 20:51

    another thought, from a non programmer, is maybe create a large tile background that scrolls, etc.. and a second top layer where moveable items (players, npc, items) are drawn on top of the background. therefore scrolling should be faster and less overall (re)rendering. I imagine this might be more resource intensive than referencing already rendered tiles (as mentioned in another suggestion above).. but it might not be, you'd have to give it a shot and see. :-)

    0 讨论(0)
提交回复
热议问题