Postmortem: The Bombay Intervention

December 19th, 2013 4:47 pm

Title card for The Bombay Intervention

The Bombay Intervention is a collaboration between Jason Mize and mildmojo. Mildmojo’s completed a few Ludum Dares before, but this was Jason’s first. Jason took care of music, writing, and shared design duty with mildmojo, who coded the game in Unity 4.3 (javascript) and composed some of the sprites.

DESIGN in the abstract

Photo of the Set card game's box.

Set, a card game about pattern matching

You play as a time traveler, working your way through a spotted history on missions to clean up the worst of the (fictional) disasters.

Your view of the past is through an event wall that shows you when events will occur during your trip. These events could be as mundane as a bus driver heading to work or as important as a world leader coming to power; you only know that patterns in the wall lead to catastrophes.

If you freeze several events in the same general place and time, you prune that timeline out of history. Prune enough contributing timelines and you’ll find that the crisis collapses without causal support.

The original kernel of a game idea was inspired by the card game, Set.

What went well

The game features a dynamic soundtrack. Jason wrote and recorded three original pieces of music, each of which has four parts (see his description below). When you begin a mission, you only hear a single part. The other parts are selected at random and added to the soundscape when you complete a stage by making a match. We weren’t sure it would work, but it’s really exciting to hear in action.

Screen shot of gameplay from The Bombay Intervention

Gameplay

Unity’s new 2D sprite system makes it trivial to turn images into game objects and, even better, compose layered sprites from lots of sub-sprites, each of which can then be independently addressed in code. Each timer prefab is a background square, dark text, light text, and a flag, all of which can be controlled separately if needed. It’s so much easier to do this stuff visually in Unity’s editor.

mildmojo: I typically work in languages with dynamic typing, so I picked Unity’s javascript syntax. While not type-free, it saved an untold amount of C# ceremony and let me just get things done. Heresy to some, but it makes using coroutines and anonymous function callbacks (aka lambdas/delegates) ridiculously easy.

I’m pretty happy with the simple ShuffleDeck class I threw together for randomization. It works like a deck of cards; you shove a bunch of stuff into it and call draw() to get one or more back at random. Like drawing from a deck, you won’t see items repeated again until you shuffle() or you draw() the last item and trigger an automatic shuffle. Some people do this for dice-based games like Settlers of Catan to avoid streaks or “hot” random events that keep occurring. I wrote it to pick mission names (seen at the end of a level), but ended up using it for country flags, music choice, and picking parts within a song to play and layer. Big win.

Tweened animations are the easiest way to add polish. Tween the hell out of everything, then start stacking the tweens. iTween worked well enough.

Jason Mize:  I recorded all the music by plugging my Yamaha DGX-640 directly into an iPad and using Garageband.  I’m traditionally a guitar player and would have recorded via either direct line or mic.  The keyboard gave me a much cleaner sound and made mixing much simpler.   It completely removed troubles that I’ve had in the past with background noise, static, and fuzz.  I made the drum tracks with Garageband’s built in drum machine.  It was easy to use but lacked complexity.  I played the other tracks myself.

Since each 2 minute song needed to be divided into 4 tracks, each of which could stand on it’s own or be layered randomly with the other 3 tracks, I composed the pieces as jams with short melodic lines with variations.  My logic was that if I made the melodic phrasing too long, then having the track added in the middle of the phrase would be confusing to the ear – the listener wouldn’t have any musical environment to make sense of where the tune was.  I think I made the right call there.  Layering the tracks in random order worked even better than I hoped.

Initially I had trouble making all the tracks capable of standing on their own.  Once I realized that I needed to pair any tracks that were overly eclectic or melodic with a grounding bass line composed of roots, the whole thing came together.

What didn’t go well

mildmojo: Getting out of the Software Architect frame of mind. I should’ve just thrown global scripts on the camera like everybody else does rather than using generic class singletons. These work great until you need to use coroutines or iTween callbacks. Coroutines only work on classes descended from MonoBehaviour, not ScriptableObject, and the result is that functions with `yield` calls are just skipped. No errors, they just don’t run. Super frustrating to debug.

Lining up the sprites in a grid was unnecessarily obtuse. Let me save you a whole bunch of time: get a sprite’s bounding box in world coordinates from myGameObject.renderer.bounds. Put your camera’s lower left corner at (0,0) and get the screen dimensions in world coordinates from Camera.main.ViewportToWorldPoint. With that, you should have all the info you need to position things in code.

iTween is so focused on GameObjects that it doesn’t know how to take a callback to run on anything else and doesn’t support lambda functions; you have to have a real function defined in a behavior script attached to a real GameObject. So for a while I was kicking off tweens and using `yield WaitForSeconds` to pause until the tweens were finished rather than using iTween’s `oncomplete` callback. I DO NOT RECOMMEND THIS. HERE BE BUGS.

I found a workaround, though: have iTween call back to a function that can run a function object, and pass the anonymous function as an argument through iTween.

Jason Mize:  This was my first game jam and I completely underestimated how much time everything I needed to get done would take. A lot of graphics that I spent time in the beginning thinking through and planning in my head didn’t get made because the music and text writing took longer than anticipated. Next time I think I’ll have a better idea of how to pare the basic project down to just the minimum needed to succeed and not think about anything other than that until it is built. Then move on to embellishments.

What didn’t make it

CONTENT

Jason wrote a lot of extra phrases to be shown at the start of each mission and when each stage is completed, but we didn’t have time to code up the UI to use them.

PROGRESSION

We ran out of time to do ramping difficulty over multiple chained missions. The idea was to start with a small board with only one flag, then expand the board and use two flags, then require matches to match a provided flag, then start scrolling the rows of timers so that you might lose a locked timer if you wait too long to pair it with others. We expected to have at least 10 missions by twiddling those factors. The mission in our entry is middle-difficulty, maybe 4 of 10.

POLISH

There’s lots of room for UI paint. Plenty of room for visual polish.

♥ §§§ ♥

Please come on over to The Bombay Intervention! Let us know if you stop by, and tell us what you think.


Leave a Reply

You must be logged in to post a comment.

[cache: storing page]