Hacker News new | comments | show | ask | jobs | submit login
The Matrix in JavaScript in less than 600 bytes (timelessname.com)
319 points by doublextremevil 1361 days ago | hide | past | web | 70 comments | favorite

The closest environment I got to work with Matrix-like UI but real experience was:

There is board I'm developing on with serial port, and kernel debug prints so much garbage it literally fills the entire screen in less than couple of seconds. It was because of faulty/broken hardware and there is busy loop that keeps retrying to access the device.

I could enter shell commands but I/O lines get mixed in between the verbose kernel debug lines. After some time my eyes synced to the screen scroll rate and I could follow the output from bottom to top to read it (repeatedly run command until I could catch the output correctly).

For the moment, I saw "blonde" in fast scrolling random code :) Anyone else had to work like this?

Embedded hackers of the world unite?

Everytime u-boot barfed on me or I messed up the serial port I ended up having to scan through screenfulls of ASCII junk scrolling by at full speed to get my commands and results out.

The closest I ever got to -real- blonde/brunette effects was when I was debugging the output from a H264 streamer. I could figure out video resolution and slicing properties from the tcpdump trace scrolling by :)

Have you ever tried to config a router that has debug to console turned on?

Makes me want to throttle whomever made this with no option to pause output.

You're 99% there. The leading characters need to be white, with the tailing characters being green.


Let's get real picky:

- chunks should vertically move down together, they don't just change color

- leading char is a bright green with outer glow

- movement doesn't always start at the top

- there are gaps in the chars

- there are vertical groups as small as 1 char that change chars at random

- there is no trailing transition in the color


Furthermore, the characters are supposed to be horizontally inverted (flipped) half width katakana (Japanese) characters, not the Chinese kanji.

Also digits, flipped as well.

If we're going to get real nitpicky, this is just a rendering of the Matrix UI, and not the code of the Matrix itself. I imagine that would be orders of magnitude bigger than 600b, considering the original storyline had the brain being part of a network (and not just human batteries).

golf clap

(did actually lol)

Inconsistency among visualizations of The Matrix code [1] is a really common problem, and I don't think all or even most of it is for copyright reasons. The solution is obvious: if it doesn't yet exist (I wasn't able to find one) somebody should write a specification for what a "correct" visualization is.

It might be a decade too late but better late than never.

[1] Wikipedia calls it the "Matrix digital rain", see https://en.wikipedia.org/wiki/Matrix_digital_rain.

- The "leader" seems to cycle from one character to the next faster than it advances from cell to cell.

- The "random" groups don't look random at all to me. More like there's a series of "standing" characters left behind by the light-green leader, and behind that there's a stream of "running" characters advancing at a different rate. We only see the running characters through gaps in the standing characters, and only in cells that the leader has already visited.

This kind of thing makes me love HN

hey thanks for the endless video link...didn't know this tool existed.

http://jsfiddle.net/muV99/16/ done

Sadly I never really used canvas before, so I don't know how to hide the dark-green afterglow.

Why is this using a map when the result is just being thrown away? Imagine how left out forEach feels :(.

Also: the afterglow is caused by the main loop filling the entire canvas with a black rect with very low opacity. The result is that after so many frames, everything but the actively drawing characters are much darker. Increase the opacity if you want to reduce the length of the effect.

As he wrote in the fiddle's test he worked from the deobfuscated code of the original item, which probably used map to save 4 characters

I didn't mean the "rgba()-fillRect-command", but why the font blur is still slightly visible as dark green, while the character itself has already faded to black.

If we're being picky, they aren't white. Definitely not #FFF. More of a pale green.

Also, if we're being picky, the characters change in the trails, trails have different lengths, not every trail is lead by a brighter char, some moving/stationary single chars, etc.

light green + glowing + pulsating.

pretty sure it was Japanese, not Chinese

here it is at 324 bytes, since your going to end up with scrollbars no matter what, you might as well not worry about document size

    <canvas id=q width=3000 height=3000 style=margin:-10><script>for(m=Math.random,p=[],i=0;i<256;p[i++]=1);setInterval('9Style="rgba(0,0,0,.05)"9Rect(0,0,3000,3000)9Style="#0F0";p.map(function(v,i){9Text(String.fromCharCode(3e4+m()*33),i*10,v);p[i]=v>758+m()*1e4?0:v+10})'.split(9).join(';q.getContext("2d").fill'),33)</script>
edit... and at 319

    <canvas id=q style=margin:-10><script>for(q.width=q.height=b=3000,m=Math.random,p=[],i=0;i<256;p[i++]=1);setInterval('9Style="rgba(0,0,0,.05)"9Rect(0,0,b,b)9Style="#0F0";p.map(function(v,i){9Text(String.fromCharCode(3e4+m()*33),i*10,v);p[i]=v>758+m()*1e4?0:v+10})'.split(9).join(';q.getContext("2d").fill'),33)</script>

If this is your thing, why not enter something for js1k? http://js1k.com/2013-spring/

Looks like there's already a very similar submission: http://js1k.com/2013-spring/demo/1382. This one however is significantly better.

They need to publicize this more. It was really fun in 2010, and I didn't even know they decided to do it annually since!

Shameless self-promotion: http://js1k.com/2013-spring/demo/1423

Nice work.

nice, and if you want to test it quickly, just paste it in the address bar:

    data:text/html,<canvas id=q width=3000 height=3000 style=margin:-10><script>for(m=Math.random,p=[],i=0;i<256;p[i++]=1);setInterval('9Style="rgba(0,0,0,.05)"9Rect(0,0,3000,3000)9Style="#0F0";p.map(function(v,i){9Text(String.fromCharCode(3e4+m()*33),i*10,v);p[i]=v>758+m()*1e4?0:v+10})'.split(9).join(';q.getContext("2d").fill'),33)</script>

Could you please explain the 9 thing? 9Style, 9Text etc ? First time seeing this for me. Thank you !

It's used a delimiter for splitting lines.

I took the liberty do de-obfuscate the code : http://jsfiddle.net/tburette/w6npr/5/

Great, I changed it to one of the katakana ranges and flipped the canvas http://jsfiddle.net/muV99/1/

Now it just needs overflow:hidden to lose sidebars and it's perfect.


overflow-hiddened: http://jsfiddle.net/muV99/1/

"Headlong motion through walls of emerald green, milky jade, the sensation of speed beyond anything he'd known before in cyberspace... The Tessier-Ashpool ice shattered, peeling away from the Chinese program's thrust, a worrying impression of solid fluidity, as though the shards of a broken mirror bent and elongated as they fell --"

http://project.cyberpunk.ru/lib/neuromancer/ (1984)

Great book! been years since I've read it.

There has been some interesting discussion and code golfing on this piece over at Reddit that may be a worthwhile read for some:


"Code golfing" is a truly marvelous term.

Reminds me of layer tennis: http://layertennis.com/

Why kanji instead of mirrored katakana?

If The Architect hadn't thought he was smarter than JSLint, they wouldn't have ended up with that pesky anomaly.

Attempted to upload my consciousness to this but it just crashed Chrome. Github issues link pls.

Worked for me in Firefox nightly.

Have you gotten the Data link hardware to work? I've been trying to install it into my spinal cord, but I'm getting Neurons_Out_Of_Bounds exceptions all the time.

If anyone is curious how the code actually works, I've commented up a version below:

    <script type="text/javascript">

    function matrix() {
        // initialize variables
        for (s = window.screen,
             w = q.width = s.width, // on my monitor: 1920
             h = q.height = s.height,  // on my monitor: 1200
             m = Math.random,   // random number from 0-1
             p = [],
             i = 0; 

             // i ranges from 0 to 255, one element for each character horizontally
             // this is enough characters to fill the entire screen horizontally
             // canvas won't let you draw off the screen - so I could set this to 1000
             i < 256;

             // initialize p (the y coordinate of each character) to start at 1
             p[i++] = 1);

            // every time we call this function we draw the entire screen a very faint black (with a high transparency of 0.05)
            // this means every 33 milliseconds the screen is getting slightly darker
            // this also acts to darken and fade the green characters - when they are first printed they are dark green, then they slowly fade to black
            function() {
                // draw black (0,0,0) with alpha (transparency) value 0.05
                // fill the entire screen
                // #0f0 is a short form for color green (#00FF00)

                    // this function will be called 256 times - once for each element of array p, 
                    // map over the array p
                    //      v is the value in the array p, which represents the y-coordinate of the text going down
                    //      i is the index of the array p, which represents the x coordinate
                    // start from unicode char code 30,000 (0x7530) then add a random number from 0-33
                    // from wikipedia: http://en.wikipedia.org/wiki/List_of_CJK_Unified_Ideographs,_part_2_of_4
                    //      U+753x 	田 	由 	甲 	申 	甴 	电 	甶 	男 	甸 	甹 	町 	画 	甼 	甽 	甾 	甿
                    //      U+754x 	畀 	畁 	畂 	畃 	畄 	畅 	畆 	畇 	畈 	畉 	畊 	畋 	界 	畍 	畎 	畏
                    //      U+755x 	畐
                    randomNum = m()*33;
                    // note how the asian characters are slightly different shades
                    // of green, this depends on their line thickness etc, and doesn't
                    // really happen for english characters
                    randomAsianChar = String.fromCharCode(30000 + randomNum);

                        i*10,   // x coordinate - each character is 10 x 10
                        v       // y coordinate 
                    // draw at least 758 characters down before reseting to the start
                    num = minimumHeight+m()*10000;
                    p[i] = (v>num) ? 0 : v+10   // increment the y coordinate by one character (10 pixels), reset when y-coord gets too big
            33) // call every 33 milliseconds

    <body style=margin:0 onload="matrix()"><canvas id=q>

Looks like you improved upon the one I posted yesterday https://news.ycombinator.com/item?id=5387553 - but it works much better in canvas for sure!

When my eyes follow the raindrops it's impossible to see the Chinese characters. I have really to force myself to stare at one spot to see the characters. Interesting phenomena.

It's pretty simple - the symbols don't move. Their brightness changes. So if you move your view - you jump across many symbols and obviously can't "follow" anything.

I think what apunic is noting is our natural tendency to track movement. If you try to read something too close to the leading bright letter, your eyes get hooked by it and get dragged along for the ride. You have to stay a safe distance back to be able to read anything.

This can be rendered directly into Chrome by:

    data:text/html, <canvas id=q style=margin:-10><script>for(q.width=q.height=b=3000,m=Math.random,p=[],i=0;i<256;p[i++]=1);setInterval('9Style="rgba(0,0,0,.05)"9Rect(0,0,b,b)9Style="#0F0";p.map(function(v,i){9Text(String.fromCharCode(3e4+m()*33),i*10,v);p[i]=v>758+m()*1e4?0:v+10})'.split(9).join(';q.getContext("2d").fill'),33)</script>

removing the 9 split jazz is actually shorter (and more readable) http://jsbin.com/idijay/1/edit

I think it are the wrong type of characters. The Asian characters in the Matrix are less complex than those (Wikipedia says "half-width kana").

Wow, what a coincidence. I just made one two weeks ago. Mine is way over 600 bytes though.

Requires Chrome:


Doesn't work for me in Chrome 27.

I'd love to have one that accurate emulates the real animation.

Ah, newer versions of Chrome broke (https://code.google.com/p/chromium/issues/detail?id=180007) the htmlpreview tool. Here's a link that should work with the newer Chrome. Please let me know what you think! It's modeled after xmatrix rather than the original film footage, but I think it's pretty good. Still Chrome-only:


All I see is this:

sed: 2: "x;s/\n//g;${p;x;} }'s) ": unexpected EOF (pending }'s)

Are you using OS X?

You need GNU Sed for this to work.

Ah. Thanks.

http://timelessname.com/sandbox/matrix_orig.html is the only version that works for me. I don't have time right now to figure out why that is.

This is what a webcam packet dump looks like on a black console with green text: http://bluesmoon.livejournal.com/32581.html

That is cool, wish I could make it my background.

What's cool about 600b is you can use it for your browser start page. I'd like to see the picky stuff implemented. :)

XP SP2, Firefox 19.0.2 and all I get is a screen that quickly fades to black and then ... nothing.

"XP SP2"

I'm nostalgic too (not about Windows that said) but... Windows XP is the most exploited Windows right now: zombie botnets are made of a huge part of Windows XP PCs. Microsoft ain't patching several critical exploits on XP and it has been demonstrated for a fact that any local hole on XP means admin rights.

and "SP2" At least get to SP3

I can't. This is a PC that is too slow for SP3 now. I tried it when SP3 was released and it just made it slower. I had to roll back. I use defensive measures and have been able to ward off bots and virii so far (not that they didn't get through a few years ago...).

Makes one heck of a screen saver

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact