One Snowy Day The Game
I made a small game that you can now play. Before you continue reading about the hows, whats, and whys, I recommend you play it.
Ok, but why though?
Earlier this year, around late January, I believe, I saw a Bluesky post where someone had made a Tetris game with social media posts being visible on the side of the screen. At the same point I saw a couple posts where the OP had clearly caught some form of poster madness, and thus the idea of a simple game mechanic had spawned in my head: making bad choices in a game should punish you by making you see random social media posts.
Because I was preoccupied with other things, I did not implement anything at that point, but I did write a basic plot outline and eventually sat down and wrote some more scenarios. Then I did nothing for about 3 months; I had thought about how to implement my idea and started building something in Godot, but for some reason it felt sluggish in more ways than one, and my concentration simply was not there to dive into a whole game engine. I ended up doing the most sensible thing anyone would do in such a situation; I wrote a barebones TypeScript thing that could drive a simple text-based game.
And over roughly the last two weeks I picked away at how to do certain things and ended up with something I think is okay for the time I put into it so far. The story ended up being not so connected to the initial idea as I had planned at first, but I think it is fine; after all, it is more or less the first creative writing like this I have done since I was in school.
How does it work?
The idea was really simple so that even my intellect could execute it. The heart of the whole operation is a function that re-renders the whole site, even though just replacing certain things would probably also work. The text that is shown to a user, as well as the choices, is stored in a big JSON file. That file holds each scene as an object, and each choice in it holds the id of the scene it should lead to. With only that, I can make all kinds of linear stories just by swapping out the JSON file and reusing the code.
But it was not enough for anything dynamic; neither looping scenes nor anything in the form of animation or broader gameplay mechanics was possible at first. For the main mechanic, floating social media posts driven by a hidden mental score, I needed the choices a player picked to influence the game state and trigger some stuff. I did that by simply giving each choice an array of effects it could use; then, when a choice is selected, a function iterates over all effects of that choice and calls whatever function is needed based on the effect’s id. Now it is possible to trigger whatever effect I want, all based on what the player does in the game. With a bit more refactoring in the future, I could make this process more modular and keep the base mechanics separate, but for now it works well enough.
The problem with looping scenarios is not really solved at the moment All that I implemented so far are some things to manipulate the scene objects, allowing me, for example, to delete choices so that one scene can be encountered multiple times and each choice can be picked only once. However, at the moment, the actual looping scenario… is a sham. I simply copy & pasted the looping scenes, and the choices get deleted from the second set of scenes. It is possible to do this better, but honestly, I did not feel the need to make this more work for me right now than it had to be. One pair of copies is not great, but it is something I can accept for now.
Tl;dr: The code reads scenes from an object that is stored as JSON, renders the text within into a basic HTML layout, and calls functions based on effects that are given to the choices a player picks.
Posts and Mental Meter
The main mechanic, of course, is the mental meter, a hidden score that is influenced by the player’s choices. A simple effect subtracts or adds to the meter, and every time it changes, the game checks if it is in certain areas. Then based on the value, some posts are spawned, respawned, or despawned. I made it so that it could only get worse as long as the player is below a certain threshold, and once that threshold is cleared, all posts disappear.
Because I wanted the posts to be authentic, raw, unfiltered social media madness, I decided to fetch Bluesky’s Discovery feed and pick the first ~150 posts. I also wanted there to be at least some posts if the fetching failed, so I made ~30 posts myself, but of course these cannot hold a candle to the true poster madness one can encounter on social media.
Animations
This probably took the longest time of the whole project. I wanted the posts to be annoyingly in the way, and for that, they would need to be in front of the on-screen text. However, I also did not want them to make the game unplayable, so a player needed a way to get rid of them in some way.
In order to not make things kaput on scene change, I gave the animations their own big div element and placed them with absolute positions so they could float around while the text and choices underneath them still worked. After testing some stuff with the Web Animations API, I could spawn posts, fade them in, and let them idle in place. At first I made them non-interactable; that way a player could still pick choices even if they did not see them.
After much more time I settled on a way of animating the posts when a player moves their mouse into them, nudging them away from the mouse and thus allowing players to clear the screen. I also added an observer that nudges posts back into the screen if they ever go astray. The main problem with animations was to make sure they did not interrupt each other too early or even stop any process that might be triggered only after an animation ends, like the kill animation.
In a more complex situation I think the animation stuff could need its own special logic, but I managed with the basic API and in the end only three or four relatively simple functions to handle everything animation-based.
Thoughts about future projects like this
For now I am going to do other things, but I did enjoy making this game. I can definitely see myself picking at the base code a bit more or, once I can find the concentration needed, actually porting this thing into Godot. Until then, I think I am going to write some more, even without any game mechanics that are meant to drive you mad.
