Anders Tornblad

All about the code

Phenomenal & Enigmatic, part 2

Stars and text intro

Stars and text Enigma screendumpThe opening scene of Enigma by Phenomena starts out looking like an average side-scrolling star parallax, which was very normal in 1991. Nice way to lower people's expectations. :) But after just a couple of seconds, the stars begin twisting and turning in space around all three axes.

Back in 1991 I knew how to rotate a plane around the origo, by simply applying the angle sum identities of Sine and Cosine. I also realized that rotating any 3D coordinate in space could by done by simply the case of rotating around more than one axis, one axis a time.

Stars and text screendumpIn the Phenomenal & Enigmatic demo, I only rotate the stars around two axes. First I rotate the (x,z) components around the Y axis to get (x',z'), and then the (y,z') components around the X axis to get (y',z''). I also translate each star along the X axis before the rotation takes place. To finally get the 2D screen coordinates of the 3D space coordinate, I take the (x',y') coordinate and multiply by (2/(2+z'')) for a pseudo-distance feel. The z'' value controls both the color alpha component, and the size of the rectangle being drawn.

The even better way of doing this is through vector addition and multiplication, but I'm sticking to the math that I know. :) After all this math is in place, the trick is to change the offset and rotation variables in a nice way.

Rendering text is just a couple of calls to the context.fillText method and animating the value of context.globalAlpha.

Pseudo code

// Prefetch sin and cosine of angles var cosY = Math.cos(yAngle); var sinY = Math.sin(yAngle); var cosX = Math.cos(xAngle); var sinX = Math.sin(xAngle);   for (var star, i = 0; star = stars[i++]; ) {     // Fetch x, y, z and translate x     var x = star.x + xOffset;     var y = star.y;     var z = star.z;         // Limit x to [-1 .. 1]     while (x > 1) x -= 2;     while (x < -1) x += 2;         // Rotate (x, z) around Y axis     var x2 = x * cosY + z * sinY; // x'     var z2 = z * cosY - x * sinY; // z'         // Rotate (y, z') around X axis     var y2 = y * cosX + z2 * sinX; // y'     var z3 = z2 * cosX - y * sinX; // z''         // Transform to screen coordinates     var screenX = x2 * 2 / (2 + z3) * halfScreenWidth + halfScreenWidth;     var screenY = y2 * 2 / (2 + z3) * halfScreenWidth + halfScreenHeight;         // Draw the star     context.fillRect(screenX, screenY, 2 - z3, 2 - z3); }

Phenomenal & Enigmatic, part 1
Phenomenal & Enigmatic, part 2 (this part)
Phenomenal & Enigmatic, part 3
Phenomenal & Enigmatic, part 4

The entire demo, including non-minified JavaScript, is available on GitHub: /lbrtw/enigmatic

Add a comment