It's been quite a while, but Doggins is still on the move. The game is nearing feature-complete status, and we've submitted it to the 2014 IGF. Here are a few current screenshots:
More information and behind-the-scenes images can be found at the Doggins development blog.
Creating an adventure game has been great fun, and Corona is one of the reasons it's even possible for us. The engine has been created entirely from scratch, save for the occasional code snippet I've plugged in. As a lifelong player of LucasArts and Myst-style adventures, I had a reasonably clear idea of what functionality the engine needed, but it's grown far bigger than the prototype I put together more than a year ago. Here's a brief rundown of how the game works.
Actors, Props, and Rooms
Doggins is built on a theatre or film set metaphor, with each location (Room) containing a mix of Actors and set dressing (Props and Items). Props are typically pieces of set dressing that can be interacted with (such as the light chain in the screenshot above), while items are things that can be picked up (like the mustache) and placed in the Inventory (fourth screenshot). All actors, and most props and items, have their own LUA file which is loaded when the room is created. Actor files contain sprite sheets for the character, along with a host of member functions that control him (Move, Flip, Idle, Rest, etc.).
We make heavy use of the Storyboard API, using it for loading rooms, as well as for overlays, including the Inventory and items that are interacted with in a 'close-up' view. Once I was used to it, Storyboard provided a helpful framework for both implementing the game and understanding its organization. Each Room is a LUA file laid out similarly to the Scene Template provided by Corona: local variables are forward referenced at the top of the file and created in the enterScene event, willEnterScene is used to set the room up to appear as it was when the player last left it (turning the light on, for example), enterScene contains touch functions for interactive objects, and exitScene disposes of audio and performs other cleanup tasks.
I typically don't use Storyboard's built-in transition library, as the "fade" effect changes the alpha of all objects in a display group, allowing you to see through them. Instead I've created my own "fadeIn" and "fadeOut" functions which create a black rectangle and adjust its opacity, better approximating a real fade. I do use Storyboard transitions for some item overlays, however.
I've nicknamed the Doggins engine the "Luna" engine, as his lunar adventure is both his and our first. The engine is essentially a LUA file filled with functions that execute common in-game tasks. These functions are referenced via global variables in the Corona SDK main.lua file.
A typical bit of game scripting using these functions looks like this:
local function toExtForest ()
walkTo(-300, roomFloor, "walk")
The walkTo function moves the character to a specific set of coordinates, using the "walk" animation and movement speed. waitForPlayer waits for the character to arrive at those coordinates, and then calls toExtForest. In that function, fadeOut is called, passing in the name of the next Storyboard scene to load when the fade is complete.
This allows me to write relatively readable code that can quickly be iterated on. I like to think that it's at least a little bit like classic SCUMM code, but Ron Gilbert
would probably disagree.
Creating my own adventure game engine is something I never imagined I would do. It's been a lot like playing an adventure game, actually: searching for clues, trying things that don't work, scratching my head, and then feeling a surge of excitement when I finally realize the solution. Puzzle-solving and programming have a lot in common. Hopefully solving the game will be as rewarding for players as creating it was for the two of us at Brain&Brain.
Thanks for reading!