Archive for the ‘Screen Manager’ Tag

iPhone Gaming Framework: ObjC Template

Well, everyone… the time has finally come! Yesterday I got an email in my mailbox about a really interesting website that linked to my two blog posts about iPhone development, the Parsing XML files on the iPhone, and the iPhone Gaming Framework tutorials.

Best Universities: 100 free courses tutorials for aspiring iPhone app developers

While looking through the wealth of information on those articles, I found a really neat one.. how to create a project template! This is something I’ve wanted to do for everyone interested in getting started with iPhone game development, but have not had time to really research it on my own.

So, fast forward a few hours, I made a few changes to the ObjC framework and stored it into a template! I would like to first note, that this framework most likely has a few bugs in it. I tried to track down what I could, but I’m sure I didn’t get them all. My current efforts are more directed towards my C++ Djinn Engine, so this project took a back seat, but I felt a lot of people could really use this to jumpstart their efforts.

Anyway, if you choose to use this template, be sure to mail me with your finished projects or development blogs. I always love to see what people are up to! If you’ve used XNA at all, you’ll recognize the Screen Controller and be comfortable with how it works.

If you have any questions, feel free to comment ( so others can help answer and benefit from the questions as well )

How to install the template!
Step 1) Download the zip file located HERE

Step 2) Navigate to ~library/Application Support/Developer/Shared/Xcode/ and create the following folders: Project Templates/iPhone Templates/ .. Your final directory structure should look like ~library/Application Support/Developer/Shared/Xcode/Project Templates/iPhone Templates/

Step 3) Unzip the OpenGL Screen Controller.zip into your iPhone Templates directory. This will add the OpenGL Screen Controller folder and project template. Your new directory structure will look like:
~library/Application Support/Developer/Shared/Xcode/Project Templates/iPhone Templates/OpenGL Screen Controller/(project files here)

Step 4)Open up XCode, create new project, and you’ll see on the left side “User Templates” with a sub-category “iPhone Templates,” clicking on that will bring up your Screen Controller template.

Look at the code, see how its done. Build and run it, and if you click “Level Play” it should transition to a new screen (the gameplay screen) .. click anywhere else in the frame while on the gameplay screen, and it will remove that screen from the screen controller and go back to the title screen. Trace the code, see how it does it, and start playing around.

Advertisements

iPhone Gaming Framework: Amendment

Its been great to see a lot of you take apart the code and really see what you can do! There have been several people who have been in contacts with me via email, trying to get everything up and running.. but as you may have known, there are a few things missing from the tutorials. This is the amendment, going to patch up the final few things to get you back on track!

First thing is in the GLView.m file. We have a screen manager, but we are not telling the game to update or draw through the screen manager. Lets fix that! Go into your -(void)drawView method, and right below the glBindFrameBufferOES() call, you should have a [controller drawView:self]; … we’re going to change that to the following:

	//
	//	Update the view
	//
	[controller updateView:self WithTime:(float)[animationTimer timeInterval]];	
	//
	//	Draw the view
	//
	[controller drawView:self WithTime:(float)[animationTimer timeInterval]];

You’re going to call the controllers updateView and drawView methods, and pass in a time interval from the animationTimer. Now the controller will update and draw the game screens!

Secondly, There were a few people who never added a blankTexture to their project. I suggest opening an image editor, creating a black image called “blankTexture.png” and drag it into your resources file. You’ll notice, in the loadContent method, the screen manager allocates memory for the input manager, sets landscape mode, and then right after that loads in a blankTexture.png. If it doesn’t have one, it can’t load it.

Next amendment is more of a “clean up” since I didn’t fully understand how the retain / release system worked (Hey! i’m still a new mac developer too! :D ) In your addScreen method, you don’t need a [screen retain] since adding it to the screens NSMutableArray will retain the object. Likewise in the releaseScreen method, you’ll need to take out the [screen release] unless you like having your game crash when releasing a screen that has already been deallocated :)

With everything working, you’ll notice that your textures are being drawn “upside down” … well since we changed the way the coordinate system worked, and Apples “Texture2D” class works with the previous coordinate system, that will need to be changed. There are a few ways to do this; some people who really know their OpenGL suggested to flip the image before binding it.. the approach I took was just to adjust the vertices in the Texture2D draw methods.

This goes into your “drawAtpoint” method, comment out the current array:

	//
	//	Modified by Craig Giles to flip the texture upside down while using my coord system
	//    
	GLfloat		vertices[] = 
	{	
		-width / 2 + point.x,	height / 2 + point.y,	0.0,
		width / 2 + point.x,	height / 2 + point.y,	0.0, 
		-width / 2 + point.x,	-height / 2 + point.y,	0.0,
		width / 2 + point.x,	-height / 2 + point.y,	0.0
		
	};

This goes into your “drawAtRect” method, comment out the current array:

	//
	//	Modified by Craig Giles to flip the texture upside down while using my coord system
	//
	GLfloat	vertices[] = 
	{
		rect.origin.x,							rect.origin.y + rect.size.height,		0.0,
		rect.origin.x + rect.size.width,		rect.origin.y + rect.size.height,		0.0, 
		rect.origin.x,							rect.origin.y,							0.0,
		rect.origin.x + rect.size.width,		rect.origin.y,							0.0
		
	};

I think thats all the changes. Thanks again for everyones feedback on the last few writeups! I am looking over a few documents sent to me about templates, so I can release this as a starting template. Will let everyone know more when I can! As always, feel free to email me or post a comment if you need help with something.

iPhone Gaming Framework: Stage 2 Tutorial

NOTE:: I am still looking for a good way to turn this into a template and release it for anyone wishing to install this for the base of their game. If you know of a good resource for doing so, please let me know, as google has been fairly unhelpful as of this point.

Welcome back everyone! Did you all finish Stage 1 of the tutorial? If not, please do that, as we are going to be building off stage 1 in our next tutorial. Stage 1 can be found HERE

Okay, now that stage 1 is done, you have a working screen management system… except you don’t have an input manager to help you with input management! Remember my note from previous tutorials, there are MANY solutions to a problem, and this is just one of many. Our input class works as follows: If a touch is detected, the GLViewController will send a message to the input manager, and that message will be stored in an input “state” called “queryState.” Before the view controller updates any of the game screens, it will send a message to the input manager to update the input, and this is when the input is changed from the “queryState” to “currentState” and the current state is then set to the previous state.

So lets look at the code, yeah? First the InputManager.h file

//	
//	The input manager is a helper class that houses any input
//	that can be obtained by the game engine. As a touch is detected
//	on screen, it will send a message to the input helper. The input
//	helper will then hold onto that message and filter it into the 
//	current state on the next game loop. The current state is moved
//	to the previous state, and any incoming touches are then put
//	back into the query state, waiting to be updated.
//
//	This method of updating lets the game filter updates to the top-most
//	game screen and not have to worry about un-focused screens handling
//	input that was not intended for them.
//
//  Created by Craig Giles on 1/3/09.
//

#import <Foundation/Foundation.h>
#import "InputState.h"

@interface InputManager : NSObject 
{	
@private
	bool isLandscape;
	InputState *currentState;
	InputState *previousState;
	InputState *queryState;
}

@property (nonatomic, readwrite) bool isLandscape;
@property (nonatomic, readonly) InputState *currentState;
@property (nonatomic, readonly) InputState *previousState;

- (void) update:(float)deltaTime;

//
//	Touch events
//
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)view  WithTimer:(NSTimer *)deltaTimer;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)view  WithTimer:(NSTimer *)deltaTimer;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)view  WithTimer:(NSTimer *)deltaTimer;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)view WithTimer:(NSTimer *)deltaTimer;

//
//	Helper Methods
//
- (void) update:(float)deltaTime;
- (bool) isButtonPressed:(CGRect)rect;
- (bool) isButtonHeld:(CGRect)rect;
- (void) convertCoordinatesToLandscape;

//
//	Class methods
//
+ (bool) doesRectangle:(CGRect)rect ContainPoint:(CGPoint)point;

@end

And the .m file

//	
//	The input manager is a helper class that houses any input
//	that can be obtained by the game engine. As a touch is detected
//	on screen, it will send a message to the input helper. The input
//	helper will then hold onto that message and filter it into the 
//	current state on the next game loop. The current state is moved
//	to the previous state, and any incoming touches are then put
//	back into the query state, waiting to be updated.
//
//	This method of updating lets the game filter updates to the top-most
//	game screen and not have to worry about un-focused screens handling
//	input that was not intended for them.
//
//  Created by Craig Giles on 1/3/09.
//

#import "InputManager.h"


@implementation InputManager

//
//	Getters / Setters
//
@synthesize isLandscape;
@synthesize currentState;
@synthesize previousState;

//
//	Initialization
//
- (id) init
{
	self = [super init];
	if (self != nil) 
	{
		//
		//	Allocate memory for all of the possible states
		//
		currentState = [[InputState alloc] init];
		previousState = [[InputState alloc] init];
		queryState = [[InputState alloc] init];
		
		//
		//	Set the initial coords for the touch locations.
		//
		currentState.touchLocation = CGPointMake(0, 0);
		previousState.touchLocation = CGPointMake(0, 0);
		queryState.touchLocation = CGPointMake(0, 0);
	}
	return self;
}

//
//	Deallocation
//
- (void) dealloc
{
	[currentState release];
	[previousState release];
	[queryState release];
	[super dealloc];
}

//
//	Update the input manager. This method will take the
//	values in updateState and apply them to the current state. 
//	in essence, this method will "query" the current state
//
- (void) update:(float)deltaTime
{
	//	Sets previous state to current state
	previousState.isBeingTouched = currentState.isBeingTouched;
	previousState.touchLocation = currentState.touchLocation;
	
	//	Sets the current state to the query state
	currentState.isBeingTouched = queryState.isBeingTouched;
	currentState.touchLocation = queryState.touchLocation;
	
	//	converts the coordinate system if the game is in landscape mode
	[self convertCoordinatesToLandscape];
}
	
//
//	Touch events
//
//	These events are filtered into the input manager as they occur.
//	Since we want to control how our input, we are going to use a 
//	queryState as the "Live" state, while our current and previous
//	states are updated every loop. For this reason, we are always
//	modifying the queryState when these touch events are detected,
//	and the current state is only modified on [self update:deltaTime];
//
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)view  WithTimer:(NSTimer *)deltaTimer
{		
	queryState.isBeingTouched = YES;
	queryState.touchLocation = [[touches anyObject] locationInView:view];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)view  WithTimer:(NSTimer *)deltaTimer
{	
	queryState.isBeingTouched = YES;
	queryState.touchLocation = [[touches anyObject] locationInView:view];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)view  WithTimer:(NSTimer *)deltaTimer
{	
	queryState.isBeingTouched = NO;
	queryState.touchLocation = [[touches anyObject] locationInView:view];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)view WithTimer:(NSTimer *)deltaTimer
{
	queryState.isBeingTouched = NO;
}

//
//	When in landscape mode, the touch screen still records input
//	as if it were in portrait mode. To get around this, if we
//	are writing a game in landscape we need to adjust the coordinate
//	system on the touchscreen to match that of our world.
//
- (void) convertCoordinatesToLandscape
{
	//	If we are not in landscape mode, don't convert anything
	if ( !isLandscape )
		return;
	
	//	Otherwise, we will need to take the current touch location
	//	swap the x and y values (since in landscape, the portrait
	//	coordinate system means x will point up / down instead of
	//	left / right) and move the y position to match our origin 
	//	point of (0,0) in the upper left corner. 
	int x = currentState.touchLocation.y;
	int y = (currentState.touchLocation.x - 320);
	
	//	make sure we take the absolute value of y, since if we didn't
	//	y would always be a negative number.
	y = abs(y);
	
	//	Since we were converting the current state, we need to update
	//	the current touch location
	currentState.touchLocation = CGPointMake( x, y );
}

//
//	Looks at the previous state, and the current state to determine
//	weather or not the button (rectangle) was just pressed and released.
//
- (bool) isButtonPressed:(CGRect)rect
{
	//
	//	If the current state is not being touched
	//	and the previous state is being touched, the
	//	user just released their touch. This is 
	//	personal preference really, But i've found with
	//	my XNA programming, that its better to detect if
	//	a button was just released rather than if it was
	//	just pressed in when determining a button press.
	//	
	if ( !currentState.isBeingTouched &&
		 previousState.isBeingTouched )
	{
		
		return 	[InputManager doesRectangle:rect ContainPoint:currentState.touchLocation];
	}
	
	return NO;
}

//
//	Looks at the previous state, and the current state to determine
//	weather or not the button (rectangle) is being held down.
//
- (bool) isButtonHeld:(CGRect)rect
{
	//
	//	If the current state and the previous states
	//	are being touched, the user is holding their 
	//	touch on the screen.
	//	
	if ( currentState.isBeingTouched &&
		 previousState.isBeingTouched )
	{
		return 	[InputManager doesRectangle:rect ContainPoint:currentState.touchLocation];
	}
	
	return NO;
}

//
//	Helper method for determining if a rectangle contains a point.
//	Unsure if this will stay in the input helper or be moved to some
//	sort of "RectangleHelper" class in the future, but for now this
//	is a good spot for it. Remember, this works with our current coord
//	system. If your engine uses a different coord system (IE: (0,0) is at
//	the bottom left of the screen) you'll need to modify this method.
//
+ (bool) doesRectangle:(CGRect)rect ContainPoint:(CGPoint)point
{
	//
	//	If the rectangle contains the given point, return YES
	//	Otherwise, the point is outside the rectangle, return NO
	//	
	if (point.x > rect.origin.x &&
		point.x < rect.origin.x + rect.size.width &&
		point.y > rect.origin.y &&
		point.y < rect.origin.y + rect.size.height)
	{
		return YES;
	}
	
	return NO;
}

@end
&#91;/sourcecode&#93;

InputState just contains 2 values, and I have chosen to set them as the following:

&#91;sourcecode language="cpp"&#93;
#import <Foundation/Foundation.h>

@interface InputState : NSObject 
{
	bool isBeingTouched;
	CGPoint touchLocation;
}

@property (nonatomic, readwrite) bool isBeingTouched;
@property (nonatomic, readwrite) CGPoint touchLocation;

@end

//
//  Implementation of InputState
//
@implementation InputState

@synthesize isBeingTouched;
@synthesize touchLocation;

- (id) init
{
	self = [super init];
	if (self != nil) {
		isBeingTouched = NO;
		touchLocation = CGPointMake(0, 0);
	}
	return self;
}

@end

It should be a good time to point out, that the input manager changes the coordinates of the actual touch, depending on if you’re playing your game in landscape mode or normal mode. One of the problems I was having, before I realized what was really happening, was my coordinates for the touch screen and coordinates for the game world were different. For example, my touch screen coordinates, if held landscape, (0,0) was in the lower left corner, while in the world coordinates, (0,0) was in the upper left corner. This gave me problems, as you can imagine.

In order to change this, I wrote a method that will convert the coordinates system if the screen is detected in landscape mode. It should be pointed out, that if you’re using a different origin point for your world (IE: Lower left corner instead of upper left) you’re conversions will have to be done differently.

Another method that is currently in the input manager class, is the [self doesRectangle:rect ContainPoint:touchLocation]; Inside this method, you’ll see that both current and previous states are being used in order to detect if a touch is being “touched” or “held.” This can be done differently, but the way I’ve chosen to implement it, is as follows;

if the button was just RELEASED (current state is not pressed, but previous state was) than the button was just “pressed.”

This is important to note, because it means if the user touches the screen, and holds their finger down, it won’t register as a “button press” until they release their finger. Some people prefer to do the opposite, meaning if the current state was just pressed and the previous state was un-pressed. Use what you feel comfortable with.

So now all we need to do is add a game screen or two, right? Well, I told you that I would help you get up a paused screen. This will help you learn how to get any sort of game screen up and running. First, lets take a look at the PausedScreen.h file

//
//	The paused screen is just an overlay popup screen that is
//	displayed to the user when the game is paused.
//
//  Created by Craig Giles on 1/5/09.
//

#import <Foundation/Foundation.h>

#import "GameScreen.h"
#import "InputManager.h"
#import "Texture2D.h"

@interface PausedScreen : GameScreen 
{
	Texture2D *pausedText;
	double alphaValue;
}

@property (nonatomic, retain) Texture2D *pausedText;

- (void) loadContent;
- (void) unloadContent;

- (void) handleInput:(InputManager *)input;
- (void) update:(float)deltaTime	OtherScreenHasFocus:(bool)otherFocus	CoveredByOtherScreen:(bool)coveredByOtherScreen;
- (void) draw:(float)deltaTime;

@end

If you notice, several of these methods are in “GameScreen.h” right? You’ll also notice the LACK of touch event classes. All input is handled by the input manager, and will be called from the view controller (the [self handleInput:input] method) Aah now you are getting why I went the touch manager route instead of re-writing every single “touchEvent” method in each game screen!

There are several methods that every game screen needs in order to function properly. It will need a loadContent / unloadContent methods, handleInput method, and the update / draw methods. Also keep in mind, every game screen will need to call the [super update:deltaTime…], and every screen (other than the paused screen, which is a popup screen) will need to call the [super draw:deltaTime]; within its draw method.

So now you have the basics of the game screen, let me show you the .m file.

//
//	The paused screen is just an overlay popup screen that is
//	displayed to the user when the game is paused.
//
//  Created by Craig Giles on 1/5/09.
//

#import "PausedScreen.h"


@implementation PausedScreen

@synthesize pausedText;

//
//	Initialize the pause menu screen
//
- (id) init
{
	self = [super init];
	if (self != nil) 
	{
		//	flag that there is no need for the game to transition
		//	off when the pause menu is on top of it
		self.isPopup = YES;
		
	}
	return self;
}

//
//	Load all content associated with the paused screen
//
- (void) loadContent
{
	//
	//	Since this is a popup screen, we will over-ride the 
	//	view controllers transition time and set this to instantly
	//	transition on and off.
	//
	self.transitionOnTime = 0;
	self.transitionOffTime = 0;
	
	//	set the paused text
	pausedText = [[Texture2D alloc] initWithString:@"Paused\nTap screen to unpause"
										dimensions:CGSizeMake(self.viewport.size.width, self.viewport.size.height)
										 alignment:UITextAlignmentCenter
										  fontName:@"Zapfino"
										  fontSize:32];
	
	//	The alpha value of the background. below 
	//	the paused text.
	alphaValue = 0.75f;
}

- (void) unloadContent
{
	//TODO: all unload content goes here
	[pausedText release];
	[super unloadContent];
}


- (void) handleInput:(InputManager *)input
{
	//	If the 'tap here to resume' button was pressed
	//	resume game
	if ([input isButtonPressed:self.viewport])
	{
		[self exitScreen];
	}
}

- (void) update:(float)deltaTime	OtherScreenHasFocus:(bool)otherFocus	CoveredByOtherScreen:(bool)coveredByOtherScreen
{
	//TODO: Update logic goes here
	
	//	Update the base class
	[super update:deltaTime OtherScreenHasFocus:otherFocus CoveredByOtherScreen:coveredByOtherScreen];
}

- (void) draw:(float)deltaTime
{	
	//	Darken the screen to alert the player that it has been paused
	[self.controller fadeBackBufferToBlack:alphaValue];
	
	[pausedText drawInRect:CGRectMake(self.viewport.size.width / 4, 
									  self.viewport.size.height / 4,
									  self.viewport.size.width / 2,
									  self.viewport.size.height / 2)];
}
@end

One thing to take note, since the PausedScreen is a popup screen, it has overwritten the transition on and transition off values sent to it by the view controller. Any game screen can do the same, for example if you are transitioning to a screen that you’ve made your own custom transition, turn the view controllers transition off and let the screen transition itself. (IE: a battle screen.)

So there you have it! I don’t remember if textures are drawing upside down with this coord system, but if they are, all you have to do is edit the Texture2D.m file to fix that. If you don’t know how, send me an email and I’ll show you how I did it, but there are several ways of doing it.

I hope you enjoyed my heavily commented code for the screen manager, input manager, and game screen classes. This should give you the basic knowledge to get up and running with your own iPhone OpenGL applications. If you found these useful, let me know and I’ll write up some more when I have the time. I’m still learning all of this myself, but sharing my knowledge will lead to more interesting games for everyone! Keep in mind these are very basic systems and can be heavily expanded on by creative programmers. Can’t wait to see what you guys come up with!

Happy coding all!

iPhone Gaming Framework: Screen Manager Update

I don’t have time to write up a complete tutorial, but I will soon.. but I wanted to show just how the screen manager works. First, the video so you have an idea;

Click here for iPhone Screen Management Demo
Since I am on OSX, I am working on a way to record videos and upload them to youtube like I did with windows. When I do, I’ll embed them into the page again. For now, this solution works.

As you can see, the transitions and everything works just like an XNA project would. As said before, I converted Jeff’s GLViewController to be my screen manager. To use it, what you would do is something like the following;

TitleScreen *newScreen = [[TitleScreen alloc] init];
[controller addScreen:newScreen];
[newScreen release];

the addScreen method will retain the screen, load any content the screen will need in the game, and then add it to the screens array. Since the controller is handling the screen, and has retained the screen, we then need to release it. It is now in the controllers hands!

The controller knows if a screen is a popup screen (ala dialog box) or a full game screen (ala battle screen / inventory screen / main game screen, etc) and will transition based on what kind of screen it is. Popups get no transition, full screens will get the fade effect seen in the video. Same for transitioning off. To exit a screen, you would do the following;

if (condition == true)
{
    //in the game screens "update" method. Self refers to the game screen
    [self exitScreen];
}

the game screen will handle any transitions if it needs to.. popup’s will just pop off the stack.

One other thing that I found really interesting, was input handling. since the iPhone uses an event like system, the moment you touch the screen the iPhone sends a message saying “HEY! I’ve been touched!” What I’ve done was create an InputManager class that takes that input, and stores it in either the previousInputState, currentInputState, or queryInputState. Obviously the previous and current input states are self explanitory, the queryInputState is the state that has happened but has not been committed quite yet (meaning, the screen manager has not updated the input state quite yet) The screen manager would then update the input state, and filter it to the top-most screen.

What I would like to do, is create a project template for this framework for any 2d developer wishing to get started in iPhone Games Development. Obviously this template will be an ongoing project, and as improvements are made the template will be updated. My problem, is google has been unhelpful for trying to create a template file. If anyone knows of a good tutorial to look at, or good reading material, please send it my way! I can be reached at my listed email address ( CraigGiles9@yahoo.com ) If I can’t find a way to convert this into a template, the best way to distribute this would be to zip it up and that would be a pain when you want to start a new project.

Later this weekend, I will try to do a full writeup of the screen management system. Until then, happy coding!

iPhone OpenGL ES Gaming Framework Update

Its taken me a few days to port over some of my XNA stuff to the iPhone SDK, but it looks as if the current framework is starting to take shape. So what do I have so far? Currently the framework’s feature list is as follows;

– Started with a base OpenGL project template. This template was written by Jeff Lamarche of iPhoneDevelopment fame. He also helped write the “Beginning iPhone Development; exporing the iPhone SDK” book (amazon link HERE ) the template can be picked up at Jeff’s blog post located: HERE

– From here, I converted the GLViewController into my screen manager class. This screen manager is heavily inspired by the XNA Development Team (creators.xna.com) for use with the XNA Framework for writing C# programs. This screen manager will manage all game screens, updating and displaying their contents, and even filter all user input to the screen that is currently active.

– The GameScreen class structure, where GameScreen is the parent class of any screen I wish to create. Right off the top of my head, in the game I am currently writing my design doc for, I will have several screen classes inheriting from GameScreen, including TitleScreen, MainGame, Paused, and Achievements.

– Several helper classes such as RandomNumber for random number generation and Apple’s Texture2D class which is a life saver for getting textures and text to screen.

Right now, this is the extent of the gaming framework, but eventually I will need to add sound support and various other things. As of my progress? I have been tinkering with things and was able to get touches and game flow working. The following two screenshots demonstrate this, where the first screen shot shows nothing but 3 buttons, and the 2nd screenshot shows what would happen if you clicked inside one of the buttons.

Exciting huh? Well there is much more work to do! I have not posted the code to any of this stuff yet, because it is incomplete. I am not sure if I will be writing any tutorials on the gaming framework, but if there is enough demand than I will.

Being able to get the gaming framework set up will be a great step forward. It means I can take more time working on the actual game, and less time setting up things like the screen manager every time I want to start a new project!

Happy coding everyone! Let me know what you all think should be included in a gaming framework such as this!

ShackRPG: Screen Manager

For every game that has more than one game screen, you need a way to manage those screens. Even the old games such as Super Mario Bros or before that, Pong.. They often had at least two screens, sometimes more.

1) Main Menu Screen – Select players, show splash screen
2) Game Screen – Handles all game logic and render the game to screen
3) Credits – shows the names of all the developers and any final messages
4) Game Over – displays a Game Over screen and asks if you wish to continue

For a game with so few screens, you could simply just load them as you need them in a stack or, *shutter*, a few switch blocks in a main Update() method. With a game as complex as an action RPG such as my project, that won’t work. And thus, the ScreenManager class was born.

This class is based off of the XNA Websites GameScreenManager sample, with various changes to suit my needs. Each screen in the game inherits from a GameScreen class, and is then loaded into a few lists in the Screen Manager.

List<GameScreen> screens = new List<GameScreen>();
List<GameScreen> screensToUpdate = new List<GameScreen>();
List<GameScreen> screensToRemove = new List<GameScreen>();

Every GameScreen loaded to memory is in the Screens list, and only those screens needing to be updated is filtered into the screensToUpdate list. If a screen is needing to be removed (such as if you’re finished editing your map, and wish to exit the map editor and play it in the game) that screen is added to the screens to remove list.

Inside the screen manager, there are a few methods designed to keep the game screens in order; these are

AddScreen(GameScreen screen) – Adds a new game screen into the game
RemoveScreen(GameScreen screen) – Removes a game screen from the game
RemoveScreen(string asset) – Removes the game screen with the name you specify

the above methods are public, and are accessible anywhere within the program, and one private method that is only accessible from within the Screen Manager class is the ClearRemovedScreens(), which takes all the screens from the screensToRemove list and unloads all textures, sounds, and other assets associated with that gamescreen from memory, and finally removes that screen from the lists.

The only thing left to do now, is Update all screens needing to be updated, and render all screens to the screen. That is the job of our next two methods, ironically called “Update” and “Draw”

public void Update()
public void Draw()

In a nutshell, this is our screen class.

Link to full source code: Click Here