Frank Force: https://frankforce.com/?p=7617 (1st place)
Raimon Ràfols: http://blog.rafols.org/index.php/2020/07/21/javascript-ballo... (10th place)
Mattia Fortunati: https://www.mattiafortunati.com/detective-moji-postmortem-a-... (16th place)
Hey, that's the guy who did Bounce Back[0] for JS13K! He's got some pretty cool stuff on his website
EDIT: Wait a minute, that's KilledByAPixel, who submitted this link
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.
Path2D w/ SVG strings is byte-efficient, but is less computationally efficient vs the same Path2D w/ lineTo(), etc.
This particular demo only creates the Path2D objects once, at startup, and then hammers the canvas with a ridiculous amount of overdraw.
BUT - the few that I’ve managed to see are super cool, so when it comes back to life it’s worth checking out!
But in this case, I suspect that the server is just saturating its network connection because of poor treatment of images.
I have JavaScript disabled so maybe it’s loading more if you have JavaScript enabled, but when you exclude images, it’s only transferring about 152KB. Images are where it goes wrong: it’s serving up a large number of images, and some of them are unreasonably large and high quality (like 34ᵗʰ place, a 1000×1000 PNG of a fractal being shown at 400×400), and most significantly it’s using quite a few multi-megabyte GIFs, which is flatly stupid and wrong and they deserve to have their site fall over for pulling that.
So the end result is at least 20MB. 20MB = 160Mb, and if your server has only a one gigabit link (very common), you can suddenly only cope with about six visitors per second (though in practice things will start falling over before that, maybe round down to five), which is not quite enough for the peaks you’ll get when high on HN, and it becomes a bit of a cascading problem, kinda like a capacitor but bad.
The solution is to treat the images properly: actually compress them, use videos instead of GIFs, that sort of thing. I reckon 3MB total is readily attainable here, which would allow you to serve 40 visitors per second, which is probably enough.
So yeah, putting your pages on a platform with really fat pipes will solve problems like this after a fashion, but I’d argue that it’s not really solving them, it’s just letting you get away with doing a bad job and shifting the burden onto users.
Because there's more work in caching your dynamic server/CMS to static files and often isn't trivial. And the dynamic-rendered CMS is enough 99% of the time. You act like it's just a button you press, and you're wondering why people don't just press it.
It's also not a money-making venture. So you have very poor ROI on making your charity site endure the rare hug of death. It goes down? Oh well. It'll come back up. It's also the reason you're using some cheap CPanel setup, not deploying to a $5 VPS.
> It's also not a money-making venture. So you have very poor ROI on making your charity site endure the rare hug of death. It goes down? Oh well. It'll come back up.
This is a very strange statement to me. My impression would be that if you’re running a charity site (or any site that makes money from being visited), you would want it to absolutely not go down during a hug of death, as that’s money out of your pocket at a time when it’s getting a ton of free publicity. Why make the site in the first place if you aren’t expecting it to provide value to either you or the viewer?
Making a site is more than "just some markdown files". Can you show me what you're talking about? Maybe I'm missing it. If you mean static-site generators (they aren't just a couple markdown files), they are very nerdy and have pretty bad UX for most people. I don't even use them. They are effectively developer-only, for one.
> This is a very strange statement to me.
Well, this is how things work. This goes back to the parable of the lumberjack who didn't have time to sharpen his axe, or the guy who didn't have time to write a shorter letter.
You just want to get something online that others can modify. Any additional second your pour into it is probably a waste of time. A niche website like JS1024 is down? Maybe nobody really cares. Maybe the only person willing to host this just does things this way. Oh well.
Edit: Your confusion here reminds me when I got my first dev job and was confused why the other developers never wanted to improve these obvious problems in the code. Or use new patterns. Or learn new things (16+yo VBScript app, the website was one 500k line switch statement running on IIS). "Doesn't anyone care?!" But as I got older, "I can't be fucked" or "cbf" made a lot more sense to me. Don't underestimate how often "cbf" answers your questions. ;)
I was expecting an expensive hassle, but was happy to be wrong on that.
But hosting an Apache or nginx to serve static files is easy enough and a single $5 or $10 instance on any hosting service out there could easily survive a HN frontpage.
Just gotta make sure its setup to cache your html
https://www.sslshopper.com/ssl-checker.html#hostname=js1024....
I had good times with that calculator. 32KB taught me frugality not unlike that needed for competitions like JS1024, and how to find that there was a character/instruction akin to a semicolon in Python that took one byte, where the new line character/instruction took two bytes. (I only obtained a manual for the calculator after having it for two years. Figured out one or two new tricks after that, but I’d worked almost everything possible out by trial and error.) So power efficient, too: I changed the four AAA batteries only twice in more than three years of very heavy usage (looking back on it, I probably got more than 200h of life from each set), while all the rest of the class that had the newer, faster version (except one other who had the same model as me) would need to change them around once a term, and they didn’t use their calculators even a quarter as much as me. I’m going to guess figures of a CPU 6× as fast and power consumption 30× as high. And those newer ones were even only monochrome rather than three-colour LCD.
Then after I left they shifted to CAS calculators and battery life was a zillion times worse again. And laptops, phones and such will be even worse still. Ah well.
[1] http://martin.poupe.org/casio/ [2] https://youtu.be/cTB5YM898g4
It definitely was fun to experiment within such constraints. I can't remember being very concerned with program size, although after a certain size there was a boundary the jump statements weren't able to cross any more. Only having global one-letter variables and no function calls (and a 21*7 character screen) also made the code hard to read/write, but it was a fun puzzle and I ended up writing a ray caster (god it was slow), something akin to the game Concrete Jungle and a complete 2-player implementation of Settlers of Catan, amongst other things. Not sure if my math teacher was a fan of me not paying attention in class though.
I definitely never tried a ray caster or anything that complex. I can imagine that taking literally hours to render a single frame, if I even coded it right.
I kept my calculator in my pencil case, so I always had it with me in classes. I think all the teachers (definitely not just maths) were pretty much resigned to me using it when I finished my work in their classes (or if I didn’t want to do it and reckoned I could get away with it). Having three elder siblings that would read books or used calculators under the desk certainly helped. One teacher complained volubly about the first couple of us for this very reason (and I was very probably worse than them), but by halfway through my schooling he said to my mother once that he always loved having Morgans in his class. This amused mum greatly. Stockholm syndrome, we decided.
Demo: https://js1024.fun/demos/2020/12
Source code: https://js1024.fun/demos/2020/12/source
Shaders: https://developer.mozilla.org/en-US/docs/Games/Techniques/3D...
Check out https://www.shadertoy.com/ for lots more of these demos. You can do some really amazing stuff.
Edit: up to 24.5MB now.
Edit: 34.5MB now and still going
Edit: 44.4MB and still going. It's clearly slowing down badly. I'm killing it.
But it's not Firefox: I see exactly the same artifacts with Safari 13.1.2. (Safari is also much slower with this demo than Firefox.)
Surprisingly, it depends which GPU it starts with, not the one it's running on. Some Macbooks have two GPUs, only one active at a time.
If Wetlands is started with the Intel GPU active, it looks fine, and continues to look fine if the GPU is switched to nVidia. But if started with the nVidia GPU active, it looks a mess, lots of colour noise, and continues to look that way if the GPU is switched to Intel.
I've checked all combinations and found the same on both Firefox and Safari. So I guess it's probably the underlying OpenGL driver. I'm relieved, this means it's not a faulty GPU :-)