Welcome 微信登录

首页 / 脚本样式 / JavaScript / JAVASCRIPT代码编写俄罗斯方块网页版

俄罗斯方块方块是小时候的一个回忆,从最开始的掌上的黑白游戏机,到电视游戏机,到电脑,无不有它的痕迹,今天我们来一起重温它的一种实现方法,也算是整理一下我的思路吧......
HTML+CSS+JS实现俄罗斯方块完整版,素材只有图片,想要的下载图片按提示名字保存,css中用的时候注意路径!!主要在JS中!JS附有详细注释
效果:


按键提示:[键盘按键]


素材:图片名字与代码里对应
1、背景图片:tetris.png


2、失败时候的弹出框图片:game-over.png


3、七种色彩小方块图片:
       I.png:
J.png:
L.png:
O.png:
S.png:
T.png:
Z.png:
HTML代码

<!DOCTYPE html><html><head><meta charset="UTF-8" /><title>俄罗斯方块 — 经典完整版</title><link rel="stylesheet" href="css/tetris.css"/><script src="js/shapes.js"></script><script src="js/tetris.js"></script> </head><body><div class="playground"><p>SCORE:<span>0</span></p><p>LINES:<span>0</span></p><p>LEVEL:<span>1</span></p></div> </body></html>
CSS代码
.playground {width: 525px;height: 550px;margin: 20px auto 0 auto;position: relative;background-image:url("tetris.png");}.playground img { position: absolute;}.playground p {font-size: 30px;font-family: "SimHei";font-weight: bold;color: #667799;position: absolute;left:305px;top:120px;}.playground p+p { top:176px; }.playground p+p+p { top:232px; } 
JAVASCRIPT代码:分两段附有详细步骤解释
1、tetris.js
window.$=HTMLElement.prototype.$=function(selector){return (this==window?document:this).querySelectorAll(selector);}var tetris={RN:20,//总行数CN:10,//总列数CSIZE:26,//每个格子的宽高都是26pxOFFSET_X:15,//每个单元格的左侧都要加15pxOFFSET_y:15,//每个单元格的上面都要加15pxpg:null,//保存游戏主界面对象currShape:null,//专门保存正在移动的图形对象nextShape:null,//八、专门保存下一个图形interval:500,//每秒重绘一次==>下落的速度timer:null,wall:[],//六、保存所有停止的下落的方块state:1,//十、保存游戏当前状态STATE_RUNNING:1,//十、游戏正在运行STATE_GAMEOVER:0,//十、游戏结束STATE_PAUSE:2,//十、游戏暂停IMG_GAMEOVER:"img/game-over.png",IMG_PAUSE:"img/pause.png",SCORES:[0,10,50,80,200],//十三,要加的分数档位score:0,//十三、当前总分lines:0,//十三、当前总行数//十、为游戏添加不同状态的图片paintState:function(){//根据当前游戏状态,为游戏添加不同的图片var img=new Image();switch(this.state){//如果当前状态是STATE_GAMEOVERcase this.STATE_GAMEOVER:// img.src设置为IMG_GAMEOVERimg.src=this.IMG_GAMEOVER;break;//如果当前状态是STATE_PAUSEcase this.STATE_PAUSE:// img.src设置为IMG_PAUSEimg.src=this.IMG_PAUSE;}//将img追加到pg中this.pg.appendChild(img);},init:function(){this.pg=$(".playground")[0];//创建一个随机图形的对象存在currShape中this.currShape=this.randomShape();this.nextShape=this.randomShape();//六、将wall数组初始化为RN的空数组对象for(var i=0;i<this.RN;i++){this.wall[i]=[];}this.score=0;//十六、初始化this.lines=0;//十六、初始化this.state=1;//十六、初始化this.paint();//三、this.timer=setInterval(function(){//调用tetris的drop方法tetris.drop();//再调用tetris的paint方法;tetris.paint();},this.interval);//十一、document.onkeydown=function(){var e=window.event||arguments[0];switch(e.keyCode){case 37: tetris.moveL();break;//左case 39: tetris.moveR();break;//右case 40: tetris.drop();break;//下//十五步、case 38: tetris.rotateR();break;//上键控制右边旋转case 90: tetris.rotateL();break;//字母Z键控制控制左边旋转//十六步case 80: tetris.pause();break;//字母P键:暂停case 81: tetris.gameOver();break;//字母Q:结束游戏case 67: tetris.myContinue();break;//字母C,在暂停后有效:暂停后,继续游戏case 83: //游戏结束后,重新开始if(this.state==this.STATE_GAMEOVER){tetris.init();}//字母S键:重新开始游戏}}},//init的结束//十六、暂停,开始,继续、结束gameOver:function(){this.state=this.STATE_GAMEOVER;clearInterval(this.timer);this.timer=null;this.paint();},pause:function(){if(this.state==this.STATE_RUNNING){this.state=this.STATE_PAUSE;}},myContinue:function(){if(this.state==this.STATE_PAUSE){this.state=this.STATE_RUNNING;}},//十五、变形rotateR:function(){//按键上,向右旋转if(this.state==this.STATE_RUNNING){//十六this.currShape.rotateR();if(this.outOfBounds()||this.hit()){//验证不通过this.currShape.rotateL();}}},rotateL:function(){//按键Z,向左旋转if(this.state==this.STATE_RUNNING){this.currShape.rotateL();if(this.outOfBounds()||this.hit()){//验证不通过this.currShape.rotateR();}}},//十一、moveR:function(){this.currShape.moveR();if(this.outOfBounds()||this.hit()){//验证不通过this.currShape.moveL();}},moveL:function(){this.currShape.moveL();if(this.outOfBounds()||this.hit()){//验证不通过this.currShape.moveR();}},outOfBounds:function(){//检查当前图形是否越界//当前shape中任意一个单元格的col<0或>=CNvar cells=this.currShape.cells;for(var i=0;i<cells.length;i++){if(cells[i].col<0||cells[i].col>=this.CN){return true;}}return false;},hit:function(){//检查当前图形是否碰撞//当前shape中任意一个单元格在wall中相同位置有格var cells=this.currShape.cells;for(var i=0;i<cells.length;i++){if(this.wall[cells[i].row][cells[i].col]){return true;}}return false;},//四、重绘所有的格子,分数等的方法paint:function(){//把所有的img格子删除,再重绘/*结尾的4个/<img(.*?){4}>*/this.pg.innerHTML=this.pg.innerHTML.replace(/<img(.*?)>/g,"");this.paintShape();this.paintWall();this.paintNext();//十三this.paintScore();this.paintState();//十、},//十三、计分paintScore:function(){//找到span元素//第一个span中放this.score$("span")[0].innerHTML=this.score;//第二个放this.lines$("span")[1].innerHTML=this.lines;},drop:function(){//判断能否下落if(this.state==this.STATE_RUNNING){//该行是第十六步加的if(this.canDrop()){this.currShape.drop();}else{//六、否则//六、如果不能下落,就将图形中每个cell,放入wall数组中this.landIntoWall();//十二、消行、并计分var ln=this.deleteLines();//消除并返回本次删除的行数//十三、计分this.score+=this.SCORES[ln];this.lines+=ln;//九、如果游戏没有结束才。。if(!this.isGameOver()){//七、将等待的nextShape,换到currShapethis.currShape=this.nextShape;//七、this.nextShape=this.randomShape();}else{//十、否则,一级结束clearInterval(this.timer);this.timer=null;this.state=this.STATE_GAMEOVER;this.paint();//手动绘制一次}}}},//十二、消行,并计分deleteLines:function(){//检查wall中每一行是否要消除//遍历wall中每一行,定义lines变量存本次共删除的行数linefor(var row=0,lines=0;row<this.RN;row++){//如果当前行是满的:isFull(row)if(this.isFull(row)){// 就删除当前行:this.deleteL(row);// 每删除一行,lines++lines++;}}return lines;},isFull:function(row){//判断指定行是否已满//取出wall中第row行,存在line变量中var line=this.wall[row];//遍历line中每个cellfor(var c=0;c<this.CN;c++){// 只要当前cell无效if(!line[c]){return false;}}//遍历结束后return true;},deleteL:function(row){//删除指定行,并将其之上所有的cell下移this.wall.splice(row,1);//只删除一行this.wall.unshift([]);//顶部压入一个新空行//从row行开始,向上遍历每一行for(var r=row;r>0;r--){// 从0开始遍历当前行每个格for(var c=0;c<this.CN;c++){// 如果当前格有效if(this.wall[r][c]){// 将当前格的row++this.wall[r][c].row++;}}}},//九、判断游戏是否结束isGameOver:function(){//获取nextShape中所有cell,保存在cells中var cells=this.nextShape.cells;//遍历cells中每个cellfor(var i=0;i<cells.length;i++){//取出wall中和当前cell相同row,col位置的格子var cell=this.wall[cells[i].row][cells[i].col];//只要碰到有效的if(cell){return true;}}//for的结束return false;},//八、paintNext:function(){var cells=this.nextShape.cells;for(var i=0;i<cells.length;i++){//先将当前cell的row+1,存在r变量中var r=cells[i].row+1;//再将当前cell的col+11,存在c变量中var c=cells[i].col+11;var x=c*this.CSIZE+this.OFFSET_X;var y=r*this.CSIZE+this.OFFSET_y;var img=new Image();img.src=cells[i].img;img.style.left=x+"px";img.style.top=y+"px";this.pg.appendChild(img);}},//七、paintWall:function(){//七、遍历二维数组wall中每个格for(var r=0;r<this.RN;r++){for(var c=0;c<this.CN;c++){var cell=this.wall[r][c];// 如果当前cell有效if(cell){var x=cell.col*this.CSIZE+this.OFFSET_X;var y=cell.row*this.CSIZE+this.OFFSET_y;var img=new Image();img.src=cell.img;img.style.left=x+"px";img.style.top=y+"px";this.pg.appendChild(img);}}}},//六、把所有停止下落的方块放入wall中landIntoWall:function(){//遍历当前图形中每个cells// 每遍历一个cell// 就将cell放入wall中相同row,col的位置:this.wall[?][?]=?var cells=this.currShape.cells;for(var i=0;i<cells.length;i++){this.wall[cells[i].row][cells[i].col]=cells[i];}},//五、//判断是否继续可以下落canDrop:function(){//遍历当前currShape中的cells// 只要发现任意一个的cell的row==RN-1// 就返回false// var cells=this.currShape.cells;for(var i=0;i<cells.length;i++){if(cells[i].row==this.RN-1){return false;}//七、wall中,当前cell的下一行位置有效if(this.wall[cells[i].row+1][cells[i].col]){return false}}//遍历结束后//七、currShape中,任意一个cell的下方有wall中的cellreturn true;},//4、随机生成一种图形--二randomShape:function(){switch(parseInt(Math.random()*7)){case 0: return new O();case 1: return new L();case 2: return new J();case 3: return new S();case 4: return new Z();case 5: return new I();case 6: return new T();}},//3paintShape:function(){//3、专门绘制当前图形的方法var cells=this.currShape.cells;for(var i=0;i<cells.length;i++){var x=cells[i].col*this.CSIZE+this.OFFSET_X;var y=cells[i].row*this.CSIZE+this.OFFSET_y;var img=new Image();img.src=cells[i].img;img.style.left=x+"px";img.style.top=y+"px";this.pg.appendChild(img);}},//paintShape的结束}//tetris结束window.onload=function(){tetris.init();}
2、shapes.js
function Cell(row,col,img){this.row=row;this.col=col;this.img=img;//三下落if(!Cell.prototype.drop){Cell.prototype.drop=function(){this.row++;}}if(!Cell.prototype.moveR){//十一Cell.prototype.moveR=function(){this.col++;}}if(!Cell.prototype.moveL){//十一Cell.prototype.moveL=function(){this.col--;}}}//十四、下落的各种变化状态function State(r0,c0,r1,c1,r2,c2,r3,c3){//第0个cell相对于参照cell的下标偏移量this.r0=r0;this.c0=c0;//第1个cell相对于参照cell的下标偏移量this.r1=r1;this.c1=c1;//第2个cell相对于参照cell的下标偏移量this.r2=r2;this.c2=c2;//第3个cell相对于参照cell的下标偏移量this.r3=r3;this.c3=c3;}function Shape(img,orgi){this.img=img;this.states=[];//十四、保存每个图形不同状态的数组this.orgi=orgi;//十四、以它为固定不变的参照点,去旋转变形,就是数组states的下标this.statei=0;//默认所有图形的最初状态都是0//三if(!Shape.prototype.drop){Shape.prototype.drop=function(){//遍历当前对象的cells中的每个cell对象//调用当前cell对象的drop方法for(var i=0;i<this.cells.length;i++){this.cells[i].drop();}}}if(!Shape.prototype.moveR){//十一Shape.prototype.moveR=function(){//遍历当前对象的cells中的每个cell对象for(var i=0;i<this.cells.length;i++){//调用当前cell对象的drop方法this.cells[i].moveR();}}}if(!Shape.prototype.moveL){//十一Shape.prototype.moveL=function(){//遍历当前对象的cells中的每个cell对象for(var i=0;i<this.cells.length;i++){//调用当前cell对象的drop方法this.cells[i].moveL();}}}//十五if(!Shape.prototype.rotateR){Shape.prototype.rotateR=function(){//if(Object.getPrototypeOf(this)!=O.prototype){if(this.constructor!=O){this.statei++;this.statei>=this.states.length&&(this.statei=0);//获得下一个状态对象var state=this.states[this.statei];var orgr=this.cells[this.orgi].row;var orgc=this.cells[this.orgi].col;//遍历当前图形中的每个cell//按state中偏移量,设置每个cell的新位置for(var i=0;i<this.cells.length;i++){this.cells[i].row=orgr+state["r"+i];this.cells[i].col=orgc+state["c"+i];}//for的结束}//if的结束}//function的结束}//if的结束if(!Shape.prototype.rotateL){Shape.prototype.rotateL=function(){//if(Object.getPrototypeOf(this)!O.prototype){if(this.constructor!=O){this.statei--;this.statei<0&&(this.statei=this.states.length-1);//获得下一个状态对象var state=this.states[this.statei];var orgr=this.cells[this.orgi].row;var orgc=this.cells[this.orgi].col;//遍历当前图形中的每个cell//按照state中偏移量,设置每个cell的心位置for(var i=0;i<this.cells.length;i++){this.cells[i].row=orgr+state["r"+i];this.cells[i].col=orgc+state["c"+i];}//for的结束}//if的结束}//function的结束}//if的结束}//function Shape(img,orgi)的结束//二function O(){//1Shape.call(this,"img/O.png");if(!Shape.prototype.isPrototypeOf(O.prototype)){Object.setPrototypeOf(O.prototype,Shape.prototype);//继承}this.cells=[new Cell(0,4,this.img),new Cell(0,5,this.img),new Cell(1,4,this.img),new Cell(1,5,this.img)];}function T(){//2Shape.call(this,"img/T.png",1);if(!Shape.prototype.isPrototypeOf(T.prototype)){Object.setPrototypeOf(T.prototype,Shape.prototype);//继承}this.cells=[new Cell(0,3,this.img),new Cell(0,4,this.img),new Cell(0,5,this.img),new Cell(1,4,this.img)];//十四this.states[0]=new State(0,-1, 0,0, 0,1, 1,0);this.states[1]=new State(-1,0, 0,0, 1,0, 0,-1);this.states[2]=new State(0,1, 0,0, 0,-1, -1,0);this.states[3]=new State(1,0, 0,0, -1,0, 0,1);//[0][1] [2] [3]} function I(){//3Shape.call(this,"img/I.png",1);if(!Shape.prototype.isPrototypeOf(I.prototype)){Object.setPrototypeOf(I.prototype,Shape.prototype);//继承}this.cells=[new Cell(0,3,this.img),new Cell(0,4,this.img),new Cell(0,5,this.img),new Cell(0,6,this.img)];this.states[0]=new State(0,-1, 0,0, 0,1, 0,2);//[0][1] [2] [3]this.states[1]=new State(-1,0, 0,0, 1,0, 2,0);}function S(){//4Shape.call(this,"img/S.png",3);if(!Shape.prototype.isPrototypeOf(S.prototype)){Object.setPrototypeOf(S.prototype,Shape.prototype);//继承}this.cells=[new Cell(0,4,this.img),new Cell(0,5,this.img),new Cell(1,3,this.img),new Cell(1,4,this.img)];//十四this.states[0]=new State(-1,0, -1,1, 0,-1, 0,0);this.states[1]=new State(0,1, 1,1, -1,0, 0,0);//[0][1] [2] [3]}function Z(){//5Shape.call(this,"img/Z.png",1);if(!Shape.prototype.isPrototypeOf(Z.prototype)){Object.setPrototypeOf(Z.prototype,Shape.prototype);//继承}this.cells=[new Cell(0,3,this.img),new Cell(0,4,this.img),new Cell(1,4,this.img),new Cell(1,5,this.img)];this.states[0]=new State(0,-1, 0,0, 1,0, 1,1);this.states[1]=new State(-1,0, 0,0, 0,-1, 1,-1);//[0][1] [2] [3]}function L(){//6Shape.call(this,"img/L.png",1);if(!Shape.prototype.isPrototypeOf(L.prototype)){Object.setPrototypeOf(L.prototype,Shape.prototype);//继承}this.cells=[new Cell(0,3,this.img),new Cell(0,4,this.img),new Cell(0,5,this.img),new Cell(1,3,this.img)];this.states[0]=new State(0,-1, 0,0, 0,1, 1,-1);this.states[1]=new State(-1,0, 0,0, 1,0, -1,-1);this.states[2]=new State(0,1, 0,0, 0,-1, -1,1);this.states[3]=new State(1,0, 0,0, -1,0, 1,1);//[0][1] [2] [3]}function J(){//7Shape.call(this,"img/J.png",1);if(!Shape.prototype.isPrototypeOf(J.prototype)){Object.setPrototypeOf(J.prototype,Shape.prototype);//继承}this.cells=[new Cell(0,3,this.img),new Cell(0,4,this.img),new Cell(0,5,this.img),new Cell(1,5,this.img)];this.states[0]=new State(-1,0, 0,0, 1,-1, 1,0);this.states[1]=new State(0,1, 0,0, -1,-1, 0,-1);this.states[2]=new State(1,0, 0,0, -1,1, -1,0);this.states[3]=new State(0,-1, 0,0, 1,1, 0,1);//[0][1] [2] [3]}
最终效果图如下所示:


------------------------------------------------------------------------------------>为了生活而改变,为了改变而创造.
以上就是小编给大家分享的关于基于javascript代码编写的网页版俄罗斯方块。希望大家喜欢。