• Register

Key Features:

  • Thumb your nose at destiny, become the hero you were meant to be, and win the heart of the girl of your dreams!
  • Save the town and battle the evil goblin Bloodclot with your magic sword!
  • Charming retro 8-bit graphics and a classic quest.
  • Clever and challenging puzzles.
  • Includes a soundtrack of upbeat music to buoy the adventurer’s spirit!
  • Fourth-wall breaking fun and humor—great for fans of the golden age of adventure games!

Available now on Steam, Humble store, and Phoenix Online Publishing!

  • View media
  • View media
  • View media
  • View media
  • View media
  • View media
Post article RSS Articles

What makes a tale tick?

This is the first in a series of blog posts describing the programming, art, story, and music direction behind Tick's Tales: Up All Knight. My goal is to show some of the methodology behind the game, both for those interested in making adventure games of their own, and for those who are just curious about Tick's Tales. If there's something you're interested in hearing about, please make sure to post a comment, and I'll share what I can! If you're interested in the game, please do follow @tickstales on twitter!

I'm going to start by sharing some details about Tick's Tales' backend, as it's probably the most unique aspect amongst other adventure games.

This story has Clojure

Tick's tales is built in Clojure. It's a very atypical programming language choice for a game. As far as I know, there haven't been any sizeable games built in Clojure. So why choose it?

  • The REPL (Read Evaluate Print Loop) is very powerful, and allows me to rapidly change the game while it's running.
  • Using play-clj and libgdx means that I can target Windows, OS X, Linux, Android, and iOS easily.
  • A lot of new creative opportunities open up if I create my own engine (vs. visionaire, ags)
  • Clojure's persistent data structures could prove incredibly flexible for building out entities in a stateless way
  • I could leverage core.async to easily build a scripting language/api. (covered in a future article)

The REPL

When I started, I underestimated just how much the REPL sped development up. This dramatic speed-up came in two forms. The first is that I could make changes to the game while it's running. And secondly, I didn't have to create any editors or tool.

A quick feedback loop

Using the REPL, I can change the game while it's running. When Tick's Tales starts up in development mode, I can change any file, and see its changes immediately. A typical example might be tweaking a script. Perhaps I'm trying to fine-tune the timing in the dialogue. I can make the code changes, Cmd+Tab over to the game, and see it while it's running. If I'm not happy, I can just rinse and repeat. A picture's worth 1000 words, so watch this example of changing a font color on the fly.

An example of on-the-fly editing


It also means that I have access to game state while it's running. I can inspect any entity as the game is running, and even change it, without making any code changes.

Editor-less

Many adventure game engines will include an editor that lets you define animations, walkable areas, write scripts, place objects and characters, etc. To be sure, these are very helpful tools, and make it easy to quickly put the game together. But they also take a lot of development effort to maintain, and most of the time, probably more than the game engine itself. With the quick feedback loop that I had above, I never found the need to do this. It was a simple enough task to tweak the game as it was running.

There was another added benefit to this. When you use an editor, essentially the game is serialized to some data format. It essentially draws the boundaries of what your game can do. Without one, it made it much more rapid to try out new ideas.

For example, there's a water fountain in the game. Originally, when you walked into that scene, the water fountain would play at a constant volume. Based on a recommendation from a friend, it would be better to have the fountain's volume be based on Tick's proximity to it. This was trivial to try, and it ended up making it into the game. This was so easy, in part, because I didn't have an editor. Instead of having to define a way to describe this behavior with data, I was able to replace a constant (the volume of the sound) with a function that returns the volume of the sound.

Creative power

By rolling my own engine, I tried some things that are atypical to the adventure genre. The best example is probably the camera. Most of the time, adventure games either have a fixed background, or a panning background with some parallax. I tried something different with Tick's Tales. I wanted to make it feel like there was someone behind the camera. I wanted to have a little camera shake and zooming.

Camera panning/zooming

This was relatively easy to do (thanks libgdx!), and I think it does make the game feel more alive, even though it is low-res.

Persistent data structures

Most games these days either use Object-oriented programming or an Entity-component system for modeling the world. While you can do either in Clojure, I wanted to stick to simple data structures for modeling most things. Most everything you see in Tick's tales are simple maps, vectors, and sets. If you're familiar with json, this will look vaguely familiar.

; the clouds on the title screen 
{ :texture (get-texture "title/clouds.png" ) 
  :x 0 :y 0 
  :scale-x 4 :scale-y 4 
  :origin-x 0 :origin-y 0 
  :z 2
  :arbitrary-data [1 2  3]}


This might seem relatively simplistic, but what it meant is that I could add behavior and data to objects very easily. There's an Alan Perlis adage that goes, "It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures." I believe this to be true. For Tick's Tales it means that there is a consistent and predictable way to change all of the objects in the game. Clojure's library provides a huge tool set for manipulating data structures, and those can be used for literally everything in the game:

; change some state about an entity (
assoc-in entities [:room :entities :damsel :saved?] true) 
; shift player over 20 pixels 

(update-in entities [:room :entities :ego :x] + 20) 

; or, shift any entity to any position 
(update-in entities [:room :entities target] assoc :x 100 :y 50) 

; calculate the total distance of a walk path 
(reduce + 0 (map :distance (:path ego)))


I can't overstate how much boilerplate code I didn't have to write because I was able to use persistent data structures, and the many, consistent, operations to manipulate them.

Persistent data structures do have disadvantages, though. For one, because they are immutable, each change does require some memory allocation. In a game the size of Tick's Tales, it's pretty much negligible on the desktop. However, on mobile, garbage collection is notably slower and causes noticeable jitter and FPS, and I'm going to have to find optimization opportunities before it's ready for those platforms.

Additionally, I spent quite some time optimizing pathfinding, as Clojure's persistent data structures and arithmetic were too slow by default.

In conclusion

I'm really happy I wrote Tick's Tales in Clojure. I'd do it again in a heartbeat. Feel free to post any questions, and I'll try to answer them in the next post.

Until next time,
Bryce

Post comment Comments
Guest
Guest - - 689,057 comments

You mentioned that your data structures are mainly "simple maps, vectors, and sets." Each of these types can be made transient: see clojure.org/transients for details. I think this would give you tremendous performance gains, based on how you described your code in this article.

Reply Good karma Bad karma+1 vote
Guest
Guest - - 689,057 comments

Do you take advantage of any of Clojure's asynchronous functionality? As a Clojure user who has dabbled in making a game engine in C++, I think it could be cool to have the rendering loop done in a go block, or perhaps using add-watch.

>Additionally, I spent quite some time optimizing pathfinding, as Clojure's persistent data structures and arithmetic were too slow by default.

It'd be nice if you went into detail on this.

Reply Good karma Bad karma0 votes
tickstales Creator
tickstales - - 1 comments

Yes! I actually use core.async a great deal for game scripting, but nothing for rendering.

I'm planning on expanding on pathfinding in the next article. Thanks for the interest!

Reply Good karma+1 vote
Guest
Guest - - 689,057 comments

Er, I forgot you were using play-clj. I can just look at how they handle rendering.

Reply Good karma Bad karma+2 votes
Post a comment

Your comment will be anonymous unless you join the community. Or sign in with your social account:

X

Latest posts from @tickstales

RT @ben_304: Adventure games have very cool tree houses. T.co

Mar 19 2017

Created this #adventuregame background using the #kingsquest 7 color palette. #gamedev #indiegame #procreate T.co

Jan 22 2017

RT @IQ_Adventures: Here's some fun "AGI" screens of QFGIV and KQVI that Jason Lamb did a few years back. #SierraOnLine #AdventureGamesT.co

Jan 16 2017

Published the 1st in my #adventuregame #gamedesign series Why Adventure Games Rock! 1st up for study: #kingsquest 6 Bit.ly

Jan 12 2017

Any #adventuregame artists use ipad pro/apple pencil for #gameart? Thinking about picking one up.

Dec 20 2016

RT @Gamers247couk: We just added another bargain to our store Tick's Tales (PC/..., take a look! Gamers247.co.uk

Dec 9 2016