Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Show HN: Simple JavaScript Tetris (github.com/jstimpfle)
112 points by jstimpfle on Nov 2, 2016 | hide | past | favorite | 45 comments


EDIT: Better URL https://github.com/jstimpfle/tetris-on-a-plane/

I had fun building this and experiencing the joyful side of JS (or at least the browser ecosystem). Boarding a plane I'd had the idea of finishing a simple tetris before arrival. The game was in a working state after ~2 hours, even though I had made a few bad decisions. (it was subsequently polished, investing another few hours).

It was made with a "get things done" mindset, and the experience from dabbling with purely functional programming in Haskell was very helpful (mostly the "pure", as in "non-destructive", part).

It's nice that in Javascript we have an environment where we can code a fun game in <400 lines, without any library dependencies (not even internet connection needed) or build systems. On the downside, if it had stronger dynamic types and errors (like Python) that would have saved maybe 25% of my debugging time, probably without coding overhead.


Had you made Tetris before? Or used an external resource to see any pseudocode? Reason I'm asking is, I was doing a similar thing with Snake and it took me a bit longer (probably 4 hours) because I messed up the basic mechanics in the beginning (I didn't think of how to structure the growing body as a linked list). I want to gauge how much I suck (at least at games programming) lol.


I once spoke about it with a friend who had to do it in C. However C is a dangerous trap here, I think it gets you in the wrong mindset.

Data representation is pretty universally one of the most important things (basically the "design" part to me). Four hours is pretty quick I guess. Snake might be more difficult (but an array or llist + snake direction + board map should be straightforward). I'd done chess that week and the representation is also doable unless thinking about AI or history or... which is when I quickly go bikeshedding. Multiple different representations for different tasks (and transforming in between) might be a way to go.


I made Snake in 103 lines of ClojureScript for a talk once: https://github.com/pate/cljs-snake (LOC excludes whitespace and links to repo). Comes in under 100 LOC if you strip out the aesthetics.


Very nice!


Check out the encoding of the tetrominoes in this implementation: https://github.com/jakesgordon/javascript-tetris

My subsequent port to C and Arduino was very natural: http://youtu.be/t3QOeQbEHVs


Here's one I wrote a long time ago in Z80 assembly for the TI-86 graphing calculator: https://gist.github.com/electrum/76ac88de2e1d6c9254deaba003a...


The "Random" subroutine looks surprisingly simple


It is pretty cool. Feels very much like a smalltalk-ish environment. A WebGL context is a single HTML tag and a couple of lines of code away. However you can still get the productivity boosts from an ML-like language... there are options. And ES6 supports some patterns of FP out of the box (though it is made better with small library support).

Maybe checkout Bucklescript, Purescript, or Elm for the next one :)

One of my rituals of taking a long trip is to finish a small coding project before I land. Sudoku, minesweeper, tetris, forward-propagating constraint solvers... it's a nice practice. Thanks for sharing yours!


And here is a concise JavaScript tetris (playable: http://copy.sh/tetris/):

    f=[];p=[1];g=h=2;s=0;t=500;for(i=0;23>i;i++)f[i]=j=-16380;f[23]=-1;onkeydown=e;e(e);function e(b,a){(k=b.which)?k-38?k&-3^37||(g+=a=k^37?-1:1):(z=p,v=p[2],c=p[1],p=[2*v&2|4*c&4,p[3]/2&1|v&2|2*c&4|4*p[0]&8,p[3]/4&1|v/2&2|c&4|2*p[0]&8,v/4&2|c/2&4]):s-j&&setTimeout(e,100+t,h++);m=p[0]<<g;l=p[1]<<g;_=p[2]<<g;o=p[3]<<g;f[h+=32==k]&m|f[1+h]&l|f[2+h]&_|f[3+h]&o?a?g-=a:k^38?(f[h]|=l,f[--h]|=m,f[2+h]|=_,f[3+h]|=o,h?(g=6,x=new Date%7*4,p=[h=0,2908739>>x&15,266758006>>x&15],t*=.97):s+=" Game Over!"):p=z:k^32||e(b);for(y=_=o="";24>++y;o+="\n")for(f[y]+4||(f.splice(y,1),f.unshift(j),s+=++_,o="",y=2),x=14;x;q.textContent=o+s)o+=" X"[(f[y]|p[y-h]<<g)>>x--&1]}


Just because you minify and obfuscate this code doesn't somehow make it better or let you win the "contest".

I can walk through the submitter's code and understand what's happening clearly. It's fairly well structured and easy enough to read. This is 20x more valuable than any code that is produced using uncommented edge features for a perceived 5% gain. (Note that I'm making up these numbers to illustrate a point.)


Wait, where did the OP say it was better or won some contest?


I think you're taking this too seriously



"Clever" code. shudder It's confusing to read for anybody not used to it, particularly as you need to set the "initial" value to the "actual initial value"+1.



In other words, it's a crappy way to write `i-- > 0`

Note that it's not logically equivalent to `for (var i = 5; i > 0; i--)` because in this case the `i--` operation is applied after the body of the loop.

Try it in your browser: for (var i = 5; i-- > 0;) { console.log(i); } //4,3,2,1 for (var i = 5; i > 0; i--) { console.log(i); } //5,4,3,2,1


This is why I actually like this syntax (and get fun out of provoking "shudder" comments).

    - Can use the same limits as in ascending iteration
    - Can do decrementing in for loop (no extra line)
    - The arrow unambiguously signals that the iteration is correct :-)


!!"It's the JS way"


Link broke with new commit, here's a stable one: https://github.com/jstimpfle/tetris-on-a-plane/blob/d5d4d821...

This is a test to see how quickly someone brings up the stackoverflow link ;-)


Playable version of this code located here http://jstimpfle.de/projects/tetris-on-a-plane/tetris.html


nice, as a web developer i wanted to try my hands on making a game. which turned out to be much harder than i thought, and also see if i could do any thing with c lang, never wrote a program more than ~15 lines of code in c, so i build a tetris game, using SDL lib.

funny thing is i also represented shapes like you did as 0 or 1 on plane, but then changed to x,y list of blocks.

here it is. https://gist.github.com/spaceexperiment/4d6b116ef577a2971259...


Broken on Safari 10, and I can't figure out why. None of the keyboard keys seem to fire any events.


It seems the code uses `event.key` (which returns a human-readable string, e.g. "ArrowLeft"). `event.key` is not supported in WebKit.


Thanks to you both. I converted to using ev.keyCode. Hope it works everywhere.


yup I can confirm that, uBlock disabled


Awesome! I made a fiddle https://jsfiddle.net/wt309enw/1/


This is pretty fun to see on a fiddle. :)


Very nice. Agree with danso that keys should be case insensitive. Also - the UP arrow should rotate in some (any) direction.


Nice, I like writing things under constraint; especially without internet and manuals. Seems to take away a lot of stress and open up creativity, at least it does for me [0]. I am flying to AUS soon which will have me without internet for around 21 hours again and I will try another constraint game at that time.

[0] http://brainfisheatfishbrain.com/2015/03/writing-a-game-with...


I like that that this implementation lets you shift right/left for a split second after you let the piece fall.

Not all Tetris versions I've seen do that. I'm not sure what official behavior, though.


There's quite a few details about the official authentic tetris guidelines here, looks like it's probably reverse-engineered. https://tetris.wiki/Tetris_Guideline


I think you could optimize quite a bit of this. If you made your shape objects more robust, even just {x,y,on}, instead of doing all of those nested for loops, you could start leveraging array methods like filter to only select the ones where on === 1, then do some sort of matrix transform to swap out that x,y coord in the 4x4 with the shape you're replacing.

Either way, cool game! Pretty neat you could do that in sub 400 lines of code.


The reason why I'm (sort of) proud of this is exactly that I managed to not get hung up with such considerations and just do the obvious things. It's not a problem to scan through 200 blocks (of which often 50% will be habitated) once every 100ms or so).

If there is any need for optimization, then it would probably be to avoid DOM inefficiencies and opting for canvas or another environment.


Very neat. I was about to report a bizarre bug -- `a/d` for rotating pieces worked on my laptop keyboard but not my USB-connected keyboard -- but then I realized caps-lock was turned-on my connected keyboard. Still probably wouldn't hurt to make the conditional case-insensitive


My iteration of the same thing

This one generates a wide array of pieces upon start. And has buttons for use on mobile

http://kevinusbaragon.us/jtris/jtris.html


Here's one i made in Haskell and NCurses https://github.com/hauxir/haskell-tetris


Similar, in Python, using rudimentary CLI controls (it was a take-home test). https://github.com/andreis/bchw


I think the rotations feel wrong. If I get a Z piece, rotating twice should get me back where I started. Instead it's shifted sideways one space. I have to shift 4 times to get back.


The scheme used here is a 4x4 block (the minimum required to accomodate all pieces) and rotations by 90 degrees. You can rotate both cw and ccw, this works for undoing rotation of all pieces.


@OP License?

Can I use it as a teaching tool? :)


Sure!


Thanks. Please add a license file to repo of you haven't done so already. :)


no babel/webpack?


XD




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: