[HN Gopher] How I made a 3D game in 2 KB of JavaScript
       ___________________________________________________________________
        
       How I made a 3D game in 2 KB of JavaScript
        
       Author : pjmlp
       Score  : 330 points
       Date   : 2020-03-09 10:30 UTC (12 hours ago)
        
 (HTM) web link (frankforce.com)
 (TXT) w3m dump (frankforce.com)
        
       | m00dy wrote:
       | damn,
       | 
       | I was reading the blog post and mistakenly refreshed the page.
       | Now, BW is exhausted. I didn't know...
        
       | 6510 wrote:
       | It looks great, runs smoothly but I'm not having a gameplay
       | experience.
        
         | notkaiho wrote:
         | What do you mean by a 'gameplay experience' in this case?
        
           | 6510 wrote:
           | I don't want to hate on the creation at all but its hard not
           | to sound like that in text.
           | 
           | 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.
           | 
           | https://www.youtube.com/watch?v=nKSbOyGy_Qo
        
             | egypturnash wrote:
             | ...which is a shameless clone of Data East's Bump 'n'
             | Jump/Burnin' Rubber, which had much better art and sound.
             | https://m.youtube.com/watch?v=99gnxjpeL7s
        
               | 6510 wrote:
               | haha, so they kept only the game play. It makes a lot
               | more sense now.
        
       | mosselman wrote:
       | The game is pretty fun and playable for its size. Nice work!
        
       | throwaway77384 wrote:
       | I absolutely love projects like this. It's so interesting working
       | within these constraints.
       | 
       | 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 ;)
        
         | woogley wrote:
         | Only thing I can find is this tweet from the organizer.
         | https://twitter.com/kuvos/status/1213546333707083778
        
           | pjmlp wrote:
           | Love the WASM remark on his tweet.
           | 
           | Think WASM coding like the original Demoscene demos.
        
             | tracker1 wrote:
             | Not sure about the 2k+zip, but I do think that there will
             | be a _LOT_ of progress in wasm+canvas for interactive
             | programming... of course this leaves out accessibility, so
             | hopefully it 's done with some constraint depending on the
             | space.
        
       | sccxy wrote:
       | Controls:
       | 
       | Mouse = Steer
       | 
       | Click = Brake
       | 
       | Double Click = Jump
       | 
       | https://github.com/KilledByAPixel/HueJumper2k
        
       | iron4o wrote:
       | Why are there trees in them middle of the road? ;D
        
         | KilledByAPixel wrote:
         | Alien trees...
        
       | franblas wrote:
       | Nice ! :) Looks like a raycasting engine like this one
       | https://www.playfuljs.com/a-first-person-engine-in-265-lines...
        
         | KilledByAPixel wrote:
         | Nope! It is not a raycasting engine at all, but instead built
         | similar to old school racing game tech.
        
           | winrid wrote:
           | Could you help us understand how it's not ray casting? OP
           | doesn't mean ray tracing by the way. Ray casting is the tech
           | used in Wolf3D for example, or maybe I'm preaching to the
           | choir.
        
             | fenwick67 wrote:
             | Since the car only goes forward, there's no reason to have
             | any depth or visibility testing, things are just rendered
             | in order (painter's algorithm).
        
             | KilledByAPixel wrote:
             | With ray casting engines for each column of pixels you cast
             | a ray and collide it against world geometry to see what it
             | hit and where.
             | 
             | 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.
        
       | notkaiho wrote:
       | And thanks to this article I've learned about the Google Closure
       | compiler: https://developers.google.com/closure/compiler
        
         | Cthulhu_ wrote:
         | Is it still relevant and updated nowadays? IIRC that one's been
         | around for at least a decade already.
        
           | lvh wrote:
           | Absolutely. It took a long time for everyone to catch up on
           | basic features (Closure had modules figured out while the
           | rest of the JS community still had several competing
           | standards), but it's still tremendously effective.
           | 
           | 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.
        
             | nathell wrote:
             | There is a JavaScript port of the Closure compiler,
             | available from npm: https://www.npmjs.com/package/google-
             | closure-compiler
        
             | Scarbutt wrote:
             | A real downside and the reason it never took off, is that
             | you have to annotate all your Javascript code to really
             | leverage the Closure compiler.
             | 
             | 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.
        
               | nathell wrote:
               | > 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.
        
               | Scarbutt wrote:
               | Their repo says they are using version
               | "0.0-20170809-b9c14c6b"
               | 
               | https://github.com/clojure/clojurescript/blob/master/deps
               | .ed...
               | 
               | https://github.com/clojure/clojurescript/blob/master/proj
               | ect...
        
           | jyriand wrote:
           | ClojureScript leans heavily on google closure.
        
             | Scarbutt wrote:
             | yes, but since we are talking about size, a hello world
             | Clojurescript is going to be at least 80KB or greater.
        
       | jfkebwjsbx wrote:
       | I love these projects, but writing statements like "full HD" and
       | "Realistic driving physics and collisions" is a bit too much
       | unless it is tongue-in-cheek :)
        
         | KilledByAPixel wrote:
         | HD because many tiny games like this do not stretch to fill the
         | whole window. It requires extra code to do this and have
         | everything scale properly.
        
           | buzzerbetrayed wrote:
           | I've never heard "HD" be used to mean "full width"
        
             | chipperyman573 wrote:
             | I haven't either but as someone who plays games
             | occasionally, the definition makes sense to me (lots of
             | games don't scale well). Definitely not something I'd have
             | guessed, though.
        
             | recursive wrote:
             | It's "high definition". Since the graphics are all vector
             | graphics, it doesn't seem to be too far of a stretch. All
             | the rendering will be done at the resolution available.
        
             | KilledByAPixel wrote:
             | Do you have an HD monitor? If so the game is in HD. Many
             | tiny games and demos like this are rendered to a smaller
             | canvas and will either not stretch to fill your monitor or
             | are rendered at a lower then HD resolution.
        
               | jfkebwjsbx wrote:
               | When people use that term for games, it usually means the
               | assets have been reworked to look better.
               | 
               | 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.
        
       | jsgamedev wrote:
       | This is very impressive!
       | 
       | 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
        
         | KilledByAPixel wrote:
         | Thanks, I also referenced this jk1k racing game in the post...
         | 
         | https://js1k.com/2019-x/demo/4006
        
       | aylmao wrote:
       | In the final, minified code there's a lot of calls to Math
       | methods (sin, cos, tan). I wonder if there's potential to shrink
       | this even more with some assignments:
       | M=Math,s=M.sin,c=M.cos,p=M.PI,a=M.abs; // etc.
        
       | nathell wrote:
       | Also in the genre of tiny racing games, this 2004 entry from
       | IOCCC comes to mind:
       | 
       | https://www.ioccc.org/2004/vik1.c
        
       | agys wrote:
       | In the minified code there are still a lot of Math.PI, Math.sin,
       | Math.cos... could this not be optimised further with something
       | like s=Math.sin...?
        
         | cjg wrote:
         | It gets zipped so the duplication goes away. In fact,
         | repetition is deliberate to get better compression.
        
         | Elrac wrote:
         | In the original article, the author claims that lots of
         | repeated strings turn out to be beneficial insofar as they make
         | compression (gzip or whatever) more effective. According to
         | him, it doesn't make sense to manually de-redundantize code
         | when the compressor will achieve the same gain or better.
        
         | vanderZwan wrote:
         | I was about to say _" well, it's probably a lot of work to
         | verify that s isn't already a mangled variable name"_ but then
         | I realized that doing what you suggested in the pre-minified
         | code should work, yeah.
         | 
         | 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;
        
           | [deleted]
        
           | KilledByAPixel wrote:
           | You could do that, but it would not compress as well. For
           | example the word const is not use anywhere in the 2k version,
           | while Math. is used about 40 times so it becomes essentially
           | free when compressed.
        
             | vanderZwan wrote:
             | > _For example the word const is not use anywhere in the 2k
             | version, while Math. is used about 40 times so it becomes
             | essentially free when compressed._
             | 
             | 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.
        
               | KilledByAPixel wrote:
               | Ok, I just tried it. Removing every Math. and adding
               | let{cos,sin,PI,min,max,tan,atan2,abs,ceil}=Math; to the
               | top. It worked better then I expected, though it is still
               | 1 byte larger then without. Could potentially be a win in
               | some situations.
        
               | vanderZwan wrote:
               | Nice! Thanks for trying!
               | 
               | > _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!
        
       | pettycashstash2 wrote:
       | resource limit reached.....
        
       | midgetjones wrote:
       | Seems to be struggling a bit. Alternate link:
       | https://web.archive.org/web/20200309074327/http://frankforce...
        
         | itronitron wrote:
         | here is the codepen link from same article >>
         | https://codepen.io/KilledByAPixel/pen/poJdLwB
        
           | TruthSHIFT wrote:
           | FYI, there is no jump button. Also, those are rocks, not
           | ramps. Jumping is not a gameplay mechanic in this game.
        
             | KilledByAPixel wrote:
             | Double click to jump.
        
               | krossitalk wrote:
               | Thanks. Wish the controls were more obvious. After
               | learning this the game is actually quite playable.
        
         | huskyr wrote:
         | "Resource Limit Is Reached", seems a bit silly for a 2kb game
         | ;)
        
           | techntoke wrote:
           | Should call it "How I host my website for $2 a year."
        
             | huskyr wrote:
             | For $2 a year i think you could manage 2kb ;)
        
       | dlsso wrote:
       | Makes you wonder if the 70gb installs of modern games are really
       | necessary.
       | 
       | Also, obligatory kkrieger link:
       | https://en.wikipedia.org/wiki/.kkrieger
        
         | ssully wrote:
         | It's an impressive project, but it shouldn't make you question
         | why games are so large these days.
        
           | KilledByAPixel wrote:
           | I think there is a middle ground of many indie games I see on
           | steam that are much larger then they should really be.
           | 
           | As a dev, one problem I saw often is UE4 is massive, well
           | over a hundred meg for just the base engine.
        
             | meheleventyone wrote:
             | Binary size is a drop in the ocean most of the size of game
             | installs is in assets.
        
               | Sohcahtoa82 wrote:
               | While true, you do have to ask how the hell there could
               | possibly be 100 MB of _just code_.
               | 
               | 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.
        
         | austincheney wrote:
         | Makes you wonder if the nearly half gigabyte software kits are
         | really necessary to make a simple website. I am looking at you
         | Angular and React.
        
         | Goronmon wrote:
         | My non-expert opinion is that the size of most game installs is
         | tied directly to the amount of voiced dialog in the game, and
         | in a similar context, how many languages that voiced dialog has
         | been translated and included in the install.
        
       | tabtab wrote:
       | I made a 2D game in 3 KB of JavaScript. Not quite as impressive I
       | suppose.
        
       | IvanK_net wrote:
       | It reminds me my 3D demo in 47 lines of JS (without WebGL) :)
       | https://jsfiddle.net/06L845jx/86/
       | 
       | And 54 lines of JS: https://jsfiddle.net/06L845jx/127/
        
         | numlock86 wrote:
         | > It reminds me my 3D demo in 47 lines of JS
         | 
         | How exactly?
        
         | KilledByAPixel wrote:
         | That's cool! Reminds me of pavel's 1 line cube tornado.
         | 
         | https://www.dwitter.net/d/14485
        
       | rsiqueira wrote:
       | The first ideas of this 3D road game was created in just 140
       | characters (or less) and posted here (Dwitter) by him (Frank
       | Force's nickname is "KilledByAPixel"):
       | https://www.dwitter.net/h/road And many other tiny 3D effects and
       | engines in JavaScript were created by Dwitter's users, like these
       | demos: https://www.dwitter.net/h/d3
        
         | tomxor wrote:
         | Hi Rodrigo!
         | 
         | 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.
        
       ___________________________________________________________________
       (page generated 2020-03-09 23:00 UTC)