‘Reminisce’ Post-Mortem

Posted by
August 27th, 2014 5:29 pm

OS/X | Windows | LD30 | Source | Timelapse

I decided to write a proper post-mortem on the development of ‘Reminisce,’ especially on the experience of using cgame (my rapid game development engine/tool) to make a game. For more information on the design philosophy behind and the implementation of cgame do check out the paper (slightly outdated — from May — also links to a poster) I wrote on it for independent work at university.

screen0000049215

Editing the title screen in cgame’s in-game editor

Concept

When the competition actually began at around 7 pm I was out with some friends for dinner and was brainstorming game ideas. I thought maybe something modelled after Avatar, with a fire, water and earth realm, respectively with traps/enemies that utilize fire power (lava or flames), water power (flooding) and earth power (puzzles involving bushing blocks). Thus gameplay would have a different focus in each world, one on combat, one on speed and the third on puzzles. The idea was ambitious, but I wanted to start with a large concept and simplify it as I went, so that I wouldn’t have to grasp for ideas if I actually had the time later.

Eventually I dropped the combat (you don’t have weapons and just run away from monsters) and the water world entirely, and the game became mostly puzzle-based with later puzzles stretching across both hell and earth. To make it make sense story-wise I thought, “Ok, so you’re a dude going through his memories and they’re good and bad, hence the two worlds, and hence the title.”

Code

cgame made coding really easy with the entity-system model and live-coding. To add a new element to the game, say a door, I drew the sprite in the atlas, added a new entity with a sprite system, set the sprite atlas rectangle, created a new door system in the code, added the entity to it and saved it as a prefab. All this could be done without ever exiting and restarting the game, seeing changes live — as soon as I added the open property to the door system in code it appeared as an editor property in-game.

Then to add doors in a level later I just hit ‘.’ in the editor (which means ‘create from prefab’) then type ‘doo’ (or even ‘do’ — it’s an autocomplete field) hit enter and I have a door! To tie it to a switch I just select a switch and hit the ‘set’ button in the door system inspector, because cgame figures out that it’s an entity-type property and allows me to select the switch visually.

screen0000025368

Live-coding the door system (code on bottom right)

Ideally I would split the door logic into a generic door system which just exposes an open property and reacts accordingly, and a specialized door_switch system which would have a switch property and sets the door system open property based on the switch. Then you could have generic doors which may or may not be switch based — maybe have a door triggered by a scripted event instead of a switch, for example. But since this was a 48 hour compo and I was in a hurry I just put the switch property in the normal door system and went on to work on other things.

After adding the 'switch' property, which can be set with point-and-click

After adding the ‘switch’ property which can be set with point-and-click; also the new code

The prefab system also made it easy to construct objects in code. For example, the Lua statement that creates bullets in the quad-shooter enemy system is as simple as follows:

cg.add {
    prefab = prefab_dir .. '/hell-bullet-1.pfb',   -- the prefab is preset with the sprite etc.
    transform = { position = p + 0.7 * obj.dir },  -- position the bullet in front of us
    bullet = {
        creator = cg.Entity(obj.ent),              -- bullets like to remember their creators
        velocity = 8 * obj.dir,                    -- make the bullet go forward
    }
}

The cg.add function allows easy creation of entities in code, specifying systems and properties in Lua tables.

cgame’s built-in serialization capabilities made game save/load super easy. This is in fact how the portals worked — when you walked through a portal it would save the state of the exited world, then load it back when you came back, thus creating the illusion of time having paused when you left. I never had to write explicit save/load code for any of the gameplay entities, cgame handled it all automatically.

Art

cgame’s sprite system uses an atlas image, so I drew all the sprites into one big atlas. I used Pyxel Edit for drawing. Staying true to its live-editing philosophy, cgame listens for changes to the atlas file and automatically reloads sprites in game. So you can draw/edit sprites in the atlas and they’ll just update in-game without you having to exit and restart. This was great especially for editing the quad shooter animation:

Editing the quad-shooter animation in Pyxel and watching it update in the game/editor live

Drawing the quad-shooter animation in Pyxel Edit and watching it update in the game/editor live

Level Editing

I built the levels with cgame’s in-game level editor. This generally went pretty smoothly, except for two issues which I found to be pretty relevant from a practical level editing standpoint and would like to tackle before the next game project:

  1. If you make a level and then go back and edit a prefab, how should cgame propagate the property changes in the base prefab to all its intances? Right now changes aren’t propagated since the prefab link isn’t remembered (prefabs are basically like copy-pasting without any additional links). Unity, for example, has instance properties override prefab ones only if explicitly set, and so properties that aren’t explicitly set will get the new values from the updated prefab.
  2. If I play a level a bit and stuff has moved around, then I edit some parts of it and want to keep the changes, how do I merge these changes back into the original level situation given that things have moved due to gameplay? For Reminisce I would always load back the starting level scenario before editing.
The editor's duplication and box select functions make allow quick creation of levels

The editor’s duplication and box select functions allow quick level editing

The cgame editor interface takes a lot of inspiration from vim, emacs and Unity. It aims to be fully scriptable and is thus pretty easy to extend. For example, the physics system in cgame provides a visual polygon shape editor. This is simply written as an additional ‘mode’ for the editor (like modes in vim) and is not in the editor core at all. You could write your own such mode for systems you create — this could be useful for a camera track system for example to draw spline paths. The editor GUI itself is built with entities in the GUI system, so you could edit the editor GUI in the editor, or add editor buttons to physics if you really wanted to!

Sound

cgame has a sound system too, and the play_sound() utility function I wrote in the game code is as simple as follows:

function play_sound(file)
    cg.add {
        sound = {
            path = sound_dir .. '/' .. file,
            playing = true
        }
    }
end

So I just create an entity that’s in the sound system. You can see that I’m again using the cg.add function I talked about before. cgame doesn’t discriminate, anything can be done this way! And sound properties can be edited in the editor too — you can change sound gain, set loop state or seek around while it is playing in-game! The actual sounds in Reminisce were generated using cfxr, which is a Mac version of the popular sfxr tool.

In all, I learned a lot from this experience. The biggest thing I figured is that I was often really my own enemy more than cgame — just being tired, sleepy, stupid or lazy. cgame’s strengths played pretty well in a game jam scenario with all the live editing and coding. You’ll see many pauses in the timelapse, all places where I go, “Oh, wow, that worked out quicker than expected… Umm, what do I do now?” and ponder for a bit before moving on. I think it could work really well in the hands of an inspired, motivated and experienced developer, much like the ones churning out great games here at LD. This is why I hope to write some documentation on it soon and record video tutorials and such. I loved my first LD experience as a participant, and am looking forward to many more to come. Thanks for reading!


One Response to “‘Reminisce’ Post-Mortem”

  1. armixco says:

    Nice article. I also happen to have started reading a bit of your paper on cgame. Interesting. :)

Leave a Reply

You must be logged in to post a comment.

[cache: storing page]