4 minutes
Green Eyes
Eyes watching a mouse cursor have being a good GUI demo app since the early versions of X-Window. It shows how to work with color, draw simple shapes and handle mouse coordinates.
Let’s see how easy it is to build a similar app with Collider.JAM and JavaScript.
And let’s also extend the original concept by adding the ability to create additional eyes on the mouse click. There was no way to do that in the original X-Window version, but we can do it, since we have the whole canvas at our disposal.
.mod sketch project
Let’s create a Collider.JAM .mod project
and dna/eye.js
file:
mkdir eyes.mod
cd eyes.mod
mkdir dna
touch dna/eye.js
defaults
First, we need to define eye defaults in dna/eyes.js
:
// dna/eyes.js
const defaults = {
x: rx(.5),
y: ry(.5),
hr: rx(.02),
vr: rx(.03),
color: hsl(.1, .9, .9),
iris: {
size: .5,
shift: .4,
color: hsl(.42, .4, .5),
},
pupil: {
size: .2,
shift: .55,
color: hsl(.05, .3, .1),
},
}
This object contains the values we use to initialize a newly constructed eye instance.
The properties x
and y
set the eye
center position, hr
and vr
-
horizontal and vertical radiuses for the eye ellipse.
The eye color
is also defined here.
Functions rx()
and ry()
calculate
relative sizes to screen width and height.
So rx(.5)
means the half of the screen width
and ry(1)
means the full-screen height.
An eye has two internal parts - iris and pupil.
Each defined by its own property object
that determines the size (relative
to the eye horizontal radius), color, and shift.
The shift is a distance to move the iris or pupil
towards the mouse cursor.
It is also defined relative to the hr
value.
onClone()
We are going to define eye
as a simple prototype
instead of a constructor or a factory.
It means the defined object will be used as
a prototype to clone new instances.
This process doesn’t create a traditional JavaScript
prototype chain, rather produces a fully independent object.
The onClone()
function is used in Collider.JAM
to initialize a cloned object after construction.
Any fancy actions required to setup the object
can be performed here.
let id = 0
function onClone(settings) {
this.name = 'eye' + (++id) // assign a unique name
augment(this, defaults, settings)
}
The function assigns a unique name
like eye1
, eye2
etc…
Next, it augments the cloned object
with default and spawn settings.
draw()
The drawing procedure is the most complex one in this app. But the meaning of each individual command is pretty straightforward.
function draw() {
// declare local shortcuts to simplify calculations
const { x, y, hr, vr, iris, pupil } = this
// eye
fill(this.color)
ellipse(x, y, hr, vr)
// calculate direction of the mouse cursor
const dir = bearing(x, y, mouse.x, mouse.y)
const d = dist(x, y, mouse.x, mouse.y)
// iris
fill(iris.color)
const ishift = min(hr * iris.shift, d)
ellipse( x + ishift * cos(dir), y + ishift * sin(dir),
hr * iris.size, vr * iris.size )
// pupil
fill(pupil.color)
const pshift = min(hr * pupil.shift, d)
ellipse( x + pshift * cos(dir), y + pshift * sin(dir),
hr * pupil.size, vr * pupil.size )
}
We use object deconstruction syntax here
to simplify calculations, so we don’t have
to supply each value with this.
prefix.
Three ellipses are drawn here in total.
Each preceded by a fill()
call
to set the corresponding fill color.
There are also some preliminary calculations to determine the shift direction for iris and pupil.
Collider.JAM bearing()
and dist()
functions are used to calculate
the angle and distance to the mouse cursor.
setup()
The setup function creates two eyes in the /lab
node:
function setup() {
// spawn two eyes
lab.spawn(dna.eye, {
x: rx(.69),
y: rx(.25),
})
lab.spawn(dna.eye, {
x: rx(.75),
y: rx(.25),
})
}
click()
To create an additional eye on mouse click,
introduce a click trap in trap/click.js
:
// trap/click.js
function click(e) {
lab.spawn('eye', {
x: mouse.x,
y: mouse.y,
})
}
Green Eyes on the mouse!
That’s all you need for a functioning Collider.JAM app.
Run it from inside the eyes.mod
folder with:
jam play
And eyes in the browser will start to track your cursor :)
Click anywhere on the screen to create more eyes!
You can find the demo app sources on GitHub.