Skip to content

Archive

Tag: iTouch

I have now resolved importing Blender data into my game (complete article with source code will be available next).

In this article I’m covering code structure changes required to migrate from a ’2D isometric view’ (CocoaTouch rendering) to a 3D isometric view (OpenGL-ES rendering). The calculations helped me understant glOrthof a little better.

My original plan was to provide first a ‘dummy view’ to allow level design without having to create dummy assets for every other character or tile. I’ll probably still do this, but because the dummy view required vector graphics, I dived head first into OpenGL ES – the downside being that this cannot integrate directly with my current view code.

Starting from the GLES2Sample example, I have done the following:

  1. modified it to remove GL ES2 support (at least for now)
  2. Added an ‘ESContentRenderer’ interface. This could be temporary; for now it’s just an acceptable way to separate GL setup/teardown from content rendering. ES1Renderer now calls [ESContentRenderer render] within its own render function.
  3. Arranged that EAGLView now extends my ActionView class (ActionView just converts simple taps into something like clicks).
  4. Created a StageView3D subclasser to EAGLView. StageView3D is like my 2D StageView class. This is for consistency.
  5. Added a StageViewRenderer class – this implements ESContentRenderer and is meant to do actual rendering work.

I somehow mean to define a common interface for StageView3D and StageView(2D). As it stands most methods in StageView were private – the view knows about the model, not the reverse – so there’s little gained in doing this.

With my new setup, I can instantiate StageView3D in place of StageView (duplicated the constructor). EAGLView owns the contentRenderer and passes it to ES1Renderer (could be renamed FrameRenderer). StageView3D extends EAGLView and provides StageViewRenderer as content renderer.

The above realizes two goals:

  • Put GL drawing in a separate class, part of my view rendering – EAGLView and ES1Renderer are part of my GL boiler plate.
  • Keep the new view setup compatible with my existing controllers.

I’ve been tempted to fire a paint message from ES1Renderer instead. I could handle that within StageView3D. which would keep it more like StageView. For now I don’t see the difference and feel a little suspicious about dispatching an event allowing classes to contribute drawing independently.

I still need to replicate the drawing of the actors, props and board, and (until I enable gl picking) I need to make sure that my isometric view is compatible with my existing (2D) picking code.

After I am finished with setting up my StageContentRenderer and StageView3D:

  • StageView3D duplicates StageView code for 2D picking. I won’t try to factor this out just yet (I will eventually migrate this to 3D picking I guess…)
  • StageContentRenderer graces me with a beautiful gray screen.

Drawing Actors, Props and Terrain with GL.

I already have a SpriteRenderer protocol. This was originally meant to support several implementations and hardly specifies anything, so I can likely create a new implementation for actor rendering; tile and prop rendering was too simple to deserve separate classes.

Pixels to World Coordinates

Previously, my sprite coordinates where defined in pixels. I have no reason to change that (and mess my 2D picking code – I still need it for now).

When rendering the first sprite, I just by-passed applying a translation.
I then use glPushMatrix, glPopMatrix to apply and remove the translation. First I directly use pixel coordinates (expecting to see that go out of the screen) – I do get a gray screen again (no sprite), but also get an interesting error in the console:

GLES2Sample[3130] <Error>: CGContextSaveGState: invalid context

Nothing happens when tracing GL calls. Aha! This is because I left 2D rendering code (calls to drawImage) as I’ve setup only one sprite. Since I’ve managed to run this a few times (without the transformation) and could render the model, this is something that can be ignored. Nice.

I learned a few things while trying to get this right; to setup my isometric view, I use:

glOrthof(-width/2, width/2,-height/2,height/2, -depth/2, depth/2);

Where:
- width is the height of the window/view we are rendering to.
- height is the height of the window/view we are rendering to.
- depth represents the bounds of the field of view. for now I use a parameter ‘like the width or height’

So what glOrthof  does is fit a box taken from the 3D world into the target UIView.

I got a few gray screens while fiddling with that. Common causes:

  • translating the target too much
  • using too small a value for the depth parameter
  • making the width/height too large (apparently if the model is too small, no pixel is rendered.

My test model is just a unit box. When the width and height match about 1 world unit for 1 pixel, this box is hardly visible. I think using 1 meter = 1 world unit is kind of nice (considering how it feels on the Blender grid), so I apply a scaling parameter for world unit to pixel conversion. For now I’d say 1 meter is about 32 pixels (my sprite for the player was 32×64 pixels).

Finally, here’s the code for my view/camera setup…

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float width=320;
float height=460;
float depth=460;
glOrthof(-width/2, width/2,-height/2,height/2, -depth/2, depth/2);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(60,1,0,0);

…and the code for my model transformation. Note that all this stuff is ‘nearly correct, not quite correct’ because the isometric view now tracks X coordinates correctly, whereas we have a 2:1 ratio on Y coordinates and I’ll need to correct that later.

glPushMatrix();
float tx=actor.location.x-originX; // (see note for 'origin')
float ty=actor.location.y-originY;
NSLog(@"translate to: x=%f,y=%f",tx,ty);
glTranslatef(tx,0,ty);
glScalef(32, 32, 32);
// draw the model...
glPopMatrix();

The ‘origin’ is the position of the player avatar because I like to keep it at the middle of the screen. Either way the isometric view needs to have a kind of ‘camera location’ so there would be an origin – but then that should be composed once and for all as part of view transform setup.

Uhoh. That took quite a while to get through – next time I’ll do the board and props and it should be a little easier.

OpenGL is the IT industry standard for drawing triangles, lines and points, and a lot more all the way down to the best realtime 3D games around.

OpenGL-ES1 is ‘OpenGL light’ suitable for mobile platforms such as the iPhone.

ES2 is the high end version of OpenGL-ES. Available on iPhone 3GS and maybe other platforms. ES2 has shaders, ES1 doesn’t.

Do I need to know OpenGL/ES to make (mobile) 3D games?

Not really, I don’t think so. You can learn a game engine instead, such as Unity, SIO2, Panda3D, Irrlich, Ogre.

So why would I learn OpenGL/ES?

OpenGL has been around for more than 15 years. If you want to become a 3D graphics programmer, it’s probably a good idea to learn both OpenGL and a game engine.

OpenGL is low level. Compared to using a game engine, knowing how to use the GL lets you be creative in different ways.

OpenGL is a little weird, but a lot of it is actually simple. Drawing shapes is a low level, yet simple concept. If you like ‘drawing and programming in 3D’, then OpenGL could be a better choice than a high level game engine that encourages/constrains you to just get your models from a 3D artist and fire animation commands.

OpenGL is the only API that maps directly to modern graphics hardware. Some people use the GL to do weird stuff that’s not really related to graphics, just because GPUs are fast and full of maths.

I’ve been hesitating a lot between re-learning the GL and learning a game engine. I’ll probably do both in the end but for now, because I don’t need serious physics, probably can’t afford having a lot of textures and I quite like drawing, I thought OpenGL may be a reasonable choice. Also, I’m currently creating a very high level scripting API to a 3D platform, so I like to look at things from the other end in my spare time.

Today, I ‘rescued’ my game project  by migrating all my sources to a sample project file. My original problem clearly came from the source project settings. Since this is my first serious project, I possibly messed with my project settings at some point, and as a result a couple of files refused to get into the main bundle.

A great thing about CocoaTouch development is that XCode provides pre-configured projects which (in the closed world of iSomething development) just work out of the box so we don’t need to learn about the many many gritty details. Unfortunately this can lead to panic when a configuration/build level problem occurs.

For this time, I used a solution that won’t get me an award, but saved my digging further into a nasty problem for which no documentation or online help seems to be available – in short, I duplicated a sample project (containing the code I couldn’t integrate with my old project) and moved all my project files (~130) over. Something you might want to try if you’re having odd build/project configuration issues.

Here’s the steps I followed:

  1. Duplicated a sample project.
  2. Put aside all project source files in a separate group (some stuff can’t be put aside because it can’t be moved, e.g smart groups, targets, frameworks…)
  3. Moved all groups (what looks like folders in XCode, but isn’t) from my old projects to the new project. I did that by dragging and dropping from the source project to the target project, checking the ‘copy as needed’ box at the top. I moved my groups into a new group to keep things tidy.
  4. Step (3) will normally fail with conflicting files. The simplest approach in this case  is probably to replace the conflicting files (in my case, MainWindow.xib and main.m)
  5. Deleted (or at least put aside) unused nib files from the sample project.
  6. Added the frameworks missing from the new project.
  7. Run a build to make sure everything builds OK.
  8. Run the app to make sure I’m running my app versus the sample.

At this point, the template project settings pointed at my application (because the real entry point is the main nib file, and that is a file I replaced).

Note that it may not be a good idea to try replicating the target/creating a new target, especially if you haven’t done that before. In my case, I just use the existing target. For now there’s a few names that don’t match my old project, but these names are cosmetic – no logical dependencies – so it’s OK.

A couple of caveats:

  • I ran my first test build before moving conflicting files over -  this worked because the files that conflict tend to be top level in the dependencies hierarchy. But after overriding the conflicting files, XCode  didn’t detect the change and kept reusing old images from the previous build. I deleted the build folder attached to the project and ran a fresh build.
  • Quite a few warnings appeared. Because of dynamic binding, sometimes XCode can’t detect what’s right or not. These warnings have a way to disappear when running the next builds, but then recur after moving files over to a new project. It’s better to avoid getting any warnings at all if possible. In this particular case, I just went through the list to make sure nothing evil leaked into the project while migrating files.

OK, no glory here, but if like me you got into iSomething dev. by chance, just want to be productive and don’t want to learn all the details of the build process and project config, this might help.

In this article, I’m looking at two distinct things:

  • Basic use of AVAudioPlayer, a CocoaTouch class that gives reasonably good sound support for many applications. If you’re deep into waves, search OpenAL instead.
  • How to use the F* meta-pattern to integrate audio as a ‘pluggable’ feature, with minimum interaction with existing code.

As a side effect (this is integral to the spirit of the F* pattern), you might be able to integrate sample code from this article in your application very easily. If you’re not into the theory, please skip to the code and have fun.

A few days ago, I have decided to try applying the F* meta-pattern with my game integration. A first step towards this was i/o integration, for which I provided:

  • A dispatcher for in-game milestone events
  • A protocol used to identify consumers of milestone events.
  • Classes packaged separately that take care of i/o.

Practice makes better. I’m starting to understand how I can apply F* to developing my game, and audio integration is the next step.

Here, I want to associate a sound with specified actor activities. For now I’ll keep it simple, just start a sound when the actor begins an activity.

In my little game framework, the actor’s activity is updated at every frame. Activity changes only occur when the new activity is different from the previous activity. So what I’ll do is define an observer pattern allowing me to detect activity changes without creating type dependencies with the Actor class. I’ll then register an instance of a ‘sound feature class’ with the event dispatcher.

Observer Pattern

I have moved my dispatchers and listeners to a separate package. I then create a new group including the following:

  • ActivityChangeDispatcher provides static methods used to notify listeners to activity change events.
  • ActivityChangeListener specifies… activity change listener functions.

Here is the code for ActivityChangeListener (act is just a typedef in Definitions.h):

#import "Definitions.h"
@class Actor;
@protocol ActivityChangeListener
-(void)actor:(Actor*)a activityChangedFrom:(act)a0 to:(act)a1;
@end

Then the header file for ActivityChangeDispatcher

#import "Definitions.h"
#import "ActivityChangeListener.h"
#import "EventDispatcherMacros.h"
@class Actor;
@interface ActivityChangeDispatcher : NSObject
DEC_LISTENERS(ActivityChangeListener)
+(void)actor:(Actor*)a activityChangedFrom:(act)a0 to:(act)a1;
@end

Finally the implementation of ActivityChangeDispatcher.

#import "ActivityChangeDispatcher.h"
@implementation ActivityChangeDispatcher
DEF_LISTENERS(ActivityChangeListener)
+(void)actor:(Actor*)a activityChangedFrom:(act)a0 to:(act)a1{
	for (id l in listeners) {
		[l actor:a activityChangedFrom:a0 to:a1];
	}
}
@end

DEC_LISTENER() and DEF_LISTENER() are declared as follows in EventDispatcherMacros.h:

#define DEF_LISTENERS(interface)								\
static NSMutableArray* listeners;								\
+(void)addListener:(id)l{							\
	if (listeners==nil)listeners=[[NSMutableArray alloc]init];		\
		[listeners addObject:l];					\
}														\
+(void)removeListener:(id)l{							\
	if (listeners==nil)return;						\
	[listeners removeObject:l];						\
}																

#define DEC_LISTENERS(interface)						\
+(void)addListener:(id)l;							\
+(void)removeListener:(id)l;

I was kind of hoping I might be able to define a catch-all macro avoiding writing code for new observer pattern classes altogether. This isn’t quite like it although some of the boiler plate has been removed. But then I can probably do better. Next time i’ll try to make this more concise as I do not want to define more than one event per dispatcher.

Once this is done, I need to activate the dispatch by pasting this code wherever activity changes:

[ActivityChangeDispatcher actor:a activityChangedFrom:x to:y];

The Sound Feature

My sound feature will be PlaySoundOnActivityChange.

Here’s the header

#import "ActivityChangeListener.h"
#import "Definitions.h"

@interface PlaySoundOnActivityChange : NSObject  {
	NSMutableDictionary* map;
	NSMutableDictionary* players;
}
-(void)map:(tag)label to:(tag)soundFile;
@end

Now here’s the implementation:

#import "PlaySoundOnActivityChange.h"
#import <AVFoundation/AVFoundation.h>
#import "ActivityChangeDispatcher.h"

@interface PlaySoundOnActivityChange (private)
-(AVAudioPlayer*)prepareSound:(tag)name;
@end

@implementation PlaySoundOnActivityChange
-(id)init{
	if (self=[super init]) {
		map=[[NSMutableDictionary alloc]init];
		players=[[NSMutableDictionary alloc]init];
		[ActivityChangeDispatcher addListener:self];
	}return self;
}
-(void)actor:(Actor *)a activityChangedFrom:(act)a0 to:(act)a1{
	NSString* code=[NSString stringWithFormat:@"%i",a1];
	tag name=[map objectForKey:code];
	if (name==nil)return;
	AVAudioPlayer* player=[players objectForKey:name];
	if (player==nil)player=[self prepareSound:name];
	if (player==nil)return;
	[player play];
}

-(void)map:(tag)label to:(tag)soundFile{
	[map setObject:soundFile forKey:label];
}
// private ---------------------------------------------------------
-(AVAudioPlayer*)prepareSound:(tag)name{
	NSBundle	*mainBundle = [NSBundle mainBundle];
	NSError		*error;
	NSURL		*url = [NSURL fileURLWithPath:
[mainBundle pathForResource:name ofType:@"caf"]];
	//
	AVAudioPlayer* player = [[AVAudioPlayer alloc]
initWithContentsOfURL:url error:&error];
	if (!player) {
		NSLog(@"no player: %@", [error localizedDescription]);
		return nil;
	}
	[player prepareToPlay];
	[players setObject:player forKey:name];
	return player;
}
@end

I haven’t tested this yet (OK, it compiles… – PS: after testing, it actually works). Also, I’m a little bit worried about what will happen if I have a 100 or a 1000 sounds registered in my map – I don’t really know what resources players are holding to, especially once [prepareToPlay] has been invoked. Pending, note the way a feature is designed and implemented using F*, and also a couple of errors:

  • I have provided an event dispatcher allowing me to trigger sounds at the right moment. The generated events provide me with all the information I need to select sound.
  • Actor does not import PlaySoundOnActivityChange – I can remove the sound feature without breaking my code (so far).
  • PlaySoundOnActivityChange and ActivityChangeListener/Dispatcher import the actor class. This could, and should, be easily avoided (so that I can use the same sound feature for non actor sounds, or in an altogether different context.

I need to import sounds into my project and map them. Probably this would be done better with a property list defined as a resource but for now, I just want to map a couple of values and check the result. So I define a feature setup class with a couple of mappings. Invoke the setup class directly from my GameSetup class. Here’s the code for InitSound:

#import "InitSound.h"
#import "PlaySoundOnActivityChange.h"
#import "Definitions.h"
#import "VRConstants.h"

@implementation InitSound
+(void)apply{
	NSString* label1=[NSString stringWithFormat:@"%i",WALK];
	NSString* label2=[NSString stringWithFormat:@"%i",STAB];
	PlaySoundOnActivityChange* feature=[[PlaySoundOnActivityChange alloc]init];
	[feature map:label1 to:@"tick"];  // just reused the sounds
	[feature map:label2 to:@"tock"]; // from Metronome example for a try.
}
@end

Done with sound.

haXe is a high level object idiom that:

  • Compiles to C++, AS3, AS2 and Neko (‘Haxe native’)
  • Exports to javascript and PHP
  • Compiles and exports to… other stuff.

Have a look at their site! I’m just getting started here.

Setting up

Creating and running a project

  • In FD3 Go to [Project > new], scroll down and select any HaXe target. I chose javascript. and typed trace(hi); and Lib.alert(“Hi”); in Main.hx’s main function (default project template).
  • Press the play button in FD3 and, well, check what happens…

Getting up to Speed

The Haxe website has got docs for all compile/export targets. There is also a very active blog dedicated to Haxe gaming (Going all the way to teaching you how to haXe your iPhone!)

I have simple mappings between actions and animations and I will probably duplicate this for sound (sure, not all actions may have a sound, but the general idea is there).

A maybe useful resource explaining how to play sounds the easy way: This link from iCodeBlog – unfortunately the ‘system sounds’ approach doesn’t allow playing more than one sound simultaneously or even tuning volume(!)

AVAudioPlayer :)

AVAudioPlayer (apple docs link). Not hard to use; documented; allows simultaneous sound playback, volume control and other features. Link to the iPhone Programming Guide AVAudioPlayer introduction.

OK, I’ve been looking for an example that simply demonstrates how to use this. Check the Metronome example from iPhone dev connection (do Find > Find in Project with ‘AVAudioPlayer’). An immediate concern – how to convert a file path to a URL:

NSURL *soundURL = [NSURL fileURLWithPath:[mainBundle pathForResource:@"sound" ofType:@"caf"]];

Getting files from the main bundle is exactly what I want in this case because files imported into XCode projects end up inside the so called main bundle.

Expected issues:

  • Converting files to .caf. – sure apple does provide a converter, but that’ll take a bit of time to look into. Leave for later as other formats are supported and using them might just be OK.
  • Memory issues – initializing AVAudioPlayer with a URL doesn’t really tell me how sound gets loaded / unloaded.
  • Performance issues – again, initializing from a URL could mean that I experience delays playing back sound.

Now the next part is putting the code together and integrating with my proto-framework.

Open AL?

Later, I might want to upgrade to OpenAL, but like realtime 3D, this maybe more appropriate for a second game. After all, I want to cover basic ground (fun, gameplay, story…) before I worry about even moderately complex technology. I had a quick look at the OpenAL programming guide and the apple example, It would probably take a good week for an experienced programmer to get to grips with this thing (although a good tutorial would probably help). No time for doing this now (admittingly, I’m not thrilled by the prospect either).

At this stage, my Script class includes about 35 statement forms. A lot of this is a little redundant. The aim was to cover many significant cases related to decision, action and interaction.

A test suite

Today I am writing a test suite for the Script class and the underlying APIs. This is necessary because testing production graphs is, as we’ve seen before, expensive.

I won’t get into unit testing using XCode/Cocoa. Instead, I’ll just write my own tests from scratch – this is because I need to invest a little time and effort into making scripts easier to test.

This will be a fairly large test suite (for me, because i’m not terribly fond of testing), however, all cases are very simple and I can take advantage of some design features for the behavior API.

  1. Given model/view separation, I need only setup the model, not the view.
  2. There is no need to setup timers to test behavior, we can just iterate the action graph as far as we need and check the data model to test the output.

Writing the tests

Macros came in really handy to keep the tests concise, but also to avoid having to create ad-hoc data structures. Each test is about 10 lines long and I have 34 tests. Here’s a sample:

// this defines a function and stores the test name
TEST(test_observe_actor,"test observe actor")

// setup a stage and actors, with B 100 units away from A
SETUP_A_B(100);

// the actual script to test
[s type:ACTOR_A];
   [s observe:ACTOR_B];
[s xType];

// bind the script to the stage and iterate the system once.
BIND; STEP(1);

// some code to check the output
Vector* u=[[Vector alloc]initWithX:1 y:0 z:0];
Vector* v=a.orientation;

// this checks the specified condition and prints the result
CHECK([Vector angle:u with:v]<0.01);

// just a macro defining a closing bracket, because a dangling
// bracket would be odd.
END_TEST

Granted this is not a very clean use of macros, and won’t scale up to a really large test suite – but we’re not into ‘test-first’ development here – just running a few tests.

I hacked a function firing up the tests into the main.m file associated with my XCode project. Another time I’ll look into a nicer way of doing all that stuff. (need to move the framework to a library project and create a separate project for the test suite).

Pending, sample output looks like this:

2009-11-16 22:14:55.837 Generic2DBoardGame[5191:207] X test observe actor

(X tells us that the test failed :( )

Debugging

Unsurprisingly (given the way I drafted my code), a lot of tests are failing. I even had to quarantine 6 tests that seem to get into infinite loops. Since I have many tests, this is a good time to add logging. The first logs I want to produce are snapshots of the system showing the state of each entity. I will only display logs for failed tests.

After debugging a couple of test cases, I find that primarily, diagnosis falls into three broad categories:

  • An event isn’t generated. Because events often occur given conditions related to an actor, I print the condition leading to such actor being rejected by TargetSelector
  • An action isn’t being applied. I don’t expect to see this too often.
  • An action isn’t effective.

These broad categories allow me to channel log output and enable/disable channels to conclude the diagnosis.

That’s about it. I’ve got 11 pass cases so I’m about 1/3 in and should be done tomorrow.

In my previous article I’ve suggested a few scripting statements that could be used to specify interactions between actors and the board. In this post I am investigating a solution to bind these statements to the action graph in my underlying API.

Implementing interactions

If you followed the previous articles, you already know how ‘pseudo-scripted’ statements get into the action graph. First an object tree representing the script is created. I have added the following classes to support this:

  • InteractionDef – Defines an interaction as associating an EventDef with several responses.
  • EventDef – Base class for interaction events
    • ActorEventDef – Occurs when an occur performs a specified action.
    • EnvironmentEventDef – Occurs when an actor occupies/enters a given tile
    • CollisionEventDef – Occurs when an actor collides with an actor or prop.
  • ActorResponseDef – A passive reaction (typically rendered as an actor animation)
  • CapacityModifierDef – Used to capture disabling/enabling a capacity
  • RoleModifierDef – Used to capture disabling/enabling a role
  • PropertyModifierDef – Used to capture an increase/decrease to a property

The class hierarchy  could be a little more structured. Also, it seems that we may easily compress the same hierarchy later by considering similar node types. However, this is enough to render the current set of scripting statements provided by the Script class.

The next step is to feed those into the Interpreter class that will actually setup the action graph. I decided to provide ad-hoc classes to render interactions to the action graph. Compared to the design I earlier produced to model actor decisions, classes for interaction are more specialized – many of these nodes just can’t be put anywhere in the graph. This is more a change in the design than something that is specific to the problem being solved, so I guess I would take an opportunity to clean the overall design of the action graph API a little later on – it seems that using more particular types helps keep the action graph small and simplifies some of the design while offering straightforward optimization hooks. On the other hand, large, structured nodes offer less opportunities for reuse.

The class hiearchy for this looks like this:

  • AffectMap – a list of affect bindings, i.e. event/response pairs (subclass of Action)
  • AffectBinding – a list of event/response pairs
  • AffectCondition – specialized subclasses implement interaction events
  • Affect – specialized subclasses realize actor responses.

All reflex maps (see previous articles) should be processed before affect maps. Notwithstanding, it’s OK to use several reflex maps, either for each actor or for the same actor.

Unlike with ReflexMap, I decided to hold an Actor instance directly in the map and pass it to binding, condition and affect method calls, this prevents these ‘support classes’ from implementing Action, but saves memory (no need to store Actor pointers in each node) and  seems, overall, a better choice.

With this, my original draft for a behavior programming API and pseudo scripting interface is complete. Next time I’ll write a small test suite for this and hopefully I’ll then find time to discuss the overall design.

If you are a solo developer, it may be a good idea to consider learning one of the sprouting game engines for iPhone/iTouch.
Well – if you’re dedicating your time to writing a game engine, are your kids gonna do the graphics, your uncle produce the soundtrack and G’ma Doom take care of level design?

Frankly, if your game is neither an action game nor a 3D game, you’re probably better off just using UIKit and core animation. For the rest of us, rumor has it that core animation is slow enough that it should be avoided. Then you’re left with either using a game engine or writing ‘a fair bit of OpenGL-ES code’ – even for a 2D shooter.
I am not suggesting you shouldn’t learn OpenGL-ES. OpenGL is kinda cool, and about the only piece of gaming technology that survived the browser wars… pending, here’s a few game engines that deserve attention.

Cocos2D for iPhone is a port of the Cocos2D game engine. It seems reasonably documented and a lot of sample code is available.
Do I need to stress that Cocos2D is a 2D game engine. I’m testing this one at the moment, my main question being whether it supports isometric 3D.
Cocos2D for iPhone has a lot to offer:

  • Fairly well documented; sample source available.
  • OpenGL accelerated graphics and special effects
  • Tiled compatible – you need a board editor, right?
  • Integrated game physics
  • Free

SIO2 is a 3D game engine. It looks fairly comprehensive and there’s a free version (you need to display a splash screen when putting your game up on the app store). I feel curious because SIO2 seems to integrate tightly with Blender, and I lovc blender.

If you mean business or wish to invest into something the industry will ‘respect on your CV’, Unity (3D) may be the deal for you. This engine lets you deploy on the iPhone, Wii, Windows/MacOS and even embed your stuff in a web browser. It’s kinda free but not for iPhone or web deployment.

This list is definitely not meant to be exhaustive (google more…) but I feel you’ll come back to it later on.

The apple dev center feels like a foggy, non linear nebula of documents – not really convenient either to get a comprehensive overview of how stuff works, or to come back to something I viewed before.
Here’s a few pointers to the most useful resources I found - Hope this helps you too.
If you’re completely new to the game, you’ll need to setup for iPhone development. Read my article for getting Started in 24 hours or less.

Application Programming - covers generalities, UI and event handling, graphics and IO.

  • View Controller Programming Guide – explains how to use view controllers in the CocoaTouch MVC paradigm. Explains how to manage tabbed panes and navigation bars to create multi-page displays of information.
  • Core data frameworks and device services -  somehow,
    Getting started with data Management provides links to various data frameworks, as well as how to handle touch events, geo-location, the accelerometer and device orientation.
  • Coding How-Tos - Covers much useful stuff with a hands on approach, unfortunately, sample code isn’t always provided.

Networking - Getting Started With Networking & Internet links various
(low level/compatible/object etc…) APIs for networking.

  • Networking for Peer to Peer Gaming - The GameKit programming guide introduces P2P networking over bluetooth and voice chat.

Application Management

The following pointers relate to the process involved in getting your application to be distributed on the app store.

Non-Apple resources

There is definitely a few blogs and other websites out there definitely worth reading:

Disclaimer

NONE of the above links is pointing at content created by the author of this blog. The content pointed at belongs to it’s respective owners. This article is not endorsed by Apple or iCodeBlog or whomever else.