6 ProgramDesign
Tim Young edited this page 2017-10-04 03:24:25 +02:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Program design

This section is geared towards helping describe how you may want to design a game that is built with SpriteLibrary. This is a suggestion only. It will probably help you to read this section, as it does contain a fair bit of hard-won thought. BUT, every developer must make a lot of their own decisions. There is nothing magical about this.

One Form

It is a lot simpler to program a game if it is all within one form. While you can develop games using multiple forms, things can get very messy. The SpriteLibrary was designed for use with one form, and bouncing between different forms can result in some very strange behavior.

In my AdventureDemo, I used multiple forms. That was a bad idea. The main "bad" thing I did was to take a sprite from one form and try to use it on another form. I used the SpriteController.AddSprite function to take a sprite and add it to another controller on a different form. If I closed the main game window during a battle, the game exited and the game-menu popped up. Then, the sprites continued to fight, even though they were technically gone. The party continued to take damage, and sometimes die. Seeing your party turn into a gravestone on the start-menu was funny, but it was a bug

The game is a lot simpler to deal with if you only have one form. This means you can draw your menu on the same PictureBox that you have your game running on, or have separate PictureBoxes on one form. If you use only one PictureBox, you can change the PictureBox background when you are playing the game, vs when you are looking at the menu. This gives you a different looking window when the game is up. It does not really matter too much. But, please, try using putting it all in one Form if possible.

Using only one PictureBox is truly the easiest way to do it. When you resize the form, the PictureBox can resize with it, and it does a nice job. It is by far the simplest way to do it.

Having multiple PictureBoxes works fairly well, particularly with linked sprite-controllers and / or a SpriteDatabase. Both of those allow you to define a sprite once but use it on multiple picture boxes. But having multiple PictureBoxes does make resizing a little more complex.

Enum for Game Mode

To get everything to run in one Form, it is usually easiest to have an Enum, which tells you which mode you are in. The enum might be something like:

public enum GameMode { Menu, Menu_Settings, Menu_HighScores, Playing, Won, Lost }

You will have a “Tick” function (more information below), and the first thing in your tick function is to determine what mode you are in, and process things accordingly.

Instantiate Named Sprites (or instantiate on demand)

Loading your sprites at the beginning of the game is often the simplest way to do it, but it can make the game feel slow when it first opens.

Loading the Sprites the first time you use them can add some complexity to the game (though the SpriteDatabase does most of the work for you if you choose to use it.) If the process of instantiating a sprite is quick enough that it can be done in the middle of action. Otherwise, you will want to pause long enough at the beginning of the game to load all your sprites.

You can make your own functions to load sprites on demand too. That is basically what the SpriteDatabase does, but it defines all the sprite information in an XML file, which you might not want to mess with.

If you have twenty or thirty sprites, you will probably want to take the time to understand the SpriteDatabase. Otherwise, just program them into your code and load them at the beginning.

Function to change mode

You should create a function to change the game mode. We will place a call for this in a moment, but for now, we do something like:

  • Clear all sprites: The sprite controller has a process for returning all sprites that are duplicates of named sprites. We can use that to clear all the sprites like:
void ClearAllSprites()
{
   foreach(Sprite one in mySpriteController.SpritesBasedOffAnything())
      one.Destroy();
}
  • Start Game: Change the background to whatever the game background is. Duplicate all the sprites you need for the game and place them in their starting positions.
  • Start Menu: Change the background to whatever the menu background image is. Duplicate all the menu sprite buttons and place them in their respective menu spots. (You should have menu buttons for things like “play”, “settings”, “high-scores”, and “exit”)
  • Start Settings: This is usually a special “menu” that has items like: “volume”, “speed”, etc.
  • Start Game Won: This is usually a special menu that shows you a “you have won!” message, as well as your score, and any special “win” message. You usually have a “next” button or something to go on to the menu from there.
  • Start Game Lost: This is usually a special menu that shows you a “you have Lost!” message, as well as your score, and any special “lost” message. You usually have a “next” button or something to go on to the menu from there.

Game Tick

The Game Tick function is where most of the work on your game goes. The Tick happens every few milliseconds. When you create your SpriteController, you need to add your Tick function with something like: MyController.DoTick += GameTick; You usually check first to see if you are switching your mode to something else:

If(newmode != currentmode) ChangeMode(newmode);

And then, you have an if (or switch) block to process things depending on which mode you are in:

If(currentmode == GameMode.Playing) {
CheckForKeypresses();
CheckForChangeInLevel();
}

Making a Game Menu

Your Menu is usually set up by creating a bunch of functions, one for each MenuButtonSprite. A MenuButtonSprite is basically a sprite that does something when you click it.

A menu image

For an example, we will use an “exit” sprite button. This button will look something like the one on the left. We load the sprite as three different animations. The first one, at the top, we will use for when we show the menu. The second menu item is just a little bit lighter in color, and we will use that when we mouse-over the menu item. And we will use the green one when we click on it.

We will want to have some functions for this button. Lets call them ExitClick, ExitMouseOver, and ExitMouseLeave.

When we instantiate this menu button, we will do something like the following:

Sprite ExitButton = Sprite(new Point(0, 0), MyController, Properties.Resources.Exit, 100, 100, 1000, 1);
ExitButton.AddAnimation(new Point(0, 50), Properties.Resources.Exit, 100, 100, 1000, 1);
ExitButton.AddAnimation(new Point(0, 100), Properties.Resources.Exit, 100, 100, 1000, 1);
ExitButton.Click += ExitClick;
ExitButton.MouseOver = ExitMouseOver;
ExitButton.MouseLeave = ExitMouseLeave;
ExitButton.SetName(ExitButton);

Now, lets make our different functions.

public void ExitClick(object sender, SpriteEventArgs e)
{
    If(sender is Sprite)
    {
	Sprite ExitSprite = (Sprite)sender;
	Sender.ChangeAnimation(2); //What it looks like when it is clicked.
	NewGameMode = GameMode.Exiting;
     }
}

public void ExitMouseOver(object sender, SpriteEventArgs e)
{
    If(sender is Sprite)
    {
	Sprite ExitSprite = (Sprite)sender;
	Sender.ChangeAnimation(1); //Animation 1 has a glow around it and it is a different color
    }
}
public void ExitMouseLeave(object sender, SpriteEventArgs e)
{
    If(sender is Sprite)
    {
	Sprite ExitSprite = (Sprite)sender;
	Sender.ChangeAnimation(0); //Animation 0 is "normal looking"
    }
}