javascript demoscene
techniques
or
how to have fun in a constrained environment
(10/12/13)
Philippe Deschaseaux
history
demoscene
Dates back to the end of the 70's
cracked games + demos
constraint triggers creativity and ingenuity
recreational programming
-
code golf: shortest code that implements an algorithm
(various languages)
- obfuscation and language abuse: IOCCC
- quines
javascript ?
- historically constrained
-
ubiquitous: in every browser, and now on the server
-
easy: no preprocessing or compilation
-
multipurpose: graphics, sound, webGL, webRTC, asm.js, etc.
js particularities
C-like syntax
-
control structures (if, for, while, ...)
- statements / expressions
- ! variable scope (block / functions)
- ! use of semicolon
dynamic
primitive types and objects
0, abc, true { a: 12, b: function() {...} }
Function, Date, Math
dynamic typing
var a = 1;
a = '1';
0, null, undefined, false, "", NaN
[] + [] = ""
[] + {} = [object Object]
{} + [] = 0
{} + {} = NaN
evaluation at run-time
eval('a = b+1')
functional
functions are first-class citizens
var f = function() {};
n = f.length;
f.call();
button.onclick(f);
higher-order functions
var adder = function(b) {
return function(a) { return a+b }
}
prototypal
prototypal inheritance
var parent = { prop: 'foo' };
var child = Object.create(parent);
enfant.prop; // 'foo'
method != function
obj.getProp = function() {
return this.prop
}
obj.getProp();
obj.getProp.call(obj2);
challenges/contests
140byt.es
-
must fit in a tweet
-
entry = javascript function
- permanent challenge
js13kgames
-
game-oriented
-
entry = zipped package (index.html + assets)
- no dependencies
-
september-august
js1k
-
loosely themed
-
entry = js code runnable inside the shim
-
no dependencies
-
march-april
demoparties
Assembly, Revision, demoJS, etc.
various techniques
demo types
(non-exhaustive)
engine
fractals / IFS
pseudo random generators
genetic algorithms
! Math skills required
algorithms & data structures
optimization
no recipe, but needs time & imagination
example:
color palette compression
fuzzy trigonometry
π/2 ≡ π/2+2π ≃ 8
π/3 ≡ π/3+28π ≃ 89
π ≡ π+6π ≃ 22
-π/2 ≡ -π/2+4π ≃ 11
sin(α) = cos(α-π/2) ≃ cos(α+11)
X=x*Math.cos(a)-y*Math.sin(a);
Y=x*Math.sin(a)+y*Math.cos(a);
becomes
C=Math.cos;
X=x*C(a)-y*C(a+11);
Y=x*C(a+11)+y*C(a);
js bytes saving techniques
heavily based on implicit type casting
examples
a = Math.floor(b);
a = 0 | b;
if (a != 0) { b = 'on' }
a && b = 'on';
setInterval(function F(a) {
if (a) { return ... }
...
b = F(12);
...
}, 100);
function names shortening
canvas (Martijn Haverbeke)
for(k in c)c[k[0]+[k[6]]]=c[k];
c.fc == c.fillRect
c.qt == c.quadraticCurveTo
c.da == c.drawImage
...
WebGL (Mathieu 'p01' Henri)
for(k in g)g[k.match(/^..|[A-Z]|1f$/g).join('')]=g[k];
g.coS == g.compileShader
g.enVAA == g.enableVertexArrayAttribute
g.veAP == g.vertexAttributePointer
...
Minification
-
parser-based
-
removes useless white-spaces, semicolons, brackets
-
removes unused code
-
obfuscates variable nouns
Crushing
(Aivo Paas)
1st pass: entropic compression of the source code
_="X=x*Math.cos(a)-y*Math.sin(a);Y=x*Math.sin(a)+y*Math.cos(a);"
becomes
_="X=x2-y1;Y=x1+y2;4*Math.3(a)24cos314sin3"
with self-extracting code
for(Y=0;$="tokens"[Y++];)Z=_.split($),_=Z.join(Z.pop());eval(_)
2nd pass: compressed code optimization using regexps
PNG packing
(Jacob Seidelin / Alex Le)
Uses the browser's PNG decompressor (zlib)
1 .html file + 1 .png file
<script>
var o=new Image();
o.onload=function() {
r="",t=document.createElement("canvas").getContext("2d");
t.drawImage(o,0,0);d=t.getImageData(0,0,o.width,o.height).data;
for(i=0;d[i];i+=4)r+=String.fromCharCode(d[i]);
eval(r)
};
o.src=m.png";
</script>
-
code is compressed into PNG beforehand
-
HTML code evaluation
-
PNG image is loaded into a canvas
- levels of grey are converted into ASCII codes
PNG bootstrapping
(Cody 'Daeken' Brocious / Mathieu 'p01' Henri)
Same idea, but only 1 .html file !
...image data...
<canvas id=c>
<img src=# onload="for(a=c.getContext('2d'),i=e='';a.drawImage(this,i--,0),t=a.getImageData(0,0,1,1).data[0];)e+=String.fromCharCode(t);eval(e)">
</canvas>
-
first pass: '.html' extension has priority
-
HTML code evaluation: canvas + img
-
file is reloaded as a PNG image
-
levels of grey are converted into ASCII codes
demos
js1k 2013
p01
demo tweaking
links
JS demoscene techniques
By Philippe Deschaseaux
JS demoscene techniques
- 4,633