Spinning a Persistent Yarn
Ever have a conversation with a sentient factory? With YarnSpinner for GDScript, you can!
There’s a lot to unpack here, so let’s take a step back.
I had the skeleton of a game, but not the connective tissue; the pieces existed, but there wasn’t a cohesive experience, a sense of moving from A to B. I’ve been working at adding persistence, which has taken some rearchitecture.
I made some early system decisions that I needed to remove, such as assuming that the game would always be in “conflict” (which is how I refer to the card battling). I also simplified and streamlined some of the underlying systems.
I built out some additional layers of persistence; in addition to the game configuration, there is now the active game state and the progression. The player’s current hull is in the game state, their name and memories of what they’ve accomplished are in progression.
This allowed me to finally the enable “Continue” button and add some logic to “New Game,” which works now. I have a mockup of the introductory cinematic, but how do you start a run?
I had previously experimented with YarnSpinner and built a simple encounter system, but beyond being able to talk to an Outpost (who asks if you have any string), I hadn’t fully fleshed it out.
This past weekend, I rewatched Alien (1979) with my 11-year-old at the Little Theater in Rochester. She loved it, and I was inspired by some of the user interfaces. I’m definitely trying to echo some of the initial pacing as well, and it was a good tonal reminder.
So, the user interfaces; there was more white and blue, but a lot of stark interfaces and chunky terminals. There’s no need for a keyboard in-universe, and frankly no need for a screen, but I can justify that the player can perceive interactions through a virtual monitor as a real-world anchor.
Drawing from the opening credits of Ghost in the Shell (1994) and Sneakers (1992), I created a text-only field of static that coalesced into characters. I also really like the text art of Effulgence RPG.
The sequence has multiple stages. I calculated the maximum columns and rows with a monospaced font, then rendered a grid of random ASCII characters. The next phase has a couple of passes; the first places the text, then the second eases the amount of random characters until just the text is shown. This two-pass approach makes the text appear out of the noise.
YarnSpinner waits for input, then when moving between lines, chaos returns, the text changes and the chaos clears again. The loop continues until it runs out of lines. The final line fills the screen with chaos, then shuts off.
I used FMOD for the audio, but tried a couple of different techniques. Each frame of chaos is accompanied by a small sound, which is a hard drive defragmenting processed with Reaper with a gated slice, then exported the first 100. These went into a multi-instrument. There’s a second sound effect that triggers when the text is revealed; this is a failing hard drive. Finally, there’s a sound effect loop over the background with logic for both the intro and an outro, triggered by a stop event. Finally, there’s a music bed with a similar loop and ADSR.
The options work behind the scenes; if you choose damage, you take damage, if you chose scrap, you receive scrap. Colors change based on the quality of the choice you made.
There’s a lot of little touches that went into making that short exchange, but it’s a foundation for a lot more. I can reuse that dialog system for any communication; the character name comes from YarnSpinner and I can set the theme to whatever I want to indicate a threat or hostility level.
Now that I have this dialog, the sequence will be:
- New Game
- Specialization Selection
- Intro Dialog
- Map (choose a node)
- Conflict
- Map (choose another node)
- Encounter
and so forth. Specialization select doesn’t exist, but it doesn’t have to be complex, it could be a secondary panel on the main menu. There’s one specialization right now, I could skip it for now, but I want to remind myself to add some options.
Thanks to the feedback from the RocGameDev Discord (especially soliloquy, who called out linear transitions) and assist from Paris from Yarn who helped me with an implementation and fixed a bug I found.
Want to learn more? Join the Null Band Games Discord, it’ll be great to have you!