Jagpie: A journalling game
I have been working on a long project to build a video game. I am building a story-driven tactics game using the MonoGame framework.
As a beginner game developer I am learning a lot about programming in C-sharp and managing the game UI elements but it is hard to stay motivated on a project that might never end.
I have some time off this week and initially I was planning to spend the time working on my game but instead I got interested again in an algorithm that I am struggling to implement in Computational Geometry (I might make a separate post about this).
So I wondered. can I try making a game in a day?
Quantity over quality
As always I am inspired by the team at Sokpop and their ability to churn out many games. In particular Ruben Naus talks about "quantity over quality" as an ethos for getting better.
Also I have been inspired by UFO 50 (a collection of 50 minigames) and some of the fandom surrounding it.
It makes me want to explore trying lots of different game genres - what if I made a small platformer, what if I made a metroidvania?
And so last night I couldn't fall asleep because I was thinking of an idea for side scroller around journalling.
The idea
You write a journal entry and through the act of typing you allow a magpie to explore the world and collect ideas from your writing.
I was inspired by Buster Benson and Kellianne's 750words.com which encourages users to write 750 words every day as a journalling practice.
I am hoping I can introduce some of the concepts I read about in a post about local-first development patterns.
Dev log
With a goal of having something finished by the end of today as a personal game jam I am writing this post to log my thoughts and experiences with the project.
1100 Start!
Start writing the blog post. I'm glad that I set up this blog already, it makes it very easy to start typing something new. I am resisting the urge to start optimising how the blog looks.
I am listening to the soundtrack for Hollow Knight to get the vibes going.
1130 Actually start
Ok, enough writing, let's start making some code. I want to build this as a web game. I'd like to host it on my existing home page https://beho.dev. Ideally this should be separately buildable and a separately deployable unit of code but maybe let's not worry about that just yet.
1200 A game is born
After some playing around with the existing homepage, but these are hosted with Preact and firebase libraries which I don't want included in the game.
I think it makes more sense to start a new repo and host the game on a subdomain. That also makes it more flexible if I want to move the game in the future.
So not as much progress as I would have liked but I have a window with a cornflower blue background.

I have copied some existing website code to set up a vite server that will compile my typescript into a single build artefact along with any images I need.
Let's continue!
1230 Web hosting created
I've got a web host set up on Deno Deploy (Classic) which has a nice free tier. They make it easy to point a subdomain to their application and they even set up certificates for me. Just need to wait for the DNS to resolve.
As for the game experience the main game play is built around one textarea. So I'll dust off my DOM API knowledge and get that to be rendered to the screen.
The game is now viewable at https://jagpie.beho.dev
1300 design research
Doing some research in to the design.
I quite like the aesthetic from this PC-98 dating sim , perhaps I can recreate some of the ideas here for arranging the panels in my user interface.

For now let's start researching images of magpies to get a feel of how the main character should look. It turns out magpies have some pretty cool colours going on!

1330 Some panel layout coming along
I've opened up Aseprite and started sketching out some layout for the application.

1430 Sketching Magpies
OK after getting into a fairly serious flow state I realised I need to be careful not to spend the entire day drawing birds.
I'm pretty happy with these results. I've probably broken all of the rules of pixel art.

I'm going to take a break now and go to the gym.
1730 the main game mechanic
It is about time started validating the actual core gameplay mechanic. I would like to have a little on screen magpie which moves at different paces based on how you have been typing.
I'd like to encourage the player to get into an uninterrupted stream of conciousness so depending on how long they have been typing for without a break, the bird will move more quickly.
1800 four states
I've managed to get a prototype working with just text. If keep typing in the text box then the magpie will progressively get faster and faster.
I'm going to try giving the magpie four states: "standing", "walking", "hopping" and "flying". If you start typing from standing we immediately start walking, and then in 30 second steps the pace advances to the next level.
Play testing it, I feel a slight stress to keep typing, I'm worried about losing the progress that I've made with my little bird. 30 seconds does feel too long though, maybe we'll try with 20 seconds.
Next I'd like to implement some side scrolling action.
1830 sketching terrain
Having a go sketching some terrain for background was fun. It makes me wonder if even I could have some luck procedurally generating it.
I'm quite happy with the results. I am wondering how to smoothly animate it - potentially with a parallax effect.
1900 drawing the sky
I had a go prcedurally generating a curve using the HTML 2D canvas API. Here's the code I have:
function fillUnderSine(scale: number, frequency: number, offset: number, heightOffset: number, color: string) {
// define the function for the sine curve we want to trace
function heightCurve(n: number) {
return Math.sin(n * frequency + offset) * scale + heightOffset;
}
// start drawing a path
context.beginPath();
// start at the left
context.moveTo(0, heightCurve(0));
// move across to the right
for (let i = 1; i < gameWindow.width; i++) {
// convert the x coordinate into Radians
context.lineTo(i, heightCurve(2 * Math.PI * i/gameWindow.width));
}
// bottom right
context.lineTo(gameWindow.width, gameWindow.height);
// bottom left
context.lineTo(0, gameWindow.height);
// draw the shape and close the path out
context.fillStyle = color;
context.fill();
context.closePath();
}
Let's ignore for a moment that this isn't actually how light in the sky works.
It's not terrible, but it does look a bit too smooth. Importantly we're losing the pixel art style - I wonder if there is some kind of anti-aliasing at play here.
We still haven't achieved our goal of producing a side-scrolling effect.
1930 modelling speed and distance
I've almost completely fixed the anti-aliasing with two commands.
// on the canvas element
gameWindow.style.imageRendering = "pixelated";
// on the CanvasRenderingContext2D
context.imageSmoothingEnabled = false;
I'm still seieing some anti-aliasing in the sky, presumably something inherent in how paths work.
I now have a crude model for distance, speed and acceleration. When the bird changes to a different pace the background starts to scroll faster but not immediately.
We set a maximum speed based on the current pace and then accelerate or decelerate accordingly.
pace = classifyPace(timeSinceLastBreak);
maxSpeed = calculateMaxSpeed(pace);
// increase until we hit max speed, at first linearly and then a bit more quickly
if (speed < maxSpeed) {
speed = Math.min(maxSpeed, speed + Math.max(0.00001, speed * 0.05));
}
// decelerate if we are going to fast
if (speed > maxSpeed) {
speed = Math.max(0, speed - Math.max(0.00001, speed * 0.02));
}
// assume 60 calls to this update method per second
distance += speed / 60;
In the draw method I can debug by printing directly on the screen
context.fillText(pace, 0, 10);
context.fillText(`distance: ${distance}`, 0, 20);
context.fillText(`speed: ${speed}`, 0, 30);
Next I think I'd like some sprites for my magpie.
2000
Some sketching later and I have a first sprite for a bird mid-game.
Fortunately there are some videos on YouTube with slow motion footage of magpies walking. Let's see if I can make some animation frames.
2030
Adding six more animation frames it looks like I've got some approximation of a bird that can walk. Let's see what it takes to get it rendered on the HTML canvas.
It looks like this article by Oscar Lindberg is just what we need.
2100
It looks like the Canvas API for drawing an image, was designed for rendering from sprite sheets! It allows you to specify a rectangle from the source image.
drawImage(image,
// source rectangle
sx, sy, sWidth, sHeight,
// destination rectangle
dx, dy, dWidth, dHeight
);
I can model loading an image as an image element that never gets added to the DOM.
function loadImage(url: string): Promise<HTMLImageElement> {
const image = new Image();
image.src = url;
return new Promise((resolve, reject) => {
image.onload = () => resolve(image);
image.onerror = reject;
})
}
OK that seemd to work. Time for some dinner. Next step is to loop through the animation frames as time goes by.
2400
After dinner I decided that I'd done enough for today. The game is not complete but I am very happy with the results. I'm looking forward to finishing this project.

Wrap up
On reflection I spent around:
- 1.5 hours on hosting and blog setup
- 0.5 hours on research
- 2.5 hours on graphics
- 1.5 hours on coding
- Total: 6 hours
If I wanted to get the project closer to completion I think it would have been better to focus less on graphics (or get better at making graphics quickly). One approach would be to use smaller sprites - my bird sprite came out at 52x30 pixels.
I think realistically this game will require another six hours to complete - so realistically for a real one-day game jam either finding more time or cutting scope will be essential. It also would have been quicker if I hadn't been writing this post along the way.
In future I would like to focus on validating that the gameplay mechanic is fun as early as possible.
Thanks for reading. If you have any questions feel free to contact me at inkpot at beho dot dev or find me on BlueSky.