{"id":18853145,"url":"https://github.com/luxedo/tetris-almost-from-scratch","last_synced_at":"2025-08-09T00:24:01.834Z","repository":{"id":97349401,"uuid":"93578209","full_name":"luxedo/tetris-almost-from-scratch","owner":"luxedo","description":" This is an attempt of making the game Tetris using modern programming languages","archived":false,"fork":false,"pushed_at":"2019-02-18T22:05:38.000Z","size":15496,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-27T23:41:46.372Z","etag":null,"topics":["game","game-development","hackathon","javascript-games","old-games","tetris"],"latest_commit_sha":null,"homepage":"https://tetris-almost-from-scratch.firebaseapp.com","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/luxedo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-06-07T01:18:21.000Z","updated_at":"2023-04-12T14:46:04.000Z","dependencies_parsed_at":"2023-04-16T00:18:51.626Z","dependency_job_id":null,"html_url":"https://github.com/luxedo/tetris-almost-from-scratch","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luxedo%2Ftetris-almost-from-scratch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luxedo%2Ftetris-almost-from-scratch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luxedo%2Ftetris-almost-from-scratch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luxedo%2Ftetris-almost-from-scratch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/luxedo","download_url":"https://codeload.github.com/luxedo/tetris-almost-from-scratch/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248860444,"owners_count":21173437,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["game","game-development","hackathon","javascript-games","old-games","tetris"],"created_at":"2024-11-08T03:43:05.695Z","updated_at":"2025-04-14T10:23:18.190Z","avatar_url":"https://github.com/luxedo.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TETRIS ALMOST FROM SCRATCH\nThis is an attempt of making the game [Tetris](https://en.wikipedia.org/wiki/Tetris) using modern programming languages. The idea is to time the development and track the progress and the time it took to get in each stage in this document. If possible I want to finish this project in under 24 h.\n\nTetris is the first software to be exported from the USSR to the US and became and not only became one of the most famous computer games, it has been released for nearly every videogame console and computer operating system.\n\nFor this project, I'll be using the engine built for the [asteroids-almost-from-scratch](https://github.com/luxedo/asteroids-almost-from-scratch). I'll try to improve it and try to draw only characters on screen. The idea is to simulate the original game and also show an improved view using the same engine.\n\n![original tetris](https://upload.wikimedia.org/wikipedia/en/7/7c/Tetris-VeryFirstVersion.png)\n\nThe game is based in html5/canvas, CSS and ES6 javascript.\n\n#### Check it out [here](https://tetris-almost-from-scratch.firebaseapp.com/)\n\n## Goals\n*   ~~Add `LICENSE.md` and `README.md`~~\n*   ~~Host somewhere~~\n*   ~~Copy [TETRIS](https://luxedo.github.io/pong-almost-from-scratch/) project base~~\n*   ~~Cleanup the old game~~\n*   ~~Create the board~~\n*   ~~Update drawing/writing functions~~\n*   ~~Create the 'block' class~~\n*   ~~Create \"gravity\" and game timing~~\n*   ~~Tweak the user input mechanics~~\n*   ~~Implement rotation mechanics~~\n*   ~~Create collision mechanics~~\n*   ~~Create line destruction mechanics~~\n*   ~~Create levels/scoring~~\n*   ~~Create game over mechanics and screen~~\n*   ~~Create \"next piece\" display~~\n*   ~~Create Menu screen and Credits screen~~\n*   ~~Create high-scores~~\n*   ~~Add sounds~~\n*   ~~Fix playtesters requests~~\n*   ~~Finished!~~\n\n## Progress reports\n00:00 - START! Well, now it's 6th of June 2017 and I'm a little drunk already.\nI'm not going to work that much today but at least it's a beginning.\n\n## 00:30 - Copied files from TETRIS project and hosted the page\nWell, I'm quite slow today, but the foundations have been built. The game should\nbe available already using [gh-pages](https://pages.github.com/)\n\n## 00:45 - Cleanup the old game\nIt was quite easy to cleanup the old game, now I have a clean canvas to start\nworking.\n\n## 01:30 - Creating the board\n#### Aaaaand two years later we're back\nThe idea to render the game, is to use fixed character positions and draw layers\nof characters over this grid. The background layer should be the board and any\nother data from sides of the board. I used a *mono spaced* font and intend to\nuse a [black square ■ from UTF-8](https://www.fileformat.info/info/unicode/char/25a0/index.htm) as the building blocks for the [tetrominoes](https://en.wikipedia.org/wiki/Tetromino).\nOne problem, is that using a regular space between the lines results in a weird\nboard shape:\n![board regular spacing](/report-assets/board_regular_spacing.png)\nThe original developer, [Alexey Pajitnov](https://en.wikipedia.org/wiki/Alexey_Pajitnov),\nsolved this problem by using two characters for each block in the tetrominoes.\nSince these **almost-from-scratch** projects always have a few twists, I will\ncompress the lines and draw the blocks with a single character.\n![board compressed spacing](/report-assets/board_compressed_spacing.png)\n\n## 03:45 - Update drawing/writing functions\nFirst of all, I had to change the structure of the project because of some\nannoying messages in my editor about variables out of scope. I renamed the files\nto use them as modules and use the [`import` statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import).\n\n![modules](/report-assets/modules.png)\n\nThen, I proceeded to creating the drawing functions. First I wrote the data for\nthe tetrominoes. They're just some ■ characters in the correct position.\n\n![tetrominoes](/report-assets/tetrominoes.png)\n\nWe also need to rotate the tetrominoes, I did not put much tought in for the\nrotation for now. The final result looks like this:\n\n![rotation](/report-assets/rotation.png)\n\n## 04:00 - Create the 'block' class\nWith the drawing functions in place, it was quite easy to draw the blocks. We\ndon't have the collision mechanics nor the user input, that will change the\nclass quite a bit.\n\n![moving](/report-assets/moving.gif)\n\n\n## 04:20 - Create \"gravity\" and game timing\nGravity was quite simple to implement, just move the block down at a certain\ninterval. Then, this interval was added to a variable to set the level of\ndifficulty afterwards.\n\n## 06:30 - Tweak the user input mechanics\nFirst of all, I had to rewrite the gameloop. The old version was very confusing\nand hard to tweak. Now it's simpler and I wrote using ES6 `class` notation. This\nrefactoring took quite some time.\n\n![game class](/report-assets/game_class.png)\n\nI have deleted the old user input, so we're going to make it again. I salvaged\nsome of the old code, but to summarize I made a class that listen for the `keyup`\nand `keydown` events and stores the pressed buttons in an `object`. I also\nimplemented three handful methods:\n-   `isDown` - Checks if the current key is pressed\n-   `isActive` - Checks if the current may be triggered again. The key gets active again if the player releases it.\n-   `isHolding` - Checks if the current key is being held for an specified time interval. This is useful to make the tetrominoes move when the player holds the key.\n\nAfter this refactoring we can move the pieces!!\n\n![input](/report-assets/input.gif)\n\n## 7:00 - Implement rotation mechanics\nLooking up in the interwebs, I found that the rotation mechanics has a name,\nit's called [Super Rotation System](http://tetris.wikia.com/wiki/SRS) or **SRS**\nfor short.\n\n![pieces rotation map](https://i.stack.imgur.com/JLRFu.png)\n\nFortunately, the simple rotation method that I implemented previously is exactly\nthe **SRS**, So I don't need to change it:\n\n![srs](/report-assets/srs.gif)\n\n\n## 11:40 - Create collision mechanics\nNow we need to know when the pieces are touching the borders of the board.\nThere are two checks that needs to be done:\n1. Check for collision with the walls and bottom.\n2. Check for collision in spinning moves and\n[Wall Kick](http://tetris.wikia.com/wiki/Wall_kick) the tetromino when\napplicable.\n\nThere's a third check that could be made, the\n[T Spin](http://tetris.wikia.com/wiki/T-Spin). Hopefully it will occur naturally.\n\nTo do this, each update fires a function to check for the sides of the pieces,\nif the piece is going through a wall then it's kicked back or rotated back\n(before the draw). If the bottommost side of the piece is below another piece or\nwall, then it's kicked back and locked in place.\n\nTo do this it took quite some time. Sometimes the pieces would clip into each\nother, or rotate apparently at random. But alas it's done. The main problems that\nI had were to prioritize the actions to apply to the pieces according to user input.\nEg: if the user spins and the piece kicks off the wall, then by rotating it again\nit wouldn't go back to it's previous position.\n\n![collision](/report-assets/collision.gif)\n\n## 12:10 - Create line destruction mechanics\nAnd we're half way there! So far we have a playable demo, but the lines that are\nfull doesn't break.\n\nThe solution for this was to just filter the array that contains the placed\nblocks for complete rows. Then I map over the array sliding down all pieces that\nwere above that line.\n\n![break](/report-assets/break.gif)\n\n\n## 13:00 - Create levels/scoring\nThe scoring system I used was the [Original Nintendo Scoring System](http://tetris.wikia.com/wiki/Scoring). In summary it is a table of a base according to the number of broken lines times the current level+1.\n\nFor the levels, I chose to increase it for every 10 broken lines, as in the NES\nversion.\n\nTo show the socores (`СЧЕТ`) and the level (`УРОВЕНЬ`) I decided to use the\noriginal words in russian.\n\n![score](/report-assets/score.gif)\n\n## 15:30 - Create game over mechanics and screen\nTo check for a `Game Over` is quite simple with the `Block` class. I just have\nto ask if there's any block above the screen. Then I had to create the screen\nwith some options after the game is over.\n\n![Game Over](/report-assets/gameover.gif)\n\n## 16:00 - Create \"next piece\" display\nFinally an easy task again! For this display, we already had all the pieces in\nhand. The `Block` class provided us with the tetromino draw and the screen\nalready had text in it, which I just edited.\n\n![nextpiece](/report-assets/nextpiece.gif)\n\n## 17:00 - Create Menu screen and Credits screen\nFor those screens I just had to copy the `Game Over` screen and edit a bit the\ntext for each one. I also created another parent class that is a screen with\nthe background and border for those screens to inherit.\n\n![Menu and Credits](/report-assets/menu_credits.gif)\n\n## 22:30 - Create high-scores\nI implemented the `High Scores` for the [Asteroids](https://luxedo.github.io/asteroids-almost-from-scratch/) game and deployed on [Heroku](https://www.heroku.com/).\nI'ts quite easy to work with them but unfortunately I'm out of [dynos](https://www.heroku.com/dynos).\nBecause of that I had to look for another host.\n\nI chose to host at [Firebase](https://firebase.google.com) because their free tier\nis quite nice. This game is not built for mobile but I intend to port it in the\nfuture. It was also a chance to learn how to use the `Firebases`'s services and I\nreally enjoyed the experience. It took around 5 hours of studying and messing around\nand 30 minutes of coding to make the `High Scores` work.\n\nIn the end, `Firebase` takes care of a lot of complexity when setting up a\ndatabase which is very nice. In the end, I just had to use their javascript\nclient to read and write in the database and hopefully the security part is\nhandled by them. I still don't understand how [Progressive Web Apps](https://developers.google.com/web/progressive-web-apps/)\nare meant to be built, but I know that this app is working.\n\n![High Score](/report-assets/high_score.png)\n\nBecause of the Firebase studies, I'm going to extend the project's deadline to\n26 hours.\n\n## 26:00 - Add sounds\nPhew this took more time than I imagined. I just blew my newest deadline.\n\nI had code from the previous games to play sounds, but I decided to\ninvestigate whats new. I found out that the [Web Audio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API)\nis much better than the old `\u003caudio\u003e` tags that I used to use. I had\nto learn how to use it, but it feels much better than the old method\nthat included a couple of `setTimeout`s.\n\nI'm not sure if the original tetris had sounds or music. For nostalgia\nsake, I included the game theme in the `Menu Screen`. I also added some\ngeneric blip noises for other commands.\n\nI made a class to hide the complexity of dealing with sounds:\n\n![Sound](/report-assets/sound_class.png)\n\nThen I just have to call the sounds whenever they're needed:\n\n![Calling Sound](/report-assets/calling_sound.png)\n\n\nThanks to [archive.org](https://archive.org) for the theme, `n_audioman`,\n`LittleRobotSoundFactory` and `jeckkech` for the other sounds in [freesound.org](https://freesound.org)\nand `David Whittaker` for the gameover sound at zxart.ee.\",\n\nNow, I'm releasing the game for the playtesters.\n\n## 27:15 - Fix playtesters requests\nI deployed the game and got the following feedback\n\n-   ~~Confusing gap between pieces and side walls (Ule)~~\n-   ~~Rotate piece with `ArrowUp` (Ule)~~\n-   ~~Pause game with ESC (Ule)~~\n-   ~~Tetrominoes have rectangular blocks (Me)~~\n-   Game has frozen (Kaska)\n-   ~~Menu cursor is out of place (Sofia)~~\n-   ~~Improve High Scores sreen font size (Me)~~\n\n## 27:20 - Finished\nSo I have finished this version of the game, unfortunately I blew the schedule\nbut only by a small portion, also I could not reproduce a bug that happened to\n`Pedro`, whenever I have more information about it I'll fix it.\n\nThanks to the playtesters Ulisses Sato, Pedro Kersten, [Sofia \"faifos\" Faria](https://github.com/faifos).\n\nNext up! Minesweeper? 🤔\n\n\n## License\n\n\u003e This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\u003e\n\u003e This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\u003e\n\u003e You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluxedo%2Ftetris-almost-from-scratch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fluxedo%2Ftetris-almost-from-scratch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluxedo%2Ftetris-almost-from-scratch/lists"}