title: How to draw lots of bitmaps on screen in an Android game without slow performance
body: <p>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 tiles depending on what character it finds to draw the level.</p>
  
  <p>I have allowed the user to scroll the screen using scrolling gestures.  However the game is too slow.  It takes a long time to update the screen after the user scrolls.  I presume this is because it has to draw each tile's bitmap individually.</p>
  
  <p>What would be a faster way to draw the level?  I was thinking I could merge all the tiles into one bitmap.  But I don't know how to do this.  Any ideas?</p>
  
  <p>Anyway here is my code so you can see the problem:</p>
  
  <pre><code>package org.example.tutorial2d;
  
  import android.app.Activity;
  import android.os.Bundle;
  import android.view.GestureDetector;
  import android.view.MotionEvent;
  import android.view.GestureDetector.OnGestureListener;
  
  import org.example.tutorial2d.Panel;
  
  public class Tutorial2D extends Activity implements OnGestureListener {
  
  GestureDetector gestureScanner;
  Panel main;
  
  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
  
      gestureScanner = new GestureDetector(this);
  
      //requestWindowFeature(Window.FEATURE_NO_TITLE);       
      main = new Panel(this);
      setContentView(main);       
  
  }
  
  @Override
  public boolean onTouchEvent(MotionEvent me)
  {
   return gestureScanner.onTouchEvent(me);
  }
  
  @Override
  public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
  {
   main.handleScroll(distanceX,distanceY);
   return true;
  }
  
  ////////////////////
  ///////////////////
  //////////////////
  @Override
  public boolean onDown(MotionEvent e)
  {
   return true;
  }
  
  @Override
  public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
  {
   return true;
  }
  
  @Override
  public void onLongPress(MotionEvent e){    }
  
  @Override
  public void onShowPress(MotionEvent e) {   }    
  
  @Override
  public boolean onSingleTapUp(MotionEvent e)    
  {
   return true;
  }
  ////////////////////
  ///////////////////
  //////////////////
  }
  </code></pre>
  
  <p>And the class that does all the work:</p>
  
  <pre><code>package org.example.tutorial2d;
  
  import android.content.Context;
  import android.graphics.Bitmap;
  import android.graphics.BitmapFactory;
  import android.graphics.Canvas;
  import android.graphics.Color;
  import android.graphics.drawable.Drawable;
  import android.util.Log;
  import android.view.View;
  import org.example.tutorial2d.Point;
  
  public class Panel extends View {
  
  private int scrollX = 0;
  private int scrollY = 0;
  
  public Panel(Context context)
  {
      super(context);
  }
  
  @Override
  public void onDraw(Canvas canvas)
  {
      /*Bitmap scratch;
      //Drawable scratch;
      //scratch = getContext().getResources().getDrawable(
      //        R.drawable.icon);
      canvas.drawColor(Color.BLACK);
      //scratch.draw(canvas);
      int origin = 0;
      scratch = BitmapFactory.decodeResource(getResources(), R.drawable.horizontal5);
      canvas.drawBitmap(scratch, origin, origin, null);
      int width = scratch.getWidth();
      int height = scratch.getHeight();
      scratch = BitmapFactory.decodeResource(getResources(), R.drawable.room4entrynesw3x3);
      canvas.drawBitmap(scratch, origin + width, origin - 32, null);
      */
  
      String sucide_mission = 
  "                  wwwww\n" +
  "                  wfffw\n" +
  "                  wfffw\n" +
  "                  wfffw\n" + 
  "                  wwfww\n" +
  "                   wfw\n" + 
  "                   wfw\n" +
  "                   wfw\n" +
  "             wwwwwwwfwwwwwfw\n" +
  "             wfffffffffffffw\n" +
  "             wfwwwwwfwwwwwfw\n" +
  "     wwwww   wfw   wfw   wfw\n" +
  "wwwwwwfffwwwwwfwwwwwfwwwwwfw\n" +
  "fffffffffffffffffffffffffffw\n" +
  "wwwwwwfffwwwwwwwwwwwfwwwwwfw\n" +
  "     wwfww         wfw\n" +
  "      wfw          wfw\n" +
  "      wfw          wfw\n" +
  "      wfw          wfw\n" +
  "      wfw          wfw\n" +
  "     wwfww         wfw\n" +
  "     wfffwwfw      fff\n" +
  "     wffffffw      www\n" +
  "     wfffwwfw\n" +
  "     wwwww";
  
      canvas.drawColor(Color.BLACK);
      int x = 0, y = 0;
  
      for (int i = 0; i &lt; sucide_mission.length(); i++)
      {
          Bitmap tileImage;
          char tile = sucide_mission.charAt(i);
  
          Log.d("Draw tiles", Character.toString(tile) + " " + x + "," + y);
  
          switch (tile)
          {
              case 'w':
                  if (x &lt; tileImage = BitmapFactory.decodeResource(getResources(), R.drawable.walla);
                  canvas.drawBitmap(tileImage, x - scrollX, y - scrollY, null);
                  x += 32;
                  break;
              case 'f':
                  tileImage = BitmapFactory.decodeResource(getResources(), R.drawable.floore);
                  canvas.drawBitmap(tileImage, x - scrollX, y - scrollY, null);
                  x += 32;
                  break;
              case ' ':
                  x += 32;
                  break;
              case '\n':
                  y += 32;
                  x = 0;
                  break;
          }
  
      }
  
      //canvas.drawBitmap(adapt, 0, 0, paint);
      //canvas.drawBitmap(corner, origin -scrollX , origin -scrollY, paint);
  
  }
  
   public void handleScroll(float distX, float distY)
   {
        // X-Axis ////////////////////////////////
  
        if(distX &gt; 6.0)
        {
             if(scrollX &lt; 460)
             {
                  scrollX += 30;
             }
        }
        else if(distX &lt; -6.0)
        {
             if(scrollX &gt;= 30)
             {
                  scrollX -= 30;
             }
        }
        ////////////////////////////////////////////
  
        // Y-AXIS //////////////////////////////////
        if(distY &gt; 6.0)
        {
             if(scrollY &lt; 100)
             {
                  scrollY += 30;
             }
        }
        else if(distY &lt; -6.0)
        {
             if(scrollY &gt;= 30)
             {
                  scrollY -= 30;
             }
        }              
        ////////////////////////////////////////////
  
        if((scrollX &lt;= 480) &amp;&amp; (scrollY &lt;= 120))
        {
             //adapt = Bitmap.createBitmap(bmp, scrollX, scrollY, 320, 480);
             invalidate();
        }
   }
  }
  </code></pre>