Rainbow ziggurat

We’ll define a new behavior to attach to the blocks of a ziggurat. We write the function makeColorAnimator that cycles the colors of the rainbow upward or downward. For example, to cycle colors upward at a rate of one full cycle every 10 seconds, we use this call:

moveChildren(zig, makeColorAnimator(-0.1));

In the following program, colorRate refers to cycles per second.

Rainbow ziggurat

Function makeColorAnimator gets called with a color rate which determines hue over time. We may also supply saturation and brightness values for the color.

function makeColorAnimator(rate, saturation=1.0, lightness=0.5) {
    function f(child, i, children) {
        child.crate = rate;
        child.cval = i / children.length;
        return function (delta) {
            this.cval += delta * this.crate;
            this.cval = mod(this.cval, 1);
            this.material.color.setHSL(this.cval, saturation, lightness);
        }
    }
    return f;
}

makeColorAnimator assigns the current child two properties: crate is the cycle rate, and cval represents the child’s current hue, a value between 0.0 and 1.0. Initially, each block is assigned hue based on its relative position in the ziggurat. In the method that gets returned by makeColorAnimator and bound to the child, the child’s color is set to the current hue, saturation, and lightness, where hue is a function of elapsed time and the and the child’s color cycle rate. Note that negative cycle rates cause colors to shift upward because the hue values assigned to blocks decrease over time.

The method increments the color value cval using modular arithmetic so that values ‘wrap around’ the range [0,1]. If cval gets assigned 1+ε, the call to function mod sets it to ε ; if cval gets assigned –ε, the call to mod sets it to 1-ε. 1

So far we’ve defined behaviors for rotating blocks and a behavior for cycling colors. On the next page we’ll look at an approach for combining these and other behaviors.

  1. JavaScript’s % operator doesn’t perform modular arithmetic when its first operand is negative. Rather, we write function mod(x, n) { return (x % n + n) % n; } to include negative values. See The JavaScript Modulo Bug for more information.