├── .gitattributes ├── .gitignore ├── README.md ├── images ├── game_play.png ├── game_play_crop.png ├── original tetris images │ ├── tetro_i.jpg │ ├── tetro_j.jpg │ ├── tetro_l.jpg │ ├── tetro_o.jpg │ ├── tetro_s.jpg │ ├── tetro_t.jpg │ └── tetro_z.jpg ├── tetro_i.png ├── tetro_i1.png ├── tetro_j.png ├── tetro_j1.png ├── tetro_j2.png ├── tetro_j3.png ├── tetro_l.png ├── tetro_l1.png ├── tetro_l2.png ├── tetro_l3.png ├── tetro_o.png ├── tetro_s.png ├── tetro_s1.png ├── tetro_t.png ├── tetro_t1.png ├── tetro_t2.png ├── tetro_t3.png ├── tetro_z.png └── tetro_z1.png ├── index.html ├── js_tetris.css └── js_tetris.js /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vanilla Javascript Tetris App! 2 | 3 | 4 | 5 | _Classic Tetris game written entirely in pure Javascript, HTML and CSS_ 6 | 7 | 8 | 9 | Play it [here](https://andysterks.github.io/JS-Tetris) 10 | 11 | 12 | 13 | 14 | 15 | ## Summary 16 | 17 | Back in 2014 I was determined to become a programmer. After reading the Head First Javascript book, I wasn't sure what project to work on. I eventually landed on Tetris. 18 | 19 | It took me more than a month to work through building out all the functionality that was needed. I learned A TON about problem solving and some of the different concepts I had learned in Javascript (such as working with classes). It was challenging at times but worth every minute. :-) 20 | 21 | ## Author 22 | 23 | - **Andy Sterkowitz** - _Full-Stack Software Developer_ - [Website](https://andysterkowitz.com) | [LinkedIn](https://www.linkedin.com/in/andrewsterkowitz/) 24 | -------------------------------------------------------------------------------- /images/game_play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/game_play.png -------------------------------------------------------------------------------- /images/game_play_crop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/game_play_crop.png -------------------------------------------------------------------------------- /images/original tetris images/tetro_i.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/original tetris images/tetro_i.jpg -------------------------------------------------------------------------------- /images/original tetris images/tetro_j.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/original tetris images/tetro_j.jpg -------------------------------------------------------------------------------- /images/original tetris images/tetro_l.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/original tetris images/tetro_l.jpg -------------------------------------------------------------------------------- /images/original tetris images/tetro_o.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/original tetris images/tetro_o.jpg -------------------------------------------------------------------------------- /images/original tetris images/tetro_s.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/original tetris images/tetro_s.jpg -------------------------------------------------------------------------------- /images/original tetris images/tetro_t.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/original tetris images/tetro_t.jpg -------------------------------------------------------------------------------- /images/original tetris images/tetro_z.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/original tetris images/tetro_z.jpg -------------------------------------------------------------------------------- /images/tetro_i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/tetro_i.png -------------------------------------------------------------------------------- /images/tetro_i1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/tetro_i1.png -------------------------------------------------------------------------------- /images/tetro_j.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/tetro_j.png -------------------------------------------------------------------------------- /images/tetro_j1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/tetro_j1.png -------------------------------------------------------------------------------- /images/tetro_j2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/tetro_j2.png -------------------------------------------------------------------------------- /images/tetro_j3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/tetro_j3.png -------------------------------------------------------------------------------- /images/tetro_l.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/tetro_l.png -------------------------------------------------------------------------------- /images/tetro_l1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/tetro_l1.png -------------------------------------------------------------------------------- /images/tetro_l2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/tetro_l2.png -------------------------------------------------------------------------------- /images/tetro_l3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/tetro_l3.png -------------------------------------------------------------------------------- /images/tetro_o.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/tetro_o.png -------------------------------------------------------------------------------- /images/tetro_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/tetro_s.png -------------------------------------------------------------------------------- /images/tetro_s1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/tetro_s1.png -------------------------------------------------------------------------------- /images/tetro_t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/tetro_t.png -------------------------------------------------------------------------------- /images/tetro_t1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/tetro_t1.png -------------------------------------------------------------------------------- /images/tetro_t2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/tetro_t2.png -------------------------------------------------------------------------------- /images/tetro_t3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/tetro_t3.png -------------------------------------------------------------------------------- /images/tetro_z.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/tetro_z.png -------------------------------------------------------------------------------- /images/tetro_z1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andysterks/JS-Tetris/6761f075a89dc9cd756e949adb632782a4a5fcba/images/tetro_z1.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | JS Tetris by Andy 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | JavaScript Tetris 16 | 20 | 21 | 22 | 23 | 24 | 25 | Instructions 26 | 27 | UP ARROW = Rotate Tetrominoe 28 | LEFT ARROW = Tetrominoe Left 29 | RIGHT ARROW = Tetrominoe Right 30 | DOWN ARROW = Tetrominoe down one spot 31 | SPACE BAR = Send Tetrominoe to the bottom 32 | P = Pause/Resume game 33 | SCORE: 0 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /js_tetris.css: -------------------------------------------------------------------------------- 1 | #game_screen { 2 | width: 434px; 3 | margin: 0px 0px; 4 | padding: 0px; 5 | } 6 | 7 | #game_box { 8 | width: 436px; 9 | padding: 0px 0px; 10 | margin: 0px 0px 0px auto; 11 | float: left; 12 | } 13 | 14 | h2 { 15 | text-align: center; 16 | padding: 0px 0px 10px 0px; 17 | margin: 0px; 18 | } 19 | 20 | #instructions { 21 | float: right; 22 | width: 350px; 23 | margin: 0px auto 0px 0px; 24 | } 25 | 26 | #screen { 27 | width: 900px; 28 | margin: 0px auto; 29 | } 30 | -------------------------------------------------------------------------------- /js_tetris.js: -------------------------------------------------------------------------------- 1 | const fps = 7.5; 2 | const W = 432; 3 | const H = 528; 4 | const X = 0; 5 | const Y = 0; 6 | let ITER = 0; 7 | let paused = false; 8 | const canvas = document.getElementById("canvas"); 9 | const ctx = canvas.getContext("2d"); 10 | ctx.fillStyle="#000000"; 11 | ctx.fillRect(0,0,432,528); 12 | let canvasData = ctx.getImageData(0,0,432,528); 13 | ctx.putImageData(canvasData,0,0); 14 | 15 | const gameStatus = { 16 | points: 0, 17 | fps: 7.5, 18 | boardW: 432, 19 | boardH: 528 20 | } 21 | 22 | const keyPresses = [ 0 ]; 23 | const storedFunctions = [ ]; 24 | 25 | const tetro = { 26 | position: {x: (W-48)/2,y:0}, 27 | boundaryPoints: [ [ 18, 36, 54,{x:24,y:48},{x:48,y:48}], [ 48, 48, 48 ] ] 28 | } 29 | 30 | function Tetro(imgSrc, xBound1, yBound1, xBound2, yBound2, xBound3, yBound3) { 31 | this.image = new Image(); 32 | this.image.src = imgSrc, 33 | this.boundaryPoints = [ xBound1, yBound1, xBound2, yBound2, xBound3, yBound3 ] 34 | } 35 | 36 | const tetroO = new Tetro("images/tetro_o.png", 12, 48, 36, 48, 36, 48); 37 | const tetroT = new Tetro("images/tetro_t.png", 12, 48, 36, 48, 60, 48); 38 | const tetroT1 = new Tetro("images/tetro_t1.png", 12, 48, 36, 72, 36, 72); 39 | const tetroT2 = new Tetro("images/tetro_t2.png", 12, 24, 36, 48, 60, 24); 40 | const tetroT3 = new Tetro("images/tetro_t3.png", 12, 72, 36, 48, 36, 48); 41 | const tetroI = new Tetro("images/tetro_i.png", 12, 96, 12, 96, 12, 96); 42 | const tetroI1 = new Tetro("images/tetro_i1.png", 12, 24, 36, 24, 84, 24); 43 | const tetroJ = new Tetro("images/tetro_j.png", 12, 48, 36, 48, 60, 48); 44 | const tetroJ1 = new Tetro("images/tetro_j1.png", 12, 72, 36, 72, 12, 72); 45 | const tetroJ2 = new Tetro("images/tetro_j2.png", 12, 24, 36, 24, 60, 48); 46 | const tetroJ3 = new Tetro("images/tetro_j3.png", 12, 72, 36, 24, 36, 24); 47 | const tetroL = new Tetro("images/tetro_l.png", 12, 48, 36, 48, 60, 48); 48 | const tetroL1 = new Tetro("images/tetro_l1.png", 12, 24, 36, 72, 36, 72); 49 | const tetroL2 = new Tetro("images/tetro_l2.png", 12, 48, 36, 24, 60, 24); 50 | const tetroL3 = new Tetro("images/tetro_l3.png", 12, 72, 36, 72, 36, 72); 51 | const tetroZ = new Tetro("images/tetro_z.png", 12, 24, 36, 48, 60, 48); 52 | const tetroZ1 = new Tetro("images/tetro_z1.png", 12, 72, 36, 48, 36, 48); 53 | const tetroS = new Tetro("images/tetro_s.png", 12, 48, 36, 48, 60, 24); 54 | const tetroS1 = new Tetro("images/tetro_s1.png", 12, 48, 36, 72, 36, 72); 55 | let currTetro = new Tetro("images/tetro_o.png", 12, 48, 36, 48, 36, 48) 56 | 57 | const storedT = [ tetroO, tetroI, tetroJ, tetroL, tetroT, tetroZ, tetroS ]; 58 | 59 | function rotateTetro() { 60 | if (currTetro === tetroJ) { 61 | currTetro = tetroJ1; 62 | } else if (currTetro === tetroJ1) { 63 | currTetro = tetroJ2; 64 | } else if (currTetro === tetroJ2) { 65 | currTetro = tetroJ3; 66 | } else if (currTetro === tetroJ3) { 67 | currTetro = tetroJ; 68 | } else if (currTetro === tetroT) { 69 | currTetro = tetroT1; 70 | } else if (currTetro === tetroT1) { 71 | currTetro = tetroT2; 72 | } else if (currTetro === tetroT2) { 73 | currTetro = tetroT3; 74 | } else if (currTetro === tetroT3) { 75 | currTetro = tetroT; 76 | } else if (currTetro === tetroI) { 77 | currTetro = tetroI1; 78 | } else if (currTetro === tetroI1) { 79 | currTetro = tetroI; 80 | } else if (currTetro === tetroL) { 81 | currTetro = tetroL1; 82 | } else if (currTetro === tetroL1) { 83 | currTetro = tetroL2; 84 | } else if (currTetro === tetroL2) { 85 | currTetro = tetroL3; 86 | } else if (currTetro === tetroL3) { 87 | currTetro = tetroL; 88 | } else if (currTetro === tetroS) { 89 | currTetro = tetroS1; 90 | } else if (currTetro === tetroS1) { 91 | currTetro = tetroS; 92 | } else if (currTetro === tetroZ) { 93 | currTetro = tetroZ1; 94 | } else if (currTetro === tetroZ1) { 95 | currTetro = tetroZ; 96 | } 97 | } 98 | 99 | function drawCanvas() { 100 | ctx.putImageData(canvasData,0,0); 101 | } 102 | 103 | function copyCanvas() { 104 | canvasData = ctx.getImageData(0,0,432,528); 105 | } 106 | 107 | function drawTetro(tetro,xpos,ypos) { 108 | ctx.drawImage(tetro,xpos,ypos); 109 | } 110 | 111 | function detectCollision() { 112 | getHitInfo(); 113 | if (tetro.position.y + currTetro.image.height === H || (currTetro.hit1.data[0] !== 0 || currTetro.hit2.data[1] !== 0 || currTetro.hit3.data[0] !== 0)) { 114 | rowCheck(); 115 | resetTetro(); 116 | copyCanvas(); 117 | ITER++; 118 | } 119 | } 120 | 121 | function rowCheck() { 122 | const imgDataArray = [ [], 123 | [], 124 | [], 125 | [], 126 | [], 127 | [], 128 | [] ]; 129 | const positionArray = [ 516, 492, 468, 444, 420, 396, 372 ]; 130 | for (let j=0; j