首先这里感谢@jdkleo 提出的宝贵建议!
说实在的吧,我这个俄罗斯方块大家玩起来别骂我就万岁了,还没完全完成的,只完成了50%,而且还有很多BUG。
可以实现的功能:
1.掉方块
2.随机生成新方块
3.方块移动。
目前BUG还很多,由于是第一次写这么“大”的游戏,有1000多行代码,所以还请高人指点,BUG太多了。
按START开始游戏。
大家提提建议,我第一次写JS游戏。
参考了一下网上其他人的代码,但是不是照抄。
代码可以直接运行,不用引用JQUERY。
希望大神们能给点建议!!!!不甚感激!!!
Ver 0.2版本已经出来了哦(2014-12-26),最新的代码:
此次修正的东西:
1.左边右边可以移动。
2.可以旋转
3.可以消除满行的方块。
代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>无标题文档</title> <style type="text/css">#test{/*width:25px;*/} .t{width:10px;height:10px;border:1px solid black;float:left; } body{margin:0 auto;width:1000px;height:600px; } /*游戏相关*/#startGame{ } #lines{ } #level{ } #time{ } /*俄罗斯方块实体类*/#tetris-area{width:auto;height:auto;background:blue;} /*JS生成的CLASS,俄罗斯方块实体*/#tetris .block0,#tetris .block1, #tetris .block2, #tetris .block3,#tetris .block4,#tetris .block5,#tetris .block6{z-index:1000;font-size:10px;line-height:1em;position:absolute;width:13px;height:13px;border:0.5px solid red;background:#000;}</style> <script src="jquery.js"></script><script type="text/javascript">//2维数组,用来存放俄罗斯方块的坐标 var xYAxis=[];xYAxis.push([1,2],[3,4]); //alert(xYAxis[1][0]); //复制节点/*$(document).ready(function(e) { for(i=0;i<2;i++){if(i==1){ // $("#test").append("<br>");//加上换行符}$(".t").clone().appendTo("#test"); } //动态得到test(container)的宽度,包含两边的边框BORDER$("#test").width(($(".t").width()+2)*2+1);});*///获得区域的横坐标和纵坐标function getArea(x,y,unit,id){this.x=x;this.y=y;this.unit=unit; //每个单元的大小,单位为像素this.el=document.getElementById(id); //得到ID对象 this.board=[]; //面板,即在区域范围内的元素(俄罗斯方块) /*创建2D范围矩阵*/for(var y=0;y<this.y;y++){this.board.push(new Array());for(var x=0;x<this.x;x++){this.board[y].push(0); }} /*从2D矩阵中消除元素*/this.destroy=function(){for(var y=0;y<this.board.length;y++){for(var x=0;x<this.board[y].length;x++){if(this.board[y][x]){this.el.removeChild(this.board[y][x]);this.board[y][x]=0;}}} } //添加元素this.addElement=function(el){//得到起始元素的X开始坐标和Y开始坐标的位置(错误)//得到X坐标的下落次数,和Y轴的左右移动的次数var xBegin=parseInt(el.offsetLeft/unit);var yBegin=parseInt(el.offsetTop/unit); if(xBegin>=0&&xBegin<=this.x&&yBegin>=0&&yBegin<=this.y){this.board[yBegin][xBegin]=el; //确定元素的位置} } //消掉所有的行this.removeFullLines=function(){var lines=0;for(var i=this.y-1;i>0;i--){if(this.linesRelated(i)){this.removeLines(i);lines++;y++;}}return lines; //返回线条} //和线性有关的东西(判断是否满了)this.linesRelated=function(y){for(var x=0;x<this.x;x++){if(!this.board[y][x]){return false;} //如果不为0的话,那么菜返回FALSE} return true;}; //去掉行this.removeLines=function(y){for(var x=0;x<this.x;x++){this.el.removeChild(this.board[y][x]);this.board[y][x]=0; }y--;for(;y>0;y--){/*今天暂时写到这里*//*继续于2014-12-21*/for(var x=0;x<this.x;x++){if(this.board[y][x]){var el=this.board[y][x];el.style.top=el.offsetTop+this.unit+"px";this.board[y+1][x]=el;this.board[y][x]=0; }}}}; //活动区域this.getBlock=function(y,x){if(y<0){return 0;}if(y<this.y&&x<this.x){return this.board[y][x];}else{throw "Area get failed!";} }} /*俄罗斯方块实体类*/function Tetris(){var self =this; //自身var operate=null; this.area=null;this.operate=null; //操作 this.status=new State(); //新建状态/*初始化X,Y,单元为5或者20*/this.x=20;this.y=20;this.unit=20; this.running=null; //是否在运行中 //俄罗斯方块实体IDthis.id="tempid"; /*开始的时候暂停是FALSE的*/this.paused=false; //开始游戏this.start=function(){self.reset(); //重新开始游戏self.status.start(); this.area=new getArea(this.x,this.y,this.unit,"tetris-area"); //获得Area对象,其中TEMPID是俄罗斯方块实体类IDthis.operate=new OperateTetris(this.area,self); //是否可以替换if(this.operate.mayPlace()){//alert(1);this.operate.place();}else{self.gameOver();}} //游戏结束this.gameOver=function(){self.status.stopGame(); //停止游戏self.operate.stopGame(); //操作类停止游戏 } /*重置游戏*/this.reset=function(){if(this.operate){self.operate.destroy(); //重新开始self.operate=null; }if(self.area){self.area.destroy();self.area=null;}//隐藏游戏结束document.getElementById("game_over").style.display="none";document.getElementById("next_operate").style.display="block"; //下一个操作document.getElementById("keys_Press").style.display="block"; //显示按键 self.status.reset();self.paused=false; document.getElementById("tetris-pause").style.display="block"; //暂停按钮 } /*暂停游戏*/this.pause=function(){if(self.operate==null){return ;}if(self.paused){self.operate.running=true;/*这里还没写完2014-12-22*/}else{ } } //上this.up=function(){if(self.operate&&self.operate.isRunning()&&!self.operate.isStopped()){if(self.operate.mayRotate()){self.operate.rotate();self.status.setActions(self.status.getActions()+1); }}} //下this.down=function(){if(self.operate&&self.operate.isRunning()&&!self.operate.isStopped()){if(self.operate.mayMoveDown()){self.operate.moveDown();self.status.setActions(self.status.getActions()+1);}}} //左this.left=function(){if(self.operate&&self.operate.isRunning()&&!self.operate.isStopped()){if(self.operate.mayMoveLeft()){self.operate.moveLeft();self.status.setActions(self.status.getActions()+1); } }} //右this.right=function(){if(self.operate&&self.operate.isRunning()&&!self.operate.isStopped()){if(self.operate.mayMoveRight()){self.operate.moveRight();self.status.setActions(self.status.getActions()+1); }}} //开始游戏document.getElementById("startGame").onclick=function(){self.start()};//} //Tetris是一个整体类,里面包含了很多方法。var keyboard=new Keyboard(); //创建键盘类实体keyboard.set(keyboard.n,this.start);keyboard.set(keyboard.up,this.up); keyboard.set(keyboard.down,this.down);keyboard.set(keyboard.left,this.left);keyboard.set(keyboard.right,this.right); document.onkeydown=keyboard.event; //按下按键按钮的事件/*键盘操作方法*/function Keyboard(){this.up=38; //上this.down=40; //下this.left=37; //左this.right=39; //右 this.n=78;this.p=80;this.r=82;this.space=32; //空格this.f12=123;this.escape=27; //退格键 this.keys=[]; //键位集合this.funcs=[];var self=this; //设置键位this.set=function(key,func){this.keys.push(key);this.funcs.push(func);} this.event=function(e){if(!e){e=window.event;} for(var i=0;i<self.keys.length;i++){if(e.keyCode==self.keys[i]) {self.funcs[i]();}}}}//具体的操作类function OperateTetris(area,tetris){var self=this; //当前对象this.area=area;this.tetris=tetris; this.types=null; //方块的类型;this.nextType=null; //下一个类型 //初始化X和Ythis.x=null;this.y=null;this.position=0; //初始位置 this.board=[]; //用来填充HTML元素的this.elements=[];this.nextElements=[]; //下一个元素 this.running=null; //是否在运行中this.stopped=null; //是否停止 this.fallDownId=null; //往下掉落的this.speed=null; //速度 /*方块的组合方式,用数组进行组合(二维数组)用0,1表示是否有方块存在,如果是0:不存在,1:存在,以下的逻辑就可以非常的清楚了。*/this.blockComplex=[[[0,0,1],[1,1,1],[0,0,0] //_|], [[1,0,0],[1,1,1],[0,0,0] //L], [[0,1,0],[1,1,1],[0,0,0] //T], [[0,0,0],[1,1,1],[0,0,0] //--], [[0,0,0],[0,1,1],[0,1,1] //口], [[0,1,1],[0,1,0],[1,1,0] //Z]]; this.stopGame=function(){this.running=false; } /*一连串的GETTER方法分别是速度,X,Y轴,运行和停止的GETTER方法*/this.getSpeed=function(){return this.speed; } this.getX=function(){return this.x; } this.getY=function(){return this.y; } this.isRunning=function(){return this.running;} this.isStopped=function(){return this.stopped;} //重置(初始化)this.reset=function(){if(this.fallDownId){clearTimeout(this.fallDownId); //下落的时候去掉时间间隔}this.types=this.nextType;this.nextType=random(this.blockComplex.length);this.position=0;this.board=[];this.elements=[];this.x=null;this.y=null;this.speed=200; //速度暂定为51 this.running=false;this.stopped=false; //移除下一个元素for(var i=0;i<this.nextElements.length;i++){document.getElementById("next_operate").removeChild(this.nextElements[i]);} this.nextElements=[]; //下一个元素}//下一个类型,随机抽取this.nextType=random(this.blockComplex.length); //重置this.reset(); /*判断是否替换*/this.mayPlace=function(){var isOperate=this.blockComplex[this.types]; /*area开始的坐标原点*/var areaStartX=parseInt(this.area.x-isOperate[0].length);var areaStartY=1;var lineFound=false;var lines=0;for(var y=isOperate.length-1;y>=0;y--){for(var x=0;x<isOperate[y].length;x++){if(isOperate[y][x]){lineFound=true;if(this.area.getBlock(areaStartY,areaStartX+x)) {return false;}}} if(lineFound){lines++;}if(areaStartY-lines<0){break; } } return true;} /*替换*/this.place=function(){//初始化var operate=this.blockComplex[this.types];//区域开始X轴的位置var AreaXStartPos=parseInt(this.area.x-operate[0].length); //区域开始Y轴的位置//var AreaYStartPos=parseInt(this.area.y-operate[0]);var AreaYStartPos=1; //因为X轴的位置可能变化,而Y轴总是从最上面下来的,所以是1 this.x=AreaXStartPos; //把新的位置赋给X;this.y=AreaYStartPos; //把新的位置赋给y; //构建空对象,并存入BOARD/*y:行,x:列*/ //alert(operate[0].length+" "+operate.length);this.board=this.createEmpty(operate[0].length,operate.length); /*线条,往下掉落,初始化*/var lines=0;var foundLines=false; //循环遍历,先遍历行,每一行再来遍历列for(var yAxis=operate.length-1;yAxis>=0;yAxis--){for(var xAxis=0;xAxis<=operate[yAxis].length;xAxis++){if(operate[yAxis][xAxis]){var el=document.createElement("div");el.className="block"+this.types; //确定这个元素的CLASSNAME//确定左边距和上边距el.style.left=(this.x+xAxis)*this.area.unit+"px";el.style.top=(this.y+yAxis)*this.area.unit+"px";this.area.el.appendChild(el); //这个EL去APPEND主要的EL。 this.board[yAxis][xAxis]=el;this.elements.push(el); //推入elements中 }} /*个人感觉这个功能应该是加速往下掉落的方法?不明觉厉*/if(lines){yAxis--;} if(foundLines){lines++; } }this.running=true;this.fallDownId=setTimeout(this.fallDown,this.speed); //间隔时间,掉落下的 var nextOperate=this.blockComplex[this.nextType];for(var y=0;y<nextOperate.length;y++){for(var x=0;x<nextOperate[y].length;x++){//创建元素if(nextOperate[y][x]){/*先写到这里:2014-12-22*/var el=document.createElement("div");el.className="block"+this.nextType;el.style.left=(x*this.area.unit)+"px";el.style.top=(y*this.area.unit)+"px"; document.getElementById("next_operate").appendChild(el);this.nextElements.push(el); //下一个元素 }}} } //创建空对象,即所有的都为0的对象,并返回对象this.createEmpty=function(x,y){var elements=[];for(var y2=0;y2<y;y2++){ elements.push(new Array()); for(var x2=0;x2<x;x2++){elements[y2].push(0);} }return elements;} //下落(这是一个最关键的函数,决定了这个游戏的成败)this.fallDown=function(){if(self.isRunning()){ if(self.mayMoveDown()){self.moveDown();self.fallDownId=setTimeout(self.fallDown,self.speed); //下落的间隔时间 }else{for(var i=0;i<self.elements.length;i++){self.area.addElement(self.elements[i]);}var lines=self.area.removeFullLines();if(lines){/*这里到时候再写*/self.tetris.status.setLines(self.tetris.status.getLines()+lines);} self.reset();if(self.mayPlace()){self.place();}else{self.tetris.gameOver(); }}}else{ } }//是否可以旋转俄罗斯方块this.mayRotate=function(){for(var y=0;y<this.board.length;y++){for(var x=0;x<this.board[y].length;x++){if(this.board[y][x]){ /新的X,Y的值/var newY=this.getY()+this.board.length-1-x;var newX=this.getX()+y; if(newY>this.area.y){return false;}if(newX<0){return false;}if(newX>=this.area.x){return false;}if(this.area.getBlock(newY,newX)){return false;} //获得区域}}}return true;} //旋转俄罗斯方块this.rotate=function(){var puzzle=this.createEmpty(this.board.length,this.board[0].length); //创建一个空的矩阵for(var y=0;y<this.board.length;y++){for(var x=0;x<this.board[y].length;x++){//旋转,X轴和Y轴的坐标互换if(this.board[y][x]){var newY=puzzle.length-1-x;var newX=y;var el=this.board[y][x]; //旋转前的对象 var moveY=newY-y;var moveX=newX-x; //长度是offsetTop或left加上偏移量el.style.left=el.offsetLeft+(moveX*this.area.unit)+"px";el.style.top=el.offsetTop+(moveY*this.area.unit)+"px"; puzzle[newY][newX]=el; }}}this.board=puzzle;} //下落方法(进行判断)this.mayMoveDown=function(){for(var y=0;y<this.board.length;y++){for(var x=0;x<this.board[y].length;x++){if(this.board[y][x]){if(this.getY()+y+1>=this.area.y){this.stopGame=true;return false;}//如果触底,那么就停止游戏if(this.area.getBlock(this.getY()+y+1,this.getX()+x)){this.stopGame=true;return false;}}}} return true;} //下落this.moveDown=function(){//用一个循环去控制下落for(var i=0;i<this.elements.length;i++){this.elements[i].style.top=this.elements[i].offsetTop+this.area.unit+"px"; }this.y++;} this.mayMoveLeft=function(){/*可以向左移动(判断方法)*/for(var y=0;y<this.board.length;y++){for(var x=0;x<this.board[y].length;x++){if(this.board[y][x]){if(this.getX()-1+x<0){return false;}if(this.area.getBlock(this.getY()+y,this.getX()+x-1)){return false;} }}}return true; } //向左移动this.moveLeft=function(){/*向左移动(判断方法)*/ for(var i=0;i<this.elements.length;i++){this.elements[i].style.left=this.elements[i].offsetLeft-this.area.unit+"px";}this.x--; } /*是否可以向右移动*/this.mayMoveRight=function(){for(var y=0;y<this.board.length;y++){for(var x=0;x<this.board[y].length;x++){if(this.board[y][x]){if(this.getX()+1+x>=this.area.x){return false;} if(this.area.getBlock(this.getY()+y,this.getX()+x+1)){return false;}}}} return true;} /*向右移动*/this.moveRight=function(){for(var i=0;i<this.elements.length;i++){this.elements[i].style.left=this.elements[i].offsetLeft+this.area.unit+"px";}this.x++;} /*摧毁方法*/this.destroy=function(){for(var i=0;i<this.elements.length;i++){this.area.el.removeChild(this.elements[i]); }this.elements=[];this.board=[];this.reset();}} /*俄罗斯方块状态*/function State(){/*初始化*/this.level;this.time;this.score;this.opeate; this.lines; this.apm; //不明觉厉 this.actions; //动作 this.el={"lines":document.getElementById("lines"),"level":document.getElementById("level"),"time":document.getElementById("time"),"apm":document.getElementById("apm"),"operate":document.getElementById("operate")} this.timeId=null;var self=this; //开始游戏this.start=function(){this.reset(); //重置this.timeId=setInterval(this.incTime,1500); } /*停止游戏*/this.stopGame=function(){if(this.timeId){clearInterval(this.timeId); } } //重置this.reset=function(){this.stopGame();this.level=1;this.time=0;this.score=0this.opeate=0; this.lines=0; /*以后可能加INNERHTML*/this.el.level=this.level;this.el.time=this.time;this.el.score=this.score;this.el.operate=this.opeate;this.el.lines=this.lines; } //和SetInterval有关this.incTime=function(){self.time++;self.el.time.innerHTML=self.time; //设置时间self.actions=parseInt(self.actions/self.time)*60;this.el.apm.innerHTML=self.apm; } /*设置分数*/this.setScore=function(i){this.score==i;this.el.score.innerHTML=this.score;} /*设置等级*/this.setLevel=function(i){this.level=i;this.el.level.innerHTML=this.level; //设置内部HTML}; this.getLevel=function(){return this.level; } //线条的SETTER方法this.setLines=function(i){this.lines=i;this.el.lines.innerHTML=this.lines; } this.getLines=function(){return this.lines;} //设置动作this.setActions=function(i){this.actions=i;//this.el.actions.innerHTML=this.actions;} this.getActions=function(){return this.actions;} //设置apmthis.setApm=function(i){this.apm=i;this.el.apm.innerHTML=this.apm; } this.getApm=function(){return this.apm;} //控制下落操作的类this.setOperate=function(i){this.opeate=i;this.el.operate=this.operate;} this.getOperate=function(){return this.opeate; }} //随机数,产生1~6的function random(i){return Math.floor(Math.random()*i);} } /*Tetris是一个整体类,里面包含了很多方法*/</script> </head> <body> <div id="tetris"><!--正方形 --><div id="test"><div class="t"></div></div> <!--长方形--><div id="rect"><div class="r"> </div></div> <!-- 俄罗斯方块实体类--><div id="tetris-area"> </div> <!-- 下一个操作--><div id="next_operate"></div> <!--游戏结束--><div id="game_over">Game Over</div> <!-- 按键 --><div id="keys_Press"></div> <input type="button" id="startGame" value="Start" /> <!--线条 --><div id="lines"></div> <!--等级 --><div id="level"></div> <!--apm(不知道有什么作用) --><div id="apm"></div> <!--时间 --><div id="time"></div> <!--控制下落操作 --><div id="operate"></div> <!-- 功能键(暂停)--><div id="tetris-pause"> </div> <!-- 功能键(继续)--><div id="tetris-resume" style="display:none"> </div></div><script>var tx=new Tetris();tx.x=12;tx.y=22;tx.unit=14;//tx.start(); //开始游戏</script> </body></html>演示图:

项目git地址:
http://git.oschina.net/KMSFan/Tetris_Yang
项目演示地址:http://runjs.cn/detail/ggo07ery
以上所述就是本文的全部内容了,希望能够对大家学习javascript有所帮助。