Scaling Part II: the Game Begins
Wednesday, 27th May 2015
The next step of my development learning curve is to learn to manipulate images. In particular, I want to take a board graphic and put pieces on it. I'm making small steps at a time, so my first trick is to plonk a piece on a set position on the board.
The most suitable way "perhaps for a chess game...or another slowly-animated application", the Android developer site tells me, is to draw straight onto a custom view. If one creates a View class that extends ImageView, then the class's onDraw() method is passed a handy canvas onto which bitmaps may be placed with gay abandon.
So I started by taking my picture display app and swapped the sample images I was using for a Hare and Hounds board that I drew up. I also drew up some pieces in The GIMP, complete with pretty drop shadow. I calculated the position of the piece based on the board's pixel size, and put the pawn anto the canvas.
Oops. The pawn was offset towards the upper left. I checked my calculations and they appeared to be correct. But looking closer at the screen, I saw that the pawn was apparently placed according to the screen's hardware coordinates. So I overestimated the convenience of Android's scaling. An ImageView's initial source image may be scaled nicely by XML, but one is still dealing with hardware pixel coordinates when drawing onto the view's canvas.
Not only was the pawn's position not scaled according to the board's pixel size, but its size was unscaled too - it looked far too small on the board. Position could easily be calculated according to the screen size, but what about scaling the pawn's size too?
This was the right time to learn about rectangles. A canvas's methods allow bitmaps to be copied AND scaled. One simply has to define a rectangle on the destination canvas, and specify it when drawing the bitmap onto the canvas. The bitmap will be suitably scaled to fit in the defined area. So after a bit more learning, I could put a pawn in the centre of my hare and hounds board.
Elated by this success I pushed on to make the demonstration more interactive. Taking my cue from a simple example drawing app, I overrode my view method's onTouchEvent() method to detect the location of a touch, convert it from a pixel position to a board position, reject positions where no piece can rest, and display a pawn in the specified location.
The easiest method I have found for this is to maintain a proper array of what is present on each board position, as I would in a full-fledged board game app. Then the onDraw() method draws the entire empty board onto a canvas, draws pawns onto that board according to the array, and copies that canvas onto the canvas given by the system.
So now I can plonk pawns onto my empty hare and hounds board. Since I mastered the game logic a decade ago, and I can now make a board that interacts with user input, I'm ready to start thinking about implementing an actual game.