The primary purpose of this example is to dig up some basic Android 2D features and get familiar with some game programming principles. Although TicTacToe is not really an interactive game, I think its simplicity will help us to be focused on what matters most which is actually how to do things in Android rather than how to design and develop an efficient game algorithm for a particular game. (I'm gonna use the same technique that has been used in LunarLandar application, which by the way is a pretty good example in this area).
first of all let's have a look at how our application will be looking like:
Despite the fact that TicTacToe is a pretty easy game to develop, Graphic wise I mean, and can be simply done by extending View Class, I have actually used 'SurfaceView', since apparently it's a better option for developing interactive games in Android. the most important point about SurfaceView class is that it uses two buffers, a drawing buffer and a displaying buffer, you are not allowed to draw directly on displaying buffer and if you need to draw something you will have to get the drawing buffer , fill it and post it as display buffer. as API documentation has mentioned there is no guarantee that anything gets preserved in drawing buffer and as a result we always need to draw anything we want to be shown without taking any presumption that something is already there from last drawing operation.
OK... now that we learned some basic facts about how SurfaceView works, let's have a look at my code and see what we have got there :
The first thing we're gonna need in any game is a Game Thread, The idea here is to constantly call a series of methods which are responsible to update some states and draw something based on those states. as I said before when you are dealing with SurfaceView you need to draw into the draw buffer and then post it on the surface, It can be done by calling lockCanvas() and unlockCanvasAndPost() methods of SurfaceHolder class, you can get the associated SurfaceHolder instance of your SurfaceView by calling getHolder() method. as you can see in the above code I have implemented the SurfaceHolder.Callback interface; this interface provides 3 callback methods for monitoring the life-cycle of the SurfaceView, here is my implementation of these methods:
in surfaceCreated() method I have initialized some variables and objects such as an instance of TicTacToe class (which will actually take care of game's logic and rules), background Image , cross and circle images and Paint objects that all will be used later to draw the game, here is also a good place to create and start our main thread. then we will kill the main thread in surfaceDestroyed() method to make sure no one's gonna make an attempt to draw anything on the surface after it has been destroyed.
now that we have got anything initialized and the main thread running let's see what is happening in each loop of our thread, as you saw in the first chunk of code above we are actually calling 2 methods each time, doDraw() and updateScores() :
The Last thing I would like to handle is the ability to keep the state of the game when user flips the phone and goes to landscape mode or vice versa, so we are gonna have to save current state of the game just before application get killed and then retrieve that state later when the activity get started again which mean our activity class will be something like this:
getInternalState() method returns the associated TicTacToe object of the TicTacToeView, as I said before TicTacToe class is just a simple class that holds the game matrix and players' scores and actually that's all we need to save and retrieve each time the configuration gets changed in this example.
I also though it would be interesting to start the game with some sort of animation so I wrote a piece of code to have the game table being drawn when you start the application, something like this I mean :
and here is the code that generates this animation:
I'm not sure if it's the best way to do this but it works just like i want it to work ;). (since just calling lockCanvas() and unlockCanvasAndPost() alone takes something around 200ms on my emulator - which is of course ridiculous but i have no idea why! - I didn't need to add any delay but on real device it will probably be needed to have some delay).