Lifeforms of Collider.JAM live in the /lab, as you might know from my previous post.

The Essence of Life is simple and ruled only by 2 functions - evo(dt) and draw(). The first determines the lifeform’s behavior in a short timespan (usually a single frame). The second - how the lifeform looks in its current state.

To have a lifeform on the screen, you just have to define these two functions on any object and place it in /lab.

Note, that you don’t have to extend from any special class like GameObject or do any other crazy stuff.

You and only you define how your objects are going to be created and organized. Collider.JAM just provides some conventions to simplify that.

You can use a prototype hierarchy, you can use a composition of mixins, you can create custom factories…

Moving Circle

Let’s create a circle that moves horizontally:

// === mover.mod/lab.js ===

// coordinates and radius
let   x = rx(.5)  // center horizontally
const y = ry(.5)  // center vertically
const r = ry(.05) // 5% of the screen height

const SPEED = rx(.25) // 25% of the screen width per second

function evo(dt) {
    // move the circle horizontally
    // warp the coordinate, so it always stays on the screen
    x = warp(x + SPEED*dt, 0, rx(1))

function draw() {
    fill(.45, .5, .5) // color in HSL
    circle(x, y, r)

We are placing our entity directly in /lab.js. It is OK as long as we are not going to have any other lifeforms. Otherwise, it is better to place it deeper, e.g. /lab/circle.js.

You can run it by typing jam in the mover.mod folder. Check the sources at GitHub.

After initializing coordinates, radius and speed, we are defining functions evo(dt) and draw().

The purpose of evo(dt) is to update object state before the next drawing cycle. In our case, it determines the movement behavior of the circle. Each step, it moves to the right at the declared SPEED in pixels/second.

Note, it is crucial to factor on dt everything you do in evo(dt). It represents the time in seconds passed after the last update.

Since the speed is defined in pixels per second, we need to factor the speed value like SPEED * dt to find the actual movement over the X-axis for the current frame.

When properly factored, the movement doesn’t depend on the actual framerate.

The draw() function sets the fill color and draws the circle.

Each frame, all lifeforms in /lab evolve with their evo(dt) and rendered on the screen with their draw() functions.

Any object within the /lab subtree with evo(dt) and draw() functions is an actor on the scene. It shows something and behaves somehow.


Some lifeforms might have only a draw() function. So they are not actors on the scene, but props. We call them plants since they have a visual representation, but no behavior of their own.

It might be an ammo indicator, showing the hero’s ammo supply. Or maybe a score indicator. Or a static wall…


Plants are visible but static. But what if we have behavior, but no visual representation whatsoever. These entities are called ghosts and they have evo(dt) but no draw() function defined

A collision detection node can be an example of a ghost.


That is all there is to life in Collider.JAM. Only two functions are needed to define how lifeforms look and behave.

But evo(dt) and draw() are not the only convention functions you can define on nodes in Collider.JAM. There are also init(), onSpawn(), kill()

But I’ll save them for another time :)