Step Six: Adding Graphics
Before adding the final game logic, add the graphics that will be used to show player progress. For this game, this includes seven progress graphics, one to start and one for each bad guess, with the final bad guess resulting in a Game Over image. It also includes a splash screen and a graphic for the win condition. Each of these images are 150x150 jpegs—create your own or download an existing set.
As mentioned before, you might experiment with using a database to store game images in order to provide flexibility in changing image sets or allowing players to add their own. But for this example, you'll add two ImageList controls:
- From the Toolbox, drag two ImageList controls onto the form design. Name one "imgConMan" and the other "imgBeginEnd".
- Set the ImageSize for both controls to 150, 150.
- Edit the Images property for imgConMan, which should read "(Collection)".
- Add images 0.jpg through 6.jpg, in that order. This should result in a Members list with indices 0 through 6. Because of the Guesses.Draw code, these indices should be exact. If something happens to knock them off, just delete the control and add a new one.
- Edit the Images property for imgBeginEnd the same way. This time, add the images start.jpg and win.jpg, in that order.
Now the game assets will be available programmatically. Note that at no point did you need to copy the images manually to your project directory or explicitly add them to your project via the Solution Explorer. Using the ImageList controls will cause the images to be embedded in your project library as resources.
With your image controls in place, you can begin to incorporate them:
- Add a container for the images themselves. In Design View, add a PictureBox control to the pnlGuesses panel, positioning the PictureBox so that it sits over the panel. It should be 150 by 150.
- Name the PictureBox picProgress. In the Properties pane, if the PictureBox has been positioned correctly, it should have a Location of 0, 0 to indicate its relevant position within pnlGuesses.
- In the constructor code for the form, just below InitializeComponent(), add:
picProgress.Image = imgBeginEnd.Images[0];
Step Seven: Menu Options and Game Logic
It's time to start adding the final game logic, starting with Menu options, which are selected using the device buttons. This game uses a very simple menu tree, which you can create in the design view:
-
On the device skin, click on the bottom left space, just above the left device button. Type Menu. In the Properties panel, call this mnuMenu.
- Just above that, where it says "Type Here", type "New Game". You've just added a child menu control. Rename it mnuNewGame.
- Below "New Game", type "Quit". Call that option mnuQuit.
- On the bottom right, above the right side device button, add a menu option by typing "Guess". Name this control mnuGuess. This is how players will guess individual letters. You want to allow players to back out of accidental entries, so you need some sort of confirmation mechanism. Because mobile devices accept input in different ways, such as through a slide-out keyboard or stylus, it's easier to enable confirmation through a device button rather than an "Ok" button, which can be obscured by the flyout writing space.
Before adding Click event code, go to the frmGameMain partial class definition and add two new methods:
private void disableInput()
{
txtGuess.Visible = false;
lblGuesses.Visible = false;
}
private void enableInput()
{
txtGuess.Visible = true;
lblGuesses.Visible = true;
lblAnswer.Text = "";
lblGuesses.Text = "";
picProgress.Image = imgConMan.Images[0];
txtGuess.Focus();
}
These simply toggle control visibility and text values depending on game status. Note how the starting image is referenced.
Under the frmGameMain() constructor, add:
disableInput();
At this point, the constructor should look like the following:
public frmGameMain()
{
InitializeComponent();
disableInput();
picProgress.Image = imgBeginEnd.Images[0];
Orientation = new SystemState(SystemProperty.DisplayRotation);
Orientation.Changed += Orientation_Changed;
adjustScreen();
}
In the class definition, under SystemState Orientation, add:
Answer theAnswer;
Guesses theGuess;
Adding Click events works the same here as with any app. Go back to the design view of the form and click once on "Menu" to bring up the sub-menu, and then double-click on "New Game". In mnuNewGame_Click(), add the following:
theAnswer = new Answer();
theGuess = new Guesses();
Random r = new Random();
taWords.Fill(dsWordList.WordList);
theAnswer.Set(dsWordList.WordList[r.Next(0, dsWordList.WordList.Count)].word);
enableInput();
This instantiates your two new game classes. Especially take note of the two lines following "Random r...". Because of the data controls you dragged onto the design view, this is all it takes to hook up to your SQL Server Compact Edition database. One command fills the dataset. Another picks one word at random and assigns it to your Answer object. Notice how the upper limit of the Random object is set to the row count for the dataset.
Back in design view, double-click the Quit menu option. In mnuQuit_Click(), add the following:
this.Close();
Finally, click on the Guess menu option. This is where it all happens. In mnuGuess_Click(), add the following:
if (txtGuess.Text.Length < 1)
{
//Add a system message here or just don't do anything.
}
else
{
string thisGuess = txtGuess.Text.Substring(0, 1).ToLower();
if (theGuess.Contains(thisGuess))
{
//This letter has already been guessed.
}
else
{
if (theAnswer.Contains(thisGuess))
{
theAnswer.Add(thisGuess);
lblAnswer.Text = theAnswer.Draw();
if (theAnswer.isGameOver())
{
//Win condition
picProgress.Image = imgBeginEnd.Images[1];
disableInput();
}
else
{
//Correct guess
txtGuess.Focus();
}
}
else
{
theGuess.Add(thisGuess);
lblGuesses.Text = theGuess.Get();
picProgress.Image = imgConMan.Images[theGuess.ImageIndex()];
if (theGuess.isGameOver())
{
//Lose condition
lblAnswer.Text = theAnswer.RevealAnswer();
disableInput();
}
else
{
//Incorrect guess
txtGuess.Focus();
}
}
}
}
txtGuess.Text = "";
In the above code, opportunities have been added for player feedback or for debugging code, which have been commented with the game status at that point. As you can see in this code, when guesses are made, they're checked against the correct answer. Game graphics are updated based on the number of bad guesses. On win or lose conditions, appropriate action is taken and input controls are disabled.
Now would be a good time to test the game. Compile and run. To see what your results should look like, here's a video of the finished product. Hopefully your version will exhibit the same behavior.
Where to Go From Here, or Potential Problems to Play With
This walkthrough should give you some idea of how straightforward it can be to build a mobile app based on .NET Compact Framework 3.5 and SQL Server Compact Edition 3.5 using Visual Studio 2008. Even so, Visual Studio 2008 offers many more features for mobile development that have not been touched on here. Chief among these is its new debugging functionality.
You may notice that this code has no error handling. That's because the best way to explore Visual Studio 2008's new mobile debugging tools is to make mistakes—particularly unhandled exceptions. To familiarize yourself with the new debugging features, here are some "mistakes" you can make in the code:
Some additional resources worth looking at:
Walkthrough: Adding a SQL Server Compact 3.5 Database to an Application and Deploying it
How Do I: Build a .NET Compact Framework 3.5 Application for Windows Mobile 6 Devices?
Using Setup Projects to Deploy Windows Mobile 5.0 Applications (Level 200)
MSDN Webcast: What's New for Device Developers in Visual Studio 2008 (Level 200)
* This article was commissioned by and prepared for Microsoft Corporation. This document is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS SUMMARY.