Jump to content
  • Advertisement
  • entries
  • comments
  • views

About this blog

PC, 360, iPhone, and Android game development talk.

Entries in this blog


Rocket Rascal Postmortem

[color=#282828][font=arial]My latest game, Rocket Rascal, was just released into the iOS and Android app stores.[/font][/color]
[color=#282828][font=arial](You can get it here for iOS and here for Android)[/font][/color] [color=#282828][font=arial]It's a little too early to tell whether the game was a "success," though it has definitely had a slow start. Instead, I just wanted to discuss some of the good and bad points that came along with development. [/font][/color] [color=#282828][font=arial]There were definitely a few major headaches and a few places I thought would be headaches that turned out blissfully pleasant. So here we go:[/font][/color] [color=#282828][font=arial]What Went Right[/font][/color]
[color=#282828][font=arial]Tumblr & TIG for Recruiting[/font][/color]
I found the artist I worked with off a random Tumblr post, and I couldn't be more pleased with our working relationship. I put out a public call for localizers on Tumblr and TIG and within a week found all the people I needed and then some. Not a single person disappointed, a real triumph when you're trying to wrangle 11 people on a small budget and you have no prior management experience. I also put a call out to integrate third-party game characters in the game, and a lot of Tumblr/TIG developers were very awesome to let me use their works. This created a lot of opportunities for cross-promotion and fan building.
(above: one of our featured characters, Carrie, by Ink Dragon Works)
Game Dev Meetups
I host a coworking event on meetup.com that allowed me to put my game in front of people regularly and get feedback. It also provided a consistent, reliable schedule for certain aspects of development. Further, there was never going to be an Android release - I don't have an Android device, and the one device I could get access to wouldn't run the game. Some people at a different meetup allowed me to see the game running on 4 different Android devices and convinced me that Android was a feasible target. So now it exists. Preproduction
This is such a boring point, because everyone says that prototyping is important, but Rocket Rascal really went through a large number of iterations before the core mechanics were sussed out. It went from a chaotic survival game more like Luftrausers to a portrait-style platform jumper to the rocket jumping vertical climber you see now. Preproduction took a little longer than I wanted, but I think the game is better for it. Here's an early screenshot: Handing Over Art Direction
This was always "my" project - I spawned the idea, ran the design, implemented everything, and managed people I needed. I knew very early that my eye for art design was less than stellar, and I sought a partner who could drive that. When I did find that person, I handed her a rough outline of the visual style I was targeting and let her run with that. She came up with the construction paper styling and the Beetlejuice-esque sandworm design and even the idea for different rocket launchers (the initial design called for multiple characters but only one rocket launcher). Had I run the art direction, things would've looked much different - and looking back, probably would've taken a lot longer and not been as good. [color=#282828][font=arial]What Went Wrong[/font][/color]
I didn't stay on top of my game's performance on actual devices, and it came back to haunt me. Near the end of development I found I had significant performance issues, and what turned into a 2-day time estimated turned into over a week plus occasional revisits. Next time I'm going to strive to stay on top of this with periodic performance checks built into my milestones. Budget
This was a small game that I self-financed, and I let my expenses get a bit out-of-control. I didn't take into account just how much it can cost to finance 9 localizations even when you're paying sub-standard rates. Will those pay for themselves? I don't know, but I'm getting skeptical - I know so far the vast majority of my downloads are in English. So why did I do this anyway? My last game was featured in the app store, but it was only really featured in America. I became convinced that if I had localized it during the time of the promotion, it would've picked up in other countries and been more successful. Next time I'm going to start with a much smaller batch of localizations and gradually add in more as necessary. VFX
I really wanted to go crazy with the VFX for this game. I wanted poppy visuals and really attention-grabbing effects. I tried to implement a bunch of stuff, but none of it worked - they didn't fit the game or they interfered with the play or they just weren't that good. Compound this with the fact that I don't have a very visual eye. It ended up being a lot of wasted time, and the things that made it in were not as profound as I wanted. Next time I'm going to strive to find someone else who can drive this and take my queues from them. What Went ... Somewhere in Between
I'm usually a Unity proponent, and for the most part development went fine. But somewhere near the end things turned pear-shaped. I updated to a patch release and started having real troubles keeping my project from breaking. There were days where Unity would freeze or crash multiple times an hour, and the Services tab gave me no end of grief. I guess it's my own fault for switching Unity versions during the tail end of development, but I really needed a few of those bug fixes. Localization Setup
Don't underestimate how much sheer time it takes to setup localization in iTunes Connect or Google Play, especially if you have a large number of achievements or in-app purchases. It's not hard, it's just... draining. [color=#282828][font=arial]Conclusion[/font][/color]
[color=#282828][font=arial]Like I said, it's too early to tell whether the game will be successful or not. The adoption rate thus far is small, and it hasn't been featured anywhere. I can't predict if any of that will change, but I'm still doing a heavy marketing push and looking for promotion venues. As any mobile developer (or any developer, really) knows, it's an uphill struggle.[/font][/color] [color=#282828][font=arial]Hopefully these lessons which are independent of the success of the game will be somewhat useful. I'll see a few weeks down the line whether the game's performance warrants a second postmortem. Until then, you ought go play the game maybe.[/font][/color]




Rocket Rascal Optimizations

My latest game, Rocket Rascal, was just released into the iOS and Android app stores.
(You can get it here for iOS and here for Android)

I wanted to write a little bit about how I got the performance of this game to an acceptable level. For being such a casual game, I hit some serious performance issues late in the game. The iPhone 5 ran pretty much flawlessly, but the iPad 3 ran at 30-35 FPS, and the iPod Touch 4th Gen ran at 12-17 FPS. The 4th Gen was my low mark, and I wanted to get that up to at least 30 and the iPad 3 to at least 45. Problem 1: Garbage
If you develop in Unity for mobile, the garbage collector is going to crop up in your profiler at some point. The general rule: never generate garbage per-frame. This is harder than it sounds, since seemingly innocuous calls generate garbage. Things like gameObject.name generate garbage, and gameObject.GetComponent generates garbage only if the component doesn't exist. Converting numbers to text can also be obnoxious, especially if you have something like a "Score" string that changes frequently. This was mostly low-hanging fruit though - the Unity profiler made the problem points easy to identify and address. Problem 2: Fillrate
Have a look at the cityscape for the game:
There were 3 large images (*large* images) that were very fill-rate heavy. The resolution of iPad 3 is 2048 x 1536, and stacking these gets really expensive. I couldn't cut these out, they were critical to the aesthetic of the game, but they were definitely dragging me down. The solution here was to cut all those images up into two sections: the bottom portion didn't have alpha at all, whereas the top (smaller) portion still needed the alpha. Then I wrote dirt simple shaders to render this. Making the bottom portions opaque allowed them to be rendered much faste. This had the most pronounced impact on performance, and I quickly saw a 15 FPS boost on iPad 3. Problem 3: Colliders
Unity doesn't like having colliders manually moved around. It gets fussy, and performance starts to drag. The game uses almost exclusively hand-controlled colliders, however, so I had to do something there. I got a decent bump by just not updating the colliders of entities that weren't visible. It wasn't huge, but I couldn't exactly overhaul the game to address this. Problem 4: Sandworms
There are 3 sandworms that are constantly chasing the player, and sometimes there are extras in the background for aesthetics:
The sandworms were created by tweening the control points of a spline and then dynamically generating a mesh from that. Two subproblems arose from this: dynamically generating the mesh was expensive, and updating the collider was killer. Optimizing the mesh generation required just rolling up my sleeves and hammering on problem points the profiler picked up. There was only so much I could do here. I made a few loops take up less time and simplified how the curve was extruded, but ultimately didn't gain much. Optimizing the collider yielded significant boosts. Initially I was using a mesh collider for the snake, which was brutally expensive. Instead, I switched to approximating the shape with multiple capsule colliders. I also switched to only updating those colliders when the snakes were visible.
Problem 5: Device Hangups
The 4th Gen iPod just isn't that good a machine. There was an upper bar that I was never going to exceed. I turned off several features for the low-end devices. Motion blur had to go, and some of the background VFX get turned off dynamically. Dumb Luck
I reached a peak on the iPad 3 of between 45 & 55 FPS, leaning toward the low end. Then I updated Unity to the latest release and the average became closer to 55-60. So... that was nice. Conclusion
There were a bunch of other tiny things that needed tweaking, but the above had the most significant impact on performance. I managed to hit my iPad 3 target. 4th Gen iPod fell a little below the mark - it averages closer to 25 FPS, whereas I wanted 30, but I can live with that. It was definitely a *long* week of banging my head against a wall, so I'm very glad I was able to hit my performance targets.




Alien Star Menace Post-Mortem


[color=#444444][font='Helvetica Neue']Alien Star Menace is available now for iPhone & iPad on the Apple App Store and on Android in the Google Play Store.[/font][/color]


[color=#444444][font='Helvetica Neue']Alien Star Menace started with a simple goal (if you're a dumb person) - make 7 small games in 7 days. There was some downtime at my day job, and I was itching to put another game out there; I hadn't released my own indie game since Cuddle Bears three years ago. So I browsed the net for some art assets I could use and jotted down some designs.[/font][/color]

[color=#444444][font='Helvetica Neue']The more I looked over the list, the more "strategy game in space" stuck out at me. I knew it wasn't a 1 day task. But it was interesting me more than all the other ideas I had. So I decided to throw out the original motivation and instead undergo a more ambitious project.[/font][/color]

[color=#444444][font='Helvetica Neue']I grabbed the art from Oryx Design Lab, prototyped some early gameplay in Unity, and Pixel Space Horror was born. Obviously, that name changed later in development. But we don't need to go into that.[/font][/color]

What Went Right

[color=#444444][font='Helvetica Neue']TIGSource Forums & Early Web Builds[/font][/color]

[color=#444444][font='Helvetica Neue']The initial design of the game had some fundamental flaws. The Action Point system - which was modeled after Hero Academy's - didn't work for this kind of strategy game. It encouraged standing still and letting enemies come to you. Units couldn't move or shoot through allies. Hallways were too narrow. All things which seemed OK as I was developing but which very much weren't.[/font][/color]

[color=#444444][font='Helvetica Neue']I was using Unity, so even though the game was targeting mobile devices, it wasn't terribly hard to push out a web build for public feedback. The folks at TIG immediately rallied against the game's obvious flaws. I fixed those issues, and through a steady stream of feedback polished up other pain points in the game.[/font][/color]

[color=#444444][font='Helvetica Neue']Flexible Milestones[/font][/color]

[color=#444444][font='Helvetica Neue']My mindset on milestones has always been to try to respect them vehemently. No new major features after alpha, certainly none after beta, Time leading up to an RC candidate should be all about bug fixing.[/font][/color]

[color=#444444][font='Helvetica Neue']I don't think I've ever worked on a game where these rules actually held, and Alien Star Menace was no exception.[/font][/color]

[color=#444444][font='Helvetica Neue']Case in point #1: I didn't have a finished title screen until a week before submission. I had some very pixel-art looking text. I wasn't even sure there *was* a title screen being worked on until the artist surprised me with it. What's there now is much, much better than what used to be there.[/font][/color]

[color=#444444][font='Helvetica Neue']Case in point #2: Two days before RC, I decided I absolutely hated the banner ads. They made the entire game look hideous, and they were almost certain to make no money. So I switched to Unity Ads - interstitials. Which were, by the way, scary easy to implement and have been giving pretty good return rates for the number of players I'm seeing[/font][/color]

[color=#444444][font='Helvetica Neue'].[/font][/color]

What Went Wrong

[color=#444444][font='Helvetica Neue']Content Heavy Design[/font][/color]

[color=#444444][font='Helvetica Neue']I've come to accept that level design is not a strong suit of mine, and it saps away energy like nothing else in game development. I gradually learned which things in my levels worked better than others, but it was hard learning and not terribly rewarding personally.[/font][/color]

[color=#444444][font='Helvetica Neue']I'm not unhappy with how the levels turned out, I actually think a lot of them work really well, but I think a talented level designer could've done better and had more fun doing it.[/font][/color]

[color=#444444][font='Helvetica Neue']Writing was also stressful. It was something I enjoyed initially - I like telling jokes and crafting stories. My enthusiasm came and went for this; I think I would've benefitted from having another person punch up the text some.[/font][/color]

[color=#444444][font='Helvetica Neue']Art Direction[/font][/color]

[color=#444444][font='Helvetica Neue']Sometimes I trick myself into thinking I have an artistic eye, and then I try to use it and quickly realize I was horribly, horribly wrong.[/font][/color]

[color=#444444][font='Helvetica Neue']I had a huge struggle trying to get the later levels to look good. Once you touch down on the alien planet (spoiler), the background changes - a starfield didn't make sense anymore. And I had no idea what to do.[/font][/color]

[color=#444444][font='Helvetica Neue']I hacked for days trying to get something that looked good. And I was never satisfied. I'm still not satisfied. I came up with a neat, creepy visual effect, but the backgrounds still feel flat overall[/font][/color]

[color=#444444][font='Helvetica Neue'].[/font][/color]

What's Undecided

[color=#444444][font='Helvetica Neue']Task Tracking[/font][/color]

[color=#444444][font='Helvetica Neue']I signed up for a bug tracking system over at Axosoft. I used it for about two days before I nixed it. Instead, I either fixed bugs as I went or jotted them down in a notepad. It might've helped if the project had more people, but for a one man game it didn't do much for me.[/font][/color]

[color=#444444][font='Helvetica Neue']Marketing[/font][/color]

[color=#444444][font='Helvetica Neue']I put together a pretty comprehensive Press Kit. I wrote over 160 e-mails/messages to various reviewers & YouTubers. I kept running dev logs on Tumblr, TIGSource, and GameDev (that last one not as frequently). I posted almost daily on Twitter and less frequently on Facebook. I talked to everyone I met about my game, including a few dates who couldn't have been less interested ;). I attempted community involvement wherever I could fit myself in.[/font][/color]

[color=#444444][font='Helvetica Neue']It's hard to gauge the impact this has all had. The initial launch has been slower than I'd like, but there's time for it to build. [/font][/color]


[color=#444444][font='Helvetica Neue']It's still a little early to determine if Alien Star Menace was a success or failure. I'm writing this while everything's fresh in my mind, and the game hasn't been out long enough to get a good impression of its performance.[/font][/color]

[color=#444444][font='Helvetica Neue']I'm pleased with how the game came out. It's my largest independent work, and in some regards my best. I think it brings a type of strategy game to mobile that was previously missing or underserved.[/font][/color]

[color=#444444][font='Helvetica Neue']I'd like to thank owmywrist for her constant support, testing, and for listening to my endless gamedev babbling, multitude-ofcasualities for her naming help and press kit advice, pythosart for her fantastic title screen art which I used in a ton of different unintended ways, ua86 for some really solid gameplay advice / feedback, and missmesmer for basically being my #1 Tumblr fan.[/font][/color]

[color=#444444][font='Helvetica Neue']I hope you enjoy the game, and I'd love to hear your feedback![/font][/color]




Alien Star Menace is Out

My latest game was released! For both iOS and Android - I didn't intend to make an Android build, but it turned out to be way easier than I thought.

Here are the relevant links:
App Store
Google Play
Press Kit

Feedback, comments, and ratings are welcome.

I'll probably write up a post-mortem in a few days. Currently heads down on marketing.
Here are some of the final screenshots that made it into the marketplaces:




Promotional Materials

Alien Star Menace is in review with Apple right now and should hopefully be available for iOS devices in the next few days.

Here are various promo elements I've been putting together for marketing:

Follow Alien Star Menace on Facebook




Pixel Space Horror Demo 2

I've just released the second demo for my game Pixel Space Horror.
Play the Second Public-Ish Demo Here

I'm not going really wide until the alpha build, but I've made enough progress to push up another "kinda private" build for feedback. A lot of changes:
Action Point system has been entirely overhauled
You can now move & fire through allies.
Significant camera changes
15 levels & 12 units fully implemented and playable
Sound & music (though you may not be able to hear it in the web build
Proper level & unit unlocking and progress saving
AI improvements.
A million other tiny things.

W - Win current battle
L - Lose current battle
R (in lobby) - Reset game

Known Issues:
The unit balance is still way off.
Level balance is also way off.
The Commander's special power isn't working right.
The enemy doctor doesn't behave correctly.

Any and all feedback is welcome.




Pixel Space Horror Rebalancing

[color=rgb(68,68,68)][font='Helvetica Neue'] Rebalancing[/font][/color]

One of the criticisms of my pre-alpha demo of Pixel Space Horror was the balance - not so much the unit-to-unit balance (which was and still is broken), but the overall game balance. The action point (AP) system encouraged sending in a single unit, doing as much damage with him as possible, and then either pulling him out or watching him die.

I've made a number of changes to the balance to address this and other issues:

The largest change was to completely change the action point system. Instead of 5 global points that can be used however the player wishes, we now have 2 points per unit. A unit can move twice, attack twice, or move and attack.

[color=rgb(68,68,68)][font='Helvetica Neue'][font=inherit][size=1][/font][/font][/color]

When a unit can't be moved again that turn, I darken it to make this clear to the player. I'm not thrilled with the UI - it takes up too much room and isn't especially pretty - but I haven't found another alternative. (I don't show the UI for the enemies).

This had the side effect of making enemy turns take too long. A map with 10 enemies would take 4x longer per turn (20 AP versus 5). To counter this, the enemies can only ever use up to 10 AP max. It means some enemies won't move every turn, but it keeps battles faster. It also gives me a dial to turn if I want to add harder difficulties.

The next (and simplest) thing I did was rescale all the numbers. Instead of hit points in the range 2-10, they're now in the range 20-100. Attack has been scaled appropriately. This gives me more room to play with numbers, which is especially important for my splash damage units.

The final task was to allow units to move & shoot through allies. This was a constant complaint, and there was no real design thought that went into it prior - I just let the pathfinder do its work naturally. But most strategy games allow moving through allies for a number of reasons: it allows for more strategies, and it awkwardly confines units less. You still can't move through enemies, and only a few attacks allow shooting past them.

I think these addressed most of the concerns, and the game does feel better as a result. The balance is still horribly broken, but that'll be fixed as I playtest more.




Pixel Space Horror Levels

During this phase of development for Pixel Space Horror, I'm focusing on content. Specifically, I'm trying to get the first 15 levels roughed in - not final, definitely not polished, but playable.

I'll keep this update short on words and instead just show you:

How am I going to rationalize a graveyard on a spaceship? I'm not.




Pixel Space Horror Units & Enemies

I spent most of the weekend adding the vast majority of units & enemies for Pixel Space Horror that will be seen in the game. The majority of the implementation details were already there: the game already supported most of the attack types & buffs that units would provide.

I created a simple test level to make sure everything was behaving - that units were attacking and moving correctly and nothing exploded.

So here it is, the full cast of Pixel Space Horror:

The units aren't done-done. Visually, most of the attacks use stubs. I want to add flashy VFX (particle systems, camera fun, full-screen effects) to make the game fun to watch. Not quite Atlus-level. I don't have those resources, and also I don't want to slow the game down the way Atlus does in their games. The stats need heavy tweaking - heavy, heavy tweaking after a lot of playtesting - and the writing for them isn't final.




Pixel Space Horror Pre-Alpha Demo

Update 4: Pre-Alpha Demo
[color=rgb(0,0,0)][font=Verdana][background=rgb(252,252,252)]I wanted to put together a small web build, mostly for friends to evaluate. If you want to try, [/background] [/font][/color]here's the link.[color=rgb(0,0,0)][font=Verdana][background=rgb(252,252,252)] I'm not putting it up in Playtesting yet - it's a little early to get a huge number of eyes on it. Feel free to leave any comments/feedback. Pointing out bugs isn't as useful at this stage, as it has plenty.[/background] [/font][/color]

[color=rgb(0,0,0)][font=Verdana][background=rgb(252,252,252)]My goal with this demo was to just make a small slice of representative gameplay. To that end, there are:[/background] [/font][/color]
5 levels
5 available units
A handful of different enemies
Stub UI - this definitely isn't anywhere near complete

[color=rgb(0,0,0)][font=Verdana][background=rgb(252,252,252)]None of the numbers/unit stats are final, and the levels definitely still need tweaking. The "story" will get edited, but the jokes in there are pretty close to what the game's humor will be like. The UI flow will be similar, but I've scheduled in a lot of time for heavy polish.[/background] [/font][/color]

[color=rgb(0,0,0)][font=Verdana][background=rgb(252,252,252)]Features not even remotely represented:[/background] [/font][/color]
Unit unlocking - you don't actually start with 5 units
Level ratings - you'll get stars based on how well you do
Multiple win conditions - not every mission requires you just kill everything

[color=rgb(0,0,0)][font=Verdana][background=rgb(252,252,252)]So far I've only put it in front of one other person. She tells me there are some crash bugs (I have yet to see them myself). She also tells me it's pretty easy. It is only the first 5 levels though, so being pretty easy is kinda the point. Oh, and please forgive the font. I'll be changing that ASAP.[/background] [/font][/color]

[color=rgb(0,0,0)][font=Verdana][background=rgb(252,252,252)]Anyway, lots of forward progress! I'll probably have an alpha build before the month's end which I'll push out to more people.[/background] [/font][/color]




Pixel Space Horror UI Update

Most of the last few days has been spent putting together some necessary UI elements. I'm trying to keep the game pretty UI-lite, but there's no avoiding some things.

First, the level selection screen or "lobby." Right now we're assuming all the levels are unlocked, which is definitely not the start state. There are some graphical flares that don't get represented in a screenshot: stars randomly twinkle and the moons rotate around their parent planets.

Then there's the squad selection screen, where the player selects which units will go into combat. Will probably need a bit of text to tell the player what to do. But it's fully functional - you can drag units into the squad and they will be represented in battle!

And finally, the basic cinematic text dialog. Most of the story is going to be represented by one or two sentences at the beginning/end of each mission. This isn't an RPG - it's a tactics game, and the story is not a driving focus.

It all needs a little love. More flares, tweaked layout, definitely a better font. But it's functional, which right now is the most important part!

Pixel Space Horror Tumblr




The AI of Pixel Space Horror

Pixel Space Horror (PSH) is a very streamlined strategy game: units can only move and attack. For movement, they have a fixed range they can move. Attacks are more varied - every unit has some special qualities when it attacks, such as whether attacks do explosion damage or whether they require line of sight.

Being turn-based, the AI doesn't have the complications of many other games: we have plenty of time to calculate pathfinding and decisions without the player noticing any lag. We don't have to rely on as much estimation and can take a more complete view of the scene. Further, we don't have to respond in real-time to a changing game - the player can't move out of the way mid-action.

However, being a strategy game, the AI comes under extra scrutiny: it has to make solid tactical decisions to wipe out an enemy team. Everything it does can be seen at all times, and if it does something stupid, players will immediately notice.

The goals for the AI system were the following:
Don't be stupid - enemies don't need to think 10 moves ahead, but they can't stupidly move back and forth every turn.
Don't be predictable - the game should play differently each time, and the enemies should respond differently to the exact same situations.
Don't be boring - if there's one over-powered enemy, that enemy should not move every time even though it may make tactical sense.

The pathfinding is crazy-simple, but no AI article would be complete without mentioning it. PSH doesn't have the real-time, large-scale needs of many games: we have plenty of time to consider movement possibilities, and the slow speed of the units makes the decision space pretty small.

PSH uses a simple breadth-first search to evaluate all the different spaces a unit can walk. It starts at the unit and evaluates every neighboring space for walkability. Once all the neighboring spaces have been evaluated, it then repeats the process starting at those neighboring spaces, and then repeats that process again until it has reached the unit's maximum distance and/or exhausted all walkable spaces.

This produces paths which are good enough - they may not be quite the most natural paths, but for our purposes the player won't notice.

Decision Making
PSH uses a brute-force mechanism to determine the next action. It evaluates every possible action for every unit and uses some priority-based decision making rules to determine which action to take next.

There are three varieties of actions for the AI system to consider:
Move + Attack

Strictly speaking, Move + Attack is two actions, but we group them because it often looks more natural for a unit to move and then attack immediately after (it looks like the unit moved with the intention of attacking).

We evaluate an action based on the following parameters:
Does this action kill anyone? These actions take the highest priority. If an obvious kill is left dangling, players will notice.
How long has it been since the unit last moved? We want to spread out actions over all the units so the system doesn't get boring.
Does this action involve an attack? Actions that hurt the opponent take priority over actions that are simple movements.
If this action involves an attack, how much total damage does it do? Attacks which do a lot of damage to multiple units take priority over attacks which only hit one unit for a little.
If the action involves an attack, what kind of units are we attacking? We may want to hurt healers more than other units.
How close will this bring the unit to the enemies?

Each of these criteria is weighted so that some are more important than others. If the unit just moved, it might move a second time in a row if that move can do a lot of damage. If it has moved three times in a row, the odds are unlikely it'll move again even if it could do a lot of damage.

We add up all those weights to calculate a priority and then pick an action based on that priority. We don't necessarily pick the action with the highest priority - instead, we randomly pick an action, but the actions with the higher priorities are more likely to be selected. Obviously non-ideal actions can still happen, but it's more likely the system will pick something better. This gives us our unpredictability.

Results and Future Work
The system isn't yet perfect. There are edge cases that aren't being handled gracefully. For instance, if there is only a single unit left to attack, sometimes the system thinks it's more valuable to just move away than it does to attack. This leaves it possible for the player to gain victory over an obvious defeat. Some of this can be fixed by tweaking the weights on all our criteria, but some special handling will be required to be safe.

We also don't yet account for special units - units which heal or which apply stat bonuses. These will introduce new edge cases and new weighting considerations.

Still, the AI is producing reasonable results. It's moving and attacking and killing left and right. It's taking reasonable actions. I can beat it every time (some of this is the product of immature level design), but it usually takes down several of my units on the way. I'm happy thus far with the results.




Cuddle Bears Gets Update, Free Version

I haven't posted here in a while. Most of that has been because my side-projects were completely buried under the weight of my job project (go play Lil' Birds for iPhone/iPad !), and I don't really have the authority/clearance to speak publicly about my work, leaving me without content suitable for a GameDev journal entry.

Work has settled for me a bit though, so I've had some opportunity to revisit my personal work.

You might remember Cuddle Bears. You really should only remember it if you have amazing memory or you're way more interested in me than you ought be, but you might. There's always been an update planned, and I finally gained the free time to execute on it.

So it's out now. It adds a fair bit to the game - most notably, unlockable score multipliers to give players incentive to continually play.

The game's free version was also released. It has complete feature parity with the paid version, with the only change being that some of the menus now have ads at the bottom.

It's my first experiment into ad-driven games, dipping my toes in to see how they perform. Cuddle Bears is by far my most downloaded side project, so I figured it was a good candidate, and I'm not sold on the efficacy of trial versions for iOS games.

It's interesting to look at some of the differences between how the two are doing:
Whenever I set the paid version to free, its download count bumps up to about 200+ a day. That's not a large number by iOS standards, but it's large by the standards of all the games I've released independently. On the other hand, the free version is being largely ignored. It's a little early to tell, but it's currently sporting about 25 downloads a day. That's pretty tiny by any standards. Neither version is being rated very much. The initial version of CB had about 40+ ratings (mostly acquired during free periods). Currently the update & free version have yet to hit 5. Ads on iOS have a surprisingly high click through rate. MdotM is reporting 4 clicks from 70 impressions. Again, the numbers are too small to make many definitive statements, but I had about that many clicks from Facebook ads with 10,000 impressions. The ratio of new downloads to number of play sessions is *much* better for the paid version, though that's probably just a function of how many players the paid version has.
Those are just some initial thoughts. It's not a lot of data to work with yet - I'll put up an updated post after some time has passed to evaluate how progress is going.

In the meantime, you should definitely get the game and leave a rating. Either version, I won't be picky. ;-)




Cuddle Bears is Out for iPhone, iPod Touch & iPad!

Our latest game, Cuddle Bears, is now available for iPhone, iPod Touch, & iPad. Here are some links for your pleasure:
Website iTunes Link Facebook Page Press Packet - contains screenshots, more information, that sortta thing.
The game is free for a limited time, so feel free to try it out. If you're a member of the gaming press & would like to review it, by all means get in touch. If you'd like to chat with any of the developers, we'd be happy to talk with you.

Here's the game's description:
Run from the Big Baddie Wolf through the land of Cuddle Bears. Cuddle Bears love to cuddle, but their little hugs slow you down. Luckily for you the wolf has a taste for bear. Bop the Cuddle Bears on the head to stun them and slow the wolf down while he devours the little guys. But watch out! Murdering Cuddle Bears may have consequences.

- Jet Packs! Trucks!
- Hop from bear to bear and earn huge score multipliers
- Time your Perfect Jumps and go sailing through the air
- 20 Game Center achievements to unlock
- Local & global leaderboards

And a promo poster!




iPhone Development Pitfalls

These are fresh in my mind, so I thought I'd put together a quick blog post:

Don't assume that because your app runs on an iPhone 1st generation that it runs on an iPhone 3G. The 1st gen is bound to iOS 3.1.3, and despite everything you might say about that, 3.1.3 hogs considerably less memory. A 3G running 4.3.1 can collapse pretty quickly. The iOS devices in general have slow fill rates. This is especially pronounced with the iPad, where even clearing the screen can crop up on your profiler if you're unlucky. Game Center requires a little finesse. Sometimes, through no fault of your own, Game Center will seem cleanly logged in but won't actually do anything. Before slamming your ahead against a wall wondering if it's your fault, it's a pretty good idea to try signing out & back into Game Center. XCode 4 displays target membership to you differently - groups no longer have a sense of membership. This might alleviate confusion, but it makes changing the target membership of nested groups a bit of a pain. You have to watch this closely if you're maintaining two versions of your game (ie: iPhone + iPad), since if two files of the same name & path are included in a single target, the device will... pick one. Never the one you want. Sometimes the compiler warns you of this, but not always. XCode 4 actually does a lot of little nitpicky things like remapping virtually every keyboard shortcut or removing some useful dialogs. It's worth spending some time to explore fully before jumping in, because it's significantly different than XCode 3. Remember that accessing a nil object is not an error in Objective-C. It just does nothing. Textures must be POT. PVR textures must be square. If you see a big white block, look there first. Weak linking & library verification are extremely important, especially if you want to use Game Center. People are still using those old OS's that don't support framework X - more than you'd like to think.I think I've dedicated enough posts to iPhone development, so I'm going to lay off it for a while.




I'm Not Too Bright

Spot the insanity:

struct WordTreeNode
bool IsWord;
StringBuilder Word;
DynamicArray Nodes;
DynamicArray UsedNodes;
int UsedNodeCount;



WordTreeNode::WordTreeNode() : IsWord(false), Nodes(26), UsedNodes(26)

void WordList::AddWordToTree(const StringBuilder& word, const StringBuilder& fullWord, WordTreeNode* node, int letterIdx)
WordTreeNode* currentNode = node;
for (uint32 i = 0; i {
char letter = word;

int idx = letter - 'A';
if (currentNode->Nodes[idx] == NULL)
currentNode->Nodes[idx] = new WordTreeNode();
currentNode->UsedNodes[currentNode->UsedNodeCount++] = idx;

currentNode = currentNode->Nodes[idx];

currentNode->IsWord = true;
currentNode->Word = fullWord;

If you said, "you're using your own containers instead of STL!," sorry, but that's not it. This code was written before the Android NDK had full STL support. Writing my own containers was (at the time) a necessity.

The answer is that I'm using *way* too much memory.

Here are some raw numbers:
About 160,000 of these WordTreeNodes get created and stored in memory for my word tree.

Which means that, assuming 4-byte integers, for UsedNodeCount we're using 160,000 * 4 = 640,000 bytes (~640 K).
Worse yet is UsedNodes, which is 160,000 * 26 * 4 = 16,640,000 (~16MB !!)

Solving this is painfully simple.

We can cut out UsedNodeCount entirely and just use the Size() method for UsedNodes, which drops that bit of memory.
Further, we can change UsedNodes to use uint8 instead of int, cutting out essentially 3 bytes per element, or 12.5 MB.

We can also take this a step further and only make UsedNodes as big as it needs to be instead of having a constant size of 26. I'm not doing this right now for speed reasons (trying to keep loading time fast), but... writing a quick test app here, I would be saving about:

4 MB.

The same operation can be applied to Nodes, reclaiming about another 4 MB.

Thus, after fixing some incredibly stupid mistakes of mine, I can reclaim over 20 MB of memory. This is a *big deal* for an iPhone app.




Digging Into my Toolbox

I've spent the better part of my professional game development career developing tools. All the same, when I'm involved in a personal project, I have 0 interest in writing a tool. I much prefer the free (or cheap) stuff off the internet. Here's what I've been using lately:

I've done a fair bit of searching for bitmap font generators, and the best one I've found - either free or paid - is BMFont. It supports every locale I've encountered and includes the option to only generate characters from a list (useful when you're making bitmap fonts for Japanese or Chinese). It gives a good bit of control over the generated textures and multiple export options. Rendering using the generated information is also pretty trivial (there's a forum post floating around that outlines pretty much the exact code).

I do a lot of iOS development, but most of the tools I love are only available on Windows. CrossOver provides a nice solution - it emulates Windows (based on wine) and allows me to run my tools on my Mac without restarting or virtualization. So far everything I've tried has worked, including tools which require DirectX support. The standard version is $40 and well worth it.

Opal is a very simple level editor. You draw polygons, setup their textures, and add extra data to entities. It supports easy addition of special border textures and layering. Quite honestly, I could sit down and write this in a couple days, but someone has already done the work for me. Right now it's doing everything I need it to do, and that makes it mighty.

Tiled Map Editor
Despite the fact that game developers have been using tile maps since before I was born, there aren't really many good options in the way of tile map editors. Tiled is one of the more competent tools I've found. Unfortunately, it only goes so far - this is one of those areas where I've found I have to roll up my sleeves and do the heavy lifting myself. Alas, my tile editor isn't really fit for show. DAME looks promising though.

Softimage XSI
XBLIG subscribers used to get this for free. I don't know that that's still the case anymore, but if it is, I suggest grabbing this. It's a decent 3D modeling package - at least decent to someone who's not a great 3D modeler. Definitely better than Blender. Maybe not as great as Max/Maya? I don't know; that's what my artist buddy tells me, but I'm not competent enough to say.

It's way past my bed time, so I'm going to cut this short. I'm sure there are some other great tools laying around. Have any of your own?




Thoughts on Android NDK

In my spare spare time (that is, my time not dedicated to my day job or an active side project), I've been hacking with porting Word Duelist from iPhone to the Android NDK. I wrote my core iPhone code in C++ without STL specifically to facilitate this. Of course, then Google announced the newer versions of the NDK would have full STL support, but that is neither here nor there.

Here are some of my experiences in no particular order:

Eclipse integration is a little wonky. I've found that after I build my C++ library, if I don't then manually refresh the Eclipse project it doesn't pick up my changes. This caused a lot of hair pulling in the beginning until I figured this out. All the same, most everything just worked. Aside from some blatantly platform dependent code (file loading mostly) and a few minor nitpicks, I was able to move my C++ codebase over with ease. I was relieved that the OpenGL rendering code required no changes to get the game up and rendering. Calling C++ code from within Java is trivially easy. The other way around, though, has a fair number of quirks. I still haven't figured out how to call a void Java method from w/in C++ - all my methods return integers or else things go wrong. Loading files is hairy. I haven't found a good way to read an entire file in as a single string. There's a good reason to want to do this - reading in a file line-by-line generates garbage, which in turn invokes the garbage collector, which drastically slows down load times. When you're talking about loading a 40,000 line word list or a large XML file, it's prohibitively expensive. For a lot of files, a solution is to flatten the file into a single line (if possible), but that hasn't worked for the word list since it takes up too much memory when loaded in bulk. I may get away with moving my assets to a different directory and loading them w/in C++ code? I'm not sure yet. This isn't NDK specific, but developing on the actual device is usually faster than using the emulator. Android emulators are *slow.* The OpenGL rendering does have a few glitches. Alpha blending seems to behave a little strangely in some cases. Still trying to isolate this. Debugging is fussy. The Eclipse debugger is not wildly great as is, but I haven't yet worked out a way to debug my C++ code. Luckily most of my code was already debugged during iPhone dev, so I only have to worry about the communication layer between Java & C++. It's pretty important to decouple updating & rendering when using GLSurfaceView. With the iPhone I just wrapped them up together and it worked fine, but when using GLSurfaceView there's a noticeable slowdown (I'm guessing the redraw isn't invoked as often). Unfortunately the multithreading is a little tricky since any texture operations need to be invoked within the rendering thread, and I didn't plan for that initially. Oops. I haven't found a good way to handle memory issues. I'm finding I exhaust memory quickly. On iPhone, I got a memory warning that I could respond to before my app shut down and unload unneeded gunk, but I haven't found an equivalent for Android - probably because it expects to manage all the memory. This probably just means I need to be more careful about when I unload textures.
Working with the NDK hasn't been completely painless, but it's not the worst platform I've worked with. I don't have a timeline for Word Duelist's release there, there's still a fair bit of debugging ahead, but if progress moves the way it has I expect a month or two.




Word Duelist iPhone Post Mortem

Just a quick word before I get into the post mortem proper: Word Duelist for the iPhone shipped about 12 hours ago. I'm writing this while it's still very fresh in my mind - but I'm also writing it at 2:30 AM, so my mind is perhaps not its greatest.

You can get the full version on iTunes here and the lite version here.

Word Duelist traces its routes back to my days as a grad student at West Virginia University. The Experimental Gameplay Project, spearheaded by Carnegie Melon, staged a competition requiring participants to design and then implement a game utilizing a DDR dance pad. I was playing a lot of Wario Ware at the time, and I had just recently watched Volcano High, so I thought fusing the two might be a good idea; the original "Duelist" game had players wandering around a university challenging students to telekinetic duels, where each duel was a series of small minigames involving the dance pad.

The game was actually pretty unfortunate. The graphics were abysmal - poorly edited pictures of people run through some Gimp filters. The DDR pad was super sensitive and didn't play nicely at all with the minigames I had. I didn't do so well in the competition that time around.

Fast forward a few years. Emergent Game Technologies had recently had a major layoff, impacting me in an unfortunate way, and I found myself with time. I decided to spend that time making XBLIG games. My first game was See the Light, a niche puzzle game that maybe 8 people played. The XBLIG version was admittedly an eye sore (a problem I would correct in the mobile versions), but that's neither here nor there. I wanted to move onto something fairly small, and this Duelist idea came back around.

I really don't know where I got it into my head that I could take the concept and adapt it to word games, but it was an idea that latched on and I ran with it. Word Duelist was born. I finished the XBLIG version just as I was starting my job with Spark Plug Games. I then had a bit of a hiatus from indie games while I worked there.

My job at Spark Plug requires me to do a lot of iOS development. I was interested in seeing how the market was, and I was settling into a routine that allowed some measure of indie development. I decided to take my two XBLIG games and move them over - first See the Light and then Word Duelist. - for two reason: to experiment with the market and to build up a C++/Objective-C codebase for more intricate games.

Word Duelist shipped earlier today. I honestly can't tell you how it's doing commercially - whether it's a "success" or not is still to be determined. I can, however, talk about the development.

What Went Right
(1) Data-Driven UI
During my XBLIG days, I vastly underestimated how much work a good UI requires even for a small puzzle game. There are the simple things like laying out widgets, and there are the more intricate things like animations and transitions. When I was doing it all by code, the amount of code quickly added up, and it was a cluttered mess.

One of my first priorities with the new codebase was to never let that happen again. I invested a good amount of time creating a solid data-driven UI system (which I outlined in this post), and it was a huge boon to development. Especially in a game like Word Duelist which has a huge amount of UI.

(2) Scoping
It's amazingly hard to develop a good game in spare time. I juggle a full time job, a social life, a lady-friend, a handful of other hobbies, and finally my game development. On a peaceful week I can work anywhere from 1-3 hours a night with added time on the weekends. It comes out to between 15 & 30 hours a week, generally around 20. That's not a lot of time.

I've made the mistake of over-scoping before; I'm probably doing it right now with another project. But Word Duelist was just the right size - the hard bits had been worked out for the XBLIG version and a good chunk of code had been written for See the Light. The art was 90% finished, with some extra bits needed to make it mobile friendly.

There was still work involved - the UI required migration to the new system, there were new features (Game Center achievements, a Quick Battle mode), and there were some iOS hurdles. Total, I think development took around 2 months, which sounds about right for a game of this size.

(3) Experience
I've been working pretty much exclusively with iOS for the past year (with some Android and XBLIG mixed in for flavor). Had I jumped into this project without having shipped a couple iPhone games already, there would've been headaches.

Objective-C has a bit of a learning curve of its own... much like any of the C-based languages. Quirks of the iTunes review guidelines - like not using private APIs that forums seem so fond of, properly handling memory issues, or handling device rotation - are things I'd seen. I knew how to properly work with Game Center and the quick paths to saving data.

In short, there were no real gotcha's from a tech perspective.

(4) End Cycles
I'm a fan of sticking to end cycles. Alpha, beta, RC. My development up to that point isn't as structured, but the path from feature complete to getting the game released is well defined.

This involved a lot of testing, and a lot of ranting when the later tests failed. Better I rant than have my game fail review, though. I went through 3 RC candidates before the game finally shipped, and had I tried shipping any sooner I wouldn't have actually released by now.

As an indie, it's easy to try & ditch end cycles or underestimate how much time they'll take. Every time I've tried that, though, it was a huge mistake; I'm glad I followed through with Word Duelist.

(5) Screen-Based State Management
My codebase has a somewhat intricate state management system involving processes and how they interact when responding to messages. I've made the mistake before of going crazy with that system, making virtually every task its own process that handles its own execution and then continues.

Word Duelist was a bit more relaxed. Basically every distinct "screen" had its own logic that handled things happening in that screen - input messages, for instance. Screens were broken up fairly well so that nothing became monolithic (no "Game" screens). The code was easy to trace, modular, and just logically made sense.

(6) The Team
This is the obligatory post mortem shout-out to the team I was working with. The artist (Laura Walters) made some charming art for this game. The musician (Michael Taylor) responded to feedback very well and was extremely fast. He also provided a lot of good sound integration ideas that I had never considered but which added a little extra. I will no doubt work with them in the future if given the chance.

What Went Wrong
(1) Memory Management
One of these days I'm going to be able to tell you exactly why I didn't build my codebase with good memory management in mind from the start. Naked new/delete statements shouldn't really get a lot of play in production code, but there they are. All over the place.

Smart pointers are a very noticeable omission. I've had to be very cognizant of what owns what, and it's a headache I'd much rather do without.

This all came to bite me late in development when there was some awkward memory thrashing. In the UI code, I was handling control transfer between windows, and code was trying to return focus to a widget that no longer existed. This manifested in crashes where the debugger would land in some random spot with random memory being thrashed but no clear signs of why it was thrashed. A proper weak reference system would've made that bug a non-issue, but instead it took me the better part of a day (during beta) to track.

(2) No Multiplayer
This is the kind of game that screams multiplayer. If there were more time, I would gladly put in multiplayer, but I'm scared of multiplayer development. Every time I do it, I feel like I've put in a series of inelegant hacks to band-aid my lack of expertise in the area.

The game is actually pretty well architected for multiplayer if I ever decide to add it later (the XBLIG version did support hot-seat multiplayer and a lot of that intrinsic support carried over). I'm familiar with Game Center's multiplayer development. But it will still take some convincing to get me to go down that road.

(3) Poor Time Estimates
I'm criminally bad at estimating how long something will take. I thought I'd have this game finished at the beginning of the month, and that slipped by about 3 weeks. There were various factors involved in that delay - a major deadline at work, various social obligations, etc, - but my plans should have accounted for those inevitabilities.

As a result, some other projects that I would have liked to work on got pushed by the wayside. I had a lovely Valentine's Day game idea that I missed my window for. Maybe next year.

(4) Texture Atlasing
I did a pretty crummy job of managing my texture memory. Items that weren't used anywhere near each other were lumped into the same image, most of the locations were loaded at the same time, and there was still a lot of unused texture space resulting from me manually laying out all the atlases.

Oh, and all the textures were uncompressed.

If you play the game long enough in one sitting, all of the above becomes a noticeable problem in the form of memory consumption issues that result in textures being unloaded and reloaded awkwardly. It's generally edge-case type stuff (basically beating the whole thing a couple times in one sitting), but still not something you want in a shipped product if it can be avoided. Alas, by the time I realized this problem existed, I was just putting the finishing touches on RC2 and didn't want to make the risky changes necessary to try and fix it.

I don't know if Word Duelist will be a success. Its XBLIG performance wasn't anything to write home about, but I think the iPhone is a different market more interested in word games (I hope, anyway). So far it only has a single rating from a person I know, but it's been less than 24 hours.

Regardless, I stand by it. It's definitely one of my better games, and the iPhone port was a worthy successor.

If you haven't already, you really oughtta get it. And rate it. And talk about it.

Just sayin'.




Word Duelist Ships!

My second personal iPhone game has now shipped and is available on the app store! Go get it:

Free Version
Full Version

I'm a bit rushed for time right now - later I'll augment this post with screenshots, trailers, information, all that fun stuff. In the meantime, you should play the game, rate it, and tell all your friends. Because it'd be totally rad of you.




Word Duelist is Near Release ...Help?

Word Duelist has been submitted to iTunes Connect and is now "Awaiting Review." Based on how long my previous games have taken, I would expect it to be through review in about a week. Hoping it passes.

The end cycles were brutal.

Even with my independent development (probably moreso, actually), I try to keep to rigid end cycles. Those cycles being:

Alpha - Every feature is complete and a majority of the content.
Beta - Content complete. The game has been polished & tested thoroughly, and all major bugs are fixed, though there are still probably some hiding.
RC - The game has 0 bugs... ideally. Usually RC requires a few passes before shipping, though.

I'm less concerned about the stuff leading up to alpha - my preproduction is pretty loose, and I don't keep to milestones like First Playable or Second Playable. This has worked fine with games where development involves less than 3 people over the course of a few months (and when I say 'few months', I'm talking about the few hours a day I can spare between work and life).

I'm super glad I keep those end cycles and regular testing, because I'd release some extremely buggy games without them. Word Duelist had a bug that would lock up the entire game as late as RC2 - a rare edge case that few people would encounter, but if Apple had encountered it I'd have wasted a week in review.

Anyway, that's that.

So here's why my title includes "...Help?" : I'm rubbish at marketing and could use some advice.

I sent a press package for See the Light to about 25 sites. It was fairly competent, I thought - included descriptions about the game, a description of the "company", assorted screenshots/promo images, and a free download code to play the full game. Of those sites, 1 reviewed the game. 3 sent me canned responses offering to sell me a review and advertising. I never heard from the other 21.

I'll grant that See the Light was a niche game (raking in, so far, about $12), but that still seems askew.

Word Duelists''s appeal is broader - I think - and I'd like to see it do better in the market. I have no illusions of buying a retirement home with it, but ideally I'd like to cross the $150 threshold where Apple actually pays out.

I figure there are a lot of extremely knowledgeable folk around here, so if you have any ideas on how I could effectively market/promote this, I'd love to hear them.




Porting Word Duelist & Thoughts on iPhone Dev

I've currently been working on porting my Xbox Live Indie Game Word Duelist to the iPhone (and potentially the Android). Here are some unfiltered thoughts while I've been going through the process:

UI implementation has more caveats on touch devices than it does with a controller. You have to worry about overlapping buttons, for instance, or what happens when a dialog should block out some UI elements but not others. There's nothing hard here, but there are details that need addressing. Although it's a little daunting going from a memory managed language (C#) to one which isn't (C++ + Objective-C), a carefully coded framework can insulate you from most dynamic memory allocations. I have a lot of containers and low level framework code that ensures that my actual game contains naked dynamic allocation in only one place. Of course, the framework is doing a fair bit of allocation under the hood, but I don't ever see that. You really can't make any assumptions about how the iPhone emulator runs compared to the device. Surprisingly, sometimes the emulator will actually run *slower* than the device even though the machine I'm using is considerably more powerful. Regular device testing is essential. Regular device testing is imperative to suss out memory concerns. The iPhone runs out of memory a lot faster than you think. Even a simple Match 3 game can have memory concerns. An unfortunate reality of developing for the device, I'm afraid. I really should have created a good texture atlasing system, because doing it by hand is a *pain.* Texture atlasing is pretty essential, because iPhone textures must be powers of two, but like I said above, you really have to watch your memory and thus conserve as much as you can. I've seen some decent greedy algorithms laying around that would honestly probably do a better job than my manual atlasing. Didn't have to worry about this with XBLIG. Users really, really do not seem to like the "in-app upgrade to full version" model that was made available when in-app purchases were introduced for iPhone. Looking over the app store, I see a ton of comments accusing developers of false advertising because the game is labeled as "free" even though only a trial portion is actually free. The market seems to expect a Lite version in those instances. This is the reverse of XBLIG, where an upgradeable trial is a requirement. The "Universal App" is non ideal. It unnecessarily bloats iPhone games. Same goes with retina support. There are better ways. It's quite honestly shocking that I can use achievements & leaderboards on the iPhone and not on XBLIG - why is *Apple* paving the way for indies here? But at the same time, I do love the XBLIG avatar integration. Avatars would've been a good thing to add to the XBLIG version of this game that I just, well, didn't. I don't like Objective-C or XCode. I'm not going to talk about why here, and I really have no interest in debating the points; XCode is a poor substitute for Visual Studio, and I find myself avoiding Objective-C and instead writing most of my game in C++ (which may not be great since XCode and the Instruments tools don't always play nice with C++). On the plus side, my inclination toward C++ will hopefully make porting to the Android - using the NDK - easier down the line. I sure do hope ExEn gets funded so that I can use one language between several platforms. I already have a C# version of Word Duelist for XBLIG, but it's not mobile friendly and quite honestly the code base is a mess. The only way it will ever see WP7 is if Microsoft at some point provides a C++ path so I can take the much nicer mobile version and port it over. Wishful thinking.
That's all for now. The Word Duelist port is nearly finished - it has every feature the XBLIG version does (except sound right now), so I'm just spending my time polishing and putting in additions (ie: achievements). I expect in about a week's time I'll be able to put it up for review.

Let's hope it makes more than $12, which is what my last indie game has made in the app store. ^^




Introductions are in Order

I realized that after two content heavy posts, I hadn't actually made the obligatory "hi" post. Plus the install time for my current project is monumental, giving me time to kill. So here's who I am and a discussion on my motivations with this blog:

I'm Brian. Currently an engineer at Spark Plug Games, where I have developed Pac-Match Party and am Lead Engineer on the Puzzle Quest 2 iPhone/iPad project. Whether or not I'm actually qualified to be a lead anything is a question nobody seems to be asking, and I'm definitely not answering. At any rate, both of those have shipped, so go buy them.

Before Spark Plug I spent about 1.5 years at Emergent Game Technologies as a Tools & Framework Engineer on Gamebryo. I touched a bunch of different areas there, mostly art tools. Then bad things happened to the company, and I don't know any more than anyone else reading the GD.net Dailies.

Before *that* I was an intern at Electronic Arts Chicago... to which bad things also happened shortly after my internship ended. And before that I was a debugger/porter at CSP Mobile... which the internet tells me has gone bankrupt.

Bit of a trend there. I try not to think about it much.

All this has been punctuated with stints as a grad student doing various amounts of teaching and tutoring and university level software engineering. I also keep a healthy number of side projects going, developing for XBLIG and iOS and Android. GameDev tells me I've been a registered user since 2000. Yikes I'm old.

So that's me. And here's where I'm going with this blog:

Basically I want a place to babble about purely game development related technical/design ideas. I already keep a separate blog (The Animal Farm Creations) that showcases some work and has plenty of geeky technical posts, but it's more personal and not entirely targeting fellow developers. That's what I'm hoping to do here.

I make no warranties about the quality or interestingness of my posts. I also don't guarantee I won't make up words like interestingness. These are risks you take as a reader.




Data Driven UI


For one of my first XNA games, I decided to hand code my UI. This left me with a ton of statements like this:

StaticImage img = new StaticImage(someImage);
img.Position = (50,50)
img.CenterHorizontal = true

I thought this would be OK, since the project was intended to be small and essentially over upon release. Then I decided to port it to the iPhone; when I looked over the code again, I threw myself on my sword.


The UI code made my codebase a bloated, cluttered mess. It was hard to port correctly (not to mention hard to develop initially), and it cropped up all over the place. The UI animations added even more. In the end, I think more of the code was devoted to UI than to actual gameplay.

I vowed right then and there - never again. I got to work creating a new UI system that would allow me to data drive everything with minimal code work.


Here were some of the requirements:
(1) No UI should need to be created in game code aside from a "LoadWindow" call.
(2) Creating custom UI code should require as little typing as possible - reasonable defaults should be used for virtually everything that wasn't explicitly specified.
(3) I should be able to specify simple animation sequences. Fades, Slides, Rotations, etc.
(4) This should interface with string table support in case I want to do any future localization.
(5) The UI files should be human readable. Not necessarily XML, but definitely not binary.
(6) The system should support relative, auto-adjusting layouts. If I ever want to move to a different platform/resolution, I don't want to have to recreate everything. Full UI portability is not 100% feasible, but every little bit helps.

Most of these problems have pretty straight-forward solutions. The actual widgets are defined in code, and a factory parses an XML-esque file to instantiate them. Here's an example:

Name: image_dolly
Image: background
Position: 50,50

Name: label_title
Text: "Hello World"
FontName: Vera

Fade widget=image_background StartPosition=res,* EndPosition=*,* /Fade

When I call LoadWindow on this file, it loads up all the widgets and animations. I can then make a call to "PlayAnimation" to actually play the animation.

That's the high level look. Now let's take a look at how the system was built to fulfill the above mentioned requirements:

(1) No UI should need to be created in game code aside from a "LoadWindow" call.
This should be fairly self-explanatory. The UI loader knows how to interpret all the possible widgets (all the ones I've implemented so far) and any parameters that need to be set on them like position and color. Sometimes writing the UI file can end up more verbose (I don't support looping to create groups of widgets), but generally the files trend smaller than the equivalent code that would otherwise be necessary.

(2) Creating custom UI code should require as little typing as possible - reasonable defaults should be used for virtually everything that wasn't explicitly specified.
This is also straight-forward. If something isn't specified in the UI file, a default is used. Conversely, I have asserts in place for where parameters are required and not specified (for instance, the Image parameter of a StaticImage). The defaults generally make sense - centering is off by default, a default system font is created for strings, the default color is white, and so on.

(3) I should be able to specify simple animation sequences. Fades, Slides, Rotations, etc.
There was a little work involved in this one.

First, the system recognizes two types of animations: Parallel Animations (default) which are animations where all the steps run in parallel - ie: fading all the widgets in at the same time. And there are Chain Animations, which happen in sequence - moving a widget to one location and then to the next and then to the next.

Each animation can have a series of operations - fades, slides, stalls, and rotations right now. Each of those operations applies to a single widget. So an operation can slide a widget from off-screen to the center of the screen as part of a larger animation. For convenience sake, I also define an "all" widget, which tells my UI system to apply that animation to every widget in the file - useful for full-screen fades.

An animation operation can also be another animation. So if I have a Chain Animation named slide_in_out, I can reference that animation from within a Parallel Animation and thus have the chain occur while other things are going on.

There are lots of little nuances that go into this - animations can loop, for instance; operations can have easing associated with them for more interesting transitions; operations can also show widgets once they begin or hide widgets once they end.

Finally, you may be wondering what the * characters in my example represent. They basically represent the value of the associated parameter when that widget was initially created. For instance, in the above example, *,* gets interpreted as 50,50 when the animation executes. This is a convenience token that allows me to move widgets around without finding every animation that references the widgets and changing those as well.

(4) This should interface with string table support in case I want to do any future localization.
Whenever a string is read within the UI file - for example, for labels - the underlying code first looks to see if that string exists within a master string table. If not, it logs a message and uses the string as-is. This allows the code to run unhindered but also lets me know where my string table is lacking.

Unfortunately, right now the system does not have good support for formatted strings. So I can't put a string in my table that reads "Player 1 has {1} points" and have the system resolve {1} automagically. That requires code.

(5) The UI files should be human readable. Not necessarily XML, but definitely not binary.
You'll notice that the above example looks XML-esque while not actually being XML. There's no dark secret here; I had some file loading code in my codebase but no XML loaders (Objective-C is not as nice about this sort of thing as C#). I opted for the lazy route. I could just as easily put tags around everything but opted not to.

(6) The system should support relative, auto-adjusting layouts. If I ever want to move to a different platform/resolution, I don't want to have to recreate everything. Full UI portability is not 100% feasible, but every little bit helps.
This is honestly where my system is the weakest. WPF has all sorts of nice little grid layouts and tables and what-not that will automatically rearrange/resize widgets. Getting that to work well would require more time than I wanted to devote, so I opted for a lazy route:

I have two variables: res and halfres. When they are seen for a vector2 parameter, they are translated to, well, the screen's resolution or half the screen's resolution respectively. This makes doing things like centering or sizing a little easier.


Obviously the system has holes. If I had more time to devote, I'd work on some nice auto-layout features. I might also add a variable system to specify UI global variables (ie: a common "down color" for text buttons). Sound integration is on the TODO list. The biggest thing I want to do, though, is write a nice layout tool so I don't have to hand-write these files: they're 150% better than writing the associated code but still time consuming.

Regardless, the system is a big step up from where I was. It's made my iPhone development much less painful and allows me to focus less of my time on nice UI effects and more on the actual gameplay.




Scripting Languages are Overrated

Back when I was first starting ambitious game dev projects, I believed a good scripting system solved a lot of problems:

(1) It appeared super modular. After all, I could keep so much game logic outside of my code and only use C++ for engine development.
(2) Rapid iteration! Who doesn't want to change a logic file and instantly see the results on screen?
(3) Everyone can understand scripting languages. I mean, c'mon, Lua is the most readable thing ever.

I went down the scripting road, rolling my own, integrating outside languages, and bragging about how awesome my code was. Except that it wasn't - pretty much none of the above was actually true. And there were hidden costs I wasn't seeing.

Since then I've had the opportunity to mature a bit, and I've worked on large code bases with varying amounts of scripting in place. This has caused me to reevaluate the above.

(1) was true enough, I guess, except where you have to worry about binding. Where scripting languages are involved, a healthy portion of engine code must be dedicated to getting the engine & scripts to communicate. Scripts aren't much good if they don't know about game objects after all. This is less true with languages like C# where reflection can automagically handle a lot of the binding, but if you've ever looked at code that binds Lua & C++ you know it's a mess. Plus in the end, even if we discount binding, the scripts aren't any more modular than, say, just having separate source files in their place.

(2) is incredibly tempting, but it comes at a non-significant cost in development time. Rapid iteration isn't free, and depending on the game's complexity, can be prohibitively difficult. That's just for PC development - if you want rapid iteration over an iPhone or an Xbox, you're looking at a whole new set of challenges. It's great if you have the time to develop and maintain it, but it's a lot of work.

(3) completely depends on your people; Lua and Python are a little easier on the eyes to those who don't code all day, but in the end that's mostly syntax and semantics - the real challenges of coding are more about problem solving. Odds are if you have people who can write good Lua code, they could write the equivalent in C++ with a little added extra education (you may want to leave out pointers/dynamic memory, though). More importantly, a lot of people *don't* write good script code, and so you're looking forward to a bright future of hearing "Hey Engineer, come help!"

Those are rebuttals to the initial three points, but I also mentioned hidden costs associated with scripting.

(1) The number one thing most engine integrated scripting systems lack is a good visual debugger, and that's a crime. By far the largest boon of modern development environments (ie Visual Studio) is a quality debugger. I used to tell my operating systems class that they'd be spending upward of 70% of their time debugging problems, and I think that's true with a lot of development (especially at the end cycles). With a large group of game scripting systems, the best you can hope for is a stack trace. Helpful, but not a lot. Willfully throwing away a debugger is crazy talk. Of course, you can develop an integrated debugger, but that's tricky business.

(2) You're moving a lot of errors to be run time checks instead of compile time, and that time adds up, especially if you're developing for a system where the turnaround time between changing something and reinstalling the game is non-zero (ie: iPhone). I can't count how many times I've made a silly Lua mistake over the last couple months only to slap my forehead and have to restart the program. Depending on your system, the error may not even be immediately evident. If scripting errors cause a soft fail + error log versus a hard break, you could overlook a vital error.

So that's that.

The above might give you the impression that I hate scripting, which isn't completely accurate. If you have the time to create a proper rapid iteration solution and a real-time visual debugger, scripting can be pretty awesome. Even without that, confining scripting to small chunks of logic that can easily be made iteration friendly (ie: spell effects) has proven to save me a lot of time. But unless it can be done right, using scripting to drive game logic can often involve more work than it saves.



  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!