Quick update on some of the game’s modes

Just wanted to add a quick update with a video on the progress of my game. The features it has so far: almost working 1-player mode, easily customizable menus, level progression, a level editor, 3D graphics for billboard sprites, and a slick screen animation system.

The graphics are still not final (far from it) and game art will probably be the last thing on my list to finish. More details to come soon!

Advertisements

New screen system, but stuck on the visuals

Bubble Tower is still underway, but the progress has been somewhat slower since its inception. There’s a lot that I fixed and improved under the hood, but I’m at a standstill for creative work. First the good news…

I spent a lot of time last week with moving from a game state management system to a screen management system. If you are familiar with the XNA code sample, you’d know what it is. If you’re not, I basically have moved away from using a last-in-first-out data structure to manage game states. Menu management and state management are now one and the same, with them all being treated as “screens” which can be added on and removed at any layer. This adds a ton of flexibility for creating better interactions and transitions within games, and easier to scale in more complex games.

Through the course of converting all of my code, I stomped out a lot of bugs related to loading and displaying menus, background screens, and content in the game. I also got around to getting levels to save and load correctly with a flat binary file. All the levels in the main single player mode of the game are to be stored in one file. Before, any level you saved completely overwrote the entire file, so it was impossible to keep more than one level at a time, but now all levels should save and load correctly. Now to improve on the menu so that I can scroll through several “pages” of levels.

Coming short on visual details

Now for the stuff I’m still stuck on. I really need some art for my game. After doing so much to improve the functionality of the game, I want to move on to the more artistic visual work. Problem is, I’ve hit a creative roadblock. There’s not much inspiring me to add some nice art to the game, and it’s really killing me to keep working on my game when visually, it’s not so appealing.

I know this is a puzzle game, where I can get some leeway to be more simple and abstract with the art, but I’m already getting tired of looking at the same plain screens and graphics. Maybe this is part of what game testers feel when they’re repeating the same tasks, but at least they’re not responsible to do the work that artists will eventually do.

What’s interesting is that I’m a visually inclined person- I majored in art, and know a good UI when I see one, but I am not really that good in going into extensive periods of drawing and sketching out from my ideas. Those only come to me in short bursts. Also interesting is that making 3D art tends to come easier to me than 2D art. Not that I make some super detailed, realistic stuff, but that I am more satisfied with the finish product in 3D than whenever I take a shot at doing 2D art.

Looks like I should start playing more games for inspiration. The theme of climbing and ascending towers is still something I want to do, so at least I have a starting point there. I might have to go the 3D route to do most of my art, but it will take me some effort to actually get into sketching out some ideas on paper until I find something that I like and can work with on the computer. Time to get my other side of my brain to work overtime.

Making a flexible level selection menu: Part 2

Continuing off from last time, we’re going to improve on the Level Selection menu made using the Game State Management sample. If you haven’t done so already, read part 1 of the article so you can catch up.

For any other game modes you would want, you do need other classes that differ from GameplayScreen to some extent, because they’ll need to run different code, for different game rules and settings. But do we also need to make another class like the LevelSelectScreen class, displaying the same list of level choices, but change the Select event so it loads these other game modes? Not really, and that would be too much repetition. Instead, the menu screen can be re-purposed to recognize different entry and exit points and load the appropriate game mode.

The end result would be making the Level Select menu reusable. It will load a different GameScreen from the Level Select menu, depending on what item you selected in the Main Menu.

Main Menu -> Select “Play Game” -> Select a level -> Gameplay on selected level

Main Menu -> Select “Level Editor” -> Select a level -> Level Editor on selected level

Suppose you’re tired of coding those levels by hand and you finally want to start working on a fancy level editor. All its functions and logic will neatly reside in a LevelEditorScreen class. We can use GameplayScreen as a starting point. So let’s copy GameplayScreen.cs and rename it to LevelEditorScreen.cs, and also rename the class as such.

You may notice that it carried the new constructor and parameters that we introduced into GameplayScreen class with it. These will be used for the Level Editor as well. To distinguish it visually from the Gameplay screen, replace the "Playing level " text in the Update and Draw functions with "Editing level ", noting the trailing space at the end.

Now, let’s add another entry to the Main Menu screen. Just below the playGameMenuEntry, add another new MenuEntry with the text “Level Editor”. Add it to the MenuEntries list and assign an event handler to it as well. Copy the PlayGameMenuEntrySelected method and rename it to LevelEditorMenuEntrySelected, this will be the method to attach the event to. Here is the class, only showing the constructor and methods we just updated:

// MainMenuScreen.cs

        public MainMenuScreen()
            : base("Main Menu")
        {
            // Create our menu entries.
            MenuEntry playGameMenuEntry = new MenuEntry("Play Game");
			MenuEntry levelEditorMenuEntry = new MenuEntry("Level Editor");
            MenuEntry optionsMenuEntry = new MenuEntry("Options");
            MenuEntry exitMenuEntry = new MenuEntry("Exit");

            // Hook up menu event handlers.
            playGameMenuEntry.Selected += PlayGameMenuEntrySelected;
			levelEditorMenuEntry.Selected += LevelEditorMenuEntrySelected;
            optionsMenuEntry.Selected += OptionsMenuEntrySelected;
            exitMenuEntry.Selected += OnCancel;

            // Add entries to the menu.
            MenuEntries.Add(playGameMenuEntry);
			MenuEntries.Add(levelEditorMenuEntry);
            MenuEntries.Add(optionsMenuEntry);
            MenuEntries.Add(exitMenuEntry);
        }

        /// Event handler for when the Play Game menu entry is selected.

        void PlayGameMenuEntrySelected(object sender, PlayerIndexEventArgs e)
        {
			ScreenManager.AddScreen(new LevelSelectScreen(), e.PlayerIndex);
        }

		/// Event handler for when the Level Editor menu entry is selected.

		void LevelEditorMenuEntrySelected(object sender, PlayerIndexEventArgs e)
		{
			ScreenManager.AddScreen(new LevelSelectScreen(), e.PlayerIndex);
		}

We now have two menu choices that take you to the Level Select menu. But Level Select still takes you to the Gameplay screen no matter where you came from. Let’s change that! The Level Select menu needs to know where to go next. To do that, we’ll have to pass the Type of the GameScreen as a new parameter to LevelSelectScreen’s constructor.

The two event handlers of the Main Menu that take you to the Level Select menu use this updated constructor, and each call to AddScreen will pass to the constructor a different Type. For selecting “Play Game”, GameplayScreen is passed, and for “Level Editor”, it is a LevelEditorScreen.

// MainMenuScreen.cs

        /// Event handler for when the Play Game menu entry is selected.

        void PlayGameMenuEntrySelected(object sender, PlayerIndexEventArgs e)
        {
			ScreenManager.AddScreen(new LevelSelectScreen(typeof(GameplayScreen)), e.PlayerIndex);
        }

		/// Event handler for when the Level Editor menu entry is selected.

		void LevelEditorMenuEntrySelected(object sender, PlayerIndexEventArgs e)
		{
			ScreenManager.AddScreen(new LevelSelectScreen(typeof(LevelEditorScreen)), e.PlayerIndex);
		}

// LevelSelectScreen.cs

        Type gameScreenType;

		public LevelSelectScreen(Type gameScreen)
            : base("Select a Level")
        {
            gameScreenType = gameScreen;
        /* ... */
        }

        /// Event handler for when the Play Game menu entry is selected.

		void MenuEntrySelected(object sender, PlayerIndexEventArgs e, int currentLevel)
        {
			LoadingScreen.Load(ScreenManager, true, e.PlayerIndex,
				(GameScreen)Activator.CreateInstance(gameScreenType, currentLevel));
        }

The LevelSelectScreen class now takes in a Type parameter and for the selection event handler, an Activator creates a new instance of the GameScreen, casting it down and passing the currentLevel parameter. Since the type is chosen from the Main Menu, we can always make sure that any GameScreen that gets passed from it must take an extra parameter for the level.

Our new menu gives you two possible choices to access the Level Select menu from, but you can add more if you want. Nothing more needs to be done to the Level Select menu- the menus are already linked at this point. All you need to do is, for every GameScreen that you would want to load a level, create a new menu entry for the Main Menu and pass along the type for the GameScreen.

You can try improving the Level Select menu in other ways, like showing a different list of levels depending on what game mode you choose. To start out, you may set a condition to offset the level ID in the menu.

A more complex problem would be to display an extra selection screen before the “final” screen at the end of the selection process. In racing games, you often would select a vehicle in addition to the track you’ll race on. The logic from the Level Selection screen is flexible and bare-bones enough so you can duplicate it to make a menu for selecting characters, vehicles, etc. It’s pretty much open from there, so hopefully you’ll be able to find better uses for the menu, and make it easier to manage your menu code. Let me know if you have other ideas to improve it.

Making a flexible level selection menu: Part 1

Lately, most of my work on Bubble Tower has been on creating a menu system. The menu will need to support multiple game modes, options, and a screen to select levels with. Since I am basing this off the XNA Game State Management sample, a lot of the work has been done. But my game uses a separate system to handle game states, so I modified to code to keep menus and game states as different kinds objects.

I have finished the first step of building a working level select screen for the game, and notice that it’s pretty easy to do, but it does need a few modifications in the logic. I will show you how to make your own level selection screen with the Game State Management sample, and have it be reusable for as many game modes as you like. This way it’s possible to load a level -whether it’s for a single player game, multiplayer, or for editing- by going through the same menu as an intermediate step.

I won’t be teaching you how to actually load your level data into the game. This article is mainly to show how to create a flexible menu that can pass any parameters you wish to any game screen/state so you can do whatever you want with it. Whether your levels are hard-coded or stored in separate files doesn’t matter.

Adding a new menu

The GameStateManagement sample takes you to the Gameplay screen with the following steps:

Main Menu -> Select “Play Game” -> Gameplay

We’ll add a menu which will change the course of action to the following:

Main Menu -> Select “Play Game” -> Select a level -> Gameplay on selected level

For brevity, all these graphs ignore the Loading screen.

The first thing we’ll do is to copy the MainMenuScreen.cs file from the sample project, and rename the new file LevelSelectScreen.cs. In it, rename the class to LevelSelectScreen and remove all methods except for PlayGameMenuEntrySelected. This will be renamed to MenuEntrySelected. We’ll also make changes to the menu entries to replace with level names, and modify the MenuEntrySelected method. The class should look like this so far:

// LevelSelectScreen.cs

    class LevelSelectScreen : MenuScreen
    {
        public LevelSelectScreen()
            : base("Select a Level")
        {
            // Create our menu entries.
            MenuEntry level1Entry = new MenuEntry("Level 1");
			MenuEntry level2Entry = new MenuEntry("Level 2");
			MenuEntry level3Entry = new MenuEntry("Level 3");

            // Hook up menu event handlers.
			level1Entry.Selected += MenuEntrySelected;
			level2Entry.Selected += MenuEntrySelected;
			level3Entry.Selected += MenuEntrySelected;

            // Add entries to the menu.
			MenuEntries.Add(level1Entry);
			MenuEntries.Add(level2Entry);
			MenuEntries.Add(level3Entry);
        }

        ///
<summary>
        /// Event handler for when a menu entry is selected.
        /// </summary>
        void MenuEntrySelected(object sender, PlayerIndexEventArgs e)
        {
            LoadingScreen.Load(ScreenManager, true, e.PlayerIndex,
                               new GameplayScreen());
        }
}

A lot of repetition going on, but we’ll fix this soon. Now in the MainMenuScreen class we’ll change the PlayGameMenuEntrySelected method to match this:

// MainMenuScreen.cs

        void PlayGameMenuEntrySelected(object sender, PlayerIndexEventArgs e)
        {
			ScreenManager.AddScreen(new LevelSelectScreen(), e.PlayerIndex);
        }

If we run the code right now, we should see the “Play Game” entry in the main menu have a different function. Instead of taking you to the Gameplay screen, it should load the new menu we just made. This will let you choose between three options, which do load the Gameplay screen. But still, the options call the same exact method with no differences in them. This is where the next step comes in.

Choosing the level

The MenuEntrySelected method must have some way of knowing what level it needs to load. We will add a parameter to the method that will pass the level number, and in turn the Gameplay screen will also need to be modified to take that info and load the specified level.

Back in the LevelSelectScreen class, update MenuEntrySelected so it takes an integer, the selectedEntry from the MenuScreen class, for an extra parameter. The parameter will also be passed into the GameplayScreen constructor so change that as well:

// LevelSelectScreen.cs

		void MenuEntrySelected(object sender, PlayerIndexEventArgs e, int currentLevel)
        {
            LoadingScreen.Load(ScreenManager, true, e.PlayerIndex,
                               new GameplayScreen(currentLevel));
        }

Now there’s a problem. Because of the extra parameter, there’s no method overload that currently matches the delegate. To have the event handlers recognize the new method, let’s add an anonymous function. We’ll have to replace MenuEntrySelected on each event handler with the following delegate:

level1Entry.Selected += delegate(object sender, PlayerIndexEventArgs e)
				{ MenuEntrySelected(sender, e, selectedEntry); };

To do this on each handler will be repeating the same code. Since all the menu entries are linked to the same method, we can rewrite the LevelSelectScreen constructor to take in the entries as an array. To keep things simple, we’ll assume our game has a fixed number of levels and the array is hardcoded in. Here is the complete code for the constructor:

// LevelSelectScreen.cs

		public LevelSelectScreen()
            : base("Select a Level")
        {
			int totalLevels = 3;
			MenuEntry[] levelEntries = new MenuEntry[totalLevels];

            // Create our menu entries.
			for (int i = 0; i < totalLevels; i++)
			{
				// Add entries to the menu
				levelEntries[i] = new MenuEntry("Level " + (i + 1));
				MenuEntries.Add(levelEntries[i]);

				// Hook up menu event handlers
				levelEntries[i].Selected += delegate(object sender, PlayerIndexEventArgs e)
				{
					MenuEntrySelected(sender, e, selectedEntry + 1);
				};
			}
        }

Another problem remains, but it’s much simpler to fix. selectedEntry is part of the MenuScreen class, and can’t be accessed anywhere else. Changing it from private to protected will fix this. It will also make other custom menus that derive from MenuScreen more flexible.

Finally, we’ll put that selectedEntry parameter to use in GameplayScreen. Edit the constructor and add a variable to store the parameter as a sort of level ID:

// GameplayScreen.cs

	int currentLevel;

        /// Constructor.

        public GameplayScreen(int level)
        {
            TransitionOnTime = TimeSpan.FromSeconds(1.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);

			currentLevel = level;
        }

To see the effect in having the level being chosen for this screen, replace both instances of the string "Insert Gameplay Here" found in the Update and Draw methods with "Playing level " + currentLevel. If you want, you can also remove the “//TODO” text just so the context makes more sense. Run the code, and go through the Level Select menu to choose a level.

Level selection screen

Gameplay screen

The above screens are an example of what you’ll see with the new Level Select menu fully implemented. The Gameplay screen knows what level it’s running, and therefore can load contents specific to that level, and apply its Update and Draw logic to the level as it is played.

Extending the menu further

Normally, we would be done with the menu at this point, but it can still be improved and taken to another level (sorry). What if we wanted to have two or more different game modes for playing the same levels? Maybe it’s a racing game and you’d want to go for a time trial, or play head to head with other players on the same track. Or, maybe even introduce a level editor that can be used right in the game. Suddenly we have more than one reason to use the Level Select menu. In the second part of this article I’ll show you how to reuse the same menu for different GameScreens to load levels with.

Meteor Engine will soon be available for download

So the Meteor graphics engine I was working on a few months ago is back in progress, it’s still around! Although I want to keep busy on making Bubble Tower, I also want to continue the XNA project I have put most of my time into. But this time, I am making the source code public!  I finally decided it’s progressed far enough so that I can share it with everyone, and hope to have it up within a day or two. The engine is far from done, but I have the core concepts already planned and it’s at least functional and stable to some degree.

Meteor Engine was born out of the need to separate rendering steps. It all started when working on Catalin Zima’s tutorial on deferred rendering and porting the code myself to XNA 4.0. (This was before I knew there already was an existing XNA 4.0 port) As I added more features to it, the Deferred Renderer class got a bit too long for my liking so I decided to break it into several steps. I had to figure out how to take the output of each step and introduce it into the next one, and also combining results from multiple steps as input. Eventually I streamlined the approach with using several classes that are self-contained render passes, each with their own shaders, and moved the scene organizing code into its own class.

Although Meteor comes with built-in render passes, you can extend and create your own. Here are some of the rendering features that Meteor Engine uses in its samples.

Deferred and Light Pre-Pass Lighting

Gamma Correction

Post-Processing Effects

The engine is capable of supporting multiple render profiles, so you can have a dual or multiple approach with drawing objects onto the screen with different effects. Each render profile can render one scene at a time, and the current one renders the the scene it is assigned to. For now, the engine can use only one render profile at a time, which can be switched on the fly. But in the future I hope to support the rendering of scenes using several profiles, making the use of multiple materials much easier.

Meteor Engine will be hosted on CodePlex, as soon as I get rid of the extra old files that I won’t use in part of the project. It is able to be used by compiling from source or linked as a library.