I'm Morgan McGuire (@CasualEffects). I've been working on computer graphics and games for 20 years at great places including NVIDIA, University of Waterloo, Williams College, Brown University, Roblox, Unity, and Activision.

See my home page for a full index of my blog posts, books, research, and projects.

Saturday, April 13, 2013

Spy Game Intro Animation

I've been putting in a few hours on my spy themed virtual board game on Saturday evenings. Today I refactored a lot of code to start ramping up from the single-encounter prototype with minimal mechanics to a scalable game engine.

The first distinction was having a container class for each encounter, which is a room.  I call these Locations in the code, since sometimes they might be outside or in areas that aren't "rooms" properly. The design calls for the players to move as a group through the Locations. Beating the challenge in one unlocks one or more paths. Satisfying the winning conditions for a mission will require traversing most of the rooms on a map.

Adding Location was straightforward, but I had to change all of the initialization code to build each one separately rather than dumping everything straight into the world. I ended up having Location as a subclass of G3D::MarkerEntity, which is intended for invisible objects like spawn points and gameplay triggers. This naturally gives it bounds and allows it to exist in the world without a visual representation.

Location manages placement of objects.  It ensures that every object is in a location that can be seen from the camera.  There was an ordering ("chicken and egg") problem in that midway through being initialized some objects insert other objects into the Location and the partly initialized objects don't have proper bounding boxes.  I solved this by having Location force any partly initialized object to immediately simulate itself for 0 seconds and then pose for rendering, thus ensuring a valid coordinate frame and bounding box before it can trigger insertion of other objects that might overlap the box.

The animation subsystem uses a class called Transition that computes splines between positions for moving objects and reserves the target position space with an invisible bounding box so that nothing can occupy an intended landing position before the moving object reaches it.  There is no dynamic physics in the game--everything is handled with ballistic splines that are computed as soon as an object begins to move. This design was inspired by a relatively old computer graphics paper by Barzel et al. on Plausible Animation: given the desired end state, solve backwards for the initial conditions that give you what you want. Notice in the animation below that the "tumbling" pieces always land face up, at no more than a 45-degree angle, and in locations that are visible to the final camera position.

To create some visual progress in addition to this infrastructure improvement, I made objects and the camera Transition to their starting positions instead of simply spawning there. This creates a nice camera track that zooms in to the starting room, and the playing pieces appear to rain down from above.  I think that this helps maintain the board game aesthetic, and only required four additional lines of code:


One visual direction rule that I've enforced throughout development is that objects should never appear or disappear. To remove or add a piece it must transition to or from an occluded area or outside the frame.  This makes them feel solid and real.

The whole game is now up to 1800 SLOC of C++ and JavaScript.  I remain concerned to be approaching 2k lines for the project but see few opportunities to reduce the amount of code at this stage.  Each C++ class is about 150 lines and I use a fairly deep inheritance tree to avoid code duplication.  The webserver aspect naturally introduces some boilerplate and the client is about 700 lines of JavaScript broken across a few files.

The next steps are to create a map with multiple locations and to transition between them.  I currently have mechanics implemented for picking objects up, dropping them, handing them to other characters, and shooting the pistol.  I'd like to take on other interaction mechanics next: conversing, melee weapons, and actions like lock-picking.




Morgan McGuire is a professor of Computer Science at Williams College and a professional game developer. He is the author of The Graphics Codex, an essential reference for computer graphics that runs on iPhone, iPad, and iPod Touch.