Tetris is a very classic little game, and I also tried to write it. But I want to implement it with code that is as concise and logical as possible. There is no need for too much code to record the model of the falling blocks, or to record the x and y of each falling block. I thought about the following ideas, and then found that it is very concise to write like this. There are 7 basic models of Tetris: There are many ways to record these models, such as recording their relative positions, recording the x, y coordinates of each block, etc. I came up with an idea to record these 7 models. It is very concise and easy to use when writing left shift, right shift and rotation functions. The following array records these models. var cubeArr=[[6,7,12,13],[7,8,11,12],[6,7,11,12],[7,12,17,8],[7,12,16,17],[7,12,17,22],[7,11,12,13]]; Ideas:A 5*5 table, numbered starting from 0. The point numbered 12 is the center point. Each model is recorded with its label, for example, the first model is [6,7,12,13]. Taking the upper left corner of the table as the reference point, there is such a rule: assuming that the number in the table is value, the remainder of value divided by 5 is the x offset of the point relative to the reference point, and the integer part of value divided by 5 is the y offset of the point relative to the reference point. It is also very simple to rotate. By rotating around the center 12, you can also find some patterns. var movex=cubeNow[i]%5; var movey=Math.floor(cubeNow[i]/5); Draw a model with a loop function drawEle(color) { ctx.fillStyle=color; ctx.strokeStyle='#fff'; for(var i=0;i<4;i++) { var movex=downInfor.cubeNow[i]%5; var movey=Math.floor(downInfor.cubeNow[i]/5); ctx.fillRect(cubeW*(downInfor.point[0]+movex),cubeW*(downInfor.point[1]+movey),cubeW,cubeW); ctx.strokeRect(cubeW*(downInfor.point[0]+movex),cubeW*(downInfor.point[1]+movey),cubeW,cubeW) } } Rotate the model: The relationship between the current position and the next rotation position can be easily realized through this array to rotate the model. For example, if the position is numbered 0 and we rotate clockwise, the next position is 4. The position numbered 6, the next position is 8. The following array can find the next position from the previous position. var rotateArr=[4,9,14,19,24,3,8,13,18,23,2,7,12,17,22,1,6,11,16,21,0,5,10,15,20]; Code: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Tetris</title> </head> <body> <div> <div style="display:inline-block"> <canvas id="can" height="480" width="300" style="border:3px solid black;"></canvas> </div> <div id="info" style="display:inline-block;height:600px;vertical-align: top;font-family: tmb; font-size:14pt; color:green;"> <span>Score:</span><span id="score">0</span> </div> </div> <script type="text/javascript"> var cubeW=20; var cubeArr=[[6,7,12,13],[7,8,11,12],[6,7,11,12],[7,12,17,8],[7,12,16,17],[7,12,17,22],[7,11,12,13]]; var colorArr=['#ffc0cb','#dda0dd','#9370db','#6495ed','#fa8072','#ff8c00','#008000']; var rotateArr=[4,9,14,19,24,3,8,13,18,23,2,7,12,17,22,1,6,11,16,21,0,5,10,15,20]; var canvas = document.getElementById('can'); var ctx = canvas.getContext('2d'); var score = document.getElementById('score'); var canWidth=canvas.width; var canHeight=canvas.height; var downInfor={}, staticCube=[]; var myinter; window.initialize = function() //initialize { drawline(); for(var i=0;i<(canWidth/cubeW);i++) { staticCube[i]=[]; for(var j=0;j<(canHeight/cubeW);j++) { staticCube[i][j]=0; } } initCube(); myinter=setInterval('movedown()',200); //The first parameter should be quoted} function drawline() { ctx.lineWidth=1; ctx.strokeStyle='#ddd'; for(var i=0;i<(canWidth/cubeW);i++) { ctx.moveTo(cubeW*i,0); ctx.lineTo(cubeW*i,canHeight); } ctx.stroke(); for(var j=0;j<(canHeight/cubeW);j++) { ctx.moveTo(0,cubeW*j); ctx.lineTo(canHeight,cubeW*j); } ctx.stroke(); } function initCube() { var index=Math.floor(Math.random()*cubeArr.length);//randomly generate downInfor.cubeNow=cubeArr[index].concat(); downInfor.index=index; downInfor.prepoint=[5,-1]; downInfor.point=[5,-1]; drawEle(colorArr[downInfor.index]); } function movedown() { //Judge whether the next position is reasonablevar length,isempty=true,px,py,movex,movey,max=0; for(var i=0;i<4;i++) { if(max<downInfor.cubeNow[i]) max=downInfor.cubeNow[i]; } length=Math.ceil(max/5); for(var i=0;i<4;i++) { px=downInfor.point[0]+downInfor.cubeNow[i]%5; py=downInfor.point[1]+1+Math.floor(downInfor.cubeNow[i]/5); if(staticCube[px][py]==1) { isempty=false; break; } } if((downInfor.point[1]+length)<(canHeight/cubeW)&&isempty) { downInfor.prepoint=downInfor.point.concat(); //Note the reference type downInfor.point[1]=downInfor.point[1]+1; clearEle(); drawEle(colorArr[downInfor.index]); } else //When unable to move { for(var i=0;i<4;i++) { px=downInfor.point[0]+downInfor.cubeNow[i]%5; py=downInfor.point[1]+Math.floor(downInfor.cubeNow[i]/5); staticCube[px][py]=1; } drawEle('#555'); checkfullLine(); } } function moveLeft() { var leftroom=4,isempty=true,px,py,movex,movey; for(var i=0;i<4;i++) { px=downInfor.point[0]-1+downInfor.cubeNow[i]%5; py=downInfor.point[1]+Math.floor(downInfor.cubeNow[i]/5); if((downInfor.cubeNow[i]%5)<leftroom) leftroom=downInfor.cubeNow[i]%5; if(staticCube[px][py]==1) { isempty=false; break; } } if((downInfor.point[0]+leftroom)>=0&&isempty) { downInfor.prepoint=downInfor.point.concat(); downInfor.point[0]=downInfor.point[0]-1; clearEle(); drawEle(colorArr[downInfor.index]); } } function moveRight() { var rightroom=0,isempty=true,px,py,movex,movey; for(var i=0;i<4;i++) { px=downInfor.point[0]+1+downInfor.cubeNow[i]%5; py=downInfor.point[1]+Math.floor(downInfor.cubeNow[i]/5); if((downInfor.cubeNow[i]%5)>rightroom) rightroom=downInfor.cubeNow[i]%5; if(staticCube[px][py]==1) { isempty=false; break; } } if((downInfor.point[0]+rightroom+1)<(canWidth/cubeW)&&isempty) { downInfor.prepoint=downInfor.point.concat(); downInfor.point[0]=downInfor.point[0]+1; clearEle(); drawEle(colorArr[downInfor.index]); } } function moverotate()//process rotation { var isempty=true,px,py,movex,movey, tempRotate=[0,0,0,0]; for(var i=0;i<4;i++) { tempRotate[i]=rotateArr[downInfor.cubeNow[i]]; } for(var i=0;i<4;i++) { px=downInfor.point[0]+tempRotate[i]%3; py=downInfor.point[1]+Math.floor(tempRotate[i]/3); if(staticCube[px][py]==1) { isempty=false; break; } } if(isempty) { downInfor.prepoint=downInfor.point.concat(); clearEle(); downInfor.cubeNow=tempRotate.concat(); drawEle(colorArr[downInfor.index]); } } function drawEle(color) { ctx.fillStyle=color; ctx.strokeStyle='#fff'; for(var i=0;i<4;i++) { var movex=downInfor.cubeNow[i]%5; var movey=Math.floor(downInfor.cubeNow[i]/5); ctx.fillRect(cubeW*(downInfor.point[0]+movex),cubeW*(downInfor.point[1]+movey),cubeW,cubeW); ctx.strokeRect(cubeW*(downInfor.point[0]+movex),cubeW*(downInfor.point[1]+movey),cubeW,cubeW) } } function clearEle() { ctx.lineWidth=1; ctx.strokeStyle='#ddd'; for(var i=0;i<4;i++) { var movex=downInfor.cubeNow[i]%5; var movey=Math.floor(downInfor.cubeNow[i]/5); ctx.clearRect(cubeW*(downInfor.prepoint[0]+movex),cubeW*(downInfor.prepoint[1]+movey),cubeW,cubeW); ctx.strokeRect(cubeW*(downInfor.prepoint[0]+movex),cubeW*(downInfor.prepoint[1]+movey),cubeW,cubeW) } } function checkfullLine()//Check if there is a full line { var isFullLine=true,index=0,changeScore=false; for(var i=0;i<canWidth/cubeW;i++) { if(staticCube[i][0]==1) { alert('Game over!'); clearInterval(myinterval); return; } } for(var i=canHeight/cubeW-1;i>=0;i--) { isFullLine=true; for(var j=0;j<(canWidth/cubeW);j++) { if(staticCube[j][i]==0) { isFullLine=false; } } if(isFullLine)//Add one point { score.innerHTML=parseInt(score.innerText)+1; changeScore=true; for(var s=i;s>=0;s--) { for (var j = 0; j < (canWidth / cubeW); j++) { (s- 1) >= 0 ? staticCube[j][s] = staticCube[j][s - 1] : staticCube[j][s] = 0; } } } } if(changeScore) { ctx.clearRect(0,0,canWidth,canHeight); drawline(); ctx.fillStyle='555'; ctx.strokeStyle='#fff'; for(var i=0;i<(canWidth/cubeW);i++) { for(var j=0;j<(canHeight/cubeW);j++) { if(staticCube[i][j]==1) { ctx.fillRect(cubeW*i,cubeW*j,cubeW,cubeW); ctx.strokeRect(cubeW*i,cubeW*j,cubeW,cubeW); } } } } initCube(); } window.onkeydown=function (evt) { switch(evt.keyCode) { case 37: //leftmoveLeft(); break; case 38: //moverotate(); break; case 39: //right moveRight(); break; case 40: //movedown(); break; } } </script> </body> </html> Effect: The above is the full content of this article. I hope it will be helpful for everyone’s study. I also hope that everyone will support 123WORDPRESS.COM. You may also be interested in:
|
<<: Implementation steps for building a MySQL master-slave replication environment based on Docker
>>: Detailed steps to upgrade mysql8.0.11 to mysql8.0.17 under win2008
This article uses examples to describe the add, d...
What is a profile? We can use it when we want to ...
A style sheet describes how a document should be ...
1. After entering the container cat /etc/hosts It...
Generally, the colspan attribute of the <td>...
Table of contents 1. Achieve results 2. Backend i...
Table of contents utils: Use in vue: explain: Ima...
Table of contents Create a global shared content ...
Nginx's configuration syntax is flexible and ...
MySQL 8 new features: My personal opinion on MySQ...
Preface I watched web.dev's 2020 three-day li...
There are many seemingly true "rumors" ...
1. Basic structure of web page: XML/HTML CodeCopy...
For Linux system administrators, it is crucial to...
0. Introduction August 18, 2016 Today, I noticed ...