Adventure Gam Jam 2023

I took a two-week break from my current game project (“Twin Towers”), to experiment with a few ideas for my submission to Adventure Game Jam 2023 on itch.io. Just barely made the deadline 😀

My ongoing adventure game project is eating up a ton of time, even though it isn’t even particularly large in scope. I am thinking a lot about ways to tell stories about Amy’s world in smaller increments. Another issue I’m facing with writing adventure games, or generally story-driven games, is – I already know all the answers! Don’t get me wrong, it’s fun to write and think up stuff, but there’s no surprise element left for me as the author. Especially after testing every turn over and over.

So, I had a few goals and questions for this jam:

  • Generate a procedural world to explore
  • Can I create stories in that world procedurally, too? Something that surprises me, when playing my own game?
  • Exercise my existing lua script dialogue framework for Unreal Engine

In the end, I still don’t have an answer to automated story creation. But there is some groundwork now that I hope to expand on. My jam result in itself isn’t all that impressive, but there were so many lessons, I had to write it all down in this post mortem. Hopefully, you find it interesting, too!

Application structure and test setup

I was going for a 3D application in UE. Since my main story engine runs completely in Lua, my first step was to implement what I had in mind essentially as a text adventure.

The basic layered structure of the application looks like this:

Framework

  • Lua story: interaction functions, some game state (did we talk to this character before, does the player know this piece of information already, etc.)
  • Lua map generation: builds data structure for locations, paths, places items and characters

Text Game

  • Lua game loop: a simple console-based interface exercising the map generation and story functions

Actual 3D Game in UE

  • Lua / UE interface (C++ and blueprint): a thin layer of functions to get game state from the Lua side to UE, and user actions back to Lua
  • UE game: the 3D representation of the game, and handling of user input (with its own game loop)

This setup had a couple of advantages:

  • rapid iterations – write and run, no build times
  • conveniently debuggable Lua console application (in Visual Studio Code, for example)
  • easy to scrap ideas and try out something new, without having to re-implement UI, 3D interaction logic, etc.
  • running test scenarios for story logic would be really simple
  • clean separation between story logic and UI

Map generation

Early on, I imagined the map consisting of a series of connected “islands”, where getting from one island to the next would be fun and somewhat challenging. Sort of a generated stage, which works independently of the main story.

So, the majority of the two weeks went into implementing graph algorithms in Lua, keeping in mind that the layout of the connected islands in the 3D game should be very straightforward. No time for complex graph layout algorithms!

I settled for a center node surrounded by more nodes. Connections between them are randomized and intersection-free. “Bridges” connect the outer circle to the next island. Here’s what it looked like in the end:

(There are some hidden locations, too: single nodes attached to some other node. These can easily fit into the “gaps” between the main nodes).

To test and debug the map generation algorithm, I delved into learning graphviz. This proved tremendously useful! Completely disregarding beautiful visualization, I had an easy way to check the structure of my generated game graph:

The “tiers” are the islands, the player starts at the top and has to get to the bottom. Locations are assigned different types (house, bridge, etc.) and are populated with characters and items to interact with.

Characters and relations

One of my main ideas was to not just randomly distribute characters, but also set up relationships between them, such as love, hate, parent/child. Additionally, more relations to items on the map are added, such as ownership, current possession (a character can “have” an item that actually belongs to someone else), want or need, etc.

This network of character/character/item relations was to be a seed for interesting story constellations. This turned out to be way too complex for a game jam, so the relationships are there, but unused by the current game.

Story / quest structure

Since story generation was not going to go anywhere, I eventually set up a main story and a few quests explicitly. There is still a procedural element to this, as characters and items are appearing in different places on the map with every new game.

(This simple randomization has drawbacks: you may encounter a key much earlier in the game than the lock – solution before puzzle.)

With the code to place characters and items already implemented, adding this handcrafted story on top of the generic structure turned out to be quick and easy, though! So I see a possible path towards generating stories by authoring “building blocks” and combine them in some way on a given map.

Moving around the map

The basic game mechanic for getting around:

  • as the player moves to a location, paths to adjacent locations are discovered
  • the player collects crystals to pass the bridge to the next island

Visiting locations and interaction

When you enter a location in the game, the 3D visualization is created on the fly from the information in the corresponding graph node stored on the Lua side. Items and characters are “interactables”, which I had already implemented. Only very little additional coding was needed to support the “point and click” mouse interface for this game.

Here’s a screenshot showing one of the locations, with

  • Amy (our protagonist)
  • A character she is talking to
  • two items: a trapdoor revealing a hidden room, and a crystal to use as bridge toll
  • a door to exit the location
  • the player’s inventory
  • two of four map parts that the player needs to collect to solve the main quest (visualizing game progress)

What’s next?

Most obviously, the environment is pretty bland now. Generating a more interesting map and locations would be a great start. Compared to designing, modeling and set-dressing a whole map manually, I see this as the greatest potential time saver for getting a story-driven game out more easily.

  • more types of places and buildings per island, with some structure depending on the type of area (village, open country, forest)
  • more item types with specific properties and behavior
  • more diversity in the look of places and items (there is a concept for “item roles”, so having many instances for “money”, e.g. coins, jewels, gold nuggets, … is possible)
  • a more diverse cast of characters, with attributes such as profession, age, etc. – which can be used to generate visually distinct individuals

A next step towards story generation could be to utilize the character relationship concept to add some smaller side quests and stories.

  • E.g. Alice has “lost” an item, and it turns out to be stolen by Bob. Get it back from Bob and return it to Alice to receive a reward. The reward might be something needed for the another automated quest, or the main story.
  • Eventually this would lead to automatic generation of “puzzle dependency graphs”. At the very least, I could produce a puzzle structure that is guaranteed to be solvable, and enrich it with meaning and story manually.

State of The Game

Most surprisingly, my adventure game is taking way longer to finish than I thought! I’m working hard to get a polished demo running that I can show around. Will have to make a new, more reasonable estimate for the whole game then, too. For the time being, here’s a screen from one of the more or less finished locations – my current motivational desktop background. Feel free to put it on your screen, too!

Amy discovers the workshop area

Follow my twitter account @scruffyowlgames for regular dev updates!

Amy’s Prologue

Yay, I did it! As part of the Narrative Game Jam #5 on itch.io, there is now a playable prologue for my upcoming game. It is still very rough – a game jam submission after all – but a big milestone for me: the first public artifact introducing the game world. And there’s finally a title for the project, too. Give it a spin, it’s a click-through story that should take you only a couple of minutes.

Eventually, I plan to integrate this as an intro into the actual game.

Initial feedback on my main character, Amy, has been very positive (thanks to everyone for encouragement!). I’ve also invested far more into worldbuilding already than initially estimated, so, if all goes well, there will be more episodes of “Amy Sparks” adventures in the future.

Follow me on twitter or itch.io to get updates on how the game progresses. It’s still a looong way to go, but I’m deeply enjoying the journey 🙂

Unreal Adventures

Having done some smaller games, it is time to start something bigger and better! I am currently working on an action adventure title using Unreal Engine, involving a slightly nerdy fox lady named Amy, in a world populated by animals and robots in peaceful coexistence. There’s an epic story, of course, which I already had to divide into three parts to arrive at a manageable project size. At the time of writing, this project is in week six, early prototyping stages. Follow updates on my twitter @scruffyowlgames!

visual development – no logic in here!

Tiny game #7: Ascent – my first game jam!

This is my submission for the GameDev.tv 2022 10-day Game Jam – first game jam ever. It’s been intense, but totally worth it!

You can download a Windows executable (and the Unity source code, if you’re interested) at the above link, or play the game in your web browser by clicking on the image below:

click on the image to open the game in a new window – webgl-enabled browser required!

The theme for the game jam was “Death is just the beginning”. I’ve always been fascinated about the great circle of life – how life began from nothing, and evolves in a constant cycle of reproduction and decay, where the deceased provide the raw materials for the next generation of life. Struggle for survival and pressure to evolve.

So, huge concept, and almost no time – an ideal combination 😀

The major challenge (and charm) in doing these “game thumbnails” is to find a way to boil your highflying ideas down to a workable solution. Narrow the scope to a central mechanic that expresses the idea. And don’t forget it should be fun to play!

Game mechanics

What I came up with is a game about evolving a tiny deep sea creature, to eventually reach the surface and leave the ocean behind. It’s meant to be a rather chill experience, so the game play is not too tough. I had to throw away most of the ideas popping into my head all the time, but the major elements of the concept are there:

  • Your creature starts as a baby on a primitive level, feeding on the plankton floating around. It’s vulnerable at this stage, likely to get eaten by bigger fish.
  • Once grown up, go look for a mate! The only phase of the game where there’s some time pressure.
  • To produce offspring, the player needs to collect biomaterials left behind by deceased sea creatures. These get more complex as evolution progresses.
  • The baby becomes the new incarnation of the player, slightly more evolved, and the cycle continues.

I had this idea about a “spark of life” or “soul” that exists independently of the body. That made it into the game as a sort of failsafe:

  • When the player creature dies (gets eaten, for instance), you enter a “netherworld”, where your spirit needs to find a new suitable body.
  • Only baby creatures of your own species are suitable. Find one and the game continues, the only penalty being thrown back one evolution level.
  • Touching any other adult creature in that state means “Game Over”. The only way you can truly die in this game.

Lessons learned

These mechanics are still pretty complex, and not anything players will be familiar with from the get go. So, the major problem turned out to be how to communicate what’s going on to the player. All the required sprites and animations would have broken my back for sure – so in the end I had to resort to text messages explaining some things to the user. That actually worked out ok, and I ended up with “only” around 50 handdrawn sprites.

The scope of the game felt just right coding-wise: Develop the concept at speed, disregarding a lot of production code best practices, just to make it work in time. Knowing the code is discardable anyway made this a very relaxing and fun experience (of course, there was still cursing and pulling of hair).

Prototyping the prototype: I spent the first 2 days just thinking and making notes on paper. The first implementation used squares and circles as sprites, no animations. That approach really paid off, and saved a lot of time, even when the final result is still just a prototype.

This was the first game where I was able to add sound! Had to resort to free assets available on the internet, but it adds so much. Learned a lot about how to do sound mixing in Unity.

So what?

All things considered, I’m pretty happy with the result. Just exploring the concept conjured up a vision of “the real game”, which would be at least 10x larger, involve majestic underwater visuals, tons of cool creatures, more challenges, etc. This could look fantastic in Unreal Engine, with partly procedurally generated 3D creatures, lighting effects, and so on. There’s a project!

Also, I’m absolutely planning to participate in more game jams. It’s intense and exhausting, but a priceless experience. And who knows, someday there might be real commercial game coming out of one of these.

Tiny game #6: Bones

A tiny edutainment game, inspired by the “find & click” prompt from the list of prompts from an RMIT Games class. Learn about the human skeleton!

Update: I published a vastly enhanced version on itch.io! Play it here.

click on the image to open the game in a new window – webgl-enabled browser required!

This took a lot longer than expected – I jumped at the opportunity to 3D model a basic human skeleton in Blender (it’s rough, but still anatomically correct), and went a little further than strictly necessary with designing the 3D environment as well.

Also, even though this is a simple game, the interaction handling proved really complex. Very limited use of physics simulation (otherwise, there’s bones flying about everywhere), defining and dealing with attachment points on the skeleton, user feedback (the talking skull, color markers, colored bones), auto-aligning a bone when the user picks it up, etc. The devil’s in the detail!

On a side note, I went almost insane about MeshColliders with WebGL again. Only by chance, after hours of frustration, I discovered I had to check “read/write” in the import settings of the skeleton model. Otherwise, the MeshColliders in the WebGL build simply wouldn’t collide. Everything was running just fine in the editor, of course.

Tiny game #5: Life in 10

A 10-second game! This is the first in a list of prompts from an RMIT Games class I decided to follow.

click on the image to open the game in a new window – webgl-enabled browser required!

Along with the prompts come some pointers at related games for inspiration. These are a few years old, so only some are still working out of the box – one of these is Queers in Love at the End of the World, a piece of interactive fiction in 10 seconds. I found the combination of urgency, intimacy, and epic end-of-the-world setting really appealing, so I went for “life in 10 seconds” as my topic – think big, right?

First lesson: the time limit is ridiculous! I had tons of subtle ideas for this game, but after implementing the first prototype that ran through in 10 seconds, about 90% went straight out the window. It was cool, though, because it forced me to strip down and streamline everything to the bare minimum. For instance:

  • Free player movement was discarded in favor of simple lane switching.
  • A numeric score display in the corner? there’s no time to even look at it. So I put symbols right below the player avatar.
  • I reduced the number of items to just 2 per lane, a “regular” and a “special” item.

Still, there is way too much going on. You probably need to play a few times to even realize how this works 🙂 Which is partly intentional, I wanted to play with the feeling of having no control, life speeding up, and not knowing what just hit you. As it stands, I don’t feel it’s too successful a game, but as an exploration off the beaten track, this was immensely valuable.

Note to self: I really need to add sound one of these days!

Tiny game #4: Groundhog Downhill

[UPDATE: I’ve published a slightly more polished version of this game here, give it a shot: https://scruffyowl.itch.io/groundhog-downhill]

This time I wanted to do something with 3D terrain and physics. Did you know groundhogs love having downhill contests in winter? Try to finish the course in under one minute! (My personal best is around 50 seconds.)

click on the image to open the game in a new window – webgl-enabled browser required!

I didn’t spend much time on optimization – the terrain is essentially a giant mesh, and there are a lot of unneccessary realtime light and shadow computations. It should run OK on a current PC, but my old laptop was aching a lot in fullscreen mode.

At first, I though about using Unity’s terrain engine and editor, but that turned out to be unsuitable for a game like this. It’s meant for huge natural terrains, as in an open-world game, but it’s based on height fields – and sculpting a race track with precision is pretty much impossible. So in the end, I modelled the track in Blender using curves, and added a simple polygonal terrain and a few extras here and there.

The physics engine is based on rigid bodies, so our little friend behaves much more like a tennis ball than a floppy soft creature. But it’s fun that way 🙂 I did add an extra force to make him stick to the ground just a little more.

Having this really rough implementation working in WebGL with decent performance out of the box is pretty cool! There’s a bug regarding mesh collisions in Unity with WebGL, though, which has been around for FOUR years and will likely never get fixed. If you check the bug tracker issue and related forum discussions, it is rather disheartening to see how a problem such as this is treated. It’s unfortunately not the first time I see quite relevant issues remaining on the table for many years without getting fixed in Unity. With any luck, someone in the community has come up with a clever workaround (which helped me out this time, too). But in the long term, these things make you wonder about their priorities and whether it’s time to explore other options.

Tiny game #3: Escape

It’s NaNoWriMo, and even though I’m not writing a novel, it’s the perfect month to work on a game with narrative!

There are some great GDC videos on narrative in video games by Jon Ingold from inkle. Over the years, they have developed a scripting language for games based on branching narrative called “ink”, which has recently been open-sourced. The system is completely text-based. They do provide a very lean C# API, too, so it’s almost a no-brainer to use ink for authoring the story backbone of a graphical adventure-type game!

In ink, a “game” is essentially constructed around pieces of content (text) presented to the player, and sets of choices to direct flow to other pieces of content. Programming logic is provided to allow state tracking and flow control. There are no concepts for “rooms”, “objects”, “containers”, “actors”, though. What about action adventure / rogue-like gameplay, where you wander around a dungeon, encounter NPCs, collect and use items?

So that was my challenge, and here’s the result:

click on the image to open the game in a new window – webgl-enabled browser required!

This is very much a proof of concept rather than a full game, but I am quite happy how it all worked out! Gameplay is completely driven by the following .ink text file:

// items that can be picked up

LIST items = nothing, soap
VAR inventory = ()

// states

LIST playerState = walking, (inBed), soaked, soaped
LIST bedState = (down), up
LIST manholeState = (closed), open, examined
LIST showerState = (off), activated

// locations
LIST locations = (none), BED, CELL, SHOWER, SHAFT

VAR playerLocation = BED
VAR prevPlayerLocation = none

VAR bedItems = (BED)
VAR cellItems = (CELL)
VAR showerItems = (SHOWER, soap)
VAR shaftItems = (SHAFT)

-> hub

// functions for moving around

// did we enter location x for the first time?
=== function first(x) ===
~ return x == 1

// did we just enter the current location from somewhere else?
=== function enter ===
~ return prevPlayerLocation != playerLocation

=== function moveTo(x) ===
~ playerLocation = x

=== function removeItem(ref itemList, item) ===
~ itemList -= item

// pick up an item from current player location
=== function getItem(item) ===
{ playerLocation:
  - BED: ~removeItem(bedItems, item)
  - CELL: ~removeItem(cellItems, item)
  - SHOWER: ~removeItem(showerItems, item)
  - SHAFT: ~removeItem(shaftItems, item)
}
~ inventory += item

// main story hub, switching flow to the available locations

=== hub ===
{ playerLocation:
  - BED: <- bed(->hub)
  - CELL: <- cell(->hub)
  - SHOWER: <- shower(->hub)
  - SHAFT: <- shaft(->hub)
}
<- inventory_actions(->hub)
~ prevPlayerLocation = playerLocation

-> DONE

=== bed(->back) ===
#cut
E S C A P E

The same dream, night after night.
A prison cell.
No way out.
One day after the other, your life passes by.
"Hope" is just a faint shadow of a word without meaning.
%%
You awake from restless slumber...
%%
%%
(any key to start)
%PAUSE%
#player
Zzzzz.... hrm?
Where am I?
Oh.
\*Sigh*
How do I get out of here?
%WAIT%

* [!anyaction!Get up] Ouch, my back! This "bed" is killing me. #player
  ~ moveTo(CELL)
- -> back
  
=== cell(->back) ===

+ [!trigger!shower]
    ~moveTo(SHOWER)
* [!pull!bed]
  ~bedState = up
+ {bedState ? up && manholeState ? (closed,examined)} [!pull!grating]
  Uaarrggh! Heavy! #player
  ~manholeState = open
  -> examine_manhole
* (examine_manhole) {bedState ? up} [!examine!grating]
  {examine_manhole == 1 : {manholeState ? closed : The gutter, covered with a grating.|This shaft looks REALLY tight!}} #player
  ~manholeState += examined
+ {manholeState ? open} [!use!manhole]
  {playerState ? soaped:{Are you serious?? It stinks!|It still smells!|Ewww!}|It's too tight, I'll get stuck!}#player
  + + {playerState ? soaped} [!use!manhole]
      Aah, all right.
      Down the rabbithole! #player
      %WAIT%
  ~moveTo(SHAFT)
  + + [!noaction!manhole] -> back
  - -
-
-> back

=== shaft(->back) ===
#cut
Carefully, you lower your soaked, soaped, slippery body down the hole, head first.
One last push, and off you go!
Holding your breath, you're hoping for the best.
%%
Freedom, at last!
%%
%%
(any key to restart - but why would you?)
%END%
->END

=== shower(->back) ===
{enter():{Take a shower, maybe?|}} #player

* [!examine!button] A big red button. #player
* [!push!button]
  ~ showerState = activated
  Yikes! #player
  Why didn't I undress first?
  ~ playerState = soaked
  * [!examine!soap] Disgusting.#player
    How can SOAP be so dirty?! 
  * [!get!soap] This slimy thing gives me the creeps. #player
  ~ getItem(soap)
+ [!trigger!leaveshower]
  ~moveTo(CELL)
  
-
-> back
  
 === inventory_actions(->back)
 * {inventory ? soap && !(playerState ? soaked)} [!use!soap] It's too dry! #player
 + {inventory ? soap && playerState ? soaked} [!use!soap] Yay, foam bubbles! #player
 Hmmm - lavender?
    ~inventory -= soap
    ~playerState = soaped
 - ->back

(Disclaimer: There may well be better ways to do this – it’s my first time using ink!)

On the Unity side, incoming text is processed by a StoryAdapter wrapper around the ink API. Player choices in the text are mapped to actions in the game environment by custom markup, which I made up in a very ad hoc fashion. E.g.:

  • the choice [!push!button] will be presented as a menu on the “button” object in the scene, when the player approaches it.
  • Location changes are choices, too: a choice with the !trigger! markup will be executed when the player crosses a special invisible object in the scene.
  • The #player tag sends text to a balloon displayed as the player’s thoughts.
  • #cut sends text to a cut scene screen (at the beginning and end of the game)
  • … and so on.

What you end up with, is a sort of MVC architecture of a game: the ink description is the model, being visualized by the game graphics. The player actions in the scene are sent back to the model, which then updates itself to advance the story.

Now, this is really exciting! It means:

  • the game can be played entirely in its text form! You can paste the above text into the Inky editor and play through. It’s not going to be very pretty, due to all the markup, but…
  • … authoring story and game logic is a breeze after the foundation is laid, or at least a lot easier;
  • … the game can be tested without any UI, for instance using automated randomized picking of choices;
  • … games could also be completely or in part procedurally generated.

The one thing I didn’t get around to is dialogue, which is a real shame. But something has to be left for another game, right?