Archive for the ‘XNA’ Category

The cost of education

The cost of education is great, both in financial terms as well as time, and pursuing a computer science degree has not disappointed in this regard. Over the last two semesters, my professors have shown me just how much time is required to learn about a subject as complex as physics. Mechanics of Solids and Fluids, and Electricity and Magnetism were among the hardest and most rewarding classes to get through but I did get through them.

With physics behind me, I can move forward to things I enjoy like learning new technologies and coding! I’ve dabbled into Android programming over the last few weeks and it was harder to get started. I thought it would be good to describe the various ways that you could get started, what tools you could use, and what learning material you could follow.

The first thing I noticed about android development is the platform. Everybody says Eclipse is the greatest IDE when it comes to Java Development and despite my many attempts to use Eclipse, I just can’t bring myself to enjoy programming in it. After looking around I stumbled on JetBean’s IntelliJ Community Edition with built in Android support and fell in love! Both IDE’s will get the job done, but I found IntelliJ to be more fun to work in.

And so my journey into a new platform begins.. I’ll be writing up some tutorials and interesting findings as I make them, in hopes that other android developers can learn from my mistakes. I will also be adjusting the format around these parts, as I am not only programming for XNA anymore. Sit tight, and enjoy the content!

Twitter

Interested in how things are progressing with the engine? Wanting status updates on what the thought process is behind making the iPhone gaming engine? Follow it on Twitter!

http://www.twitter.com/CraigGiles

Progress on the engine is going to start speeding up now that most of my major C++ projects for classes are complete. We’ll see how things progress after I start getting into the groove of summer coding. :)

iPhone Gaming Framework: Stage 1 Tutorial

Buckle in guys, this is going to be a rather large tutorial. The goal for this tutorial is to get a basic screen management system up and running, ready to start writing game code. I would like to start off by saying the following: This is not the only way to get a project up and running! There are many many many ways of solving problems in the programming world. Some people might prefer to use Cocos2D for the iPhone, while others might prefer to roll their own engine from scratch. I did this more as a learning process for myself, and now that I’ve learned what I could, i thought I should share the knowledge to everyone else who is struggling with the problems that I’ve solved.

Also, keep in mind that this screen management system is basically a port of the GameStateManagement demo from the XNA sample ( http://creators.xna.com/ ) from C# to Objective-C with some modifications. Anyone currently using XNA should have a fairly easy time porting this over, as a lot of the code should be recognizable to you.

So, now that I’ve got that out of the way, lets begin! Your first step is going to head over to Jeff’s blog iPhoneDevelopment and pick up the Updated OpenGL Xcode Project Template.

Next step, is to follow his directions and install it! Once you have it installed, load a new project using his template. You will find that a few things are different, and a whole lot is added. Open up the GLView.m in the classes subdirectory, and add the following four methods:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
	[controller touchesBegan:touches withEvent:event InView:self  WithTimer:animationTimer];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
	[controller touchesMoved:touches withEvent:event InView:self  WithTimer:animationTimer];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
	[controller touchesEnded:touches withEvent:event InView:self  WithTimer:animationTimer];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
	[controller touchesCancelled:touches withEvent:event InView:self  WithTimer:animationTimer];
}

What this is going to do, is when your iPod touch or iPhone is touched, a message is sent to the GLView. We are going to capture that message, and send it to the GLViewController. Okay, got that done? GREAT! Now comes the fun stuff.

Open up your GLViewController.h file. You are going to be putting in quite a bit of code, and i’ll explain everything when we do the .m file, so for right now just adjust your .h file to look like the following. You’ll see the .m file is HEAVILY commented to show what everything is and what it does, and i’ll make some additional notes here as well… so here is the GLViewController.h file.

//
//	The View Controller is a service which mananges one or more GameScreen
//	instances. It maintains a stack of screens, calls their Update and Draw
//	methods at the appropriate times, and automatically routes the input to
//	the topmost active screen.
//
//	Created by XNA Development Team ( http://creators.xna.com/ ) as a 
//	ScreenManager.cs GameComponent.
//
//  Adapted for iPhone Game Development by Craig Giles on 1/1/09.
//

//
//	Import statements
//
#import <UIKit/UIKit.h>
#import <OpenGLES/EAGL.h>
#import <OpenGLES/ES1/gl.h>
#import <OpenGLES/ES1/glext.h>

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

@class GLView;
@interface GLViewController : UIViewController 
{	
	NSMutableArray *screens;
	NSMutableArray *screensToUpdate;
	InputManager *input;
	Texture2D *blankTexture;
	
	bool isInitialized;
	bool traceEnabled;	
	
	UIView *gameView;
	CGRect viewport;
}

//
//	Properties
//
@property (nonatomic, retain) NSMutableArray *screens;
@property (nonatomic, retain) NSMutableArray *screensToUpdate;
@property (nonatomic, retain) InputManager *input;
@property (nonatomic, retain) Texture2D *blankTexture;

@property (nonatomic, readwrite) bool isInitialized;
@property (nonatomic, readwrite) bool traceEnabled;

@property (nonatomic, retain) UIView *gameView;
@property (nonatomic, readwrite) CGRect viewport;

//
//	Methods
//	
- (void) setupView:(GLView*)view;
- (void) loadContent;
- (void) addScreen:(GameScreen *)screen;
- (void) removeScreen:(GameScreen *)screen;
- (void) releaseScreen:(GameScreen *)screen;
- (void) updateView:(GLView *)view WithTime:(float)deltaTime;
- (void) drawView:(GLView *)view WithTime:(float)deltaTime;
- (void) traceScreens;
- (void) fadeBackBufferToBlack:(double)alpha;

//
//	Touches events
//
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)touchView WithTimer:(NSTimer *)timer;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)touchView WithTimer:(NSTimer *)timer;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)touchView WithTimer:(NSTimer *)timer;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)touchView WithTimer:(NSTimer *)timer;

@end

Its a good idea to look through the .h file to see what you can do with the screen manager. Obviously you can do the touch events (remember we connected those from the GLView?) but also, looking at the methods you will be able to add and remove screens from the screen manager, update and draw, fade back buffer to black, and a few other things. Lets see how it all works!

//
//	The View Controller is a service which mananges one or more GameScreen
//	instances. It maintains a stack of screens, calls their Update and Draw
//	methods at the appropriate times, and automatically routes the input to
//	the topmost active screen.
//
//	Created by XNA Development Team ( http://creators.xna.com/ ) as a 
//	ScreenManager.cs GameComponent.
//
//  Adapted for iPhone Game Development by Craig Giles on 1/1/09.
//

//
//	Import commands from Jeff's template
//
#import "GLViewController.h"
#import "GLView.h"
#import "OpenGLCommon.h"
#import "ConstantsAndMacros.h"

//
//	This indicates weather or not the game will be played in 
//	landscape or portrait mode. While in landscape mode, the
//	screen will be rotated, but also the input will be off.
//	Touch coordinates for the screen will have to be converted
//	before it reaches the input manager class.
//
const bool LANDSCAPE_MODE = NO;

//
//	The time it takes for a game screen to transition
//	These can be over written in the game screen init.
//	If there is no values in the game screen itself, these
//	will be used as the default values.
//
const float TRANSITION_ON_TIME = .70f;
const float TRANSITION_OFF_TIME = .20f;

//
//	Implementation of the Screen Manager class
//
@implementation GLViewController

//
//	Getters / Setters
//
@synthesize screens;
@synthesize screensToUpdate;
@synthesize input;
@synthesize blankTexture;

@synthesize isInitialized;
@synthesize traceEnabled;

@synthesize gameView;
@synthesize viewport;

//
//	Setup View handles setting up OpenGL's Projection Matrix and 
//	enables all states needed for rendering the game to screen.
//
-(void)setupView:(GLView*)view
{	
	//	Set the view to the gameView
	gameView = view;
	
	//	Modify the Projection matrix
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	
	//
	//	Orthof projection is used for 2d games. This sets the coordinates to
	//	(0, 0) at the top left corner of the screen, and as you move downward
	//	your y value will increase. As you move to the right, your x value will
	//	increase.
	//	(left, right, bottom, top, near, far)
	//
	//	If the game is going to be played in landscape mode, enable
	//	it via the bool switch at the top of the GLViewController.m file.
	if ( LANDSCAPE_MODE )
	{
		viewport = CGRectMake(0, 0, 480, 320);
		glViewport(0, 0, viewport.size.height, viewport.size.width);
		glRotatef(-90, 0, 0, 1);
        glOrthof(0, viewport.size.width, viewport.size.height, 0, -10.0, 10.0);  
		
	}
	else	//	Game is to be played in portrait
	{
		viewport = CGRectMake(0, 0, 320, 480);
		glViewport(0, 0, viewport.size.width, viewport.size.height);
		glOrthof(0.0, viewport.size.width, viewport.size.height, 0.0, -1.0, 1.0);	
			
	}
	
	//
	//	Setup Model view matrix
	//	Load graphics settings
	//
	glMatrixMode(GL_MODELVIEW);
	
	glDisable(GL_DEPTH_TEST);
	glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_BLEND);	
	
	//	needed to draw textures using Texture2D
	glEnable(GL_TEXTURE_2D);	
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glEnableClientState(GL_VERTEX_ARRAY);
	
	
	//	enables alpha for transparent textures
	//	I forget where I got these commands, iDevGames.net I think
	glAlphaFunc(GL_GREATER, 0.1f);
	glEnable(GL_ALPHA_TEST);
	
	//
	//	Setup clear color (cornflower blue'ish)
	//	Call me crazy, but I got so used to this color developing
	//	for XNA. This is a little nod to the Microsoft Development
	//	Team :)
	//
	glLoadIdentity(); 
	glClearColor(.39f, 0.58f, 0.920f, 1.0f); 

	
	//
	//	Call the view controllers loadContent method
	//	
	[self loadContent];
	
}

//
//	Loads all content needed to run the screen manager. This is seperated 
//	from the setupView method in order to seperate what is needed from OpenGL 
//	to setup the screen, and what is needed from the screen manager to set 
//	up the game structure. 
//
- (void)loadContent
{
	//
	//	Allocate memory for your arrays to hold the Screens "stacks." 
	//	All game screens will be housed in this array for easy manipulation. 
	//
	screens = [[NSMutableArray alloc] init];
	screensToUpdate = [[NSMutableArray alloc] init];
	
	//
	//	Allocate memory for the input manager and the blankTexture used
	//	to fade the screen in / out.
	//
	input = [[InputManager alloc] init];
	input.isLandscape = LANDSCAPE_MODE;
	blankTexture = [[Texture2D alloc] initWithImage:[UIImage imageNamed:@"blankTexture.png"]];
	
	for (GameScreen *screen in screens)
		[screen loadContent];
	
	//
	//	Once we are initialized, set the bool values to appropriate values. 
	//
	isInitialized = YES;
	traceEnabled = NO;
	
	//
	//	Adds a title screen to the game stack. This will be taken out 
	//	later, and right now is only used for debugging purposes. It
	//	will be replaced with your splash screen or game introduction
	//	screen.
	//
	TitleScreen *newScreen = [[TitleScreen alloc] init];
	[self addScreen:newScreen];
	[newScreen release];
}

//
//	When the view controller exits, we will need to clean up any memory used.
//
- (void)dealloc 
{
	//
	//	setup a delete screens array and add all of the current game screens
	//	to this array. We will then cycle through all game screens, unloading
	//	their content, and releasing them from the view controller. After all
	//	is said and done, we will then remove the deleteScreens array, and 
	//	continue on releasing any other memory allocated for the view controller.
	//
	NSMutableArray *deleteScreens = [[NSMutableArray alloc] initWithArray:screens];
	
	for (GameScreen *screen in deleteScreens)
	{
		[self removeScreen:screen];
		[self releaseScreen:screen];
	}
	
	[deleteScreens release];
	[screens release];
	[screensToUpdate release];
	[input release];
	[blankTexture release];
	
    [super dealloc];
}

//
//	If the game is going over memory, this method will be called by the device
//	warning that we are running low on memory and should release any un needed
//	items.
//
- (void)didReceiveMemoryWarning 
{
	//	<<TODO: Unload any un-needed game content here>>
    [super didReceiveMemoryWarning]; 
}

//
//	Add a screen to the view controller
//
- (void) addScreen:(GameScreen *)screen
{
	//
	//	When adding a screen to the view controller, we will be
	//	setting some default values for the screen, and then call
	//	the screens "loadContent" method. Once everything is loaded,
	//	the view controller will retain the screen and add it to the
	//	screens array.
	//
	screen.controller = self;
	screen.viewport = self.viewport;
	screen.transitionOnTime = TRANSITION_ON_TIME;
	screen.transitionOffTime = TRANSITION_OFF_TIME;
	screen.currentScreenState = TransitionOn;
	screen.transitionPosition = 1;
	[screen loadContent];
	
	[screen retain];
	[screens addObject:screen];
}

//
//	Unload all game content from the screen. This in turn
//	sets a flag within the screen itself, that the content has
//	been unloaded, and in the controllers Update method, all game
//	screens that have been unloaded will be released from memory.
//
- (void) removeScreen:(GameScreen *)screen
{
	//unload any content it has stored
	[screen unloadContent];
}

//
//	Release all game screens from memory, that have had their content
//	unloaded. This will release all screens themselves, as well as remove
//	them from the screens arrays.
//
- (void) releaseScreen:(GameScreen *)screen
{	
	//	remove the screen from all screen arrays
	[screens removeObject:screen];
	[screensToUpdate removeObject:screen];
	
	//	deallocate any memory used for the screen
	[screen release];
}


//
//	Update every screen in the screens stack, keeping track
//	of which screens are covered and which are fully active.
//	if a screen is fully active and "on top" of the stack, it
//	should receive any input.
//
- (void) updateView:(GLView *)view WithTime:(float)deltaTime
{
	//	Read the touch input
	[input update:deltaTime];
	
	//	make a copy of hte master screen list, to avoid confusion if
	//	the process of updating one screens adds or removes others.
	[screensToUpdate removeAllObjects];
	
	for(GameScreen *screen in screens)
		[screensToUpdate addObject:screen];
	
	bool otherScreenHasFocus = NO;
	bool coveredByOtherScreen = NO;
	
	//	loop as long as there are screens waiting to be updated
	while ([screensToUpdate count] > 0) 
	{
		//	pop the topmost screen off the waiting list
		GameScreen *screen = [screensToUpdate objectAtIndex:([screensToUpdate count] - 1)];
		
		[screensToUpdate removeObjectAtIndex:[screensToUpdate count] - 1];
		
		//	update the screen
		[screen update:deltaTime OtherScreenHasFocus:otherScreenHasFocus 
								CoveredByOtherScreen:coveredByOtherScreen];
		
		
		if ([screen currentScreenState] == TransitionOn ||
			[screen currentScreenState] == Active)
		{
			//	if this is the first active screen we came across,
			//	give it a chance to handle input.
			if (!otherScreenHasFocus)
			{
				[screen handleInput:input];
				otherScreenHasFocus = YES;
			}
			
			//	if this is an active non-popup, inform any subsequent
			//	screens that they are covered by it
			if (![screen isPopup])
				coveredByOtherScreen = YES;
			
		}
	}
	
	//	do we need to print the debug trace?
	if (traceEnabled)
		[self traceScreens];
	

	//
	//	For every screen that had their content unloaded.. release
	//	the memory used for that screen here. We do this up front
	//	to ensure that any released screen doesn't get their update
	//	or draw methods called, when there is nothing to update or draw.
	//
	for (GameScreen *screen in screens)
	{
		if (screen.hasBeenUnloaded)
		{
			[self releaseScreen:screen];
		}
	}
}

//
//	Draw the game screens from "Bottom to Top." This is done 
//	in order to ensure that any pop'up screens are drawn on top
//	of the full screen below it. 
//
- (void) drawView:(GLView *)view WithTime:(float)deltaTime
{
	//	Clear the screen to preset color before drawing
	glClear(GL_COLOR_BUFFER_BIT);
	
	//	Draw every screen in the screens array
	for (GameScreen *screen in screens)
	{
		//if the screens content has been unloaded, don't draw
		if (screen.hasBeenUnloaded)
			continue;
		
		[screen draw:deltaTime];
	}
}

//
//	Helper method designed to draw the screen names currently
//	in the game stack in order to see if they are being added
//	and removed correctly. 
//
- (void) traceScreens
{
	//	<<TODO: Input code to draw the screen names>>
}

//
//	Helper method to draw a translecent black fullscreen sprite, used
//	for fading screens in and out, and for darkening the background
//	behind pop up screens.
//
- (void) fadeBackBufferToBlack:(double)alpha 
{
	glColor4f(alpha,alpha,alpha,alpha);
	[blankTexture drawInRect:self.viewport];
	glColor4f(1, 1, 1, 1);
}


//
//	When the screen is touched by the user, the GLView will pass along a message
//	to the view controller that the screen has been touched. The view controller
//	will take the message, and pass it along to the input manager where the
//	necessary information will be stored and filtered to the game screen that
//	will handle the user input.
//
//	In order for this to work, in your GLView, you need to write the following
//	4 methods:
//	- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
//	- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
//	- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
//	- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
//
//	Those methods will call the methods below.
//
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)touchView WithTimer:(NSTimer *)timer
{
	[input touchesBegan:touches withEvent:event InView:touchView  WithTimer:timer];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)touchView WithTimer:(NSTimer *)timer
{
	[input touchesMoved:touches withEvent:event InView:touchView  WithTimer:timer];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)touchView WithTimer:(NSTimer *)timer
{
	[input touchesEnded:touches withEvent:event InView:touchView  WithTimer:timer];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)touchView WithTimer:(NSTimer *)timer
{
	[input touchesCancelled:touches withEvent:event InView:touchView  WithTimer:timer];
}

@end

As you can see, this is a pretty good sized class. What makes it bigger is I have a nasty habit of commenting everything to hell! I always believe it is best to comment heavily, because if you come back a year later and want to adjust your game, comments make it very helpful for remembering what does what.

The comments in the GLViewController (screen manager) class explains what everything does, but if you have any questions feel free to post them here.

So… now we need a game screen or two!! Remember, the following code should never be used to make a game screen directly. What I mean is, use this as a super class and inherit from it with your screens. For example, your TitleScreen should inherit from GameScreen. Make sense?

here is the GameScreen.h file

//	
//	A screen is a single layer that has update and draw logic, and which
//	can be combined with other layers to build up a complex screen system
//	or menu system, or even dialog system.
//
//	Developed by XNA Development Studio ( http://creators.xna.com/ ) 
//	Modified for the iPhone Gameing Framework by Craig Giles on 1/1/09.
//

#import <Foundation/Foundation.h>

#import <OpenGLES/EAGL.h>
#import <OpenGLES/ES1/gl.h>
#import <OpenGLES/ES1/glext.h>

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

//
//	Enum to describe the screens transition state
//
enum ScreenState {
	TransitionOn = 0,
	Active,
	TransitionOff,
	Hidden
};

//
//	Forward Declarations
//
@class GLViewController;

@interface GameScreen : NSObject 
{	
@private
	GLViewController *controller;
	CGRect viewport;
	
	bool hasBeenUnloaded;
	bool isPopup;
	
	float transitionOnTime;
	float transitionOffTime;
	float transitionPosition;
	float transitionAlpha;
	enum ScreenState currentScreenState;
	
	bool isExiting;
	bool isActive;
	bool otherScreenHasFocus;	
}

@property (nonatomic, retain) GLViewController *controller;
@property (readwrite) CGRect viewport;

@property (readwrite) bool hasBeenUnloaded;
@property (readwrite) bool isPopup;

@property (readwrite) float transitionOnTime;
@property (readwrite) float transitionOffTime;
@property (readwrite) float transitionPosition;
@property (readwrite) float transitionAlpha;

@property (readwrite) enum ScreenState currentScreenState;

@property (readwrite) bool isExiting;
@property (readwrite) bool isActive;
@property (readwrite) bool otherScreenHasFocus;


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

- (void) handleInput:(InputManager *)input;
- (void) update:(float)deltaTime	OtherScreenHasFocus:(bool)otherFocus	CoveredByOtherScreen:(bool)coveredByOtherScreen;
- (bool) updateTransition:(float)deltaTime	TransitionTime:(float)transition	Direction:(int)direction;
- (void) draw:(float)deltaTime;

- (void) exitScreen;

@end

and the GameScreen.m file

//	
//	A screen is a single layer that has update and draw logic, and which
//	can be combined with other layers to build up a complex screen system
//	or menu system, or even dialog system.
//
//	Developed by XNA Development Studio ( http://creators.xna.com/ ) 
//	Modified for the iPhone Gameing Framework by Craig Giles on 1/1/09.
//

#import "GameScreen.h"

@implementation GameScreen

//
// Properties
//
@synthesize controller;
@synthesize viewport;

@synthesize hasBeenUnloaded;
@synthesize isPopup;

@synthesize transitionOnTime;
@synthesize transitionOffTime;
@synthesize transitionPosition;
@synthesize transitionAlpha;

@synthesize currentScreenState;

@synthesize isExiting;
@synthesize otherScreenHasFocus;

@dynamic isActive;
- (bool) isActive
{
	return !otherScreenHasFocus &&
	(currentScreenState == TransitionOn ||
	 currentScreenState == Active);
}

//
// Constructor(s) / destructors
//
- (id) init
{
	self = [super init];
	if (self != nil) 
	{
		//initializations go here
		isExiting = NO;
	}
	return self;
}

- (void) dealloc
{
	//Deallocations go here
	[super dealloc];
}

//
// Loads all content associated with the current screen
//
- (void) loadContent
{
	
}

//
// Unloads all content associated with the current screen
//
- (void) unloadContent
{
	//	Release the screen manager
	[controller release];
	
	//	inidicate that the screens content has been unloaded
	hasBeenUnloaded = YES;
}

//
// Allows the screen to perform its update logic.
//
- (void) handleInput:(InputManager *)input
{
}

//
//	Updates the base screen. Since any game screen
//	wil be inheriting from this class, the game screen will
//	call this update method. This update just helps with the 
//	transition between two screens, and if a screen is
//	transitioning on and off. 
//
- (void) update:(float)deltaTime	OtherScreenHasFocus:(bool)otherFocus	CoveredByOtherScreen:(bool)coveredByOtherScreen
{
	otherScreenHasFocus = otherFocus;
	
	if (isExiting)
	{
		//if the screen is going to die, it should transition off
		currentScreenState = TransitionOff;
		
		if (![self updateTransition:deltaTime TransitionTime:transitionOffTime Direction: 1])
		{
			//when transition finishes, remove the screen
			[controller removeScreen:self];
		}
	}
	else if (coveredByOtherScreen)
	{
		//if the screen is covered by another, it should transition off
		if ([self updateTransition:deltaTime TransitionTime:transitionOffTime Direction: 1])
		{
			//scren is still transitioning
			currentScreenState = TransitionOff;
		}
		else
		{
			//transition has finished
			currentScreenState = Hidden;
		}
	}
	else
	{
		if ([self updateTransition:deltaTime TransitionTime:transitionOnTime Direction: -1])
		{
			//still busy transitioning
			currentScreenState = TransitionOn;
		}
		else
		{
			//transition finished
			currentScreenState = Active;
		}
	}
}

//
//	Helper method for updating the screen transition position 
//	(how much the screen has faded in / out)
//	
- (bool) updateTransition:(float)deltaTime TransitionTime:(float)time Direction:(int)direction
{	
	//	how much should we move by?
	float transitionDelta;
	
	if (time <= 0)
		transitionDelta = 1;
	else
		transitionDelta = deltaTime / time;
	
	//update the transition position
	transitionPosition += transitionDelta * direction;
	
	//did we reach the end of the transition?
	if (direction < 0 && transitionPosition <= 0 ||
		direction > 0 && transitionPosition >= 1)
	{
		//clamp transition position to 0, 1, or value;
		if (transitionPosition >= 1)
			transitionPosition = 1;
		else if (transitionPosition <= 0)
			transitionPosition = 0;
		
		return NO;
	}//end "end of transition"
	
	//otherwise, we are still busy transitioning
	return YES;
}

//
//	Each screen will have their own draw method. EVERY SCREEN
//	should call [super draw:deltaTime] in order to draw
//	the fade correctly when the screen manager wishes to fade
//	the screen in or out.
//
- (void) draw:(float)deltaTime
{
	[self.controller fadeBackBufferToBlack:self.transitionPosition];
}

//
// Tells the screen to go away. Unlike [controller removeScreen] which
// instantly kills the screen, this method respects the transition timings
// and will give the scren a chance to gradually transition off. 
//
- (void) exitScreen
{
	if (transitionOffTime == 0)
	{
		//if the screen has zero transition time, kill it 
		[controller removeScreen:self];
	}
	else
	{ 
		//otherwise flag that it should transition off and exit
		isExiting = YES;
	}
}


@end

Well that does it for the screen manager and the game screen classes.. But keep in mind.. this will NOT build until the InputManager is built. Why don’t you try to fiddle with that for a while, see what you can come up with? I’ll post Part 2 of this tutorial detailing how I did my input manager and two screens (TitleScreen and PausedScreen) in my next update.

Two thing before I go: I would really like to find a way to turn this into a template for anyone wishing to use it, but I simply do not know how. If you know how to do so, please send me an email at:
CraigGiles9@yahoo.com

Secondly, if you have any questions, comments, sly remarks, please post them. I am very good at reading everyones comments, and getting back to you if needed. You can either post a comment or send me an email and I’ll get back to you.

EDIT:
I just wanted to let everyone know that there have been a few changes to this article since first posting. I just modified the code within the GLViewController in several places. The following changes were made:
– Added [self releaseScreen:screen]; in the dealloc method inside the for loop.
– added const bool LANDSCAPE_MODE = NO; at the top of the view controller, and an if / else statement in the setup view method to help with setting up a landscape view rather than a portrait view. (The first screen manager was written for only portrait view)
– added input.isLandscape = LANDSCAPE_MODE; to the loadContent method.

Again, there are too many people to thank for helping me to get to where I am with my current knowledge. I hope this was informational to a few of you! Happy coding everyone!

Parsing XML on the iPhone

Since I am developing a game engine that I would like to re-use, I have chosen to host all game data in the form of XML files. There are various reasons for doing this, partly because I can make game editors (Map Editor, Item Editor, NPC Editor, etc) and partly because I value using re-useable code. 

In order to get it all working, I had to explore the NSXMLParser given by the iPhone SDK. With XNA and the .NET framework, I got used to reading in XML in a very specific way, and the iPhone does it quite differently. Currently, my test map’s XML file looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<Map>
	<MapName>Test Map</MapName>
	<MapContentName>Map001</MapContentName>
	<MapDimensions>
		<MapWidth>5</MapWidth>
		<MapHeight>5</MapHeight>
	</MapDimensions>	

	<TileDimensions>
		<TileWidth>32</TileWidth>
		<TileHeight>32</TileHeight>
	</TileDimensions>	

	<SpriteSheetName></SpriteSheetName>
	<MapLayers>
		<BaseLayer>0, 1, 0, 0, 0, 0, 0, 0, 0</BaseLayer>
		<MiddleLayer>0, 1, 0, 0, 0, 0, 0, 0, 0</MiddleLayer>
		<TopLayer>0, 1, 0, 0, 0, 0, 0, 0, 0</TopLayer>
		<AtmosphereLayer>0, 1, 0, 0, 0, 0, 0, 0, 0</AtmosphereLayer>
		<CollisionLayer>0, 0, 0, 0, 0, 0, 0, 0, 0</CollisionLayer>
	</MapLayers>
</Map>

In order to read in the XML, there are 3 methods that you need to implement. Since your XML parser goes line by line, you will need to write a method that starts an element, ends an element, and reads a character. Such as:

// Start of element
- (void)parser:(NSXMLParser *)parser 
			didStartElement:(NSString *)elementName 
			namespaceURI:(NSString *)namespaceURI 
			qualifiedName:(NSString *)qName 
			attributes:(NSDictionary *)attributeDict
{
}

// Found Character
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSMutableString *)string 
{
}

// End Element
- (void) parser:(NSXMLParser *)parser 
			didEndElement:(NSString *)elementName 
			namespaceURI:(NSString *)namespaceURI 
			qualifiedName:(NSString *)qName
{
}

Once you have these methods set up, all you really need to do is populate them. For instance, in the “Start Element” method, if your “elementName” = “MapName” (in the above XML case) you would allocate the map classes NSString like so;

mapName = [NSMutableString string];

When you found a character, you would store those into a string, and when the end of the element is reached, you would put that string into whatever element it was reading. For example, the map name:

mapName = stringValueFromFoundCharacter;

Not too hard, but wasn’t easy to figure out either.. At least I know it and now can implement readers for every data that I wish to store as XML!

No more teachers, no more books… until next semester!

Wow, I didn’t expect my first semester back at college to be that difficult! It turns out that every project I was doing was put on hold until I could finish my semester. My next semester schedule isn’t any lighter though, although I have cut my hours down from work as to give myself more time to work on my projects. 

So here is where we stand, The map editor is very close to release 1.0, and 1.0 is a basic update. It will do what you need it to do, but it isn’t “polished” .. more “functional.” While on winter vacation I am working with my friend to push out a release, and once that is done we will start opening up the source and add whatever features we may need.

I’ve found that my goal for this project was ambitious, but in line to what we could accomplish. I wanted this editor to work primarily for XNA projects, but not only RPGs. Any game that used a tile engine could take advantage of this project. But what about other platforms? iPhone development? Well it would just take some tweaking to the exporter and you’d have a fully functional XML file.. could that work with iPhone development? Not sure.. but I think it would be fun to tinker with :)

As always, check out my right bar links, there are a lot of awesome projects (Including EvilNando’s Animation editor) that i’ve been keeping tabs on. Lot of great things goin on in the world of XNA, here’s hoping that I can get a final push out and start my actual project here soon.

RPG Editor: Exporter Settings – First Preview

With the first version of the RPG editor just about ready to be tested, I thought I’d take the opportunity to share some of the things we’d like to implement. So lets take a look at some of the custom XML exporting!

From this first screen shot, you will notice that on the left half of the form is all of the fields that can be changed, while each change will be reflected by the XML Output on the right. Using this data, it will be easier to see how your final XML will look, before you export the XML file. 

You can also see that we’re trying to make any map created with our editor be directly “plug and play” with an XNA project. For example, the XnaContent tag is automatically implemented, and so is the Asset Type= but the user will be able to specify their project namespace as well as the map class name that will be housing the data in-game. Obviously every XNA project needs this information unless you are using a custom importer / processor for your XML data, so you can not opt out of having this information exported.

Attempting to make the XML as flexible as possible, you will notice one feature we’ve already put in. You can specify the “Output Type” of your data to take advantage of the various importing techniques of the XNA Content Pipeline. For example, if you wish to import your “MapDimensions” data as a point, the output XML will look something like:

<MapDimensions>X Y</MapDimensions>

while if you wish to import it as a custom data and write your own Content Reader / Writer for that data, you can and it will export something like:

<MapDimensions>
     <Width>
X</Width>
     <Height>
X</Height>
</MapDimensions>

and naturally, all fields are customizable so if you wish to change “Width” to “MapWidth,” you can.

So, for now… this is a small snippet of what we’re working on. Again, we expect this project to be open source once we get further down the road, so anyone can take what we’ve done and expand on it or use it for their own editors.

I hope this project encourages the creation of some great RPGs, because I love me some RPGs :) See you all soon!

Community Games has a date

If you’re working on your own game, or know someone who is.. You should be excited to know that the Community Games has a formal date!

http://creators.xna.com/en-us/xna_goes_live_october30th

“independent game developers will be happy to know that XNA Game Studio 3.0 will be available for download on October 30, 2008 so they can to convert their creations and prepare them to be a part of the launch of Xbox LIVE Community Games on November 19.”

Good news indeed. Looking forward to playing some of your creations :)

XNA RPG Editor: Soon to be Open Sourced

As stated in a previous post, our goals for this project were simple yet ambitious at the same time. We wanted to create a system that could be useable for not only our immediate needs and the RPGs we wish to create, but also any future needs and the games we have yet to think about, and taking it a step further we wanted this project to be usable for any game creator wishing to create levels for THEIR RPGs. 

Step one for my portion of the project is complete. I’ve been working on the XML Exporter class and the front end to that exporter. The goal for me was to get the XML to export all of the needed information in as customizable fassion as posible.. but at the end of the day when you hit “Export to XML,” you can take that file and plug it into your projects content pipeline and expect it to work. You won’t need to mess around with formatting, adding the asset type, change your TileMap class around because of the XML document… it will truly be a document suited for your needs.

We are really only on step one, building the basic framework and systems for the editor. Hell, the editor itself is nothing more than a blank windows form at this point hah. I have started working on the front end of the Exporter system over the next few days and hope to have something to show off then.

Keep in mind, this project is in its first stages, and has some pretty ambitious goals. Our overall goal for this though, is to ensure that people who use our editor will be able to plug the XML into their project and just “have it work” :) Also when the editor gets into a more complete state, we will open up the repository so everyone can take what they like and add it to their own projects or continue to enhance ours for their own use.

Content Creation

With the Dream Build Play project “Complete,” I’ve turned my attention to a few items that will aid in the creation of not only Meir, but any future RPG I write. Content creation is a tricky subject, as the goal is to create something flexable enough to re-use in any RPG project, but dynamic enough and easy enough to use so if I had a few people working on any given project, they would know what to do.

Well me and a buddy from the shacknews chatty decided that he didn’t want to use TileStudio anymore, but wanted something more suited for his game.. so we started colaborating on an editor that would be built specifically for XNA games, but flexable enough to use in any project. Obviously this editor will have to support several major features of basic RPGs, but how in depth are we going to really go with this thing?

Create and edit tile maps? Basic feature, has to be included.
Exporting XML in the same style of the XNA Content Pipeline? Basic feature, has to be included.

but what about features like adding a “tile” to the texture, and having the map build the texture and exporting that to a PNG file? What about creating a system that can export to multi dimensional or single dimensional arrays based on the project needs? How about a dynamic XML system that lets the user edit how their XML should look, then hitting “Export XML” and having their XML formatted correctly? There are many many more ambitious goals we wish to include, and we’re thinking a bit larger scale then just these… but its pretty interesting to see what we could come up with. As always, I’ll keep everyone up to date on whats actually going on. 

So if you had to pick and choose a few “Must Have” features of a game editor, what would you want included?

Meir available for download on Creators Club Beta

The Dream Build Play entry ‘Meir’ is now available on the Creators Club Beta for peer review. Official link to the Creators Club entry is: http://catalog.xna.com/gamedetails.aspx?releaseId=279

I am now on a mission to make substantial improvements to both the engine, technology, and adding the sub-systems that I could not impliment for the Dream Build Play competition. My goal is to have a working framework for my Role Playing Games, and then start working on assets such as quest creation / story / artwork. I figure the engine touchups and technology will take a month or two, but the rest will take longer, so I will probably be looking for either help or outright purchase assets (such as characters, tilesets, etc) from aspiring developers. But… until then, let me know what you guys think!

In order to download titles from the Creators Club Beta, you will need a premium membership. Feel free to leave feedback here or via email at: CraigGiles9@yahoo.com

Follow

Get every new post delivered to your Inbox.