Quest of Tod flow

5min read

I recently finished up Quest of Tod, a little adventure game created for the js13k 2018 game jam (theme: Offline).

Tiny speed running adventure game, where you stuck inside unknown place controlled by strange machine. Goal is to collect all the keys and codes to unlock the exit before the time runs out.

You can play it here, if you haven’t tried already.

Getting started


This doesn’t cover too much about game code itself (you can check it out on github repository), but covers mostly flow of main idea and final product, while probably skipping some parts of it.

Once the theme was announced by js13kGames, I found Offline to be a very difficult theme to work with and after few days of pondering, scribbling and research I decided to wait until something popups to my mind.

After I found out that I can spare 4-5 days to develop something, I’ve started more research about what can fit this theme properly.

machines, computers.. turn them off.. fight robots.. hack the internet, hmm?

It was kinda hard to decide what can be interesting and fun to play (especially to me). So, final idea was not clear but wanted to start anything and shape it later.

Initial idea


I wanted to improve my skills with JS/Canvas and always wanted to make procedurally generated content and interesting game mechanics, so those were at the top of my list. Found out that nickgravelyn/dungeon already done amazing job, so I’ve used it as reference to make something similar which on first was the thing I want to have in game.

Main scope:

  • Procedurally generated map
  • Pixelated NES-like graphics
  • Fast paced gameplay
  • Some kind of player progression system
  • Story which will cover theme

Half way through I realized that the scope is kinda more complicated than I thought, and that I need to cut my scope down.

Main issue, make procedurally generated dungeon and make it look interesting with different elements (trees, flowers, ..), and while I was already at day 2 of 5 I didn’t had time to make generator smarter.

Sometimes it was generated almost properly, but not enough to keep me up going with that approach.

So, just ended with flexible tile map editor - Tiled Editor to draw map on my own and decorate it properly hehe, which cut down my scope and made me not doing something which I wanted so bad. But shaped kinda nicely, so lets say it was worth.

Day 2 v2


So after giving up on first scope item, needed to make game at least nice looking.

Ok, we are making dungeon. 48x40 map should be enough, let’s say tile size 8x8? Deal!

Well I’m drawing map, assets, .. but still don’t have final idea which will cover theme, and also dropped codebase hmm with nothing left.. I decided to start from scratch, only writing code which the game would need. I tried not to worry too much about writing reusable code, because I had feeling that this will fit properly in 13kb (I have one character moving around, meh lets say 200 lines?).

And at least I had something to start with, main dungeon skeleton which I reused for collision detection.

So after day, I was basically done with first map, applied assets, exported map json, and it was time to init player with movement ability.

Bad decision - Collision detection

  • first - was imagined as player which hitbox is not whole tile, but actually some pixels under the head or depending from which side it is colliding. But was driving me crazy with detection of next steps you are reaching when you are already stuck on one side.
  • final (and I’m not very happy with it) - basic AABB collision detection model where I actually reduced characters size to make it pass through 1 tile wide space, and where collision boxes are full tile size with trees and walls so it made it harder to run through (first thing that I’m going to rewrite, in case I decide to make something like post-compo version)

Struggle decision - Viewport/camera that actually works

Kinda hard times figuring this out to work properly, without getting camera run out of map bounds and similar effects. Used standard method to slice parts of a source image and draw them to the canvas.

drawImage(assets, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)

Since the viewport was changing, player needed to be rendered properly and the render position will be different than world’s position.

The conversion was simple after few hours of struggling:

player position in world: (x, y)
viewport position: (xView, yView)

render position: (x-xView, y-yView)

Also, thanks to this demo which helped me a lot to understand world’s boundary detection and camera-player following implementation.

And basically that was everything I needed, collision done (lets say so), player movement done, camera done and map had its shape. It was time to add objects. I’ve decided to put one main enemy in game - strange machine, which needs to be turned off if you want to escape this dungeon.

keys, codes, stars, coins?

I’m developer, lets say that was main reason why you are collecting digits for machine password. And since most of areas are locked, you will need temporary solution to get to some parts of map - keys. Was kinda easy to implement, while reusing same collision detection model for objects.

Next step was to add some kind of story into game (read - render some text with sense), add countdown timer just to make it a bit harder, add basic controls for mobile, tweak image rendering style a bit and we are done.

Simple tricks that made game even more pixelated

canvas {
  -ms-interpolation-mode: nearest-neighbor;
  image-rendering: -webkit-optimize-contrast;
  image-rendering: -webkit-crisp-edges;
  image-rendering: -moz-crisp-edges;
  image-rendering: -o-crisp-edges;
  image-rendering: pixelated;
}
image.onload = function () {
  ctx.imageSmoothingEnabled = false;
}

Conclusion


This is not a full walkthrough, there are some things implemented/used that I didn’t mentioned (like adding sound with TinyMusic). I hope that this may help someone developing something cool and even better.

But it is supposed to be just an quick overview how game is made. You can have a look at source code at Github (it’s kinda messy sometimes but I’ve made my best to make it readable at least).

I tend to be a developer who is rarely revisiting his own work, but it was a really good experience where I learned a lot and will probably come back to make it even better soon, because I kinda liked how it turned out in the end.