Despite the good advice on just using a library or someone else’s solution to getting game center working, sometimes I’m just stubborn. Well it wasn’t actually completely stubbornness as it was more of a “don’t have an alternative” situation. Tilt to Live uses AGON for it’s leaderboards and awards system. It has served us well and never faltered. Despite that, Game Center has arrived to rain on it’s parade so-to-speak. To give TTL hopefully more life in the long run I decided to implement Game Center alongside AGON over the past week. It was trying, painful, and sometimes down right frustrating. Trying to get 2 closed and incompatible systems working is wrought with trial and error and lots of hackery :).

Below are just some things you may find useful if you’re considering game center in an update

1. Game Center is not a full solution

Namely, there is no offline support to speak of. Another biggie that I grossly underestimated is a lot of the ‘fault tolerance’ is on the game developer to implement. Scores don’t make it to the servers? Save them for the next time. Awards not work online? Save them. User has no internet connection? Save them. User is age restricted from using Game center? Save it again.

Are you on a 3G with 3.x iOS? Don’t use game center. Are you on a 3GS with 4.0? Don’t enable game center. Are you on a 3G with 4.1? Despite GC not having an API to detect THIS case, you need to disable it because GC doesn’t work with it.

This is where services like OpenFeint and AGON shine. They offer seamless offline support with minimal hassle. I actually ended up leveraging AGON’s offline support to help deal with the score submission failures for Game Center. This saved a lot of time, and in OpenFeint from what I hear it’s even easier. In conclusion, If you don’t have any award or leaderboard solution implemented already it may be a good idea to use one with offline support first before concerning yourself with game center.

2. Be mindful of when you send scores and awards

If you have a fast paced game, you may want to store any scores or new award unlocks until the main gameplay is done, THEN send it off to Game Center. It creates a noticeable pause mid-game. Other social gaming platforms deal with this in different ways, but I remember early on seeing some OF games do a “mass” unlock at the end game sessions and such. Nowadays I believe it’s well known to just commit the changes in 1 transaction during some low key point in the game.

3. Keep your descriptions short

This is a sad one for us, because Tilt to Live thrives on witty descriptions and jokes for it’s awards. We’ve opted to keep them the same in-game (using AGON) but we’re modifying the GC ones so that other users can see the descriptions in full in the GC app.

4. Be sure to login from your app

While the Apple documentation stated there was some way to log into the sandbox through the GC app with a test account, my mileage varied. So the sure-fire way for me to do it was to log out from the GC app, then log in from within our game. Not seeing your awards or scores? Make sure you’re logged in from your game.

5. Wait a bit after modifying your leaderboards/awards

Apparently there is some time before your GC app updates with the latest awards and stuff. I’m not exactly sure how this works or if there is some cache that has to be updated to pull the latest info down. Either way, if you’re not seeing any changes you are not going crazy.

6. Multi-tasking support can be hell

It was hell for me for several days because of one tiny issue: The simulator does not post GKPlayerAuthenticationDidChangeNotificationName messages. Not realizing this I was going mad wondering if I had my implementation wrong or whether there was a bug in GameKit itself. After discovering this was limited only to the simulator I soon found sanity in my testing of multi-tasking support. Having users change names, log in and out, all while your app is running can be daunting so approach this case with care. It seems Fruit Ninja dodged a bullet here by not fully supporting multi-tasking :P.

We sent off Tilt to Live HD to Apple for review today. I couldn’t send it off until around 3 PM today because my internet was down (since 6 AM) due to a less then stellar ISP here in Alabama. *sigh*. But that won’t get me down, I’m super excited that TTL HD will be on the ipad app store in a few short weeks! Right now I’m busy trying to cut and edit footage together for a launch trailer. We’re trying something new with this version of the game by creating a seamless ‘upgrade’ experience from a ‘lite’ version of the app to a full version, very similar to what you see on PC casual portals or XBLA. You can even upgrade mid-game and have the unlocks start showing up in the very same game session!

Invalid Product IDs

With the launch news aside, I had a pretty straight forward experience getting the IAP functioning in the game. There are some small caveats and nuances to avoid getting the dreaded “Invalid Product IDs” error while retrieving product info from Apple’s server, and that part was very frustrating. After quadruple checking everything I could find that would cause this error, it finally dawned on me that I had never deleted the app completely from my iPad since:

  • switching app IDs, provisioning profiles, and the like
  • Implementing the IAP system

I did a full delete then re-install and everything started working! Although I’m not fully convinced that this cleared up the issue, but hey, if someone else runs into this problem maybe it’ll help them :).

Hide-n-Seek with the IAP Screen

There was another issue that didn’t seem to be well documented that I stumbled across. In certain situations when the player was on this screen…

…it would hide and unhide in an annoying endless loop. It was a funny game of hide ‘n seek with the UI and the player at first, but not funny when it turns into a lost sale :[. The problem? Memory consumption issues.

I hadn’t gone through and optimized any textures or other data yet to reduce the memory consumption. It was through dumb luck that the console was on my second monitor and I noticed the timing between the UI hiding and the console scrolling with a “mem warning level 1” message out of the corner of my eye. So it appears when your app gets a memory warning as the IAP UIKit screen comes up, in an attempt to possibly not crash and burn the IAP screen unloads itself? How heavy is that UI exactly? Either way, a reboot of the iPad made the issue go away temporarily. Then once I dealt with the memory issues themselves it went away permanently.

A friend of mine sent me this list of anti-patterns common in software engineering. Being the lone developer on my team, I don’t get to see anyone else’s code except mine on a project. As a result, it’s hard to critique whether my code is “good” or not. That was one of the benefits of working at a company I suppose. Being surrounded by those with more experience than me, I would learn a lot just from an afternoon of working on a section of code that wasn’t mine. Now I tend to have to seek out code that isn’t mine to get a sense of how things are done “well” or what not to do.

It was interesting reading that wikipedia link and seeing which anti-patterns I’m currently exhibiting. A lot of this came about as I was writing up a small framework in c++ for iphone prototypes and looking at old code to recall how things were done and whether I should be using a different approach all together.

Vendor lock-in: Making a system excessively dependent on an externally supplied component

This was an unfortunate side-effect of learning objective-c and then going on to write Tilt to Live in objective-c. We’ve been really wanting to expand to other platforms, but with all the code written in objective-c it’s really hard to muster the motivation to rewrite all of it again, especially when solutions that allow you to easily port c/c++ code exist.

Magic pushbutton: Coding implementation logic directly within interface code, without using abstraction.

Another one I’m guilty of, but not entirely sure this is a bad thing in the context of real-time apps. After reading up on mollyrocket’s take on an immediate mode GUI, I’m rather liking the system I have now. It’s not purely immediate mode, but the system I have lets me do some dynamic stuff with the UI that would be a bit harder to do with an ‘abstracted’ UI system.

God object: Concentrating too many functions in a single part of the design (class)

My main “game screen” class exhibits this symptom. It came about from evolving my prototype to final production code, which isn’t a good thing most of the time. Looking at the class I can see a lot of classes I can break out to make my life easier, but I’ve just let it sit for the most part. During updates for Tilt to Live I did refactor it a lot so that supporting new gametypes wouldn’t be like gouging my eyes out with a wooden spoon.

Action at a distance: Unexpected interaction between widely separated parts of a system

This one’s a good one because due to “magic push button” and “god object”, fixing bugs tends to create a sorts of anomalies that fall into this category.

Caching failure: Forgetting to reset an error flag when an error has been corrected

I’ve run into this numerous times and it has been the source of many bugs in Tilt to Live. I used object pooling heavily and as a result, when introducing new object types into the mix or new instance variables, forgetting to add them to the reset() method would invariably cause some hiccup in animations, sounds, or even collision.

Lately, I’ve taken time out to start porting some of the framework code I’ve created over the course of Tilt to Live to c++. Having worked pretty much exclusively in objective-c for the past year, I’ve realized how rusty my c++ has become. The main purpose of the rework is so I can have a base for starting new prototypes, as I’m usually stuck with starting from scratch each time. Another benefit is being more “portable”. While developing for android would still require some considerable leg work, the option of going PC, palm, console, or some other device I think is worth it in the long run.

After reading Noel’s post on prototyping I realized I was drifting away from that mind set and getting into dangerous territory of just “thinking up a game and running with it.” Tilt to Live itself spawned into a full game from being discovered in a rough prototype. Since then we’ve just had rough documents and ideas that we wished to pursue after TTL. The past few weeks we’ve been gearing up more heavily for our next game and I’ve been getting back into the habit of whipping out fast prototypes.  I finished one prototype for an arcade/action shooter and another one over the past weekend for  a turn-based strategy game. My methods for prototyping each were very different. Ultimately, as I experiment with different tech and methods I’m trying to optimize the time from “concept” to “on the screen and working” so that we can fail quickly or move forward with the idea.

Action Shooter

With this one I had a series of prototypes I wanted to explore before we would deem it ‘good enough’. The first one was trying to see if our tilt mechanic would work. We had an idea that was a slight evolution of Tilt to Live’s controls but allowed for shooting while still avoiding annoying ‘floating D-Pads’ issue. It took about 15 minutes to do the mechanic prototype. After getting it implemented and in the hands of some friends, they actually liked the feel of the controls, which made us pretty excited about it. My next question was whether a scrolling view worked with a tilt mechanic. It made perfect sense to me in my head, but for some reason I felt that not being able to view the whole field while tilting to move (somewhat losing that 1-to-1 feel) would ruin the experience. 40 minutes later I had a camera system and some basic map trinkets scrolling by and it still felt good.

The next several hours became more of an educational exercise by implementing bluetooth multiplayer in it, and admittedly it was wasted hours in the prototype sense but very useful in a general sense. So I did go off track here a bit, but corrected myself soon after indulging in that little fun :). The tech used was the iPhone itself and objective-c as it’s hard to test very device-specific controls on anything other than the device. The next prototype in this series would be player/enemy interactions and seeing if simple enemies would suffice or would we need varied, sophisticated enemy behaviors to make it compelling (a difficult road to go down, as disposable content is not something I’m a fan of), so this’ll be a rather telling iteration.

Turn-Based Game

This was an interesting prototype to make. The game consists of a hexagonal grid where two players have bases, spawn points, and a set of different character classes. The game’s core idea was to make a very simple-to-play turn-based game but introduce interesting twists to the character classes that didn’t require some extra knowledge or rigorous ‘book keeping’ of different types of stats for each pawn to use effectively. So while the action of ‘moving’ a pawn was simple, the outcome would be varied and hopefully pose interesting choices to the players that are playing.

About Friday mid-afternoon I decided I wanted to see this turn-based game idea Adam had in an more automated form so we could give it more play time and start getting feedback from more people. The first prototype of this game was done by Adam in Adobe Illustrator. He did it in Illustrator because he was most comfortable with manipulating graphics in that program, and also (being the artist he is) had some pretty mock ups to play on top of. It was a series of duplicating object-groups to move objects, editing text boxes to adjust hit point values, deleting and adding layers and all sorts of madness. It was slow, tedious, but the game was still pretty compelling. It also goes to show that you can prototype a game with just about anything.

Having only about 3-4 hours before leaving to the beach for the weekend I had to decide what was the quickest way for me to get a more complete version of this game’s rules running on a screen. Ideally I wanted an iPad prototype, but I had almost zero framework to work with (barring using something like cocos2D) and the tediousness of C++/Objective-C slows things down. I opted for writing a prototype in Blitzmax. I ran the simple Blitzmax IDE on my mac (Blitzmax works on mac/pc/linux) and started coding away. No header files, no include dependencies, lots of high level modules to load graphics, draw graphics, draw text, load text, load data, handle mouse/key events. I feel I eliminated like about an hour of working on ‘boilerplate’ code to get a prototype up and running on a laptop.

Not having done a hexagonal-grid based game before, it was time to hit the books and just quickly skim over the basics of how to manipulate objects in that space. This was more of the ‘technical education’ part of the prototype. And this is usually the part that takes the most time in any of my prototypes. Transforming between hex and mouse coordinates, moving and calculating distances took up the rest of the time to develop.

Oh no, so I had no prototype before the weekend! Luckily, trusty Adam was driving so I spent about 1.5 hours just putting together a state-machine type framework trying to get the ruleset and player interaction working. This is one of those dangerous situations as well, as Noel and others mention, that many can get caught up in the “technical beauty” and try to create an all encompassing FSM framework of some sort. Putting a 3 hour constraint on this really helped mitigate that urge.

Then the battery died. Oh well, instead of spending some untold number of hours cooped up in a condo instead of enjoying the weekend with friends at the beach I limited myself to 30 minutes a night right before going to bed to work on it. The awesome part was knowing how little time I had to work on it allowed me to make coding decisions much more quickly. Of course the downside is the amount of ‘shortcuts’ I took code-wise to get the prototype up and running. But the thing for me to remember is it’s a prototype, not  final code. Further practice and experience will yield better code and solutions for quicker turn-arounds in prototypes. I finished that prototype after 2 30-minute sessions, and 2 players can play it on a laptop on mac or windows.

Not having it on an ipad kind of sucked as it does have a certain novel feel to it, but that “feeling” is probably more like sugar on top than having a solid design that works on any screen.

Faster, Faster, Faster!

Indeed, getting something up and running and being able to play with it holds more answers than any time spent thinking about it in your head. Things like the Experimental Gameplay project really shows what volume of ideas can be realized with very focused, short efforts. I had been doing these prototypes all the while working on finishing up TTL HD. With this newly rediscovered “do it as quickly as possible” mentality I may be able to incorporate a weekly prototype into my schedule to break up the week of working (happily, mind you) on whatever our current long term project is. Strangely, both prototypes show promise, but it may come down to how “well” we can make whatever fun prototype we choose in a short development period since we are aiming to release at least 1 more title in 2010.

I recently made a post on our official OML blog about what Adam and I are playing. Taking a look at that list you’ll find that the vast majority of games I play are multiplayer oriented. A lot of biases, inspirations, and design decisions that go into my game designs are influenced by multiplayer games.

When we set out to start One Man Left, my long term goal for the company (beyond making fun games we like to play) was to be known for making fun multiplayer indie games for whatever platform we develop for. Our first game wasn’t a real-time multiplayer game, but you gotta start somewhere, right? Admittedly, I don’t seek out purely multiplayer games on the iPhone often. Searches for “multiplayer” tend to not turn up very compelling options, and it worries me. The few games that are strictly multiplayer tend to have different reactions based on how the match making works and how ‘easy’ it is to play alone. For instance, one game was bluetooth/wifi only and had no AI opponent. It had extremely low ratings and the vast majority of them were “please add a computer opponent”. Just reading this you would think that a lot of iPhone users are isolated cases where their friends don’t have an iThing. This could very well be the case, although in my personal experience it isn’t. It may also have been a case of the app description not being detailed enough.

I’ve been prototyping some co-op multiplayer game ideas over bluetooth recently and we’re really excited about the possibilities. I feel multiplayer is an awesome tool in the game designer’s toolbox. It overcomes many challenges more traditional single player games are still struggling with:

  • Want the player to have a memorable experience? Include a friend, and now it’s a shared experience that is easier to remember.
  • Want a genuinely funny game? Add some human players and watch the hilarity ensue. It becomes a breeding ground for memes, inside jokes.
  • It’s much easier for players to evoke genuine joy, exhilaration, nervousness, anger and frustration when playing with human players in close proximity.

Yes, it’s definitely a different spin on things as you can’t exactly tailor an ‘epic’ story to many multiplayer games, but it entirely depends on the goals your game is set out to achieve. In the context of mobile games, long and epic games don’t seem to be hitting the mark compared to heavier duty, more hardcore platforms.

So where are all the awesome multiplayer games, especially with a platform that is practically connected 24/7 regardless of location and time? We’ve certainly seen some early successes so far (Words with Friends, Eliminate, NOVA, Archetype, etc), but these seem to be barely scratching the surface on what this platform can do. Now with some ideas on multiplayer on the iPhone I figured there are plenty of challenges and possibly very good reasons why we aren’t seeing many successful indie games based around multiplayer just yet.

Complexity

It’s no secret that networking, and making that networked experience seamless and easy to use is no small task. In fact, if you’re doing a server hosted solution where the game is happening at a central location, the cost and infrastructure is probably cost prohibitive for most indies to be sustainable. Even if it’s a P2P game, the complexities of managing a game over a network where any number of things can hinder the quality of the connection or the progress of the game can become a headache at times. You find you are coding for a lot “exceptions” in game events when things simply don’t arrive, arrive late, or aren’t even welcome.

It’s not common for a game to have multiplayer as it’s front and center offering. It’s usually tucked away as a “but wait, there’s more!” item in some bullet list description of features. As such, the convention seems to be a single player option with multiplayer being “extra”. That just adds to production time as now your game isn’t just a single “mode”.

Appeal

To me it seems the number of people who wish to play a game with their friends would be close if not higher to those that wish to purchase a quick 5-minute game to kill time. But I have no data to really back this up, and as such I think my bias is getting in the way here and I could be dead wrong when it comes to the iPhone game market. Social networking sites have already shown that ‘social games’ have a huge appeal, however dubious the game is. So maybe that’s good news?

Opportunity

The other dilemma is the chances the player will have to actually play the game. With a game like “Words with Friends” or “Archetype” there’s always a game at a moment’s notice. Of course, the catch being that you aren’t playing with real life friends (WWF has a slight exception here due to the nature of the game). It’s difficult enough to get players to play your game on their own, but now adding the constraint that 2+ people must buy it AND must be in the same general location to play becomes even more challenging. This drives the game more into niche territory. The question is if that niche is big enough.

The More The Merrier

Multiplayer games are sticky by nature. Players won’t drop your game after a day if they have friends playing it. There’s been a lot of ‘bigger budget’ games that are multiplayer driven on the iPhone, and the whole “social gaming platform” vendors (AGON, Open Feint, Plus+, etc) are all betting on the same thing with their leaderboards and social features. So maybe I’m not too crazy to try to create something that requires more than 1 person/iPhone to fully enjoy the game. The iPad is always an option as well, and possibly a safer one if I wish to pursue a ‘multiplayer’ centric game idea.

I had an issue where several international users were reporting that the game was crashing. As it turns out, using an NSNumberFormatter would return a weird character to display as the grouping separator. This would be all good and dandy, but the problem lies in the fact that I’m using bitmap fonts to render, and the look-up failed causing a hard crash.

In Tilt to Live’s case, this was in regards to how number grouping symbols are displayed in different locales. I use the comma to separate most of the number displays. Due to my ignorance, I just assumed ‘NSNumberFormatter’ would work with what I thought was a universal concept. Not so in some Arabic countries apparently. The fix? If you aren’t supporting localization just use the particular localization you are coding for, otherwise the formatter will use the iPhone’s language settings to pick a localization for you:

[code]
numberFormatter = [[NSNumberFormatter alloc]init];
NSLocale *locale = [[NSLocale alloc]initWithLocaleIdentifier:@”en-US”];
[numberFormatter setLocale:locale];
[numberFormatter setNumberStyle:kCFNumberFormatterDecimalStyle];
[numberFormatter setGroupingSeparator:@”,”];
[numberFormatter setUsesGroupingSeparator:YES];
[locale release];
locale = nil;
[/code]

I spent this past weekend getting retina display graphics implemented in Tilt to Live for iPhone 4. The cynic in me hates the marketing term ‘retina graphics’ because on the production side, it’s simply just a bigger image. But I guess you do need a name for it, and since ‘HD’ has already been bastardized on the iPad I guess this will do. I decided to write this post to bring a bit of awareness to some of the process of updating your OpenGL game for the retina displays if you choose to do so. I thought it’d be riddled with lots of coding work-arounds and such since our game is a 2D game with specifically sized sprites based off the resolution, but it turned out to be pretty quick and easy.

Anyway, Adam had re-exported all of Tilt to Live’s graphics at 2 times the size so the hard part was pretty much done. It was made much easier by the fact that he was using Illustrator and vector graphics, so there was zero need to redraw or redo any assets. On the coding side of things, I feared I’d be spending hours re-tweaking game code because a lot of constraints and boundaries were hardwired to image width’s and heights (bad I know). But in the end, I luckily avoided all of that. Most of my sprite rendering code is encapsulated in a SpriteImage class with width/height properties. I made a simple modification to those properties where the returned width or height was multiplied by a ‘renderScale’ variable that represents the scale of the display. In effect, the width/heights would return whatever the game was designed for at the 480×320 resolution, but under the hood would be using a larger texture.

For non-openGL apps, they get a few things for free on the retina display such as font rendering and UI scaling, but how do you set up your graphics window to support retina graphics? A quick look over at the apple docs shows how to setup your OGL context to scale by a factor of 2. When it came down to implementing it, just doing:

[code]
self.contentScaleFactor = DisplayScale();
glGenFramebuffersOES(1, &viewFramebuffer);
glGenRenderbuffersOES(1, &viewRenderbuffer);;

//..continue setting up framebuffer
[/code]

…got me rendering 4 times as many pixels. The game still looked exactly the same since I hadn’t replaced the graphics yet. What is DisplayScale()? It’s simply a wrapper I wrote:

[code]
CGFloat DisplayScale()
{
return [UIScreen mainScreen].scale;
}
[/code]

Now if you’re using UIImage to load your textures then you’re in luck for updating graphics. Adding a file with the ‘@2x’ suffix will automatically be loaded on an iPhone 4 instead of the normal resolution. For example, myImage.png and myImage@2x.png live side-by-side in your bundle, but on the iPhone 4, it will load the @2x one. I had been using libpng directly to load textures a while ago, but opted to revert back to UIImage for performance reasons.

Now this is all well and good if you’re using separate png’s for your images. But to improve rendering speed and memory consumption a lot of times one will use spritesheets. Having a @2x sprite sheet is nice if the spritesheet generator you are using puts them in the same relative positions. As for me, there were a lot of unused sprites from previous versions so I took the time to clean up things. This was a bit time consuming as I had to verify which images were still being used and which ones weren’t. The ‘@2x’ trick only works on UIImage, so if you have any supporting files (font descriptions in particular) that are needed in conjunction with the graphics file you’ll probably have to write your own ‘@2x’ searching and loading for those particular assets, which is no biggie either:

[code]
NSString *path = nil;
NSString *resource2x = [fontName stringByAppendingString:@”@2x”];
if(IsRetinaDisplay())
{
path = [[NSBundle mainBundle] pathForResource:resource2x ofType:@”fnt”];
}

if(path == nil)
{
path = [[NSBundle mainBundle] pathForResource:fontName ofType:@”fnt”];
}
[/code]

As for other caveats? Fonts were a big one depending on how you export and render them. I’ve been using BMFont to do all my font exporting. It’s a great tool but a little ambiguous when it comes to font sizes. There’s a ‘size’ field, but it refers to character height. Does doing a doubling of character height garuantee exactly twice the width/height]? What about the option for ‘line height’ [unchecked character height? I ended up using line height, since that’s the option I used initially when making the fonts. It worked pretty well. I tweaked my bitmap font rendering a bit and it supported retina graphics shortly after without having to change game or UI code. There was a slight issue with some lines of text being rendered 3-4 pixels lower, but I didn’t spend too much time investigating it as the issue isn’t noticeable in normal use.

Another caveat has to do with rendering GLPoints. Be sure to scale GLPoints when setting glPointSize() if you’re using that functionality at all. Tilt to Live uses it extensively to render enemies faster instead of quads.

It’s been hellishly busy as of late, as I’m knee deep in Tilt to Live HD.  Now on with my quick blurb:

This tip is kind of a “duh” much in the same way version control software is for most developers. The thing is I still meet a lot of developers who don’t use any form of version control. And automated builds simply weren’t even in my own tool set initially. Mostly because my build steps for projects never scaled to the complexity required to build like an iPhone application. And it wasn’t even complex. It was just a matter of remembering which command line parameters to use and which provisioning file to include and to zip it up all tidy and neat.

Now with XCode’s build and archive command a lot of this is simplified with a GUI, but that’s the crux of it. It still requires you to go through several clicks to send a build out.

My setup is pretty simple by using a makefile and the xcodebuild commandline tool. xcodebuild just allows you to build projects from a commandline very easily. Mix that with a few basic unix commands, agvtool, SVN and you have a primitive but simple build pipeline that you can execute with a single command and not thing about anything else. I’ve been using it throughout Tilt to Live’s development and haven’t had a need to really look elsewhere since it accommodates exactly what I need to do: not screw up build submissions or beta builds for testers.

Over the months my makefile has grown to include a few other ‘targets’ for faster iteration during gameplay tweaking, but the 3 essential ones were:

  • build – this just builds my app for ad-hoc distribution into a zipfile named ‘appname_versionnumber.zip’ and a debug symbols file next to it. It then moves these two into a builds folder where I keep all my builds. It works in conjunction with the agvtool so that it increments the build number and submits the new version to SVN.
  • appstore – This target does the same as ‘build’ except it builds with the app store distribution settings.
  • clean – just wipes all my intermediate object files and build temp folders if I want to build from scratch

Below is just a snippet from my current build target. It builds the projects, moves the app files and provisioning files into the current directory. Zips those two up and copies them to a build directory with the debug symbols.

[code]
build:
cd $(PROJDIR) ; agvtool -usesvn next-version -all
xcodebuild -project $(PROJ) -target Tilt_To_Live_HD -configuration Distribution

#move app files into build directory
cp -R $(DISTRODIR)/$(APPFILENAME) $(APPFILENAME)
cp $(PROVISION) $(PROVFILENAME)

#zip up the app file and move debug symbols
zip -r -y -q “$(BUILDDIR)/tilttolivehd_`cd $(PROJDIR) ; agvtool vers -terse`.zip” $(APPFILENAME) $(PROVFILENAME)
rm -rf $(APPFILENAME)
rm -rf $(PROVFILENAME)
cp -R $(DISTRODIR)/$(DEBUGSYMBOLS) “$(BUILDDIR)/tilttolivehd_`cd $(PROJDIR) ; agvtool vers -terse`.dSYM”
[/code]

I wonder if the xcodebuild tool has some commands for automating the ‘build and archive’ command. That would simplify my targets even more.

Tilt to Live has been unleashed on the unsuspecting public! So far the general vibe has been extremely positive! Adam and I are both pretty excited about getting our first app store game out the door. What’s interesting is the workload went from “lull” to “overdrive” in a matter of days as we ramped up for release and still are trying to coordinate things for a bigger media push in the coming weeks.

You can download Tilt to Live in the app store here. One of the cool things about AGON Online integration is how it’s easy to check leaderboards outside the game. Their community page for Tilt to Live is rather snazzy. We’ll be looking into integrating some of those widgets into our own landing page on onemanleft.com. But that’ll have to wait for now.

We’ve got plenty of ideas in store for Tilt to Live for future updates. So tell your friends, your mom, your dog, your twitter followers! The higher the rating the better! Things are rather hectic at the moment as you can probably imagine, but hopefully I’ll have some breathing room and be able to look back on all of this and write up some (hopefully) useful posts.

So I’m using OpenAL to do the audio in Tilt to Live. Over the course of development audio became the bottleneck of my game, both in size and in performance. The following could help you if you’re experience audio performance issues and are somewhat new to OpenAL. Let me preface this with: Don’t blindly optimize. Measure, Measure, MEASURE! Know what your bottleneck is before trying to tune code!

  1. Don’t make more than 32 sources objects in OpenAL. Of course, this number may vary from device to device and what generation the device is. Making any more than the limit the device support makes openAL fail silently, and at this point you’re wasting cycles.
  2. Load your audio buffers and create your source objects ahead of time and re-use them. This is a big one. Don’t generate and delete source objects in the middle of your game update. Instead, it’s much faster to just grab a ‘free’ source that is not playing a sound any longer and attach it to another buffer. I was pre-loading my audio-buffers, but creating/deleting sources on the fly in Tilt to Live. Then I started ‘pooling” and I got a decent gain out of re-using source objects.
  3. Keep OpenAL calls to a minimum. Especially in tight update loops, don’t repeatedly call openAL functions that don’t change frame-to-frame. I found that a good portion of my time was spent doing something as simple as ‘alSourcei()’ on each source ID per frame was causing a significant slow down.
  4. Don’t query openAL state if you don’t have to. In my case, I wrapped openAL Sources in objects with properties to get volume,pitch, etc. Initially those properties simply called the openAL equivalent and returning it instantly. This was hurting my frames due to some some innocent looking “backgroundMusic.volume += someVal” happening each frame along with other audio sources doing the same thing. Save any state you can in instance variables, and as a last resort hit openAL when you need to.
  5. As for size, you should consider compressing your sound FX and music to a reasonable size. If you’re like me, you hate giving up quality; especially if you listen to the full quality one and then the compressed one. It can seem like night and day. But in reality, when your users won’t have a full quality audio file to compare it to, they will not notice the difference.

As a sidenote, you can look at my first dev tip for batch compressing audio files.