Flexible Interactions


Part of the point of a game is to interact with the user. Sometimes this is fairly straightforward -- user hits "up" key, paddle goes up; "down" key, paddle goes down and oh, by the way, if the ball comes close enough to the paddle, it should bounce.

However, a pong game is probably not going to add something to your inventory or send you through a portal to another world (I mean, maybe it should... but it probably won't). Games with more complex scenarios need a more flexible way of specifying possible interactions. Steam+SPARK is not hugely complex (less than 300 lines of "engine" code), but the tools I want to use to tell my story demand something more reasonable than hard-coding every possible interaction. I need a better way.

What I came up with instead is a kind of "events" system. There are several different kinds of events that can get triggered during the course of play:

namedescriptionexample
trapTriggers on location.
Player walks over a certain floor tile (hence the name "trap").
hitTriggers on bump.
Player walks into a Prop or NPC.
enterTriggers when scene starts.
New scene is loaded.

So, when the user triggers an event the game needs to respond to, then the game should react appropriately. What's appropriately? Well it changes for every situation of course! So not just the event to listen to, but what to do with it must be specified flexibly. What's most flexible? Code! However, perhaps it doesn't have to be very flexible, we're not doing rocket science, just giving the user some feedback. So this leads to a simple language with a restricted vocabulary for a well defined purpose.

This is sometimes referred to as a Domain Specific Language, or DSL. Lisp is champ at doing DSLs.

Here are the commands, or actions, that I decided I needed to tell the first part of my story:

actiondescription
tellDisplay a System message.
sayDisplay dialogue from a character.
addAdd an item to inventory.
dropRemove an item from inventory.
jumpJump to another scene (all scenes have names that can be referenced).

So, say I want to provide an opportunity for the player to pick a COIN up off the ground -- I could script it like this:

((add COIN)
(tell "You found a COIN!"))

This gives me a lot of flexibility, but it's kept out of the main code and with the scene data where it belongs, making it easy to understand and change.  Here's a slightly more interesting example from the first scene in Steam+SPARK using some other commands I haven't described yet:

((trap 0 (4 1))
 (missing? PASS
       (say ME "Oh! I've got to have my PASS for the Steam-bus!")
       (done))
 (missing? PROJECT
       (say ME "Wait! I need my PROJECT for the Science Fair!")
       (done))
 (jump YARD))
This  event is triggered when the player moves onto the tile at 4, 1. If they haven't found the PASS yet (it's not in their inventory) or the PROJECT, then the main character mentions what's needed and then the event is done until the player triggers it again (hopefully after finding the missing items). Once they have them both in inventory, we jump to the next scene -- the YARD that Elektra must walk through to get to the Steam-bus.

Big super deluxe games often do something similar because it helps with division of labour. A "level designer" doesn't have to be a dedicated or professional programmer to describe how the player can interact with their level. A handful of commands under their belt and they're ready to go -- and much cheaper too...

Get Steam+SPARK

Leave a comment

Log in with itch.io to leave a comment.