Sep 6

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.

Aug 30

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.

Aug 23

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:

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;

Aug 16

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 480x320 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:

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

//..continue setting up framebuffer

...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:

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

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:

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"];
        }

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.

Aug 9

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.

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"

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

Feb 24

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.

Feb 15

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.