Graphic detail

If you’ve been following along from the previous post you’ll have screen showing a classic chequered board ready and waiting for pieces to be put on it.

There are several ways to tackle this problem, each with their trade-offs. The method we are going to use is to create a 2d array to represent the board state, and load it with drawable resource IDs. We will be returning to the game after it’s complete to demonstrate other approaches and then we can don the lab coat and start extracting statistics.

The red rock piece

Black Rock

Drawables are verysimple. Drop a compatible graphic into the project’s res/drawable-hdpi directory and Eclipse will auto generate the appropriate constant under R.drawable, in this case blackrock, ready for use. We are going to rewrite the same section of code a few times over because first time around I’ll be going for clarity of process, then building on it because the clear version will use rather more CPU than is sensible on your poor phone.

With our drawable in place we can get it rendered and on the screen. The excellent android libraries do the heavy lifting for us. We’ll put our rock in the top left square of the board. In the onDraw function, after the nested loop we will ask the canvas to draw a bitmap we decode from the drawable.

package uk.co.quarterstaff.rpschess; 
/*snip existing imports*/ 
import android.content.res.Resources; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 

public class Board extends View {
     public Board(Context context, AttributeSet attrs) {/*snip*/}

     private float mTileWidth  = 0;
     private float mTileHeight = 0;

     @Override
     public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {/*snip*/}

     @Override public void onDraw(Canvas canvas) {
         Paint light = new Paint();
         light.setColor(Color.parseColor("#FFFFAA"));

         Paint dark = new Paint();
         dark.setColor(Color.parseColor("#AAAA88"));
         
         for (int i = 0; i < 8 ; i++) {
             for (int j = 0; j < 8 ; j++) {
                 if ((i+j) % 2 == 0)
                     canvas.drawRect(j * mTileWidth , i * mTileHeight , (j+1) * mTileWidth , (i+1) * mTileHeight, dark);
                 else
                     canvas.drawRect(j * mTileWidth , i * mTileHeight , (j+1) * mTileWidth , (i+1) * mTileHeight, light);
             }
         }

         Resources res = getResources();
         Bitmap bm = BitmapFactory.decodeResource(res, R.drawable.blackrock);
         canvas.drawBitmap(bm, 0, 0, null);
     }      
} 

There’s no reason we can’t cram that all onto one line, but it’s clearer split up. The first step is to get an instance of the resources of our package and this is handled by the getResources() function. Then we use the resources and the blackrock reference, which is just an integer, with the decodeResource() function to get a bitmap object, which we can draw at the top left of the canvas (0,0) with the canvas.drawBitmap() function.
No complaints from the compiler so let’s hit play and GREAT STEAMING PILES OF ONIONS! Your mileage may vary, but I have a rock taking up one quarter of the board. This behemoth may prove unbalancing to the game dynamic so let’s cut it down to size.

Once again the Android libraries do the heavy lifting. Insert the following line between decoding the resource and drawing it on the canvas:

        Resources res = getResources();
        Bitmap bm = BitmapFactory.decodeResource(res, R.drawable.blackrock);
        bm = Bitmap.createScaledBitmap(bm, (int)mTileWidth, (int)mTileHeight, true);
        canvas.drawBitmap(bm, 0, 0, null);

Note that we are re-using the tile size we calculated earlier (cast to an integer) so the piece will scale correctly to fit any size of board including ones that don’t have square tiles. Running this shows a less imposing and slightly lonely rock in the top left corner of the board.

With the finish line in sight we can now create a 2d array, create a public addPiece() function on the board to populate it and use another nested loop during the onDraw() function to get the resources identified at each point of the array, scale them and draw them in positions related to their position in the array.

This would mean rescaling the same image over and over for each piece every time the view is redrawn. This would make Romain Guy cranky and I don’t want to make him cranky, so in the next post we are going to look at caching the scaled graphics to make the screen redraws much, much faster. In them meantime, If you want to run ahead then remember that the zeros that populate most of the array will not return valid bitmaps so check for them before trying to draw them.

Board with a single rock in the top left corner

Lonely Piece

This entry was posted in android and tagged . Bookmark the permalink.

2 Responses to Graphic detail

  1. kumar says:

    Hi Chris,

    Using this tutorial i draw one board instead of one image I have taken 12 different type of images just like chess game images .so can you please tell me how to move the coins from one place to another place and how to show the path when coin is selected.. waiting for your early and prompt reply.

    Thanks & Regards,
    kumar.

  2. Chris says:

    Simple moving of pieces has been covered in later posts (Moving sharply and Smooth operator). I’m currently writing up showing permitted moves and validating them. There is some debate among my play-testers as to the best way to go about it.

Comments are closed.