What I like about 1K demos is that you can make them in a relatively short amount of time—something like a week or so, without taking time off. After a week of work I was happy with what I had written, out of space, and had diminishing returns when I attempted to reduce the size. By comparison, JS13K can be a lot more work.
The first thing I did was set up a development environment which would reload in the browser every time I saved changes. The development page showed the number of bytes left at the top of the screen and put the exact, submission-ready code in an iframe. Saving changes would trigger everything to be minified and packed again. Packing is done with Terser -> RegPack. No potentially incompatible techniques like method hashing were used, but that’s probably because I didn’t see a size improvement when I tried them. There are some custom transformations on the code during compilation, mostly so I could have ESLint watch my back.
The demo itself has three parts to it. Most of the objects are rendered by callback functions, and there’s a big array of callback functions in back-to-front order. The function closures contain any generated data necessary for drawing the data. The parts are:
1. Mountains and clouds, which are just simple midpoint displacement fractals. The mountains were flipped upside down and stretched to make clouds. Various techniques for generating a fractal were tried, a recursive functional approach ended up being the smallest.
2. Stars, which are just randomly placed in 3D space and randomly resized each frame to make them twinkle.
3. The planet, which is drawn separately. The submitted version draws it over the clouds. This was fixed in the repo, but not re-submitted.
Notes on technique:
- Path2D turns out to be a very efficient way to specify a path for a Canvas. It uses an SVG path string to specify the path, which is more compact than using .moveTo() and .lineTo(). There is room for improvement.
- The 'color' function is a beast, it lets you represent an RGB color as a 3-digit number from 111 to 999, and calculate things like gradients. There was a lot of tweaking to get colors that I liked.
- Did a lot of inlining and un-inlining of functions at the end. For example, if a function f(x) is defined like f(x) = 4 * ..., then you can move the constant out of the function, or into the function from the call sites.
- Checked the minified code to see how functions were being emitted. If they were emitted as (x) => { a; b; }, I would try to change the code so they could be emitted as (x) => (a,b).
- RegPack gives you limited space savings for repetitive code, so use it.
- If you need local variables, just add arguments to your function and use those.
> Path2D turns out to be a very efficient way to specify a path for a Canvas. It uses an SVG path string to specify the path, which is more compact than using .moveTo() and .lineTo().
Path2D w/ SVG strings is byte-efficient, but is less computationally efficient vs the same Path2D w/ lineTo(), etc.
My demo is Star Traveler, which placed #1 in the 2D Canvas category. The GitHub repository is here: https://github.com/depp/demo-traveler
Source code: https://github.com/depp/demo-traveler/blob/trunk/src.js
What I like about 1K demos is that you can make them in a relatively short amount of time—something like a week or so, without taking time off. After a week of work I was happy with what I had written, out of space, and had diminishing returns when I attempted to reduce the size. By comparison, JS13K can be a lot more work.
The first thing I did was set up a development environment which would reload in the browser every time I saved changes. The development page showed the number of bytes left at the top of the screen and put the exact, submission-ready code in an iframe. Saving changes would trigger everything to be minified and packed again. Packing is done with Terser -> RegPack. No potentially incompatible techniques like method hashing were used, but that’s probably because I didn’t see a size improvement when I tried them. There are some custom transformations on the code during compilation, mostly so I could have ESLint watch my back.
The demo itself has three parts to it. Most of the objects are rendered by callback functions, and there’s a big array of callback functions in back-to-front order. The function closures contain any generated data necessary for drawing the data. The parts are:
1. Mountains and clouds, which are just simple midpoint displacement fractals. The mountains were flipped upside down and stretched to make clouds. Various techniques for generating a fractal were tried, a recursive functional approach ended up being the smallest.
2. Stars, which are just randomly placed in 3D space and randomly resized each frame to make them twinkle.
3. The planet, which is drawn separately. The submitted version draws it over the clouds. This was fixed in the repo, but not re-submitted.
Notes on technique:
- Path2D turns out to be a very efficient way to specify a path for a Canvas. It uses an SVG path string to specify the path, which is more compact than using .moveTo() and .lineTo(). There is room for improvement.
- The 'color' function is a beast, it lets you represent an RGB color as a 3-digit number from 111 to 999, and calculate things like gradients. There was a lot of tweaking to get colors that I liked.
- Did a lot of inlining and un-inlining of functions at the end. For example, if a function f(x) is defined like f(x) = 4 * ..., then you can move the constant out of the function, or into the function from the call sites.
- Checked the minified code to see how functions were being emitted. If they were emitted as (x) => { a; b; }, I would try to change the code so they could be emitted as (x) => (a,b).
- RegPack gives you limited space savings for repetitive code, so use it.
- If you need local variables, just add arguments to your function and use those.