tetris-min.html 9.8 KB

1
  1. <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><title>Tetris</title><style>*{margin:0;padding:0;box-sizing:border-box}body{display:flex;flex-direction:column;justify-content:center;align-items:center;height:100vh;width:100vw;position:relative}.board{height:500px;width:350px;background:black;position:relative}.block{height:25px;width:25px;border:1px solid white;position:absolute}.gridBlock{height:25px;width:25px;border:1px solid black;position:absolute}.modal{display:flex;flex-direction:column;justify-content:space-around;align-items:center;height:250px;width:500px;position:absolute;top:calc(50% - 125px);left:calc(50% - 250px);background:rgb(225, 225, 225);z-index:2}button{background:black;color:white;border:none;padding:15px 35px;font-size:20px;font-weight:bold;cursor:pointer}button:hover{background:rgb(25, 25, 25)}.scoreboard{display:flex;flex-direction:column;justify-content:space-around;align-items:center;height:100px;width:250px;position:absolute;top:0;right:-250px;background:black;color:white;border-left:1px solid white}.scoreboard h1{font-size:20px;text-decoration:underline}.scoreboard p{font-size:25px}.nextBoard{display:flex;flex-direction:column;justify-content:flex-start;align-items:center;height:250px;width:250px;position:absolute;top:100px;right:-250px;background:black;border-left:1px solid white;border-top:1px solid white;position:absolute}.nextBoard::before{content:"Next";color:white;font-size:20px;text-decoration:underline;font-weight:bold;margin-top:15px}</style></head><body><audio controls loop><source src="/tetris/music"></audio><script>class Board{constructor(){this.score=0;this.speed=500;this.grid=[];for(let i=0;i<14;i+=1){this.grid.push([]);for(let j=0;j<21;j+=1){let number=0;if(j===20){number=1}this.grid[i].push(number)}}let audio=document.querySelector("audio");audio.currentTime=1;audio.play();this.board=document.createElement("div");this.board.classList.add("board");document.body.appendChild(this.board);this.createScoreboard();this.createNextBoard();this.createControls();this.onDeck();this.nextPiece();this.onDeck()}addPieces(blocks){for(let i=0;i<blocks.length;i+=1){blocks[i].locationX+=2;blocks[i].locationY-=4;blocks[i].style.top=`${blocks[i].locationY*25}px`;blocks[i].style.left=`${blocks[i].locationX*25}px`;this.board.appendChild(blocks[i])}}createControls(){document.onkeydown=(event)=>{switch(event.keyCode){case 39:this.currentPiece.translateX(1);break;case 37:this.currentPiece.translateX(-1);break;case 40:this.currentPiece.translateY(1);break;case 32:this.currentPiece.rotate(1);break}}}createScoreboard(){let scoreboard=document.createElement("div");scoreboard.classList.add("scoreboard");this.board.appendChild(scoreboard);let h1=document.createElement("h1");h1.textContent="Score";scoreboard.appendChild(h1);this.scoreDisplay=document.createElement("p");this.scoreDisplay.textContent="0";scoreboard.appendChild(this.scoreDisplay)}createNextBoard(){this.nextBoard=document.createElement("div");this.nextBoard.classList.add("nextBoard");this.board.appendChild(this.nextBoard)}isCollision(){let blocks=this.currentPiece.blocks;for(let i=0;i<blocks.length;i+=1){if(this.grid[blocks[i].locationX][blocks[i].locationY+1]!==0){return true}}return false}clearRows(){for(let i=0;i<20;i+=1){let rowFull=true;for(let j=0;j<this.grid.length;j+=1){if(this.grid[j][i]===0){rowFull=false;break}}if(rowFull){this.deleteRow(i)}}}deleteRow(idx){for(let i=0;i<this.grid.length;i+=1){this.board.removeChild(this.grid[i][idx]);for(let j=0;j<idx;j+=1){if(this.grid[i][j]===0||this.grid[i][j]===1){continue}this.grid[i][j].locationY+=1;this.grid[i][j].style.top=`${this.grid[i][j].locationY*25}px`}this.grid[i].splice(idx,1);this.grid[i].unshift(0)}this.updateScore(28);this.increaseSpeed()}increaseSpeed(){this.speed*=0.9}addToGrid(){let blocks=this.currentPiece.blocks;for(let i=0;i<blocks.length;i+=1){let gridBlock=document.createElement("div");gridBlock.classList.add("gridBlock");gridBlock.locationY=blocks[i].locationY;gridBlock.locationX=blocks[i].locationX;gridBlock.style.top=`${blocks[i].locationY*25}px`;gridBlock.style.left=`${blocks[i].locationX*25}px`;gridBlock.style.background=blocks[i].style.background;this.grid[blocks[i].locationX][blocks[i].locationY]=gridBlock;this.board.appendChild(gridBlock)}}onDeck(){let piece=Math.floor(Math.random()*7);switch(piece){case 0:this.onDeckPiece=new PieceOne(this);break;case 1:this.onDeckPiece=new PieceTwo(this);break;case 2:this.onDeckPiece=new PieceThree(this);break;case 3:this.onDeckPiece=new PieceFour(this);break;case 4:this.onDeckPiece=new PieceFive(this);break;case 5:this.onDeckPiece=new PieceSix(this);break;case 6:this.onDeckPiece=new PieceSeven(this);break}while(this.nextBoard.children.length>0){this.nextBoard.removeChild(this.nextBoard.firstChild)}for(let i=0;i<this.onDeckPiece.blocks.length;i+=1){this.onDeckPiece.blocks[i].locationX+=4;this.onDeckPiece.blocks[i].locationY+=4;this.onDeckPiece.blocks[i].style.top=`${this.onDeckPiece.blocks[i].locationY*25}px`;this.onDeckPiece.blocks[i].style.left=`${this.onDeckPiece.blocks[i].locationX*25}px`;this.nextBoard.appendChild(this.onDeckPiece.blocks[i])}}nextPiece(){this.currentPiece=this.onDeckPiece;this.addPieces(this.currentPiece.blocks);if(this.isCollision()){this.triggerLoss();return}this.currentPiece.createTimer(this.speed)}triggerLoss(){document.onkeydown=null;let gameOver=new GameOver(this)}updateScore(num){this.score+=num;this.scoreDisplay.textContent=this.score}}class Piece{constructor(location){this.rgb=this.createColor();this.createBlocks(location)}createBlocks(location){this.blocks=[];for(let i=0;i<location.length;i+=1){let block=document.createElement("div");block.classList.add("block");block.locationY=location[i][1];block.style.top=`${block.locationY*25}px`;block.locationX=location[i][0];block.style.left=`${block.locationX*25}px`;block.style.background=`rgb(${this.rgb[0]}, ${this.rgb[1]}, ${this.rgb[2]})`;this.blocks.push(block)}return this.blocks}createColor(){let rgb=[];for(let i=0;i<3;i+=1){rgb.push(Math.floor(Math.random()*255))}return rgb}createTimer(speed){this.interval=setInterval(()=>{this.translateY(1)},speed)}translateY(num){if(this.parent.isCollision()){this.collide();return}for(let i=0;i<this.blocks.length;i+=1){this.blocks[i].locationY+=num;this.blocks[i].style.top=`${this.blocks[i].locationY*25}px`}}collide(){this.parent.addToGrid();this.parent.clearRows();this.stop();this.parent.nextPiece();this.parent.onDeck();this.parent.updateScore(4)}translateX(num){for(let i=0;i<this.blocks.length;i+=1){let newLocation=this.blocks[i].locationX+num;if(newLocation<0||newLocation>13){return}if(this.parent.grid[newLocation][this.blocks[i].locationY]!==0){return}}for(let i=0;i<this.blocks.length;i+=1){this.blocks[i].locationX+=num;this.blocks[i].style.left=`${this.blocks[i].locationX*25}px`}}stop(){clearInterval(this.interval);for(let i=0;i<this.blocks.length;i+=1){this.blocks[i].parentElement.removeChild(this.blocks[i])}}rotate(){if(this.isInterference()){return}for(let i=0;i<this.blocks.length;i+=1){this.blocks[i].locationX+=this.rotations[this.currentRotation][i][0];this.blocks[i].locationY+=this.rotations[this.currentRotation][i][1];this.blocks[i].style.top=`${this.blocks[i].locationY*25}px`;this.blocks[i].style.left=`${this.blocks[i].locationX*25}px`}this.currentRotation+=1;this.currentRotation%=4}isInterference(){for(let i=0;i<this.blocks.length;i+=1){let newX=this.blocks[i].locationX+this.rotations[this.currentRotation][i][0];let newY=this.blocks[i].locationY+this.rotations[this.currentRotation][i][1];if(!this.parent.grid[newX]||this.parent.grid[newX][newY]!==0){return true}}return false}}class PieceOne extends Piece{constructor(parent){super([[0,0],[1,0],[2,0],[3,0]]);this.parent=parent;this.currentRotation=0;this.rotations=[[[1,-1],[0,0],[-1,1],[-2,2]],[[-1,1],[0,0],[1,-1],[2,-2]],[[1,-1],[0,0],[-1,1],[-2,2]],[[-1,1],[0,0],[1,-1],[2,-2]]]}}class PieceTwo extends Piece{constructor(parent){super([[0,0],[0,1],[1,1],[1,0]]);this.parent=parent}rotate(){return}}class PieceThree extends Piece{constructor(parent){super([[0,0],[0,1],[0,2],[1,2]]);this.parent=parent;this.currentRotation=0;this.rotations=[[[1,1],[0,0],[-1,-1],[-2,0]],[[-1,1],[0,0],[1,-1],[0,-2]],[[-1,-1],[0,0],[1,1],[2,0]],[[1,-1],[0,0],[-1,1],[0,2]]]}}class PieceFour extends Piece{constructor(parent){super([[0,0],[0,1],[0,2],[1,1]]);this.parent=parent;this.currentRotation=0;this.rotations=[[[-1,1],[0,0],[0,0],[0,0]],[[0,0],[0,0],[0,0],[-1,-1]],[[0,0],[0,0],[1,-1],[0,0]],[[1,-1],[0,0],[-1,1],[1,1]]]}}class PieceFive extends Piece{constructor(parent){super([[1,0],[1,1],[1,2],[0,2]]);this.parent=parent;this.currentRotation=0;this.rotations=[[[1,1],[0,0],[-1,-1],[0,-2]],[[-1,1],[0,0],[1,-1],[2,0]],[[-1,-1],[0,0],[1,1],[0,2]],[[1,-1],[0,0],[-1,1],[-2,0]]]}}class PieceSix extends Piece{constructor(parent){super([[1,0],[1,1],[0,1],[0,2]]);this.parent=parent;this.currentRotation=0;this.rotations=[[[-1,1],[0,0],[1,1],[2,0]],[[1,-1],[0,0],[-1,-1],[-2,0]],[[-1,1],[0,0],[1,1],[2,0]],[[1,-1],[0,0],[-1,-1],[-2,0]]]}}class PieceSeven extends Piece{constructor(parent){super([[0,0],[0,1],[1,1],[1,2]]);this.parent=parent;this.currentRotation=0;this.rotations=[[[1,1],[0,0],[-1,1],[-2,0]],[[-1,-1],[0,0],[1,-1],[2,0]],[[1,1],[0,0],[-1,1],[-2,0]],[[-1,-1],[0,0],[1,-1],[2,0]]]}}class GameOver{constructor(board){this.board=board?board:null;this.modal=document.createElement("div");this.modal.classList.add("modal");document.body.appendChild(this.modal);this.createMessage();this.restartButton()}createMessage(){let message=document.createElement("h1");message.textContent=this.board?"Game Over":"Tetris";this.modal.appendChild(message)}restartButton(){let button=document.createElement("button");button.textContent=this.board?"Restart":"Start Game";button.addEventListener("click",this.restart.bind(this));this.modal.appendChild(button)}restart(){new Board();if(this.board){document.body.removeChild(this.board.board)}document.body.removeChild(this.modal)}}new GameOver();</script></body></html>