Mid November I wanted to develop a Sudoku puzzle for AIR/Flash Player/iPhone called Su. The geeky hidden goal of the project was to keep the game very simple relying on as few event listeners as possible and having as few display objects in the player at any one time. At first I went about exploring how to take a simple game data model (Array) and render out the state of the game using many display objects. In a 9×9 sudoku puzzle that meant 81+ displayobjects at a minimium. Not that player can’t manage this number of items but keeping track of all the items got to be fairly tedius and memory intensive. This is when I switched over to using bitmaps and drawing bitmaps dynamically at runtime…aka blitting.
Blitting at its most basic is when you take one bitmap and draw it into another image potentially many times. AS3 has a great bitmap API that makes it easy to draw graphics. In moving to a rendered game board, 81+ displayobject were removed from the display list and better would not require any textfields, movieclips, sprites either. With 3 events listening at the stage I could create a 100% rendered game. Here is some simple rendering code I used to get started:
gameBoard.bitmapData.draw( m1.bitmapData , new Matrix( 1 , 0 , 0 , 1 , 100 , 100 ) );
//draw the bitmap “m1” into gameboard at x:100,y:100
It is that simple to render bitmaps into each other. If you want to remove image data simply do this:
gameBoard.bitmapData.fillRect( gameBoard.bitmapData.rect , 0 );
//fill gameBoard with empty data erasing the image.
gameBoard.bitmapData.fillRect( new Rectangle( 100, 100, 100 , 100 ) , 0 );
// cut a 100×100 hole at x:100,y:100 in gameBoard
Once I started bliting, I also noticed that my memory consumption was a flat line. Memory never went up or down as I was simply reusing the memory that had been allocated initially to the bitmaps. When you write one image to another, memory consumption does not change, you simply overwrite the data in place with new data.
The next step was organizing the data model to handle history and undo. Using a simple pattern I would change the gamedata array and keep an array history of all game changes, then rendering the single change. When you press undo, I would change the data model and render the deltas. The result was that only the initial game board rendering was expensive (I use expensive relative to rendering the whole gameboard every change).
The great part about this architecture was when I took the game to mobile. On iPhone and other phones (Flash 10.1 on Mobile) the game runs very very fast with no latency. Sudoku is not a fast paced game but it is played over a long period of time so I needed to be careful with resources consumed.
The other element I rather enjoyed was creating a VirtualHitArea class. Typically I use displayobjects to determine hitarea (buttons/movieclips/sprites) but you can virtualize this in stage event listeners. The VirtualHitArea class provides a way to add hitareas that conditionally react if clicked (MouseEvents) or touched (TouchEvents). The result is virtual buttons that add no displayobjects to the overall application but filter stage events to see what is hit when. One side effect of this was the ability to cancel all events in the capture phase. This truncates the DOM level 2 events bubbling across the displaylist and sort of hotwires it. Because events do not need to cascade across the displaylist, they are processed quickly in the VirtualHitArea class at the stage and then canceled.
Su was a fun expieriment in minimalistic programming using Flash Player/AIR and I learned a ton writing it.