Archive for the ‘Game Development’ Tag

OpenGL ES: Batch Rendering on the iPhone

This one took me a while, simply because there was a LOT of research to do on my part. This is not going to be a tutorial post, per-se… but more so a “This is what I’ve found” and a request that someone take a look through it and see what I could have done better, and then let me know ! :)

Simply put, I was getting a few FPS problems with the development of my game, and thought I would come up with a way to batch all of my drawing into as few OpenGL calls as I could. I came across a few interesting tidbits, including a Stanford ‘iTunes U’ course (look that up in iTunes, its WELL worth viewing) Especially the one on OpenGL from Tim Omernick (Slide can be found HERE).

A copy of the code can be found at the google code repository, direct link to the TextureController is HERE. Well then, lets have a look at it!

The first thing that I attempted to do, was make a struct with the vertices, color information, and uv information. This is a result from Tim’s lecture and heavily influenced by his code. The hiccup was that I wanted to be able to batch based on the GLuint being drawn so I would only have to bind a texture once and then draw all vertices associated with that texture. I came up with the following solution:

struct Vertex
{
 short v[2];
 unsigned color;
 float uv[2];
};

struct VertexInfo
{
 Vertex vertex[MAX_VERTICES];
 int _vertexCount;
};

What will happen here, is VertexInfo will be stored in a map, while the Vertex struct houses all of the information that will be thrown at OpenGL to draw. MAX_VERTICES is defined at the top of the header file, and I really have not played around with it much so I am not sure how slow or fast it will be with a full game running. Currently its set for 100,000 but that was just a number I pulled out of nowhere :D I imagine it should be reduced.

The Map containing the vertex information looks like this;

typedef std::map<GLuint, VertexInfo> VertexMap;
VertexMap vertices;

You’ll see how to use this in a minute. My idea for this class was to sort of clone the way the SpriteBatch works from the XNA framework. This is another of my nods to how well this framework is put together, and how much I enjoy working with XNA. I wanted to be able to call a begin function to let the TextureController know if I plan to use blending (or any other parameter I may add, such as sorting), and then throw a bunch of stuff to draw using the Textures->draw functions provided. Each call to the Textures->draw function will take the texture to be drawn and any information needed (such as the location, source rectangle, color, etc) and pack that information into the VertexMap waiting to be thrown to OpenGL. Once all of my draw commands have been executed, a Textures->end() will initiate all drawing for the batch.

Keep in mind, is this the best way to put something like this together? Probably not.. although its my first time doing such an interesting task.. :) Lets see how it works!

NOTE: I will input breaks to make some comments… so if you want the full file, be sure to visit the code repository at code.google.com

void TextureController::draw( const Texture2D& texture, const Rectangle& destination,
 const Rectangle& source, const Color& color, const GLfloat depth )
{	

As you can see, we’re plugging in a few informational tidbits, but this is only one of the drawing commands that i’ve implemented. The simplest draw command, you only have to provide a texture and a destination rectangle… and “default” values will be put to fill in the blanks when calling this function.

 GLuint glid = texture.getId();

 //	if we don't have any vertices with the texture being drawn, create a
 //	vertex map for it.
 VertexMap::iterator it = vertices.find(glid);
 if (it == vertices.end())
 vertices[glid]._vertexCount = 0;		

 //	find all of the vertices we'll need for this sprite
 float topLeftX = destination.x;
 float topLeftY = destination.y;
 float topRightX = destination.x + destination.width;
 float topRightY = destination.y;
 float bottomLeftX = destination.x;
 float bottomLeftY = destination.y + destination.height;
 float bottomRightX = destination.x + destination.width;
 float bottomRightY = destination.y + destination.height;

The above section is interesting in that it will first find out if we’ve already batched a sprite using the texture. If we have, we’ll just add the vertices into that batch. Otherwise, we’ll create a new batch of vertices and start that new batch. Next, we find all of the vertices! This is done through the destination rectangle passed in. The destination rectangle is going to be the spritebox that the texture is drawn to. In other words, its your canvas and your texture is the paint.

 // Texture atlas
 float minUV[2];
 float maxUV[2];

 //	if the source rectangle of ZERO was passed in, it means the client want to just
 //	draw the texture as is.. otherwise, the client wishes to draw a portion of
 //	the rectangle
 if (source == Rectangle::ZERO())
 {
 float maxS = texture.getMaxS();
 float maxT = texture.getMaxT();
 float minS = 0;
 float minT = 0;

 minUV[0] = minS;
 minUV[1] = minT;
 maxUV[0] = maxS;
 maxUV[1] = maxT;
 }
 else
 {
 float minS = source.x / texture.getWidth();
 float minT = source.y / texture.getHeight();
 float maxS = source.width / texture.getWidth();
 float maxT = source.height / texture.getHeight();

 minUV[0] = minS;
 minUV[1] = minT;
 maxUV[0] = maxS;
 maxUV[1] = maxT;
 }

This section took me the longest to really figure out, because I had not done any research how Texture Atlas’s work. As I said, this was heavily influenced by Tim’s code and I really wanted to understand this section before I moved on. What we’re doing here, is if a blank rectangle is passed into the function (meaning the client didn’t specify a rectangle and therefore wishes to just use the texture ‘as is’) we’ll use the maxS and maxT coordinates for the TextureCoordinates. The way we find out what maxS and maxT are, is after the image goes through its modification to become a power of two texture (see my last article), maxS will become imageWidth / newTextureWidth. In other words
if the texture is passed into your game at 30 pixels by 30 pixels, it was re-sized by the Texture2D class to become 32 by 32. maxS will be 30 / 32, or 0.9375f. This value indicates that when using the default values, 93% of the image is drawn, while the remaining 7% of the image contains nothing more than padding in order to ensure it was a power of two texture.

What if we wanted to use a sub image, only draw a portion? This would be useful if we had several images on one texture. Lets say you have a texture with 2 frames of animation, both frames are 24 by 24. This means your texture is 48 pixels wide, by 24 pixels tall. If you only want to draw the last half of the texture (your “2nd” frame of animation) your source rectangle would be:

x=24, y=0, width=24, height=24
Meaning you’re starting 24 pixels into the picture, at the top pixel of the picture, and you’re going 24 pixels wide and 24 pixels high. This is going to be the sub-image you’re drawing.

In order to change these numbers into texture coordinates, we need to divide by the image width or height. For example, 24 / 48 is .5, so your texture coordinate for x is .5, then 0, then .5, and .5.

 //	Convert the colors into bytes
 unsigned char red = color.red * 255.0f;
 unsigned char green = color.green * 255.0f;
 unsigned char blue = color.blue * 255.0f;
 unsigned char shortAlpha = color.alpha * 255.0f;

 //	pack all of the color data bytes into an unsigned int
 unsigned _color = (shortAlpha << 24) | (blue << 16) | (green << 8) | (red << 0);

 // Triangle #1
 addVertex(glid, topLeftX, topLeftY, minUV&#91;0&#93;, minUV&#91;1&#93;, _color);
 addVertex(glid, topRightX, topRightY, maxUV&#91;0&#93;, minUV&#91;1&#93;, _color);
 addVertex(glid, bottomLeftX, bottomLeftY, minUV&#91;0&#93;, maxUV&#91;1&#93;, _color);

 // Triangle #2
 addVertex(glid, topRightX, topRightY, maxUV&#91;0&#93;, minUV&#91;1&#93;, _color);
 addVertex(glid, bottomLeftX, bottomLeftY, minUV&#91;0&#93;, maxUV&#91;1&#93;, _color);
 addVertex(glid, bottomRightX, bottomRightY, maxUV&#91;0&#93;, maxUV&#91;1&#93;, _color);
}
&#91;/sourcecode&#93;

Aah, bit packing... how do I love thee, let me count the ways! When I first learned how to manipulate bits of data, I asked myself "Why would this ever be useful?" ... guess I learned the hard way, that its a very necessary skill to have. I don't fully understand it as much as I would like to, but I do a little research on it every day.

What we're doing in the above code is taking the red / green / blue / alpha color value (which is passed in as a 'between 0 and 1' value), multiplying that by 255, and packing the bits into a single value called _color. Apparently, its a lot faster for OpenGL to use this data in this way, so hi ho, hi ho.. its off to pack we go!

&#91;sourcecode="cpp"&#93;
void TextureController::addVertex(GLuint glid, float x, float y, float uvx, float uvy, unsigned color)
{
 VertexInfo *vertexInfo = &vertices&#91;glid&#93;;
 Vertex *vert = &vertexInfo->vertex[vertexInfo->_vertexCount];
 vert->v[0] = x;
 vert->v[1] = y;
 vert->uv[0] = uvx;
 vert->uv[1] = uvy;
 vert->color = color;
 vertexInfo->_vertexCount++;
}

And packing we do! This is where the batch work is done. What we’re doing is passing in a single Vertex data (the x location, y location, texture coordinates, color, and the texture used) and packing it into the struct I showed you above. Once we do that, we increase the _vertexCount, so we’re keeping tabs on how many vertices we’re batching.

So.. thats how we batch, how do we render? Simple!

NOTE: Keep in mind, this is only a portion of the code. This function is called from the “end()” function I talked about eariler. end() will ensure that beginning was called, and then pass the buck to the render function.

void TextureController::renderToScreen()
{
 glPushMatrix();
 glMatrixMode(GL_MODELVIEW);

 //	Texture Blending fuctions
 if ( blendAdditive )
 {
 glEnable(GL_BLEND);
 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 }

 //	needed to draw textures using Texture2D
 glEnable(GL_TEXTURE_2D);		

 //	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);

 //	Enable the various arrays used to draw texture to screen
 glEnableClientState(GL_VERTEX_ARRAY);
 glEnableClientState(GL_NORMAL_ARRAY);
 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 glEnableClientState(GL_COLOR_ARRAY);

 glLoadIdentity();

The above is just standard stuff to get ready for rendering. In fact, I think this was just cut / pasted from my Texture2D class. The real interesting part happens next!

 //	loop through all of the elements of the map and draw the vertices
 VertexMap::iterator it = vertices.begin();
 for (/* none */; it != vertices.end(); it++)
 {
 //	easy access to our data
 VertexInfo *vertexInfo = &it->second;
 Vertex *vert = vertexInfo->vertex;

 //	bind the texture for the following vertices
 bindTexture( (*it).first );

 //	throw everything to OpenGL
 glVertexPointer(2, GL_SHORT, sizeof(Vertex), &vert->v);
 glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &vert->uv);
 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &vert->color);
 glDrawArrays(GL_TRIANGLES, 0, vertexInfo->_vertexCount);

 //	reset this batches vertex count
 vertexInfo->_vertexCount = 0;
 }

What we’re doing here is looping through every key (which is the GLuit of the texture, if you recall) binding that texture so that OpenGL knows which texture to draw with, and then throws all of the vertices and texture coordinates and all other info needed to render the batch. A few notes that some people might not know (I didn’t when I was researching this)

glVertexPointer(2, GL_SHORT, sizeof(Vertex), &vert->v);
the 2 means that there will be 2 vertices, and x and a y. This number could be a 3, if you’re also storing a z value. We will be using GL_SHORT (remember in the struct, all vertices are declared as short), and the interesting portion of this is the sizeof(Vertex). This is called a STRIDE, and basically tells OpenGL the distance between the data in memory. (I hope I explained that correctly!) The last value is the array of vertices!

glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &vert->uv);
This is very similar to the above.. except we’re using different values. The 2 is referring to the fact that we have 2 points per vertex for the texture coordinates (an x and a y) but if you’re going to be using a z value, this number will be changed to 3. Remember, we are using floats for this (check the struct), and the STRIDE value stays the same. Then just pass it in the array of information.

glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &vert->color);
Again, similar concept, except we did a few things differently with this. Remember our color scheme is 4 colors (red, green, blue, and alpha) but we packed all that information into a single value? We specify that via the GL_UNSIGNED_BYTE. otherwise, everything else remains similar.

glDrawArrays(GL_TRIANGLES, 0, vertexInfo->_vertexCount);
This is the reason we’re keeping track of how many vertices we have! What we’re doing here is telling OpenGL to draw the arrays using triangles, the 0 is referring to the starting index (obviously we’re going to be starting at index 0, just as if we were looping through the index ourselves), and how many elements are in the arrays.

What this will do, is put together the information in a single stream of information.. something like:

XY RGBA USUV, XY RGBA USUV, XY RGBA USUV
This is much more efficient for OpenGL to render, and therefore it will chew through the data and at much greater speeds than if you render your data once per texture. (ala, my old method)

now all thats left to do is clean up by disabling any states we enabled

 //	disable all the stuff we enabled eariler
 glDisableClientState(GL_VERTEX_ARRAY);
 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 glDisableClientState(GL_COLOR_ARRAY);
 glDisable( GL_BLEND );
 glDisable( GL_TEXTURE_2D );
 glDisable( GL_ALPHA_TEST );

 glPopMatrix();
}

and voila!

Again, this is my first pass at writing such a system.. and I am still learning the form of graphics programming. I urge you to pick up the code from the svn repository (http://code.google.com/p/djinnengine) and play around with it. If you find anything that I could do better, or things that may help me understand this process a little better, feel free to post for everyone to learn from!

Happy Coding everyone!

Advertisements

OpenGL ES Texture2D: Power of two

As most of you have figured out, OpenGL ES doesn’t like textures to be non power of two, and I really didn’t want to have to force all of my textures to be powers of two before loading them into my game. This presented me with a problem that had to be solved in-code.

To really understand texture mapping, especially if you’re doing iPhone development or OpenGL ES development in general, it is a good idea to visit Jeff’s blog on the subject located: HERE, and look up chapter 6 on Texture Mapping. I’ll wait, its a great read and should be glanced over at the very least!

Back? OKAY! So the problem is only powers of two can be used in OpenGL ES, so how do we convert our texture to a power of two? There are several ways to do this, but I chose to look at apples version of a texture file and learn from them.

They came up with the following to convert the width and height into a power of two:

//     Adjust the width and height to be a power of two
if( (_width != 1) && (_width & (_width - 1)) ) 
        {
                i = 1;
                while((sizeToFit ? 2 * i : i) < _width)
                        i *= 2;
                _width = i;
        }
        
        if( (_height != 1) && (_height & (_height - 1)) ) 
        {
                i = 1;
                while((sizeToFit ? 2 * i : i) < _height)
                        i *= 2;
                _height = i;
        }
&#91;/sourcecode&#93;

The first portion of the code will convert the texture to a power of 2. Since the texture will be stretched, and never shrunk, apple had to figure out a way  to shrink the texture if it became larger than the max texture size of 1024. The following code will do just that:

&#91;sourcecode="cpp"&#93;
        //      scale down an image greater than the max texture size
        while((_width > kMaxTextureSize) || (_height > kMaxTextureSize)) 
        {
                _width /= 2;
                _height /= 2;
                transform = CGAffineTransformScale(transform, 0.5, 0.5);
                imageSize.x *= 0.5;
                imageSize.y *= 0.5;
        }

the ‘transform’ is nothing more than a CGAffineTransform; in case you were confused with that. So, now that you’ve glanced over the code, you remember in the article where Jeff was talking about S and T coordinates? We’ll take care of those like this:

        _maxS = imageSize.x / (float)_width;
        _maxT = imageSize.y / (float)_height;

This will give us a number between 0 and 1, depending if the texture was re-sized or not. _maxS and _maxT will also be used in our textureCoordinates array for drawing the texture to screen. This should only render the portion of the texture that has any data, and not the padding we added to the texture.

While I am still learning OpenGL, I figured that a lot of people would be interested in the following solution.. especially if you did what I had, and had thrown out the Apple Texture2D file and re-wrote your own. Full source code to the Texture2D, or any other file within the D’Jinn Engine can be found HERE.

Hope this was informative! If anyone has any further information they would like to add, feel free!

Happy Coding Everyone!

D’Jinn Engine: Updates

Over the last few days I’ve been re-working a few of the OpenGL calls and a few classes in the D’Jinn Engine. The most notable change is removing the Texture2D class that apple provides, and instead loading up a Texture2D class of my own that uses the TextureController for memory management. In revamping the Textures from OpenGL, I was hopeful to figure out the problem I’ve been having with the Particle Emitter, and I have not been able to figure it out… but I’ll keep working!

The Emitters problem is documented in both the class file as well as issues on the SVN site.

Anyway, feel free to poke around and send me an email if you find anything that I could do better, or that could be re-structured better. I will start working on new extensions and making the “engine” an actual engine over the next few weeks.. especially now that the design for my game is starting to complete and I have a better idea of what I’ll need to add to the engine to make it work. After all, the D’Jinn Engine is a project of mine to help learn the in’s and out’s of C++ development, so send in that feedback!

Also of note, I obtained the 3.0 SDK and fixed the minor errors in the code that didn’t let you compile and run it under 3.0 OS. You should be able to now. Full list of changes can be found: HERE

Happy Coding everyone!
PS: D’Jinn Engine SVN: CLICK HERE

D’Jinn Engine: Open Sourced…

Is it ready for full time production? … eh, no…
Is it a fully function engine? … eh, no…
Will it aid in your thurst for knowledge?.. YEAH!

As you read yesterday, I’ve decided to put what I have of the D’Jinn Engine up on google code, for anyone to poke, pry, and have fun with. I will continue my trek to modify and improve the engine pretty much every day, but it is also free for anyone who also wishes to take what I have to use in their own project.

What is the catch? Simple… If you make any improvements, let us know about it! The iPhone and iPod Touch community is hungry for knowledge on game development, and could really use a few great resources. Will the D’Jinn Engine ever be a general enough resource for anyone to pick up and use? Probably not… but at least its there for the few of us who enjoy C++ enough to torture ourselves into making a game engine on the iPhone :)

I have spent some time working on the description and trying to comment the code as much as I could. As we speak, I am working on a texture controller class that will eliminate the need for the Texture2D from apple (and in the process, hopefully eliminate a nasty bug I introduced with the particle system…)

Remember, I will be working on this thing pretty much every day, if not every other day. Don’t expect to see a commit every day, but know that there are people making improvements to it. Dive in, have fun, learn a thing or two, teach me a thing or three… and feel free to join the discussion group if you have something interesting to share!

D’Jinn Engine: iPhone C++ 2D engine
http://code.google.com/p/djinnengine/

Happy Coding everyone!

C++ on the iPhone: Test Driven Development

I have been learning quite a few development strategies as of late, and the newest one that I’ve taken a peek into is Test Driven Development (TDD), or Unit Testing. The idea behind TDD and Unit Testing is to split up your problems into small, easily manageable problems rather than having to design everything from the get go, and living with any or all of your mistakes for the rest of the project. TDD is a very complex topic and usually requires the use of various frameworks for dynamic unit tests, but I’ll be focusing on the ‘beginning’ method of TDD, static unit tests.

How do we start? Well in my current engine, what I did was write a class called “TestGame.cpp” which was a singleton class that housed various methods for testing the game. In that class, I would write functions to test a particular class I would be creating, or an entire game loop to test the logic of a class without having to construct a game world for our object to live in. Inside the TestGame class there is a function called ‘startTesting()’ which will call anything you wish to test. Lets write a sample test to give you an idea on the very basics of what I’m doing.

//This function is public, and able to be called when you obtain the instance
//of the TestGame class. We will start every test from this function, and keep
//it kind of like a list. Whenever an aspect needs to be changed, for example
//with the actor class, we can simply uncomment the 'testActorClass()' line 
//to ensure it still passes all of our tests. 
void TestGame startTesting()
{
	testActorClass();
}

//This function, however... is private and unable to be called by anything
//outside the "TestGame" class, and should only be called by the 'startTesting()'
//function.
void testActorClass()
{
	Actor *act = new Actor();
	string testString;
	float testFloat;
	
	act->setAlpha( .50f );
	testFloat = act->getAlpha();
	
	//	identities are unique and assigned when the object is constructed.. Calling this function
	//	should not change the identity
	act->setIdentity( "newIdentity" ); 
	testString = act->getIdentity(); //should still be "Actor_#"

	act->setName( "Werewolf ");
	testString = act->getName();//should be "Werewolf"

	act->setPosition( Vector2::ZERO() );
	testString = act->getPosition();//should be 0,0

	act->setSize( Vector2(32, 32) );
	testString = act->getSize();//should be 32, 32

	act->update( .003f );
}

Now if I were to compile this code, it would spit out a bunch of errors. “Set Name? .. Get Identity? I don’t know how to do that!” and that’s the point! These functions have not been written yet. The basic idea is to construct what you want your actor class to do, and then write the code to DO it. The next step is to write JUST enough code to get the project to compile, so… to the actor class we go! Quite literally, all we’ll be doing in the next step is to write the skeleton functions like such (NOTE: The various helper classes like Vector2 have been written and added to the engine, they are already created and have already been tested using this approach and do not come ‘standard’ in C++ (or Obj-C as far as I know);

//in the Actor.h file
public:
	bool setIdentity( const string &value );
	string getIdentity() const { return identity; }

	bool setName( const string &value );
	string getName() const { return name; }

	bool setPosition( const Vector2 &value );
	Vector2* getPosition() { return position; }

	bool setSize( const Vector2 &value );
	Vector2* getSize() const { return size; }

	bool setAlpha( const float value );
	float getAlpha() const { return alpha; }

	virtual void update( const float deltaTime );
protected:
	string identity;
	string name;
	Vector2 *position;
	Vector2 *size;
	float alpha;
//in the Actor.cpp file
bool Actor::setIdentity( const string &value )
{
}

bool Actor::setName( const string &value )
{
}

bool Actor::setPosition( const Vector2 &value )
{
}

bool Actor::setSize( const Vector2 &value )
{
}

bool Actor::setAlpha( const float value )
{
}

void Actor::update( const float deltaTime )
{
}

This code should now compile and run, even though it doesn’t do anything. Well we know what we want to do, and we now have a skeleton to do it… so we should get going on writing the code!

For example, we know that we want the identity of the actor to be unique, and that the setIdentity function should only set the string if it currently does not have an identity.. so since this is going to be the most difficult function to write, lets do that one real quick.

bool Actor::setIdentity( const string &value )
{
	//	if the identity has already been set, do not
	//	re-set the identity. Object must be destroyed
	//	and re-created to reset an identity. 
	if ( identity.length() != 0)
	{
		return false;
	}
	
	//	if the identity has not been set, set it
	//	and return true
	identity = value;
	return true;
}

really, thats it. The actor doesn’t know if its identity is unique, nor does it know how to obtain a unique identity. It just says “Okay, I don’t have an identity right now, so I’ll take this one and make it my own!” The idea is the actor class exists on its own, and functions as its own data. To obtain a unique identity and to keep track of all actors in the game world, we will use an ActorController (remember that pesky thing called the Model / View / Controller? ) The Actor class is the data (model) while the Controller will manage that data and when needed, present it to the view for rendering.. but that is a topic for another post.

The last thing we should do is COMMENT COMMENT COMMENT! I am a big fan of commenting my code, and documenting not only what the function does but why its implemented the way it is. If you ever look over your code 3 months down the line, you’ll say to yourself “I didn’t write this… what was I thinking?!” … well if you commented your code, you’d know! its a good habit to get into, and if you look at my Screen Controller from a few posts back, you’ll notice just how much I comment.

So that is all for today. Test Driven Development is a HUGE area, and this is just the very very basics of how it can be done. Once you get into the frameworks, it can be pretty complex, but very much worth the effort.

Happy coding everyone!

C++ on the iPhone

C++ is an interesting language, and so is Objective-C. Since I have chosen to go back to college to get my degree in Computer Science, I thought it would be beneficial to do as much of my projects in C++ and not split up the languages (C#, Objective-C, C++, etc) so I’ve converted my projects to C++ code. What does this mean for iPhone development though? Its actually quite interesting.

Think of it this way, if you were to do EVERYTHING in a C or C++ style syntax, how would you load and bind a texture in OpenGL? What about converting the screen manager (that tutorial posted below) to C++? What about capturing the touches from the screen and filtering them to the InputManager class? It really is quite interesting.

So, the ‘Djinn Engine’ was born and is really just a pet project of mine for now. As we discuss something in class, and I finish the classes project for that section (which usually doesn’t take me long) I will stat working on those features in the engine. Its an interesting setup, and will take me longer to get a “product” on the app store, but I enjoy it more and am learning a great deal more about how things are working under the hood, and that is something I think everyone should take a look at.

I’ll make some posts soon about the progress of the engine and any projects associated with it. I have not announced anything that I am working on, but there are a few projects that are going to be coming in the next year or so. Exciting? You betcha!

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 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 [/sourcecode] 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!

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!

Building a gaming framework

I have done enough studying, research, and toying around with the iPhone SDK to have my head wrapped around the very basics of OpenGL ES. Mind you, this was not easy.. especially for a guy like me whose never had any formal training in Computer Programming, let alone graphics programming using DirectX or OpenGL… But that never stopped me in the past!

So where do I begin? Simple! I’ve already been researching some of the possibilities in the iPhone SDK. One of the major aspects that I needed was to load in-game data (levels, items, power ups, player data, etc) through the use of XML. Confusing, yes.. but I have already gotten a few emails from people who found my write up to be pretty enlightening.. and when I start doing more with XML I’ll be sure to document it further. Aside from XML, I also took some time out to learn the basic drawing capabilities of OpenGL ES and Apple’s Texture2D class, and with those little tidbits I have enough to develop my first iPhone Gaming Framework to use in my first iPhone game!

My first game is going to be a target practice game of sorts, but with a lot of added functionality. I want to give people a reason for playing my game… so I’ve drawn up a little design document describing my goals and what would set this game apart from other casual games in the app store. Right now, the game is in its very basic state, in fact I would consider it to be a pre-alpha build. How alpha? Well… judge for yourself with the current screen shot of the build.

Target Practice

Pretty basic huh? The next step for this game is to build on what I know and what I’ve constructed in the games design document. I can not stress this enough to people who wish to get started in doing these sorts of programs.. DESIGN DOCUMENTS ARE A GOD-SEND AND SHOULD BE COMPLETED FOR EVERY GAMING PROJECT NO MATTER HOW SMALL! 

I will start building some more functionality and classes that will enhance the playability of this game, and really take the time to make it fun for the casual gamer. My goal is to ensure that this game is worthy of a players time and re-playability. I want a game that a player will be able to play, enjoy, and come back to and not a game that will be played and tossed aside. After reviewing my design document, and going over a few strategies for implementation, I am confident that people will at least enjoy this venture.. and in reality, that is all I can ask.

Stay tuned, and I’ll update on my progress and post a few tidbits of code from time to time. If there is something that you would like to see, please send me an email and I’ll see if I can convert it into a post and put it up here. I won’t post the entire source code, but I will post enough to get people started who are like me, and don’t really know how to start. 

See you then!