Export (0) Print
Expand All

Games Programming with Cheese: Part One

.NET Compact Framework 1.0
 

Rob Miles
Department of Computer Science, University of Hull

Updated: March 2006

Applies to:
   Windows Mobile 5.0 for Smartphones
   Microsoft .NET Compact Framework version 2.0
   Microsoft Visual Studio 2005

Summary: An introduction to the games program on the Windows Mobile powered Smartphones that use the .NET Compact Framework version 2.0 and Visual Studio 2005. The download code sample contains several downloads of the project at different stages of development. (23 printed pages)


Download Games_Programming_With_Cheese_Part1.msi from the Microsoft Download Center.

Contents

Introduction
Adding Cheese and Images
Creating a New Project
Adding an Image to the Project
Drawing Some Cheese
Performing Animation
Adding Speed Control with Menu Buttons
Adding a Bat
Implementing Double Buffering
Moving the Bat
Conclusion

Introduction

Welcome to the world of programming with cheese. This series of articles will provide instructions about how to make games for Windows Mobile powered Smartphones. There are a few ground rules:

  1. The games all use the Microsoft .NET Compact Framework version 2.0, so you'll need a device that is running Windows Mobile 5.0.
  2. The games do not use any of the games libraries. Instead Windows Forms will be used.
  3. Each game should take a short time to write.
  4. Every game must involve cheese.

This is supposed to be a bit of fun and will develop over time. You are going to add features one at a time so that at the end you have some little games and a set of tools that can be used to create other games. The techniques this article uses have been chosen for simplicity.

Oh, and I'm sorry if the cheese thing starts to grate (groan); it is just that I like cheese.

Getting Started

You will need Visual Studio 2005.

You don't actually need a phone handset because you will be using techniques that make it possible to do all the work on the emulator provided by Microsoft Visual Studio 2005. Of course, if you have a phone, it will make things much more interesting. You will need one that supports the .NET Compact Framework. Only the most recent Windows Mobile 5.0–based Smartphones work with the .NET Compact Framework version 2.

If you want to deploy programs to an actual device, you need ActiveSync version 4.1.

All of the examples for this project will be in C#, so you may find an understanding about C# programming to be helpful.

Adding Cheese and Images

To start, you are going to create a simple program that only displays a piece of cheese on the screen, as shown in Figure 1. Later, you will move the cheese around the screen, add a piece of bread to hit the cheese with, and set the stage for creating a cheese-oriented breakout game.

Figure 1. A piece of cheese

You can use this piece of cheese, which is supplied as part of the download code sample. (Alternatively, you can use whatever image you choose.) The original image was quite large—around 200 pixels or so wide. This size is far too big for the original 96 dpi Smartphone screen, which gives you 176 x 220 pixels to play with. This image is 25 x 23 pixels in size. If you don't already have an image processing program that you like, you can use the latest version of Microsoft Paint that Windows XP supplies to resize images.

The picture was originally stored as a .jpeg image and was 594 bytes in size. The same image encoded as a .gif started out twice as large at 1.18 KB, so the number of colors was reduced to 16 and some tidying was done to get the image down to 239 bytes. Making the images smaller won't greatly affect the program speed when it runs—because you will be using bitmaps inside the program itself—but it will reduce the size of the program file.

The reduced size of the program file is especially important if you are writing a program to work on a range of devices that each have different screen sizes. In this case, you might want to produce different sized images of each of the game components and then make the program select the most appropriate one when it runs.

Creating a New Project

For the purpose of these exercises, you should use Visual Studio 2005 Standard Edition.

You have your cheese, so now you need to get it onto the screen. First you need a Visual Studio Smartphone project to put everything into.

To create a new project

  1. Open Visual Studio 2005.
  2. On the File menu, click New Project. The New Project dialog box appears. You need to create a Windows Mobile 5.0 Smartphone device application, as Figure 2 shows.

    Click here for larger image

    Figure 2. Creating the Bouncer solution. Click the thumbnail for a larger image.

    In this example, the solution's name is Bouncer and it is saved in the default Visual Studio 2005 Projects directory. You can name the project a different name and save it in a different location on your computer's hard drive disk.

  3. Press OK to create the project. Figure 3 shows a new project that contains a single form, which is named Form1.cs.

    Figure 3. The new project in Solution Explorer

Running the New Project

You should run your new project before adding items to ensure that you are happy about the way that Smartphone programs are made to run. You can select the target device or emulator in Visual Studio, as shown in Figure 4.

Figure 4. Selecting the target device

Note   You should only select Windows Mobile 5.0 Smartphone Device if you actually have a physical device that is connected to the computer by means of ActiveSync.

To run the program, select Start Debugging on the Debug menu. If you are running the program on a physical device, you will be prompted by the device to confirm that Visual Studio should run the program, as shown in Figure 5.

Click here for larger image

Figure 5. Message to confirm the program should be run on a Smartphone. Click the thumbnail for a larger image.

When prompted to confirm, press Yes to run your program. This message appears each time you deploy a new program on the device. Some library files are also loaded onto the device the first time you run a .NET Compact Framework program, which may also result in the confirm message being displayed.

Note   Your Smartphone may have been locked to prevent unauthorized programs from being run on it. In this case, you have to unlock the phone. For phone unlocking procedures, you should consult your service provider. For more about the Smartphone Application Security Model, see the article, A Practical Guide to the Smartphone Application Security and Code Signing Model for Developers.

Figure 6 shows the new project running on the emulator.

Figure 6. Running the new project on the emulator

Your program on the Smartphone will not have an exit button, so to stop the program from running, you need to click Stop Debugging located on the Visual Studio 2005 Build menu.

Note   Don't turn off the Smartphone emulator to stop your program. This action stops the program—and the emulator itself, meaning that the next time you run your program, you'll have to wait for the emulator to start running before Visual Studio 2005 can deploy and execute your program. Using the Stop Debugging command in Visual Studio works best because it only stops the program.

Adding an Image to the Project

Next, you will want to put all of the resources for the program into the program itself. You need to add the cheese image to the project.

To add an image to the project

  1. Copy the cheese image into the same directory as your project source files.
  2. Add the image file to the project by right-clicking the Bouncer item in Solution Explorer, selecting Add, and then selecting Add Existing Item, as shown in Figure 7.

    Figure 7. Adding an existing item

    This step causes the Add Existing Item dialog box to appear.

  3. Change the file type selector at the bottom of the Add Existing Item dialog box to select the image files. The cheese image file should be visible. Select this file.
  4. Click Add. The image is added to your project, as shown in Figure 8.

    Figure 8. Project with the cheese.gif image added

The image file is now part of the project, but it is not a part of the program. To do this, you must make the cheese.gif file an embedded resource.

To add an image to a program

  1. Right-click the image's icon in Solution Explorer, and then click Properties from the menu that appears.
  2. In the Visual Studio Properties pane, change Build Action from Content to Embedded Resource. The image becomes part of the assembly, so only the single executable file needs to be deployed. The properties for this project should match those that are shown in Figure 9.

    Figure 9. Project with the embedded cheese image

Using the Embedded Resource

The cheese image is now inside the assembly file that holds the executable file. When the program runs, it must get the image file out of the assembly file and make it into an image that can be displayed on the screen. To do this, the program must first get a reference to the assembly itself, as the following code example shows.

System.Reflection.Assembly execAssem = 
    System.Reflection.Assembly.GetExecutingAssembly();

The System.Reflection.Assembly.GetExecutingAssembly method returns an assembly reference, which is set to point at the currently executing assembly. After the program has a reference to the assembly, it can use the reference to get elements that are embedded within it, as shown in the following code example.

cheeseImage = new System.Drawing.Bitmap(
    execAssem.GetManifestResourceStream(@"Bouncer.cheese.gif) );

The GetManifestResourceStream method fetches the specified resource from the assembly file and supplies it as a stream. The method is given the name of the item that is required and also the name of the namespace that contains it—in this case, the "Bouncer" namespace. One of the constructors for the Bitmap object (which is the item to be drawn) accepts a stream and returns a bitmap.

Note that you need to declare a member of the Form1 class to hold a reference to the image that is loaded. The reference must be of type Image. In total, your code should look like the following code example.

private Image cheeseImage = null;

public Form1()
{
    InitializeComponent();

    // Get the assembly so you can get the cheese out of it.
    System.Reflection.Assembly execAssem = 
        System.Reflection.Assembly.GetExecutingAssembly();

    // Get the cheese.
    cheeseImage = new System.Drawing.Bitmap(
        execAssem.GetManifestResourceStream(@"Bouncer.cheese.gif")
    );
}

Note that the previous code example does not handle what happens if this process fails, but for now it will do.

Drawing Some Cheese

The program now loads the cheese image when it starts. Next, the program must draw the cheese on the display. Windows programs redraw their screens in response to paint events. The developer supplies a paint method that is called by Windows whenever the screen needs to be redrawn.

To capture the paint event and direct it to a method

  1. In Visual Studio, right-click the form inside the Smartphone simulation in the form designer, and then click Properties. You should now be able to select the Form1 properties information, as shown in Figure 10.

    Figure 10. Form1 properties

  2. Switch to the events by clicking the yellow lightning bolt icon. You should see all of the events that the form can generate and to which you can attach handlers, as shown in Figure 11.

    Figure 11. Events in the Properties pane

  3. Scroll to the Paint event, and double-click Paint. Visual Studio 2005 creates an event handler method for you and places your cursor inside the method in the code designer.
  4. Add the following code example to make the method draw the image.
    private void Form1_Paint (object sender, System.Windows.Forms.PaintEventArgs e)
    {
        e.Graphics.DrawImage(cheeseImage,0,0);
    }
    
    

If the operating system on the Smartphone needs to redraw the form, it raises a Paint event on the form. The method runs and is supplied with two parameters: a reference to the object that sent the message and a reference to a PaintEventArgs object. The PaintEventArgs object contains a reference to the Graphics object that is drawing for this event. The Form1_Paint method calls the DrawImage method on that object and gives it a reference to the image to be drawn and its position on the screen. The program draws the cheese at the top left corner of the display (coordinates 0,0), as shown in Figure 12.

Figure 12. The program draws the cheese on the device's screen

If you run the program on the emulator, you should get the same result—the program draws the cheese.

Performing Animation

The program can now draw cheese on the screen. Next, it has to move the cheese by repeatedly drawing and redrawing the cheese image at different positions. If the program does this fast enough, it creates the illusion of movement.

Moving Objects on the Screen

The following code example creates a method, named updatePositions, that moves the cheese. At the moment, the cheese will only move down (and to the right).

/// <summary>
///  The X coordinate of the cheese drawing.
/// </summary>
private int cx = 0;
/// <summary>
/// The Y coordinate of the cheese drawing.
/// </summary>
private int cy = 0;

private void updatePositions () 
{
    cx++;
    cy++;
}

The game program uses cx and cy to keep track of the location of the cheese. At the moment, their values just get bigger each time the update is called, which causes the cheese to move down and to the right. The program uses these values to draw the cheese in a different location each time, as shown in the following code example.

private void Form1_Paint (object sender, System.Windows.Forms.PaintEventArgs e)
{
    e.Graphics.DrawImage(cheeseImage,cx,cy);
}

Whenever the Paint method is called, the program redraws the cheese at the proper place.

Ticking Clocks

In the early days, a video game ran at the full speed of the underlying hardware—that is, it drew everything as fast as it could. The program is not going to allow this; instead, it is going to make the game run at a particular rate. The following are some good reasons for running the program at a particular rate:

  • The program must control the speed at which things happen.
  • The speed of the game must be the same—independent of the processor's speed in the particular device.
  • The program must not use the entire processor's time by running at full speed and stopping everything else.

Fortunately, the .NET Compact Framework provides a way of managing the processor's usage in the form of timers. You can add a timer object to a form, so a particular method is called at regular intervals. This method has to update every aspect of the game. When the method completes, the game effectively stops until the next tick of the clock. The game clock ticks 20 times per second.

To add a timer to a form

  1. In Visual Studio 2005, open the Toolbox, and then find the Timer control.

    Click here for larger image

    Figure 13. The Toolbox showing the Timer control. Click the thumbnail for a larger image.

  2. Drag the Timer control to the component tray and place the control next to the mainMenu1 item. The component tray (located at the bottom of the form designer) should look like Figure 14.

    Figure 14. The Timer control added to the form

    Note   Adding a Timer control to the form means that the processor is always active and that the device cannot go into a power saving mode. These outcomes are generally bad for battery life. For this reason, your game should disable the timer when the user puts the game into the background on the device. The game should restart the timer when the game again becomes active.

The Timer control does not add any indication to the form, but the control becomes part of it. You can adjust the properties of the Timer control by right-clicking the little clock in the component tray, which is located at the bottom of the form designer, and then by clicking Properties. The interval between ticks is originally set at 100 milliseconds, but you must change it to 50 milliseconds (to make 20 ticks a second). As shown in Figure 15, the timer's Enabled property is initially false, which indicates that the timer is off. For now, the Enabled property should be left as is because the timer must not tick until the program has loaded the image that needs to be drawn.

Figure 15. Adjusting the Timer control's properties

You can assign a method to a timer tick in exactly the same way as you assign a method to a Paint event. If you click the yellow lightning bolt icon in the Properties pane (as shown in Figure 15), the Properties pane shows the events that a timer can generate. If you double-click the Tick event, you create a method called timer1_Tick, which is bound to the timer event. Visual Studio places your cursor inside the method in the code view.

When the timer is enabled, this method is called 20 times per second. Initially, it is an empty method. You must change this method to update the position of the cheese and then force the screen to be redrawn.

Starting to Tick

When you created the timer, you didn't enable it because the timer1_Tick method may begin to draw the images before they have been loaded—causing the program to crash with the first tick. You should enable the timer after all of the images have been loaded. In the sample application in this article's download code sample, the timer is enabled in the constructor for the form, as the following code example shows.

public Form1()
{
    //
    // Required for Windows Form Designer support.
    //
    InitializeComponent();

    // Get the assembly so you can get the cheese out of it.
    System.Reflection.Assembly execAssem = 
        System.Reflection.Assembly.GetExecutingAssembly();

    // Get the cheese.
    cheeseImage = new System.Drawing.Bitmap
(execAssem.GetManifestResourceStream(@"Bouncer.cheese.gif"));

    // Start the clock.
    this.timer1.Enabled = true;
}

The constructor calls the Windows Forms supplied method to set up the form. This creates the timers and any other components that the program needs. Then, it loads the cheese image and finally the timer starts ticking.

Forcing a Redraw

Windows redraws the screen only when there is a need to. For example, on a desktop computer, the program redraws the screen when a window is maximized or the user changes its size. However, it is also possible to force a redraw by calling the Invalidate method on that window. A call to Invalidate asks the system to do all of the things that a Paint operation requires including calling the form's Paint event handler. You can place the call to the Invalidate method after the positions have been updated. The screen must be updated each time the timer event fires, so the calls are placed in the method that you bound to the timer events.

private void timer1_Tick (object sender, System.EventArgs e)
{
    updatePositions();
    Invalidate();
}

This is the sledgehammer version of the Invalidate method, which forces everything to be redrawn. If you make a version of the program with these changes, you should find that when you run your program, the cheese slides slowly down the screen and vanishes off the right corner. Drawing an image which is not on the screen will not cause a problem, but of course, it will not be visible to the player. You should also notice a bit of tearing as the object flickers during its redraw. This article addresses tearing in the Double Buffering section.

Going for the Bounce

Making items appear to bounce on the screen is simple. The program must hold the current direction the item is traveling in, and then, when a position value reaches the edge of the screen, reverse this direction value. In the first version, the position is updated by +1 when the cheese is moving forward and down and is updated by -1 when the cheese is moving backward and up. The improved version of the updatePositions method looks like the following code example.

/// <summary>
/// The direction of movement in the X axis.
/// </summary>
private bool goingRight = true ;
/// <summary>
/// The direction of movement in theY axis.
/// </summary>
private bool goingDown = true ;

private void updatePositions () 
{
    if ( goingRight )
    {
        cx++;
    }
    else 
    {
        cx--;
    }

    if ( ( cx + cheeseImage.Width ) >= this.Width ) 
    {
        goingRight = false;
    }
    if ( cx <= 0 ) 
    {
        goingRight = true;
    }

    if (goingDown) 
    {
        cy++;
    }
    else 
    {
        cy--;
    }

    if ( ( cy + cheeseImage.Height ) >= this.Height ) 
    {
        goingDown = false;
    }
    if ( cy <= 0 ) 
    {
        goingDown = true;
    }
}

Note that this code example uses the width and height properties of the object and the screen, so any-sized cheese image can bounce around any-sized screen with no problems. Note also that this code example is fairly inefficient. The program is doing more sums than it needs to, and a clever developer could speed up this code a significant amount. However, the purpose of this article is to show the principles of the software rather than the best possible way to get high performance. If you replace the previous updatePositions method in the previous program with this one, you will find that the cheese bounces around the screen.

Adding Speed Control with Menu Buttons

The previous cheese program makes a block of cheese that moves at a rather sedate speed over the screen. At 20 frames a second and with a screen width of over 100 pixels, the cheese is going to take about 5 seconds to move across the screen, which would make for slow game play. Therefore, you can impose some control over the speed at which things move, which means that rather than updating the image position by 1 pixel on each timer tick, you can change the number of pixels that the image moves on each timer tick as shown in the following code example.

if ( goingRight )
{
    cx+=xSpeed;
}
else 
{
    cx-=xSpeed;
}

By changing the value in xSpeed, the horizontal speed of the cheese can be increased or decreased. A similar value for y lets the vertical speed of the cheese change as well.

Speed Control Code

It might be fun to see how fast the cheese can move. The following code example updates the speed values.

private void changeSpeed ( int change ) 
{
    xSpeed += change;
    ySpeed += change;
}

You can call this method when you want to update the speed. The value of the parameter gives the change of speed. If you make the value negative, this method reduces the speed.

Using Soft Keys

You can use the soft keys (which are located directly below the Smartphone display) to control the speed of the cheese. You need to provide menu text for them and then assign methods to the menus. In the form designer, click the space at the base of the form above the left soft key (the text Type Here appears), and then type the word Faster. Next, click the space at the bottom of the form above right soft key, and then type the word Slower. The user interface now has two menu buttons, as shown in Figure 16.

Figure 16. Soft keys

Note   When you are writing Smartphone programs, do not add submenu commands to the left soft key. The Smartphone User Interface Guidelines indicate that the left soft key should have only one command on it (the most frequently required). The .NET Compact Framework 1.0 throws an exception if your program attempts to add command submenu items to the left soft key. The .NET Compact Framework 2.0 no longer throws an exception when you add submenu commands to the left soft key, but you should avoid adding them so your application maintains consistency with the guidelines and other Smartphone applications. You may use submenu items on the right menu button.

You can use Visual Studio to attach a Click method to each soft key, and when the user presses the soft key, the method runs.

To create the method for a soft key, double-click the menu text (Faster or Slower) in the form designer. The Faster soft key will increase the distance the cheese moves with each press, and the Slower soft key will decrease the distance. Now, you need to add calls to the changeSpeed method for each soft key, as shown in the following code.

private void menuItem1_Click(object sender, System.EventArgs e)
{
    changeSpeed (1);
}

private void menuItem2_Click(object sender, System.EventArgs e)
{
    changeSpeed (-1);
}

When this program runs, the user can speed up or slow down the cheese by pressing the soft keys. In this program, the code does not restrict the values that are passed to the controlSpeed method, which means that if the user keeps reducing the speed, the value may become negative and cause the cheese image to move in a very strange way. You might find it useful to consider how you can correct this behavior.

If you run this version, you should find that when the speed is about five or higher, the movement starts to appear jerky.

Adding a Bat

Now that the program can display cheese that bounces around the screen, next you need to get a bat that you can use to hit the cheese. The program has to draw a second item—the bat. The user also needs to control it.

Drawing with Bread

Figure 17 shows the bread bat. The idea is that the user controls the bread to hit the cheese.

Figure 17. Bread bat

The program draws the bread on the screen in the same way as it draws the cheese. You simply add the image to the project and then have the code get it from the assembly. You also need to add two variables that control the x and y position where the program draws the bread. For the moment, the program draws the bread at the top-left side of the screen, as shown in Figure 18.

Figure 18. Bread and cheese

Flickering and Drawing

What Figure 18 doesn't show is the horrendous flickering that occurs when the program runs. The cheese and the bread flash on and off most unpleasantly. This flickering is due to the very primitive way that the program draws the screen. Every twentieth of a second, the screen is drawn with white, and then the two objects (bread and cheese) are drawn separately. This process is very visible and looks terrible. Thus must be fixed before proceeding any further; otherwise, nobody will want to play the game.

Implementing Double Buffering

Video games solve the flickering screen problem by a technique known as double buffering. The idea is that the program doesn't draw on the frame the user can see. Instead, it draws on a buffer in memory. Then, when the picture is complete, the entire picture is copied onto the visible screen. The copy process is very quick, and the flicker is removed.

In the case of the flickering game, you have to create another bitmap area, draw on it, and then copy the new bitmap into position. You have to modify the Form1.Paint method, as shown in the following code example.

/// <summary>
/// Background buffer bitmap.
/// </summary>
private Bitmap backBuffer = null ;

private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
    // Make a new back buffer if needed.
    if(backBuffer==null) 
    { 
    backBuffer=new Bitmap(this.ClientSize.Width,this.ClientSize.Height); 
    } 

    using ( Graphics g=Graphics.FromImage(backBuffer) ) 
    {
    g.Clear(Color.White);
    g.DrawImage(breadImage,bx,by);
    g.DrawImage(cheeseImage,cx,cy);
    }
    e.Graphics.DrawImage(backBuffer,0,0); 
}

The very first time that this method runs, it creates a back buffer (the backBuffer bitmap variable in the preceding code example) to draw into. Then, it uses the graphics context from that buffer to draw the bread and cheese. Finally, the DrawImage method of the form's graphic context is used to copy the back buffer into position.

If you use this draw method in your program, you will find that it hasn't removed the flicker. It has replaced a small amount of flicker with a large amount of flicker. The reason this technique doesn't work has to do with how Windows behaves when it redraws. When the program paints the screen, Windows fills the screen with the background color (in this case, white). Then, it causes a Paint event to put the game elements on top of the background. The program draws the pictures on the top of the cleared white screen. The result is a large amount of flicker.

The solution to this problem is to stop Windows from doing the redrawing. The program must override the method that normally clears the screen and must replace the method with one that does nothing. The method is OnPaintBackground, and you can override it as shown in the following code.

protected override void OnPaintBackground(PaintEventArgs pevent) 
{ 
    // Don't allow the background to paint. 
} 

If you add this method to the Form1 class, you find that everything works as you expect—the cheese and bread smoothly move around the screen. Problems still arise when the cheese moves over the bread (it seems to cut a square chunk out of the bread as it passes over), but, for now, you have to use a workaround: ensure that the two objects never pass over each other. Later, you will see how to make the cheese slide smoothly over the bread.

Moving the Bat

Next, the program must move the bat around so the player can hit the cheese with it. This action requires the user to use the device's navigation pad as a joystick. All Smartphones have a navigation pad, and the navigation pads always interact with the program in the same way.

Key Events

When users interact with a Smartphone navigation pad, they are exposed to an application in the same way as when they press keys on the keyboard. Basically, when users move the cursor with the navigation pad, this action appears to the application as if the user is pressing a direction key. Normally, a program responds to a keyboard when users press and release keys—treating the press and release as a single action. However, when playing a game, users press the navigation pad in a particular direction and hold it—expecting the bat to move in that direction until the they release the navigation pad. The common behavior of treating the press and release of the key as a single action is not sufficient in this case.

To solve this problem, you have to understand how Windows Forms manages the keyboard. User actions on the keyboard generate events. These events become method calls in the form, like the timer events that make the game tick.

Usually a developer uses the KeyPress event. This event does exactly what you would expect. When a user presses and releases a key, the event is raised so the program can respond to it. In the case of a word processor program, the action might be to put the character that the user pressed into the document or perhaps to move the cursor. The KeyPress event can be bound to a method in the form, but, unfortunately in the case of this game, it doesn't provide the required control.

However, there are two other events, KeyDown and KeyUp, that are very useful. The first event fires when the user presses a key. The second event fires when the user releases the key. You can get into trouble with auto-repeat on some keys (where Windows makes repeated keystrokes when a key is held down), but my experience has been that the joystick does not behave in this way.

The program must to set a flag when the user presses the joystick in a particular direction (that is, when a KeyDown event is raised). While the flag is set, whenever the position of the objects is updated, the program moves the bat in the direction of the joystick. When the user releases the joystick and the second event is raised, the program clears the flag and the object stops moving.

You need to capture the KeyDown and KeyUp events in the same manner that you captured the other events on the form. These events include a member of the Keys enumeration indicating which direction the user moved the navigation pad. The possible values that the navigation pad generates are Keys.Up, Keys.Down, Keys.Left and Keys.Right. Figure 19 shows how the form event properties appear after the events have been captured.

Figure 19. KeyDown and KeyUp event handlers

When the events occur, the methods are called. The methods themselves are shown in the following code example.

/// <summary>
/// Use the keyArgs reference as a flag. If it refers to a key event
/// instance, you must act on the information because the user is 
/// holding down that key at the moment.
/// </summary>

private System.Windows.Forms.KeyEventArgs keyArgs = null;

private void Form1_KeyDown (object sender, System.Windows.Forms.KeyEventArgs e)
{
    keyArgs = e;
}

private void Form1_KeyUp (object sender, System.Windows.Forms.KeyEventArgs e)
{
    keyArgs = null;
}

This code actually uses the event argument as the flag itself. When the program receives the Form1_KeyDown event call, the program sets keyArgs to refer to the event item. When the program gets the Form1_KeyUp event, it sets keyArgs to null, so it is ignored. The contents of the updatePositions method are shown in the following code.

private void updatePositions () 
{
    // The cheese.
    // The cheese code as above here.

    // The bread.
    if ( keyArgs != null ) 
    {
        switch ( keyArgs.KeyCode ) 
        {
            case Keys.Up:
                by-=ySpeed;
                break;
            case Keys.Down:
                by+=ySpeed;
                break;
            case Keys.Left:
                bx-=xSpeed;
                break ;
            case Keys.Right:
                bx+=xSpeed;
                break;
        }
    }
}

This code example uses a switch that is driven by the KeyCode property of the event arguments. Depending on which key code is signaled, the program changes the appropriate bread coordinate. The bread is presently moving at the same speed as the cheese.

If you add the new version of the updatePositions method to your program, you should find that you can move the bread around the screen with the direction keys while the cheese bounces around it.

Diagonal Danger

Note that this program does not handle diagonal movement. Most game console and desktop computer game joysticks can be pulled in two directions at the same time—for example, down and left to create diagonal movement. When developing games for Windows Mobile devices, diagonal movement is not a problem because no Smartphones or Pocket PCs on the market that has a navigation pad that can move in this way.

Conclusion

In this article, you've seen how to paint graphics to the screen so they don't flicker and how to intercept key presses to move the bat. You've also laid the groundwork of the physics of the game. You can now move a bread bat around the screen and chase the cheese with it. In the next article, you'll have a chance to consider what the program should do when cheese and bat collide, and you'll see how to create the breakout game.

Show:
© 2014 Microsoft