How I made a 3D game in 2 KB of JavaScript
frankforce.com
frankforce.com
Just wanted to add... Dwitter is awesome for learning stuff like this, since everything is so absurdly small you know the ceiling of time required for understanding a dweet is pretty low - yet at the same time it's surprising how advanced techniques can get in this tiny space.
This makes them so tempting. I sometimes struggle to pick up or return to a technical book when work/life etc gets busy, but when someone posts an interesting new dweet I often can't stop myself from pulling it to pieces.
1. Create variables for any global/builtins (setTimeout/clearTimeout, requestAnimationFrame, etc) at the top of the file.
2. Create variables for global object properties, especially if used multiple times or they have longer names (Object.assign, Object.hasOwnProperty, Math.cos, Math.sin , JSON.stringify).
3. For non globals, within functions, create variables for any object properties or methods that are called multiple times to be worth it; like in formulas where obj.width/height is called 4-5 times, the minifier can't optimize the property name.
4. For Class instance methods that don't allow creating variables for methods (You have to call the method with the class, since they operate on "this" context) but don't have anything unique about "this", you can create a variable once within a function, then just bind itself. If you are using it multiple times to be worth it.
const classMethod = ClassInstance.classMethod.bind(ClassInstance)
would be minified to const Z = X.classMethod.bind(X)
and (in the minified code) used as Z() instead of X.classMethod()5. In longer functions that use "this.whatever" many times, you can create a variable once for "this" (t or _this etc) and the minifier will be able to eliminate those bytes.
Lots of counterintuitive observations when you realize the objective is for compressed 2k size, which means that duplicate code is actually a good thing!
It reminds me of this 3d maze in 1k of javascript from many years ago: https://js1k.com/2010-first/demo/459
So, js1k is not continuing? On the js1k site I can't see anything stating this. Nothing on the subreddit either. Where is that information coming from?
It's a real shame that this great tradition may not continue, though, perhaps the js2k+ will be the next big thing ;)
Think WASM coding like the original Demoscene demos.
In this case, I guess that would be the procedural generation of the background and trees, for instance, to give it better quality than simple triangles.
So not only are you right, it's actually super easy. Just do this at the top level of your code:
const {cos, sin, PI /* etc */} = Math;Except that the word const does seem to be used in the uncompressed version, so we don't know what happens during compression in the Closure compiler, no? Or is the 2k version pre-Closure compiler different from the uncompressed version?
Either way the only way to know is to try because asymptotically free is all well and good, but without measurement we don't know the actual behavior in practice and we are just making assumptions about how well or how badly things compress and how the mangling process works out.
> it is still 1 byte larger then without
That's actually pretty cool, because together with your earlier remark of ~40x occurrences of Math.<whatever> that means we have a ballpark figure for where the tipping point is!
The only downside is the compiler itself runs on the JVM, and most developers ostensibly prefer a single platform. Given how much other software you need to make a development environment work, this seems silly to me.
Google also doesn't really advertised the use of Closure, you have to go out of your way to find it in their developer website or google it to find it. It's really just an internal tool.
They break backwards compatibility in the Closure Library so much that projects that adopted Closure (like Clojurescript), are stuck with a library from 2017. The project is maintained only to serve Google.
Is that the case? The current version of ClojureScript depends on org.clojure.google-closure-library 0.0-20191016 – I know it's a fork, but I'm not sure to what extent it is being synced with upstream.
https://github.com/clojure/clojurescript/blob/master/deps.ed...
https://github.com/clojure/clojurescript/blob/master/project...
M=Math,s=M.sin,c=M.cos,p=M.PI,a=M.abs; // etc. // 1
doSomething();
console.log(Math.sin(2));
// 2
var s = Math.sin;
doSomething();
console.log(s(2));
Now, consider this definition for `doSomething()`: function doSomething() {
Math.sin = x => x
}
Now, the first prints 2 and the second snippet prints 0.9092.Keeping track of globals to get around this is complicated. Even if you do, you can't always be sure the behaviour of the code isn't changing since `doSomething` could be defined in a module your minifier doesn't know about.
On commodore 64 games tried to have nice graphics, nice music and interesting mechanics. Lots of games failed at 1 of the 3. Sometimes they did really well with the other challenges but with few exceptions it doesn't make up for it.
I think if 2 kb is the challenge the game mechanics are the best hope to make up for the lack of sound and visuals.
Reminds me of burning rubber. A game with truly ugly graphics and terrible music that is quite hilarious to play.
With this engine, and most modern 3d engines you apply a transform to 3d world space points to get a screen space point. You also need to sort objects by distance or use a z buffer.
Also, obligatory kkrieger link: https://en.wikipedia.org/wiki/.kkrieger
As a dev, one problem I saw often is UE4 is massive, well over a hundred meg for just the base engine.
Consider Windows calculator. In Windows 10, it consumes 15+ MB of RAM. When desktops have 8+ GB of RAM, 15 MB is essentially nothing. And yet, 15 MB is an astronomical amount of RAM considering the functionality Calculator offers. There's really no reason it should be more than a couple hundred kilobytes.
If you were to add all the stuff from the Unity marketplace you need to be equivalent to a base UE4 install, it would probably approach that size as well, presuming all those features were even available.
I was reading the blog post and mistakenly refreshed the page. Now, BW is exhausted. I didn't know...
And 54 lines of JS: https://jsfiddle.net/06L845jx/127/
How exactly?