Within the hour, I’ll be posting a Unity WebGL game to Reddit, in hopes of collecting a statistically meaningful sample of responses to a questionnaire. In addition, through Tuesday, June 8 at 22:00 CET I’m conducting a raffle to encourage participation. This could go wrong in so many ways, and only right in one.
The characters’ anxious hand-wringing is my own.
Edit: The raffle is open!Click here to play the test app.
Performs best in Firefox and Chrome. Feel free to play the game as much as you’d like, but please only submit one survey form.
Terms and Conditions:
Persons over 18 who submit the survey between Friday, June 4 at 22:00 CET and 22:00 CET Tuesday, June 8, and enter a valid Steam profile name will be eligible for a raffle, to be conducted by June 20th, 2021.
-One first-place winner will receive a $75 USD digital gift card, sent through Steam. -Two runners up will receive $25 USD digital gift cards, also sent through Steam.
The winners will receive a friend request from my Steam account, “rhinocrate” and receive their digital gift cards as a friend-to-friend gift.
I wish it weren’t necessary to say, but I must reserve the right to disqualify participants based on evidence of ballot-stuffing or other forms of inauthentic or abusive behavior. There is a limit of one entry per person. Steam accounts must have at least one purchased game to be eligible for the raffle. If fewer than 20 valid responses are received, the raffle will be cancelled. No data collected will be used by me or anyone else for any purpose beyond tabulating results and completing the one-time raffle, nor will personally-identifying information (including IP addresses and Steam account handles) be distributed.
For Chronovoros, I created a Twine hack using custom macros inserted via Chapel’s Custom Macro Framework. These interact with the game’s custom CSS styling by adding foreground and background image elements. The image files, indexed-color PNGs with a 1-bit alpha channel, are crushed down to surprisingly small file sizes for their resolution. (GIF would be just as useable, with interesting implications for animation.)
Each set of images has its own macro, which when called passes a list of the desired image filenames and styling to a function which displays them. The images are scaled to fit the width of the window, and positioned to align either their top edge to the top of the viewport (the entire scrollable content of the page) or their bottom edge to the bottom of the window. An additional function is called every time the window paints (started by a call to its own macro on the first page of the game) which adjusts the vertical positions of the planes based on user scrolling; the vertical positions are calculated so that whatever the height of each individual image, scrolling completely from the top to the bottom of the window displays the entire image.
In practice, the multiplane hack breaks when the window is too tall. An aspect ratio should really be enforced with some kind of letterboxing scheme in the CSS. Having to write and call an entirely new macro for each set of image planes, while not complicated, is a little inelegant for a production-ready tool. Additionally, HTML5 special effects like contrast, color adjustment and blurring are implemented, but didn’t end up used on Chronovoros. Knocking the multiplane hack into something easier to use would be a good weekend project, for a later date.
Click here to download demo files and code for the Twine Multiplane Hack.
The Nordic Game Jam 2021 is over and–as far as I know–everyone survived. My team set out to make a “cinematic text adventure” you can play in your browser. Which wasn’t totally a thing, so we had to invent some stuff.
The theme, announced at 6:30PM Friday, was “Pending.” (Yes, you can imagine the initial confusion!) We had the story, setting and characters in rough form by mid-morning Saturday. All five characters were designed, the outline was running in Twine, my basic multiplane hack was running, and I had some of the layouts sketched out by the end of that day. (Around 1AM, for all of us.) Sunday was a sprint to get the temporary artwork replaced, layers assembled and compressed, story finished, and the bugs squashed. We got it submitted at 4:50PM Sunday–10 minutes to spare!
The story and interactive logic were written by Sejr Thompson. The character design and other hand-illustrated art were by Alexander Pechlivanidis. My own role was twofold: Designing the layouts–in an animation sense–of the independently scrolling background and foreground art layers, and hacking the Twine text engine to display them.
It’s a jam game, so there are a few rough edges, but not half as many as you’d expect. Reviews so far have been very good. Check it out:
A story world pitch deck for Alex McDowell’s “Planet JUNK” collaboration. 500 years after the collapse of our civilization, an admixed tribe live an Inuit lifestyle in northern Greenland.
Destroying the world in 30 years is depressing, but this isn’t my first time down this philosophical road. God kings and abject despotism have held civilizations together for thousands of years–many times longer than democracy. Tribal-scale survival for hundreds of thousands of years.
The horror writer must look where they don’t want to. I feel that we understand, on some level, how fragile our current civilization is. With rare exceptions, we dress up collapse stories to make them more palatable–as Romero zombies, as alien invasions, as fantasy-science-gone-amok.
As dark as it was at times, I wanted to look at a downscaling of human life, and find some beauty and hope in our own survival.
Among any number of negative habits is my tendancy to come up with an idea out of desperation at the last minute, play with it for a little while, and then fall in love and want to dump six months into it. Class workshops on different aspects of game design usually trigger this problem. This one is no different. (See also a simple RPG I’m trying to get working in Tabletop Simulator.)
As boring as it sounds, being a lighthouse keeper was as much about lifesaving as shipwreck prevention. A certain solitary type seems to have been attracted to the United States Treasury’s Lighthouse Establishment/Board/Service between 1791 and 1939 (which I think we can agree encompasses the “Golden Age” of lighthouses). Hoisting a dory into four-meter swells from a flooded gear room at the base of the tower in a pitch-black howling gale was a job requirement, and having a sturdy dog with sharp senses and no fear of the water along wasn’t all about companionship. (“Saved,” from the Louis Prang Collection commemorates a real lighthouse dog’s rescue of a child.) Denis Noble’s Lighthouses & Keepers is a good intro to this world.
I’m attracted to the character of an Indian man serving as a keeper sometime around the turn of the last century–someone like WWI US Army Sergeant Bhagat Singh Thind, who under the racial ideas of the time tried and failed to gain US citizenship when the Supreme Court ruled that, while “Aryan” he was not “white.”
I envision an adventure game made up of episodes (equipment failures, hurricanes, shipwrecks) with free exploration segments before the crisis portion triggers, in which you wander the lighthouse with your dog, read water-damaged books (real ones) about “race science” and other odd but consequential ideas for your character’s situation, and maintain the equipment. The offshore lighthouse serves as a metaphor for your own situation, literally defending a shore you can never reach. In these quiet moments, most of your default push/pull interactions are small acts of cleaning and maintenance (and scritching your dog). I want to make you complicit in the feeling that you’re constantly–even lovingly–maintaining this life-preserving tower.
In truth, an offshore lighthouse was manned by a crew of 3-4. Many keepers were married, and raised families at the facilities. The “solitary” aspect would be a departure from strict historicism–though sickness, injury or just plain poor manpower planning could easily leave a single hand to run a light. It was a quiet and hardworking life, though vastly superior to the sailing trade most keepers left.
I’ll leave you with this cutaway of Britain’s Eddystone Lighthouse, and an 1892 magazine article describing a visit there. It’s a fun topic to get lost in for a few hours. But for now, I think it’s best I leave it at that.
It was always an ambitious project, and not everything made it over the finish line.
What Got Cut
Glowing=on made it into the game, but no useful HUD feedback
UI Feedback: There’s a lot happening behind the scenes that the game doesn’t explain well. Every “CPU” (the brains of the robot, but also a physical robot part in the game) has randomized stats: Processing, Memory, Inputs and Outputs. These special stats aren’t altered by Upgrades, but they can be boosted by being close to (“meshing with”) nearby robots with higher stats. Processing governs how often an AI-controlled bot can reevaluate its choices. Memory is how much you can’t see but can “remember”–the fog of war. Inputs allow you a certain number of sensors you can equip. Outputs allow a set number of moving parts you can control. Likewise, damage isn’t well described, although your damaged parts do noticeably work less well.
Multiple “Car” Robots: Everything the bots do is designed around being able to take up more than one tile, dragging parts behind like train cars. Sadly, none of this made it into the final game, making even the word “convoy” seem slightly out of place. Bots sitting on top of other bots, and being carried along is–as best I can tell–entirely possible even in the demo build, but without trailers there’s not much point to it. So, no, we don’t get to play Tiny Convoy: Fury Road.
The Conversation Grid: The idea was to coordinate with your convoy without using words. You’d click on a friend and their internal map (from the Pathfinder) would come up as a grid of little icons. You could click on things to give them “ideas,” or to dissuade them from doing something dumb. It would have fed into their AI, not as a command, but as one of the AI’s competing ideas, with a boosted weight–sort of like the forgotten but brilliant “Galapagos.”
That Said…
Tutorial subs came very late in the design process, when it was clear playtesters couldn’t understand much of what they could do in the game–breaking design pillar #1
There is the start of a fun little game here. The many interacting systems largely work as intended, and cross-talk in interesting ways. The whole visual and audio presentation is inviting and detailed. With more content, fine-tuning and iterative playtesting, this could easily become a very good game.
Since I was mostly the programmer, I’d like to look at some of the systems that make the game engine work. But first…
Inheritance?
For me, what made this game possible was an email exchange with Michael Schmidt at Unity, in which he cleared up something critical. Since Unity regards every script as a different C# type, how can you subclass a script into different variations? More specifically, how can one script interact with another when it doesn’t know if it’s the class, one of the subclasses, or one of the subclass’s subclasses?
Crunchy McCrunch-Crunch
The key is that Unity will treat a subclass script as if it were any class up its chain of inheritance. When I subclass ActualThing into Upgrade, and Upgrade into Sensor, other scripts can reference a Sensor script as if it were an Upgrade script or an ActualThing script. So these lines are equivalent:
A Sensor script can then override, for instance, ActualThing’s takeDamage() function, and respond to it differently than, say, a rock would:
//in ActualThing:
public virtual void takeDamage(float damageAmount){
//reduce hp
//in Sensor:
public override void takeDamage(float damageAmount){
//reduce hp
//reduce sight distance
This is how basic object inheritence patterns can be implemented in Unity.
Systems
The Grid: The first programming challenge was an infinite, non-repeating grid. Based on my previous thinking on large pseudorandom world generation, I worked out a system that places BigTiles (containing a 10×10 grid of normal game Tiles and other content on top of them) from a list of available BigTiles. A given x and y will always generate the same BigTile, allowing the game to dispose of BigTiles it no longer needs, but generate them again if needed. Each game picks a random x and y offset to the starting position–a pair of C# ints of value -2 billion to 2 billion. The x and y offsets are summed and used as another pseudorandom seed to further shuffle things around atop the BigTile. The list of available BigTiles changes based on the distance from the game’s starting point, allowing the game to gate more powerful and challenging content. Specific BigTiles can also be forced to appear, like the starting location.
Lots of stuff, not-quite-randomly generated
Pathfinding: The bots use an A* pathfinding system. Niek worked out the initial code, and I adapted it to allow planning without executing the route (for AI reasoning) and to talk to the existing grid-based systems. This required a deep dive into Amit Patel’s A* Pages, a deep summation of pathfinding systems, which I highly recommend.
AI: The bots not being driven by the player have competing desires, to which they assign weights based on need and availability of a solution. The highest weight wins. They may reevaluate their options several times on the way to their goal, but the current “plan” has a sunk-cost-fallacy bonus attached, to reduce indecisiveness. The AI can query the Pathfinder (a separate script) for the “cost” of a path; it will also store the steps needed for pathfinding, to avoid a processing-heavy path recalculation for the action it ultimately decides to take.
I grew up calling them that; turns out they’re “Touch-Me-Nots”
Mystery Boxes: Remember how every BigTile has its own pseudorandom seed number? MysteryBoxes are a system that uses these to “randomly” shuffle things around on BigTiles when they’re generated–plants, upgrades, whatever you’d like. The plant growing on top of a toppled monument? That’s not scripted. One limitation is that if something on a BigTile gets destroyed, it’ll reappear if the player ever goes far enough away and comes back. A special subclass, the CPUBox, will generate a new CPU (the base of a new bot) if your party is smaller than the allowed size, or a random Upgrade if not. Like other gated content, the maximum number of party members increases with distance from your starting point.
“Tiny Convoy” is as a demo-length convoy simulator–a moving base builder–developed in Unity 2019 by Niek Meffert, Lucas Oliveira and myself. Playable betas for Mac and Windows can be downloaded here. The goal is to survive as a group of tiny robots in a big dangerous world: find power, upgrade your bots, and avoid dangers.
Remember the annoying escort missions in “Warcraft III,” where your soldiers kept hauling off to attack anything that moved, instead of protecting the things they were supposed to? It’s like that. Except your bots can’t attack anything. You are essentially robot herbivores. Looked at another way, “Tiny Convoy” is a herd simulator.
One-pager
As a small team in our first year Masters, the work was loosly siloed. Oliveira took the lead on modelling and texturing, Meffert was point on UI and the first version of the A* pathfinder, and the C# code base is about 90% mine. (I also designed the Touch-Me-Not exploding plant.)
1. Emergent visual storytelling–no dialogue, no scripted beats 2. Keep moving & exploring 3. No weapons 4. Cooperation is essential to survive & thrive
Design Pilars
Our goal was to marry emergence and progression in an interesting and satisfying way. We wanted to build a game in which the player could create in their own mind an emergent storyline around an algorithmically-generated world. If the content one encountered became too boring and undifferentiated, there would be no sense of progression, and little incentive to keep exploring. On the other hand, if too many things were deliberately laid in the player’s path at defined points, it would take on the feeling of an “on rails” story game, to the detriment of replayability.
Concept sketch
Every “Civilization” player remembers when the Mongols took their capital, and they rallied back to win. What happened was only the randomized game content interacting with the rules and the player’s choices, but it took on the quality of a narrative moment because it was different and valued by the player. Likewise, we wished to create moments like “When Little Blue got stepped on,” and “When we found the field of Touch-Me-Nots on the other side of the desert”—moments created entirely by the game systems interacting with the player’s choices, but which would feel personally meaningful.
The game loop for Upgrade Mode
To do this, we needed to construct a series of game loops, with systems of player feedback. We would gradually challenge the player by introducing limits on stock (not enough power available) and new sinks (dangers that damage parts). The game engine would introduce new content and changes to the starting conditions in a measured manner as the player moved farther and farther across the game world.