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.

Friday, April 19, 2013

Polymorphic vector operations for JavaScript

I wrote a small vector math (linear algebra/geometric) library codeheart.js because any kind of physical simulation for a game becomes awkward and redundant when implemented purely with scalar expressions. My current design is the result of several radically different experiments. I'm satisfied with the blend of special- and general-purpose code. It seems neither over-engineered nor too limited. The features that I sought were:
  • Support functional addition, subtraction, Haddamard/array multiplication and division, dot product, magnitude, and direction
  • To allow implementing polymorphic math routines, allow the same set of functions to operate on vectors:
    • of any number of components
    • with differently-named fields (e.g., xyz vs rgb vs. st)
    • implemented as Javascript arrays
    • from other libraries (especially box2d.js)
    • ...and Javascript Numbers
  • Simple for me to maintain
  • Unlikely to exhibit hard to diagnose bugs (i.e., not too clever)


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.

Saturday, April 6, 2013

Shooting Mechanics for Spy Game

I put in some more work on my spy-themed virtual board game tonight. I added sound using fMOD and implemented shooting mechanics:

Tuesday, April 2, 2013

Spy Virtual Board Game

I've been working on a spy-themed virtual board game as a hobby project from a game jam last weekend.  Unfortunately, I had the flu and couldn't really complete the jam, but I did make enough progress on the game from scratch to become excited about it. It already served the purpose of helping to flush bugs and motivate new features for G3Dcodeheart.js, and mongoose, the main libraries that it uses. I hope to put in work from time to time as a hobby project.

The game uses multiple screens. The main screen is the game board seen by everyone.  Each player also has a web browser (ideally on a multi-touch mobile device, but any HTML5 browser works) to view his or her private hand of cards and initiate actions. There are no controllers used except for these browsers.

Here's a photograph from the first time I successfully connected the mobile device to the main game using a QR code and an iPod's camera:


At that point, my goal was to make a 3D tactical game, inspired by XCOM.  The game quickly evolved into this virtual board game:

Main Screen

Mobile Screen

The switch to board game mechanics and visuals was initially motivated by the limited time that I had to create artwork for the game jam. However, as I started to map out the gameplay, I realized that the increased abstraction of a boardgame allows much deeper gameplay.  A tactical spy game at a simulation level would turn into Splinter Cell or Monaco (both fine games), where fine-detail movement, combat, lock picking, etc. dominated.  I wanted much higher-level and emergent gameplay, such as planting evidence, conversations, crafting (MacGuyver & A-Team style). Abstracting interactions (similar to Munchkin's abstraction of D&D encounters) allows the player's imagination to fill in details as well, and imagination is the best graphics (see Doom I, Alien, and...books, etc.).

Tonight I implemented the animations for characters picking up, dropping, and giving each other equipment, as shown in this video:


The current implementation is currently 1421 SLOC in C++ and JavaScript (including the object database) and about 3MB of image data files. That's tiny by most project standards but already large enough to concern me. Hobby projects bit-rot quickly because they aren't tested on daily as the underlying APIs evolve. This is also code with a substantial amount of multithreading, which greatly increases the logical complexity and risk that large amounts of code have bugs. There are about 10 threads active at all times to communicate with the mobile devices and load resources to them over asynchronous channels.  That's necessary, but also nine too many for comfort.

When I next have an evening to hack on this, the next step is debugging some instabilities arising from all of those threads. I can then move on to implementing actions taken using the fun equipment and skills that are currently in the game in name and stats only but don't yet function.



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.