(???) !DOCTYPE html>
(???) html>
(???) <head>
(???) <meta charset="utf-8">
(???) <meta name="viewport" content="width=device-width, initial-scale=1.0">
(???) <title>JavaScript Tetris in 1.5 kB</title>
(???) <link href="/css/black-no6.css" rel="stylesheet">
(???) <link rel="alternate" type="application/rss+xml" title="RSS Feed" href="https://joriszwart.nl/feed/rss.xml">
(???) <link rel="alternate" type="application/atom+xml" title="Atom Feed" href="https://joriszwart.nl/feed/atom.xml">
(???) <link rel="alternate" type="application/json" title="JSON Feed" href="https://joriszwart.nl/feed/feed.json">
(???) <meta property="og:title" content="JavaScript Tetris in 1.5 kB">
(???) <meta property="og:description" content="JavaScript Tetris in 1.5 kB">
(???) <meta property="og:image" content="https://joriszwart.nl/images/projects/jstetris.png">
(???) <meta property="og:url" content="https://joriszwart.nl/games/javascript-tetris-1.5kb">
(???)
(???) </head>
(???) <body>
(???) <nav class="fixed-top sticky light">
(???)
(???) <ul>
(???) <li><a href="/articles">My articles</a></li>
(???) <li><a href="/games">My games</a></li>
(???) <li><a href="/projects">My projects</a></li>
(???) <li><a href="/talks">My talks</a></li>
(???) <li><a href="/contact">Contact</a></li>
(???) </ul>
(???) </nav>
(???) <header>
(???)
(???) <a href="/">
(???)
(???) <img src="/images/joriszwart-logo.png" alt="joriszwart.nl" width="577" height="74">
(???) <p class="uppercase">Code golf
(???) </p>
(???) </a>
(???) </header>
(???) <main>
(???)
(???) <article>
(???) <header>
(???) <div class="tags" aria-label="tags">
(???) <a href="/tags/a-language-a-year-keeps-the-doc-away" rel="tag">A language a year keeps the doc away</a>
(???) <a href="/tags/code-golf" rel="tag">Code golf</a>
(???) <a href="/tags/games" rel="tag">Games</a>
(???) <a href="/tags/javascript" rel="tag">JavaScript</a>
(???) <a href="/tags/optimization" rel="tag">Optimization</a>
(???) <a href="/tags/performance" rel="tag">Performance</a>
(???) <a href="/tags/size-coding" rel="tag">Size coding</a>
(???) <a href="/tags/tetris" rel="tag">Tetris</a>
(???) </div>
(???) </header>
(???) <h1 id="javascript-tetris-in-15-kb">JavaScript Tetris in 1.5 kB</h1>
(???) p><img src="/images/projects/jstetris.png" alt="jstetris.html"></p>
(???) h2>Introduction</h2>
(???) p><em>jstetris.html</em> is an attempt to write Tetris in JavaScript and also an exercise in size coding.
(???) /p>
(???) p>Around the time (2004) it was probably the most performant Tetris in JavaScript available.</p>
(???) p>
(???) a href="/games/javascript-tetris-1.5kb/jstetris.html" class="button">Play it!</a>
(???) a href="#source-code" class="button">Source code</a>
(???) /p>
(???) !-- TODO dl class="compact">
(???) dt><kbd>▼</kbd> <kbd>I</kbd></dt><dd>Rotate</dd>
(???) dt><kbd>▲</kbd> <kbd>K</kbd></dt><dd>Down</dd>
(???) dt><kbd>◀</kbd></dt><dd>Rotate</dd>
(???) dt><kbd> SPACE </kbd></dt><dd>Drop</dd>
(???) dt><kbd>▲</kbd></dt><dd>Rotate</dd>
(???) /dl -->
(???) h3>Controls</h3>
(???) p>
(???) se cursor keys <kbd>▲</kbd> <kbd>▶</kbd> <kbd>▼</kbd> <kbd>◀</kbd> <kbd> SPACE </kbd> or
(???) <kbd>I</kbd> <kbd>J</kbd> <kbd>K</kbd> <kbd>L</kbd> <kbd>M</kbd> <kbd> SPACE </kbd> to control the game.
(???) /p>
(???) h2>About performance</h2>
(???) p>
(???) ther versions used absolute positioned images or <code>div</code>s to make up the blocks.
(???) sing a <code>table</code> with CSS-styled cell borders as a grid seemed logical.
(???) /p>
(???) p>
(IMG) tried different ways of accessing the table cells:
(???) /p>
(???) ul><!-- TODO show <meter> with timing for each method -->
(???) li><code>getElementsByTagName('td')</code> (slow!)</li>
(???) li><code>nextSibling</code></li>
(???) li><code>table.rows[y].cells[x]</code></li>
(???) li><code>childNodes</code></li>
(???) /ul>
(???) p>We're talking 30-40 <em>milli</em>seconds here BTW, not <em>micro</em>seconds (remember, 2004) to iterate
(???) hrough the cells. Accessing it by <code>table.rows[y].cells[x]</code>
(???) as almost as fast as <code>nextSibling</code> but more convenient in terms of code-size and readability :-)</p>
(???) p>The same is true for using table methods <code>insertRow</code> and <code>deleteRow</code>. Less code and more speed than moving the cells individually.</p>
(???) h2>About size</h2>
(???) p>Nowadays you can bring it down to 1 KB or even 512 bytes, but I did not want to give up on the scoring system, preview and VIM-bindings :-) Another time maybe!</p>
(???) !-- TODO template "includefile" "/games/tetris.html" -->
(???) h2 id="source-code">The code</h2>
(???) p>The code is 45 lines and ofcourse <del>a great mess</del><ins>obfuscated</ins> but pretty readable if you beautify it.</p>
(???) pre data-lang="JavaScript">
(???) code><title>1½ kB Tetris</title><style>table{border:4px groove #6b0;font-size:9}td{width:1em;border:solid #fff}pre{margin:9;float:left}</style><body onkeydown=k(event)><pre id=s></pre><table id=t cellspacing=0></table><script>var d=document,W=10,H=25,s=l=0,Y,t</code>
(???) code>function a(){for(r=B.insertRow(0),x=W;x--;)r.insertCell(0).appendChild(d.createTextNode('Â '))}</code>
(???) code>function T(b,R,a){for(i=4;i--;){q='defgaeimdefgaeimdefjaeibdhijibfjdhefaeijhifjabfjeifjeifjeifjeifjheifaefjheifaefjdeifaeifheijebfjdeijeibfdeijeibf'.charCodeAt(b*16+R*4+i)-96</code>
(???) code>a(q%4,q>>2)}}function D(c,Y,b,r){T(b,r,function(x,y){p=' #'+(c?'0ff00f808'.substr(b,3):'fff')</code>
(???) code>v=S[Y+y].cells[X+x]</code>
(???) code>o=v.style</code>
(???) code>o.background=p</code>
(???) code>o.border=(c?'outset':'solid')+p</code>
(???) code>v.s=c</code>
(???) code>})}function M(O,P,R){</code>
(???) code>D(0,Y,b,r)</code>
(???) code>c=4</code>
(???) code>T(b,R,function(x,y){x+=X+O</code>
(???) code>y+=Y+P</code>
(???) code>if(x<0||x>=W||y>=H||S[y].cells[x].s)c=0})</code>
(???) code>if(c){X+=O</code>
(???) code>Y+=P</code>
(???) code>r=R}D(1,Y,b,r)</code>
(???) code>return c}function C(){X=3</code>
(???) code>D(0,-1,n,0)</code>
(???) code>for(p=0,y=Y;y<H;y++){for(f=0,x=W;x--;)f|=!S[y].cells[x].s</code>
(???) code>if(!f){B.deleteRow(y)</code>
(???) code>a()</code>
(???) code>p++}}d.getElementById('s').innerHTML='Score: '+(s+=9<<p)+'\nLines: '+(l+=p)+'\n\n© MMIV Joris Zwart'</code>
(???) code>clearInterval(t)</code>
(???) code>t=setInterval(F,650-l)</code>
(???) code>b=n</code>
(???) code>n=new Date()%7</code>
(???) code>D(1,-1,n,0)</code>
(???) code>Y=1</code>
(???) code>r=0</code>
(???) code>if(!M(0,1,r)){clearInterval(t)</code>
(???) code>alert(':-(')}}function F(){if(!M(0,1,r))C()}function k(e){switch(e.which||event.keyCode){case 74:case 37:M(-1,0,r)</code>
(???) code>break</code>
(???) code>case 75:case 38:M(0,0,(r+1)%4)</code>
(???) code>break</code>
(???) code>case 76:case 39:M(1,0,r)</code>
(???) code>break</code>
(???) code>case 32:clearInterval(t)</code>
(???) code>t=setInterval(F,9)</code>
(???) code>case 73:case 40:case 77:F()}}B=d.getElementById('t')</code>
(???) code>n=new Date()%7</code>
(???) code>S=B.rows</code>
(???) code>for(y=H;y--;)a()</code>
(???) code>C()</script></code>
(???) /pre>
(???) !-- TODO move technical tags to general tags -->
(???) aside>
(???) dl>
(???) dt>Where</dt>
(???) dd><a href="/">joriszwart.nl</a></dd>
(???) dt>When</dt>
(???) dd>2004</dd>
(???) dt>Technical</dt>
(???) dd>JavaScript</dd>
(???) dt>Url</dt>
(???) dd>/games/javascript-tetris-1.5kb/jstetris.html</dd>
(???) /dl>
(???) /aside>
(???)
(???) <div>
(???) <time datetime="2004-12-21 02:41:05 +0000 +0000">Tue, 21 Dec 2004 02:41:05 +0000</time>
(???) </div>
(???)
(???) </article>
(???) <div class="prevnext" id="prevnext">
(???) <a href="/games/sirtet" rel="prev">
(???) <strong>previous</strong><br>
(???) Sirtet
(???) </a>
(???) <a href="/games/esnextris" rel="next">
(???) <strong>next</strong><br>
(???) ESNextTris
(???) </a>
(???) </div>
(???) <section>
(???)
(???) <h2>Related</h2>
(???) <div class="gallery">
(???) <a href="/talks/tetris4life">
(???) <figure>
(???) <img src="/talks/tetris4life.svg" alt="Semi generic tetris logo inspired by the Elm logo" loading="lazy">
(???) <figcaption>[Talk] Tetris4life</figcaption>
(???) </figure>
(???) </a>
(???) <a href="/math/fixed-point">
(???) <figure>
(???) <img src="/images/bits.svg" alt="Bits" loading="lazy">
(???) <figcaption>Fixed point explanatorial</figcaption>
(???) </figure>
(???) </a>
(???) <a href="/articles/pico-search-50-lines">
(???) <figure>
(???) <img src="/img/fallback.svg" alt="" loading="lazy">
(???) <figcaption>PicoSearch - TF-IDF in 50 lines</figcaption>
(???) </figure>
(???) </a>
(???) <a href="/articles/minimalistic-svg-library">
(???) <figure>
(???) <img src="/images/icons/svg-logo-v.svg" alt="SVG Logo" loading="lazy">
(???) <figcaption>Minimalistic SVG library</figcaption>
(???) </figure>
(???) </a>
(???) <a href="/graphics/simple-svg-javascript">
(???) <figure>
(???) <img src="/images/icons/svg-logo-v.svg" alt="W3 SVG Logo" loading="lazy">
(???) <figcaption>Creating SVG from JavaScript</figcaption>
(???) </figure>
(???) </a>
(???) <a href="/c64/tetris">
(???) <figure>
(???) <img src="/c64/tetris/screen09-wip.png" alt="Tetris screenshot WIP" loading="lazy">
(???) <figcaption>Tetris for Commodore 64</figcaption>
(???) </figure>
(???) </a>
(???) <a href="/projects/hacker-news">
(???) <figure>
(???) <img src="/hn/hn.svg" alt="Hacker news logo" loading="lazy">
(???) <figcaption>Hacker News Client</figcaption>
(???) </figure>
(???) </a>
(???) <a href="/c64/tetris-inner-loop-6510">
(???) <figure>
(???) <img src="/articles/tetris-inner-loop-6510/tetris-innerloop.png" alt="Tetris Block" loading="lazy">
(???) <figcaption>Tetris inner loop MOS6510 / C=64</figcaption>
(???) </figure>
(???) </a>
(???) <a href="/c64/hextris">
(???) <figure>
(???) <img src="/c64/hextris-wip.png" alt="Hextris screenshot WIP" loading="lazy">
(???) <figcaption>Hextris C=64</figcaption>
(???) </figure>
(???) </a>
(???) <a href="/c64/c64js">
(???) <figure>
(???) <img src="/img/fallback.svg" alt="" loading="lazy">
(???) <figcaption>Commodore 64 emulator</figcaption>
(???) </figure>
(???) </a>
(???) </div>
(???) </section>
(???) </main>
(???) <footer id="footer">
(???) <nav>
(???) <ul>
(???)
(???) <li><a href="/search">Search</a></li>
(???) <li><a href="/categories">Categories</a></li>
(???) <li><a href="/tags">Tags</a></li>
(???)
(???) </ul>
(???) </nav>
(???) <div>
(???) <a href="/"><img src="/images/joriszwart-logo.png" alt="" width="265" height="34"></a>
(???) </div>
(???) </footer>
(???) </body>
(???) /html>