[lisp-game-dev] LGDC010: Roto Mortar post-mortem

Patrick Stein pat at nklein.com
Tue Mar 30 14:33:54 UTC 2010



On Mar 29, 2010, at 1:23 PM, "David O'Toole" <dto1138 at gmail.com> wrote:

> I'd like everyone to post an entry postmortem

My game is called Roto Mortar [1].  When I started trying to come up  
with a game that I might be able to pull off in a week, I remembered  
an exercise from the book:   Game Design Workshop [2].  The exercise  
was to design a game with a one-button interface.

The concept I came up with for this contest was that you were trying  
to defend a base against attack.  You've got two mortar cannons.   
Unfortunately, their controls have been blasted.  Lucky for you, Ace  
Repair Guy Billy Bob has rigged one of them to rotate and hooked up a  
button that let's you tilt it while you hold the button and fires when  
you release it.

Here is the game announcement I made on my blog [3].

What I got done was the basic shell of the game.  There is a quick  
title screen with a message from Billy Bob setting the stage.  Then,  
you're plopped into the game.  Another message from Billy Bob  
announces that he's gotten one turret back online.

The game scenery, enemies, and projectiles are all UV textured, X3D  
objects made in Blender with PNG textures.  The game uses shadow- 
volume techniques to overlay a range and angle indicator onto the  
scenery so you can tell where you're aiming.  Those shadow volumes are  
non-textured, X3D objects built in blender.

I used my own code for font-rendering in cl-OpenGL using zpb-ttf [4]  
to render the messages from Billy Bob and the opening title.  I used  
cl-png to load the PNG files (textures and Billy Bob icon).  I used a  
custom parser atop CXML SAX parsing to read the X3D files.  I used  
CLOS throughout and made much use of the PROGN method combination.

[1] http://nklein.com/software/roto-mortar/

[2] http://www.amazon.com/Game-Design-Workshop-Prototyping-Playtesting/dp/1578202221

[3] http://tinyurl.com/ykeahl8

[4] http://nklein.com/2010/01/better-text-rendering-with-cl-opengl-and-zpb-ttf/

> 1. what did you learn?

I had read about Shadow Volume rendering in OpenGL several times  
before.  This is the first that I actually did it.  I could probably  
do it again now without references.

I had a bunch of my methods return a new 'screen instance if you want  
to switch screens.  I think, if I were to do it again, I'd either make  
a robust check on the receiving end to ignore return results that  
aren't of type screen or add a slot to the screen class that is NIL  
until it's time to switch screens.  As it was, I accidentally returned  
T or a mesh or something incompatible from my event handlers way too  
many times (especially by the end of the second all-nighter).

> 2. what went right?

I drew a simple UV cube in Blender.  I exported it to every choice on  
the export menu. After looking a bit, I opted for X3D.  It's badly  
structured XML, but not too hard to parse.  (I say badly structured  
because its lists of number are all encoded into strings.  Rather than  
stuff like <coordinates><coord><x>3.5</x><y>2.0</y></coord>...</ 
coordinates> or even: <coordinates><coord>3.5 2.0</coord>...</ 
coordinates> they instead have attributes of comma-separated lists  
coordinates="3.5 2.0, ...".)

Anyhow, I think X3D was a good choice... easy to get going.  And, with  
baked textures from Blender, things looked pretty good.

I was glad I had already published the font-rendering code cuz I could  
otherwise have a day there.  As it was, I just pulled in the font.lisp  
I had published earlier [4].

I used SBCL's save-lisp-and-die to make a command-line executable and  
Platypus to wrap that up as an OS X executable.  Those both worked  
great.

> 3. what went wrong?

As I mentioned, having each event handler for a screen possibly return  
a new screen seems like a cool, lispy idea.  Really, it is easy to  
mess up when you're tired.

I spent lots of time, too, trying to figure out which attributes I  
hadn't saved that I should have in one place which screwed up things  
in another place.

I also spent way too much time working around the OpenGL matrix  
methodology.  What I needed to do for my direction-indicator and range- 
indicator was... translate to where they need to be and draw them at  
the appropriate angle and scale.  What I wanted to be able to do is  
set up the angle and scale and then translate things and draw.  If  
OpenGL had more room available on the :projection matrix stack or  
another :model-local matrix after the :model-view, I could have reused  
code much more.  As it was, I had to make some custom draw code for  
these objects to get the rotation and scaling to happen after the  
translation.

There is a whole list at [1] of things I wanted to get done in a week,  
but didn't.

There may well be an option to CXML to get it to ignore the DOCTYPE  
declaration. But, I just manually removed them from the X3D files to  
keep CXML from trying to fetch them.

> 4. what's lispy about my entry?

In the game-play itself? Nothing.

In the implementation, I used PROGN method combination to great effect  
here. In particular:

(defmethod update-item (item delta-time)
    (:method-combination progn :most-specific-last))

This way, the base object can track total time elapsed since some  
point, but derived objects can use either that total time or the most  
recent delta or an intermediate classes total time since some other  
indicator.

The XML parsing also makes use of interning symbols to avoid lots of  
string compares.

> 5. what interesting algorithms or designs did i use?

The basis of the X3D parser was generated from other Lisp code that I  
was working on a few weeks back.

And, the PROGN thing was pretty cool.

And, the shadow volume technique is pretty flexible for projecting  
stuff onto surfaces.


-- Patrick <pat at nklein.com>




More information about the Lisp-game-dev mailing list