1

I'm developing a simple 2D Android game and I want to draw the background of each level when the level begins. The background will be static for each level, it won't animate or move.

At first, I was drawing the background in a custom view using canvas and I was loading that view as the background of the level. That worked, however I noticed that if I draw a lot of lines and shapes, the UI begins to stutter. I solved the problem by drawing the background via canvas and saving it directly into a bitmap, which I then load into a background ImageView as you can see below:

CustomView bgView = new CustomView(this); //this view draws the background
Bitmap bitmap = Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
bgView.draw(canvas);
ImageView imageViewBg = (ImageView) findViewById(R.id.imageViewBg);
imageViewBg.setImageBitmap(bitmap);

The problem that I notice with this approach is that I'm creating a bitmap with a size of [screenWidth x screenHeight] which might cause an OutOfMemoryError.

So, what's the best approach for drawing the background of a full-screen game? The problem is that I want to draw it dynamically, I cannot load it directly from the assets. (I could use the Bitmap.Config.RGB_565 profile, but still it will just reduce the size of the bitmap in half, it's not the optimal solution).

steliosf
  • 3,669
  • 2
  • 31
  • 45

1 Answers1

1

I use Bitmap.createScaledBitmap():

Bitmap b = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.background),WIDTH,HEIGHT,false);

Get the width and height of the screen

Then draw it as usual:

canvas.drawBitmap(b, 0, 0, null);

EDIT:

Load the bitmap any way you would like. For the purposes of the example, the Bitmap-object will be called b. So first:

WIDTH = b.getWidth();
HEIGHT = b.getHeight();

Move on to rendering:

public void render(Canvas c){
    final float scaleFactorX = getWidth()/(WIDTH*1.f);
    final float scaleFactorY = getHeight()/(HEIGHT*1.f);
    //check if the canvas is null first.
    int savedState = c.getSaveCount();
    c.scale(scaleFactorX, scaleFactorY);
    //draw your bitmap.
    c.restoreToCount();
    //Do normal rendering

}

Explanation

What I do here is to scale the rendering only for the bitmap. This means anything else rendered will not be affected by this.

We need to get the scale factors to scale the screen to when rendering the Bitmap:

final float scaleFactorX = getWidth()/(WIDTH*1.f);
final float scaleFactorY = getHeight()/(HEIGHT*1.f);

Then save the state of the canvas to reload later.

int savedState = c.getSaveCount();

Now we scale the bitmap using the scaleFactors previously defined

c.scale(scaleFactorX, scaleFactorY);

And restore the bitmap to its original state to draw everything else in whatever type of scale you need. If you do not need to zoom the bitmap(if you have zoom) you can add that scaling after the background-scaling.

    c.restoreToCount();
Community
  • 1
  • 1
Zoe
  • 27,060
  • 21
  • 118
  • 148
  • I can see that you are loading the bitmap from resources, while I want to create it from scratch. Also, if the bitmap has the size of the screen, wouldn't it still be quite huge in terms of byte allocation? – steliosf Mar 08 '17 at 16:44
  • I loaded it from resources to make it testable. How you load the bitmap is up to you. As if the memory, that is an issue I didn't consider here. I will update the answer with a different solution. – Zoe Mar 08 '17 at 16:45