MATRAKA

Lessons learnt in 4 weeks and 1kb

Mathieu P01 Henri

JavaScript freak, @p01, Demo maker, JS1k runner up

MATRAKA & DemoJS

One month of preparation for a Demo-ish result

M=[R=Math.random,Q=Math.cos,c.style.cssText='position:fixed;top:0;left:0;width:100%;height:100%;background:#000',e='data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEAwF0AAMBdAAABAAgAZGF0YQAA'];for(t=2560;t--;)M[t]={t:t,u:t%48/7.64,v:t/366.7,x:128-R()*256,y:64-R()*256,z:128-R()*256};for(t=0;t++<8e5;)e+=btoa(S('13107103135701314204'[(t>>10&15)+(t>>13&4)]*t&96,R()*127*(Math.pow(t/144000%1,16)/4+Math.pow(1-t/144000%1,64)),t>>10&7^5||R()*127));Z=new Audio(e);Z.play(setInterval(function b(v,w){if(v)return w.W-v.W;M.sort(b);h=c.height=0|300*innerHeight/innerWidth;C=Q(r=Z.currentTime/2);S=Q(r-8);a.rotate((r&13)/64-.1);B=r/9;A=Math.pow(B%1,64);d=[1-A,0,A][0|B++%3];f=[1-A,0,A][0|B++%3];e=[1-A,0,A][0|B++%3];for(t=2560;t--;){v=M[t];if(v.W>0)a.fillRect(150-v.W*v.U,v.W*(v.y+Math.max(16*Q(r),150-r*42))+h/2,v.W*7,v.W*7,a.fillStyle='hsl('+[r*17-v.y+R()*48,(16+R()*48)+'%',v.W*7+32-32*Q(v.u*2-8)*Q(v.v*3-8)]+'%)');if(v.t<2304)Y=96-30*v.v,D=32+8*Q(v.u*2)*Q(v.v*3),v.x=(96-30*v.u)*d+D*(Q(v.u)*e+Q(v.u)*Q(v.v/2-8)*f),v.z=Y*d+D*(Q(v.u-8)*e+Q(v.u-8)*Q(v.v/2-8)*f),v.y=D*d+Y*e+D*Q(v.v/2)*f;v.W=128/(v.z*C-v.x*S+96);v.U=v.x*C+v.z*S}a.fillText(['P01 4MAT','MATRAKA'][B&1].substr(a.drawImage(c,0,r*h%h,32,h/8*(3+A+Q(B+A)),0,r*h%h,300,h/8*(3+A+Q(B+A))),r*8-48)+'|',32,h/2)},Z.loop=9))

This is MATRAKA

Getting the basics right

week #1

Voxels vs particles

Oregon Trail Carriage Point Cloud by p01

DOM vs Canvas

Viewport, animation loop & rendering

Compact with full control of the resolution and aspect ratio

Viewport

// the classic viewport setup/update
c.width=innerWidth-20;c.height=innerHeight-10;

Matraka's viewport

// setup
c.style.cssText='position:fixed;top:0;left:0;width:100%;height:100%;background:#000';
// update
h=c.height=0|300*innerHeight/innerWidth;

Animation loop

Particle engines go this way

Matraka's animation loop

Shadowed sort method

setInterval
(
  function b(v,w)
  {
    if(v)
      return w.W-v.W;
    M.sort(b);
    /* Display particles & compute new positions */
  },
  9
);

Combined display & compute new positions

for(t=2560;t--;)
{
  v=M[t];
  // render if the particle is in front of the camera
  if(v.W>0)
    a.fillRect(150-v.W*v.U,v.W*v.y+h/2,v.W*7,v.W*7,a.fillStyle=v.color);
  // compute new position
  // Rotation against one axis is enough
  v.W=128/(v.z*C-v.x*S+96);
  v.U=v.x*C+v.z*S
}

Week #1 over

A point cloud spinning around with full control of the viewport.

Designing the objects

week #2

The heightmap

To produce a bumpy plane, cylinder and sphere

The heightmap

The source code is the data!

h = _.charCodeAt((x+y*w)&1023)

The heightmap

cos(x) * cos(y) to the rescue

h = Math.cos(x)*Math.cos(y)

Bumpy Plane, Cylinder, Sphere

See the heightmap as normal vector, projected on these surfaces

Plane

X = x
Y = y + h
Z = z

Cylinder

X = (x + h) * cos(a)
Y = y
Z = (z + h) * sin(a)

Sphere

X = (x + h) * cos(a) * sin(b)
Y = (y + h) * cos(b)
Z = (z + h) * sin(a) * sin(b)

Morphing objects

Special cases of the spherical coordinate conversion

d=[1-A,0,A][0|B++%3];
f=[1-A,0,A][0|B++%3];
e=[1-A,0,A][0|B++%3];
/* ... */
Y=96-30*v.v,
D=32+8*Q(v.u*2)*Q(v.v*3),
v.x=(96-30*v.u)*d+D*(Q(v.u)*e+Q(v.u)*Q(v.v/2-8)*f),
v.z=Y*d+D*(Q(v.u-8)*e+Q(v.u-8)*Q(v.v/2-8)*f),
v.y=D*d+Y*e+D*Q(v.v/2)*f

Week #2 over

Morphing objects spinning around.

Packing & music

week #3

JS Packer

for($="packed code";t=$.match(/[tokens]/);$=t.join(t.shift()))t=$.split(t);eval($)

1000+ bytes

PNG bootstrap

<canvas id=c><img src=# onload=for(a=c.getContext('2d'),i=e='',S=String.fromCharCode;a.drawImage(this,i--,0),t=a.getImageData(0,0,1,1).data[0];)e+=S(t);(1,eval)(e)>

~850 bytes

Music

Something phat and glitchy!

Music

Take 1

Ambient tune by playing the source code slowly

Music

Take 2

Dubstep using the source code and playbackRate

Music

Take 3

Experimental music from very short programs

(t<<3)*[8/9,1,9/8,6/5,4/3,3/2,0][[0xd2d2c8,0xce4088,0xca32c8,0x8e4009][t>>14&3]>>(0x3dbe4688>>((t>>10&15)>9?18:t>>10&15)*3&7)*3&7]

Music

Take 4

Experimental music composed by a chiptune superstar

4mat

Music synth and replay

e='data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEAwF0AAMBdAAABAAgAZGF0YQAA';/* ... */for(t=0;t++<8e5;)e+=btoa(S('13107103135701314204'[(t>>10&15)+(t>>13&4)]*t&96,R()*127*(Math.pow(t/144000%1,16)/4+Math.pow(1-t/144000%1,64)),t>>10&7^5||R()*127));Z=new Audio(e);Z.play(/* ... */,Z.loop=9)

275 bytes, over 1 minute of 8bits music with three channels at 8khz

Week #3 over

Morphing objects spinning around with kick ass glithcy music around 1k. Still dull.

The final touches

week #4

Text writer

a.fillText(['P01 4MAT','MATRAKA'][B&1].substr(0,r*8-48)+'|',32,h/2)

Glitches

a.drawImage(c,0,r*h%h,32,h/8*(3+A+Q(B+A)),0,r*h%h,300,h/8*(3+A+Q(B+A)))

Stretch a sliding window of 32px

The Crash cymbal

R()*127*(Math.pow(t/144000%1,16)/4+Math.pow(1-t/144000%1,64))

Tilted camera

a.rotate((r&13)/64-.1)

Shifting hue

a.fillStyle='hsl('+[r*17-v.y+R()*48,(16+R()*48)+'%',v.W*7+32-32*Q(v.u*2-8)*Q(v.v*3-8)]+'%)'

And a million more things

Week #4 over

Morphing objects spinning around with kick ass glithcy music, a text writer, different camera angles, introduction panning to not give away the effect, a crazy crash cymbal in synch with the morphing, ...

Take away

Plan, test, test, test, go with the flow, keep some time to polish!

Thank you

That was MATRAKA

By @p01 and @4mat_scenemusic

See you tonight at the 1K competition.