怎么用JavaScript做俄罗斯方块游戏
这篇文章主要为大家展示了“怎么用JavaScript做俄罗斯方块游戏”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“怎么用JavaScript做俄罗斯方块游戏”这篇文章吧。
最终游戏效果一开始我们先搭个框架,以便后期使用
编写外部框架<!DOCTYPEhtml><html><headlang="en"><metacharset="UTF-8"><title></title><style>*{margin:0;padding:0;}#box{width:320px;height:450px;position:absolute;margin:0auto;left:0;top:20px;right:0;bottom:0;background:gray;border-radius:10px;}#mainDiv{width:300px;height:400px;position:absolute;margin:0auto;left:0;top:10px;right:0;bottom:0;}.bottom{width:600px;height:30px;position:absolute;bottom:1px;right:1px;}.bottom.button1{position:absolute;right:55px;width:50px;font-size:14px;}.bottom.button2{position:absolute;right:5px;width:50px;font-size:14px;}.bottom.span1{position:absolute;right:155px;color:white;font-size:8px;}.bottom.span2{position:absolute;right:255px;color:white;font-size:8px;}</style></head><body><divid='box'><divid='mainDiv'></div><divclass='bottom'><spanid='score'class='span1'>分数:0</span><spanid='time'class='span2'>时间:0</span><buttononclick='start()'class='button1'>开始</button><buttononclick='stop()'class='button2'>结束</button></div></div><scripttype="text/javascript"src='tetris.js'></script><scripttype="text/javascript"></script></body></html>
框架效果如下:
首先创建线的构造函数Line
functionLine(ctx,o){this.x=0,//x坐标this.y=0,//y坐标this.startX=0,//开始点x位置this.startY=0,//开始点y位置this.endX=0,//结束点x位置this.endY=0;//结束点y位置this.thin=false;//设置变细系数this.ctx=ctx;this.init(o);}Line.prototype.init=function(o){for(varkeyino){this[key]=o[key];}}Line.prototype.render=function(){innerRender(this);functioninnerRender(obj){varctx=obj.ctx;ctx.save()ctx.beginPath();ctx.translate(obj.x,obj.y);if(obj.thin){ctx.translate(0.5,0.5);}if(obj.lineWidth){//设定线宽ctx.lineWidth=obj.lineWidth;}if(obj.strokeStyle){ctx.strokeStyle=obj.strokeStyle;}//划线ctx.moveTo(obj.startX,obj.startY);ctx.lineTo(obj.endX,obj.endY);ctx.stroke();ctx.restore();}returnthis;}设定参数、执行绘制等相关方法
代码如下:
functionGame(el){this.renderArr=[];//待渲染对象存储数组this.aliveModel=[];//用来存到底的model组合this.score=0;//分数this.time=0;//时间this.moveCount=1;//计时控制器}Game.prototype.init=function(el,score,time){if(!el)return;this.el=el;this.scoreEL=score;this.timeEL=time;varcanvas=document.createElement('canvas');//创建画布canvas.style.cssText="background:darkgrey;border:1pxsolidgrey;";//设置样式varW=canvas.width=300;//设置宽度varH=canvas.height=400;//设置高度el.appendChild(canvas);//添加到指定的dom对象中this.ctx=canvas.getContext('2d');this.canvas=canvas;this.w=W;this.h=H;this.disX=20;//每个格子的x方向大小this.disY=20;//每个格子的y方向大小this.maxX=15;//x方向格子总数this.maxY=20;//y方向格子总数this.control();//this.draw();//绘制}//绘制地图Game.prototype.createMap=function(){varrenderArr=this.renderArr;vardisX=this.disX;vardisY=this.disY;varmaxX=this.maxX;varmaxY=this.maxY;varrectW=this.w;varrectH=this.h;varrect=null;varcolor;for(vari=1;i<maxY;i++){//20行varline=newLine(this.ctx,{x:0,y:0,startX:0,startY:i*disY,endX:this.w,endY:i*disY,thin:true,strokeStyle:'white',lineWidth:0.2})renderArr.push(line);}for(vari=1;i<maxX;i++){//15列varline=newLine(this.ctx,{x:0,y:0,startX:i*disX,startY:0,endX:i*disX,endY:this.h,thin:true,strokeStyle:'white',lineWidth:0.2})renderArr.push(line);}}Game.prototype.draw=function(){this.createMap();//绘制地图this.render();//渲染}
此时游戏区域的格子以及绘制如下:
模型定义:分别是一字形、田字形、二字形2种、七字形2种、凸字形等共7种。
变形定义:1字形可以变形2种、田字形不能变形,其他的都可以变形4种。
模型的组成:模型是有4个小方块来组成,每个模型里面有数组blocks来存取4个小方块的x、y坐标,然后绘制出来就是模型了。
模型的变形:变形的时候就只要切换每个方块的X\Y坐标就可以达到变形的效果。
下面来创建模型的构造函数//模型构造函数functionModel(o){this.blocks=[],//存储方块的数组,绘制的时候根据数组来绘制this.type=1,//模型的形状,默认是一字形(共7种)this.dir=1,//方向默认为1,总共4种,其中一字形为2种,田字形为1种,其他为4种this.x=0,//x坐标(只传入第一个x,根据这个x来生成其他的x)this.y=0,//y坐标(只传入第一个y,根据这个y来生成其他的y)this.init(o);}//初始化Model.prototype.init=function(o){for(varkeyino){this[key]=o[key];}}举例
添加一个创建七字形的方法(因为七字形有4种摆放方式,所以有dir来区分,怎么摆放)
//创建七字形1Model.prototype.createQi1=function(){varblocks=this.blocks,x=this.x,y=this.y;switch(this.dir){case1://blocks.push({x:x,y:y});blocks.push({x:x,y:y-1});blocks.push({x:x,y:y-2});blocks.push({x:x+1,y:y-2});break;case2://blocks.push({x:x+2,y:y});blocks.push({x:x+1,y:y});blocks.push({x:x,y:y});blocks.push({x:x,y:y-1});break;case3://blocks.push({x:x+1,y:y-2});blocks.push({x:x+1,y:y-1});blocks.push({x:x+1,y:y});blocks.push({x:x,y:y});break;case4://blocks.push({x:x-2,y:y-1});blocks.push({x:x-1,y:y-1});blocks.push({x:x,y:y-1});blocks.push({x:x,y:y});break;}}
创建一个七字形试试(传入的x、y是第一个放个的位置)
varmodel=newModel({//创建1字x:6,y:6,fillStyle:'#0370BD',fill:true,game:this,type:5,dir:1});this.renderArr.push(model);//当前的模型this.currentModel=model;编写变形方法(每一次变形都是按前一个模样逆时针旋转90度,修改每个小方块x、y来修改就行)
------------------------ >>>
左边这个图形要变成右边的图形,需要怎么变更呢?
-------------------->>>
标上号码就很容易明白,1还是对应的1,2还是对应的2,以此类推,只不过X\Y变了
1方块:只要x+2就可以移到指定的位置;
2方块:x、y都需要加1
3方块:y+2就可以
4方块:x-1和y+1即可
其他都是一样的道理,来写一下变形的方法
//七1变形Model.prototype.transformQi1=function(){varblocks=this.blocks,block2=blocks[1];switch(this.dir){case1://竖着的tran1();this.dir=2;break;case2://横着的tran2();this.dir=3;break;case3://竖着的tran3();this.dir=4;break;case4://横着的tran4();this.dir=1;break;}functiontran1(){//变成横着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==0){block.x+=2;}elseif(i==1){block.x+=1;block.y+=1;}elseif(i==2){block.y+=2;}elseif(i==3){block.x-=1;block.y+=1}}}functiontran2(){//竖着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==0){block.x-=1;block.y-=2;}elseif(i==1){block.y-=1;}elseif(i==2){block.x+=1;}elseif(i==3){block.y+=1}}}functiontran3(){//变成横着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==3){block.x+=2;}elseif(i==2){block.x+=1;block.y-=1;}elseif(i==1){}elseif(i==0){block.x-=1;block.y+=1}}}functiontran4(){//竖着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==3){block.x-=1;block.y-=2;}elseif(i==2){block.x-=2;block.y-=1;}elseif(i==1){block.x-=1;}elseif(i==0){block.y+=1;}}}}给 w 和向上键添加为变形事件,同时左移动、右移动、下加速也添加好事件
//按键的控制Game.prototype.control=function(){varthat=this;global.addEventListener('keydown',function(e){//if(!that.timmer)return;switch(e.keyCode){case87://wcase38://上that.currentModel.transform();//变形break;case83://scase40://下that.currentModel.move('d');//移动break;case65://acase37://左that.currentModel.move('l');//移动break;case68://dcase39://右that.currentModel.move('r');//移动break;}//测试用,记得删除that.render();});}
接下来变形试试
//移动Model.prototype.move=function(dir){varcur=this.game.currentModel,dis=1,blocks=this.blocks;if(dir=='r'||dir=='ld'){dis=1}elseif(dir=='l'){dis=-1;}elseif(dir=='d'){dis=3;}varstopMoveObj=this.stopMove(dir,dis),val=stopMoveObj.val,resDis=stopMoveObj.resDis;if(val){if(dir=='d'||dir=='ld'){//到底了[].push.apply(this.game.aliveModel,cur.blocks);//放到已到底的组合中this.game.renderArr.pop();//当前模型弹出this.game.clearBlock();//消除this.game.createModel();//绘制一个新图形}return;//如果返回true则不能再往这个方向移动}if(resDis>0){dis=resDis;}//更新每一个block的位置for(vari=0;i<blocks.length;i++){block=blocks[i];if(dir=='d'||dir=='ld'){block.y+=dis;}else{block.x+=dis;}}}加入边界判断和碰撞检测(边界检测比较简单、碰撞检测在快进的时候要注意处理一下,看代码吧)
//停止移动Model.prototype.stopMove=function(dir,dis){varcur=this.game.currentModel,blocks=this.blocks;varmaxX=this.game.maxX,maxY=this.game.maxY,res,temp;for(vari=0;i<blocks.length;i++){block=blocks[i];if(dir=='d'||dir=='ld'){if(block.y>=maxY-1){//到底了return{val:true};}}elseif(dir=='r'){if(block.x>=maxX-1){//到右边界了return{val:true};}}elseif(dir=='l'){if(block.x<=0){//到左边界了return{val:true};}}//碰撞检测temp=this.collide(block,dis,dir);if(temp.val){returntemp;}if(!res||res.resDis==0||(temp.resDis!=0&&temp.resDis<res.resDis)){res=temp;}}returnres;}//检查当前模型是否与其他存底的模型相触碰Model.prototype.collide=function(block,dis,dir){varaliveModel=this.game.aliveModel,item;varres={},val=false,resDis=0,maxY=this.game.maxY;if(dir=='r'){//向右判断for(vari=0;i<aliveModel.length;i++){item=aliveModel[i];if(!item)continue;if(item.y==block.y&&item.x==block.x+1){val=true;break;}}}elseif(dir=='l'){//向左判断for(vari=0;i<aliveModel.length;i++){item=aliveModel[i];if(!item)continue;if(item.y==block.y&&item.x==block.x-1){val=true;break;}}}else{//向下判断if(aliveModel.length>0){for(vari=0;i<aliveModel.length;i++){item=aliveModel[i];if(!item)continue;if(item.x==block.x){//下方有存在的方块if(item.y==block.y+1){val=true;break;}elseif(item.y<=block.y+Math.abs(dis)){vartemp=item.y-block.y-1;if(resDis==0||temp<resDis){resDis=temp;}}}else{//下发不存在方块if(maxY<=block.y+Math.abs(dis)){vartemp=maxY-block.y-1;if(resDis==0||temp<resDis){resDis=temp;}}}}}else{//第一个模型if(maxY<=block.y+Math.abs(dis)){vartemp=maxY-block.y-1;if(resDis==0||temp<resDis){resDis=temp;}}}}res.resDis=resDis;res.val=val;returnres;}
给当前的游戏对象的aliveModel数组,存取当前到底的模型所对应的4个小方块(执行render方法的时候就绘制出来)
在renderArr数组中此模型要删除
每次触底需要加入消除判断,符合条件就消除
绘制一个新的模型
绘制触底的模型方块//绘制存底的图形Game.prototype.aliveModelRender=function(){varcontext=this.ctx;vardisX=this.disX,disY=this.disY;context.save();context.beginPath();_.each(this.aliveModel,function(item){if(item){context.rect(item.x*disX+1,item.y*disY+1,disX-1,disY-1);//context.fillStyle='';context.fill();}});context.restore();}消除行、积分、以及下降
//消除行Game.prototype.clearBlock=function(){varmaxX=this.maxX,aliveModel=this.aliveModel;//将y相同的放在一起varrowArr=[],rowObj={};_.each(aliveModel,function(item,index){if(item){if(!rowObj[item.y]){rowObj[item.y]=[];}rowObj[item.y].push(index);}});varthat=this;varkeys=Object.keys(rowObj),row,num=0;_.each(keys,function(k){row=rowObj[k];if(row.length>=maxX){//消除这行_.each(row,function(r){aliveModel.splice(r,1,undefined);//先用undefined代替})num++;//行数计数器that.down(k,1);//清楚当前行}})//完成消除for(vari=0;i<aliveModel.length;i++){if(!aliveModel[i]){console.log(123)aliveModel.splice(i,1);}}varscore=0;switch(num){case1:score=100;//1行100分break;case2:score=300;//2行300分break;case3:score=600;//3行600分break;case4:score=1000;//4行1000分break;}//积分this.calcuScore(score);}//消除后的下降Game.prototype.down=function(y,num){varaliveModel=this.aliveModel;_.each(aliveModel,function(item){if(item&&item.y<y){item.y+=num;}});}自动往下移动、更新、显示时间、分数
//显示分数Game.prototype.calcuScore=function(s){this.score+=s;this.scoreEL.innerText='分数:'+this.score;}//显示时间Game.prototype.calcuTime=function(){if(this.moveCount%4==0){this.time++;this.time_flag=false;this.timeEL.innerText='时间:'+this.time;}this.moveCount++;}//向下移动Game.prototype.move=function(dir){varcurModel=this.currentModel;this.calcuTime();varendFlag=this.end();if(endFlag){this.stop();this.hasEnd=true;return;}this.update();this.render();}//更新Game.prototype.update=function(){this.currentModel.move('ld');}给开始、结束按钮加入事件
varmainDiv=document.getElementById('mainDiv');varscore=document.getElementById('score');vartime=document.getElementById('time');game.init(mainDiv,score,time);functionstart(){game.start()}functionstop(){game.stop()}
Game.prototype.start=function(){if(this.timmer)return;if(this.hasEnd){//如果是结束则需要重新开始,暂停的话就继续游戏this.restart();}this.hasEnd=false;this.timmer=setInterval(this.move.bind(this),250);//开始定时任务}//重新开始Game.prototype.restart=function(){this.renderArr=[];//待渲染对象存储数组this.aliveModel=[];//用来存到底的model组合this.score=0;//分数this.time=0;//时间this.moveCount=1;//计时控制器this.clearCanvas();this.draw();}//停止任务Game.prototype.stop=function(){if(!this.timmer)return;clearInterval(this.timmer);//清除定时任务this.timmer=null;}//结束Game.prototype.end=function(){varaliveModel=this.aliveModel;for(vari=0;i<aliveModel.length;i++){item=aliveModel[i];if(item&&item.y==0){alert('结束了')returntrue;}}returnfalse}源码如下:
HTML
<!DOCTYPEhtml><html><headlang="en"><metacharset="UTF-8"><title></title><style>*{margin:0;padding:0;}#box{width:320px;height:450px;position:absolute;margin:0auto;left:0;top:20px;right:0;bottom:0;background:gray;border-radius:10px;}#mainDiv{width:300px;height:400px;position:absolute;margin:0auto;left:0;top:10px;right:0;bottom:0;}.bottom{width:600px;height:30px;position:absolute;bottom:1px;right:1px;}.bottom.button1{position:absolute;right:55px;width:50px;font-size:14px;}.bottom.button2{position:absolute;right:5px;width:50px;font-size:14px;}.bottom.span1{position:absolute;right:155px;color:white;font-size:8px;}.bottom.span2{position:absolute;right:255px;color:white;font-size:8px;}</style></head><body><divid='box'><divid='mainDiv'></div><divclass='bottom'><spanid='score'class='span1'>分数:0</span><spanid='time'class='span2'>时间:0</span><buttononclick='start()'class='button1'>开始</button><buttononclick='stop()'class='button2'>结束</button></div></div><scripttype="text/javascript"src='tetris.js'></script><scripttype="text/javascript">varmainDiv=document.getElementById('mainDiv');varscore=document.getElementById('score');vartime=document.getElementById('time');game.init(mainDiv,score,time);functionstart(){game.start()}functionstop(){game.stop()}</script></body></html>
JS
;(function(global){vargame=newGame();functionGame(el){this.renderArr=[];//待渲染对象存储数组this.aliveModel=[];//用来存到底的model组合this.score=0;//分数this.time=0;//时间this.moveCount=1;//计时控制器}Game.prototype.init=function(el,score,time){if(!el)return;this.el=el;this.scoreEL=score;this.timeEL=time;varcanvas=document.createElement('canvas');//创建画布canvas.style.cssText="background:darkgrey;border:1pxsolidgrey;";//设置样式varW=canvas.width=300;//设置宽度varH=canvas.height=400;//设置高度el.appendChild(canvas);//添加到指定的dom对象中this.ctx=canvas.getContext('2d');this.canvas=canvas;this.w=W;this.h=H;this.disX=20;//每个格子的x方向大小this.disY=20;//每个格子的y方向大小this.maxX=15;//x方向格子总数this.maxY=20;//y方向格子总数this.control();//this.draw();//绘制}//绘制地图Game.prototype.createMap=function(){varrenderArr=this.renderArr;vardisX=this.disX;vardisY=this.disY;varmaxX=this.maxX;varmaxY=this.maxY;varrectW=this.w;varrectH=this.h;varrect=null;varcolor;for(vari=1;i<maxY;i++){//20行varline=newLine(this.ctx,{x:0,y:0,startX:0,startY:i*disY,endX:this.w,endY:i*disY,thin:true,strokeStyle:'white',lineWidth:0.2})renderArr.push(line);}for(vari=1;i<maxX;i++){//15列varline=newLine(this.ctx,{x:0,y:0,startX:i*disX,startY:0,endX:i*disX,endY:this.h,thin:true,strokeStyle:'white',lineWidth:0.2})renderArr.push(line);}}Game.prototype.draw=function(){this.createMap();//绘制地图this.createModel();//绘制一个图形this.render();//渲染}//渲染图形Game.prototype.render=function(){varcontext=this.ctx;this.clearCanvas();_.each(this.renderArr,function(item){item&&item.render(context);});this.aliveModelRender();}//绘制存底的图形Game.prototype.aliveModelRender=function(){varcontext=this.ctx;vardisX=this.disX,disY=this.disY;context.save();context.beginPath();_.each(this.aliveModel,function(item){if(item){context.rect(item.x*disX+1,item.y*disY+1,disX-1,disY-1);//context.fillStyle='';context.fill();}});context.restore();}//消除行Game.prototype.clearBlock=function(){varmaxX=this.maxX,aliveModel=this.aliveModel;//将y相同的放在一起varrowArr=[],rowObj={};_.each(aliveModel,function(item,index){if(item){if(!rowObj[item.y]){rowObj[item.y]=[];}rowObj[item.y].push(index);}});varthat=this;varkeys=Object.keys(rowObj),row,num=0;_.each(keys,function(k){row=rowObj[k];if(row.length>=maxX){//消除这行_.each(row,function(r){aliveModel.splice(r,1,undefined);//先用undefined代替})num++;//行数计数器that.down(k,1);//清楚当前行}})//完成消除for(vari=0;i<aliveModel.length;i++){if(!aliveModel[i]){console.log(123)aliveModel.splice(i,1);}}varscore=0;switch(num){case1:score=100;//1行100分break;case2:score=300;//2行300分break;case3:score=600;//3行600分break;case4:score=1000;//4行1000分break;}//积分this.calcuScore(score);}//消除后的下降Game.prototype.down=function(y,num){varaliveModel=this.aliveModel;_.each(aliveModel,function(item){if(item&&item.y<y){item.y+=num;}});}Game.prototype.start=function(){if(this.timmer)return;if(this.hasEnd){//如果是结束则需要重新开始,暂停的话就继续游戏this.restart();}this.hasEnd=false;this.timmer=setInterval(this.move.bind(this),250);//开始定时任务}//重新开始Game.prototype.restart=function(){this.renderArr=[];//待渲染对象存储数组this.aliveModel=[];//用来存到底的model组合this.score=0;//分数this.time=0;//时间this.moveCount=1;//计时控制器this.clearCanvas();this.draw();}//停止任务Game.prototype.stop=function(){if(!this.timmer)return;clearInterval(this.timmer);//清除定时任务this.timmer=null;}//结束Game.prototype.end=function(){varaliveModel=this.aliveModel;for(vari=0;i<aliveModel.length;i++){item=aliveModel[i];if(item&&item.y==0){alert('结束了')returntrue;}}returnfalse}//显示分数Game.prototype.calcuScore=function(s){this.score+=s;this.scoreEL.innerText='分数:'+this.score;}//显示时间Game.prototype.calcuTime=function(){if(this.moveCount%4==0){this.time++;this.time_flag=false;this.timeEL.innerText='时间:'+this.time;}this.moveCount++;}//向下移动Game.prototype.move=function(dir){varcurModel=this.currentModel;this.calcuTime();varendFlag=this.end();if(endFlag){this.stop();this.hasEnd=true;return;}this.update();this.render();}//更新Game.prototype.update=function(){this.currentModel.move('ld');}//按键的控制Game.prototype.control=function(){varthat=this;global.addEventListener('keydown',function(e){//if(!that.timmer)return;switch(e.keyCode){case87://wcase38://上that.currentModel.transform();//变形break;case83://scase40://下that.currentModel.move('d');//移动break;case65://acase37://左that.currentModel.move('l');//移动break;case68://dcase39://右that.currentModel.move('r');//移动break;}//测试用,记得删除//that.render();});}Game.prototype.clearCanvas=function(){this.ctx.clearRect(0,0,parseInt(this.w),parseInt(this.h));//清理画布}//创建模型Game.prototype.createModel=function(){vartype=_.getRandom(1,7);//type有7种vardir=0;if(type=='1'){//一字只2种dir=_.getRandom(1,2);}elseif(type=='2'){//一字只有1种dir=1;}else{//其他有4种dir=_.getRandom(1,4);}varmodel=newModel({//随机创建x:6,y:-1,fillStyle:'#0370BD',fill:true,game:this,type:type,dir:dir});this.renderArr.push(model);//当前的模型this.currentModel=model;/*model=newModel({//创建横向1字x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:1,dir:1});model=newModel({//创建田字x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:2,dir:1});model=newModel({//创建二字1x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:3,dir:4});model=newModel({//创建二字2x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:4,dir:1});model=newModel({//创建七字1x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:5,dir:4});model=newModel({//创建七字2x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:6,dir:4});model=newModel({//创建凸字x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:7,dir:4});*/}//模型构造函数functionModel(o){this.blocks=[],//存储方块的数组,绘制的时候根据数组来绘制this.type=1,//模型的形状,默认是一字形(共7种)this.dir=1,//方向默认为1,总共4种,其中一字形为2种,田字形为1种,其他为4种this.x=0,//x坐标(只传入第一个x,根据这个x来生成其他的x)this.y=0,//y坐标(只传入第一个y,根据这个y来生成其他的y)this.init(o);}//初始化Model.prototype.init=function(o){for(varkeyino){this[key]=o[key];}this.organ();}//组织图形Model.prototype.organ=function(){switch(this.type){case1:this.createYi();//创建一字形break;case2:this.createTian();//创建田字形break;case3:this.createEr1();//创建字二形1break;case4:this.createEr2();//创建二字形2break;case5:this.createQi1();//创建七字形1break;case6:this.createQi2();//创建七字形2break;case7:this.createTu();//创建凸字形break;}}//创建一字形Model.prototype.createYi=function(){varblocks=this.blocks,x=this.x,y=this.y;switch(this.dir){case1://横着的blocks.push({x:x,y:y});blocks.push({x:x+1,y:y});blocks.push({x:x+2,y:y});blocks.push({x:x+3,y:y});break;case2://竖着的blocks.push({x:x,y:y});blocks.push({x:x,y:y-1});blocks.push({x:x,y:y-2});blocks.push({x:x,y:y-3});break;}}//创建田字形Model.prototype.createTian=function(){varblocks=this.blocks,x=this.x,y=this.y;switch(this.dir){case1://横着的blocks.push({x:x,y:y});blocks.push({x:x+1,y:y});blocks.push({x:x,y:y-1});blocks.push({x:x+1,y:y-1});break;case2://竖着的blocks.push({x:x,y:y});blocks.push({x:x,y:y-1});blocks.push({x:x,y:y-2});blocks.push({x:x,y:y-3});;break;}}//创建二字形1Model.prototype.createEr1=function(){varblocks=this.blocks,x=this.x,y=this.y;switch(this.dir){case1://blocks.push({x:x,y:y});blocks.push({x:x,y:y-1});blocks.push({x:x+1,y:y-1});blocks.push({x:x+1,y:y-2});break;case2://blocks.push({x:x+1,y:y});blocks.push({x:x,y:y});blocks.push({x:x,y:y-1});blocks.push({x:x-1,y:y-1});break;case3://blocks.push({x:x+1,y:y-2});blocks.push({x:x+1,y:y-1});blocks.push({x:x,y:y-1});blocks.push({x:x,y:y});break;case4://blocks.push({x:x-1,y:y-1});blocks.push({x:x,y:y-1});blocks.push({x:x,y:y});blocks.push({x:x+1,y:y});break;}}//创建二字形2Model.prototype.createEr2=function(){varblocks=this.blocks,x=this.x,y=this.y;switch(this.dir){case1://blocks.push({x:x,y:y});blocks.push({x:x,y:y-1});blocks.push({x:x-1,y:y-1});blocks.push({x:x-1,y:y-2});break;case2://blocks.push({x:x+2,y:y-1});blocks.push({x:x+1,y:y-1});blocks.push({x:x+1,y:y});blocks.push({x:x,y:y});break;case3://blocks.push({x:x-1,y:y-2});blocks.push({x:x-1,y:y-1});blocks.push({x:x,y:y-1});blocks.push({x:x,y:y});break;case4://blocks.push({x:x,y:y});blocks.push({x:x+1,y:y});blocks.push({x:x+1,y:y-1});blocks.push({x:x+2,y:y-1});break;}}//创建七字形1Model.prototype.createQi1=function(){varblocks=this.blocks,x=this.x,y=this.y;switch(this.dir){case1://blocks.push({x:x,y:y});blocks.push({x:x,y:y-1});blocks.push({x:x,y:y-2});blocks.push({x:x+1,y:y-2});break;case2://blocks.push({x:x+2,y:y});blocks.push({x:x+1,y:y});blocks.push({x:x,y:y});blocks.push({x:x,y:y-1});break;case3://blocks.push({x:x+1,y:y-2});blocks.push({x:x+1,y:y-1});blocks.push({x:x+1,y:y});blocks.push({x:x,y:y});break;case4://blocks.push({x:x-2,y:y-1});blocks.push({x:x-1,y:y-1});blocks.push({x:x,y:y-1});blocks.push({x:x,y:y});break;}}//创建七字形2Model.prototype.createQi2=function(){varblocks=this.blocks,x=this.x,y=this.y;switch(this.dir){case1://blocks.push({x:x,y:y});blocks.push({x:x,y:y-1});blocks.push({x:x,y:y-2});blocks.push({x:x-1,y:y-2});break;case2://blocks.push({x:x+2,y:y-1});blocks.push({x:x+1,y:y-1});blocks.push({x:x,y:y-1});blocks.push({x:x,y:y});break;case3://blocks.push({x:x,y:y-2});blocks.push({x:x,y:y-1});blocks.push({x:x,y:y});blocks.push({x:x+1,y:y});break;case4://blocks.push({x:x,y:y});blocks.push({x:x+1,y:y});blocks.push({x:x+2,y:y});blocks.push({x:x+2,y:y-1});break;}}//创建凸字形Model.prototype.createTu=function(){varblocks=this.blocks,x=this.x,y=this.y;switch(this.dir){case1://blocks.push({x:x,y:y});blocks.push({x:x+1,y:y});blocks.push({x:x+2,y:y});blocks.push({x:x+1,y:y-1});break;case2://blocks.push({x:x,y:y});blocks.push({x:x,y:y-1});blocks.push({x:x,y:y-2});blocks.push({x:x-1,y:y-1});break;case3://blocks.push({x:x+1,y:y-1});blocks.push({x:x,y:y-1});blocks.push({x:x-1,y:y-1});blocks.push({x:x,y:y});break;case4://blocks.push({x:x,y:y-2});blocks.push({x:x,y:y-1});blocks.push({x:x,y:y});blocks.push({x:x+1,y:y-1});break;}}//变形Model.prototype.transform=function(){switch(this.type){case1://一this.transformYi();break;case2://田//无需变形break;case3://二(1)this.transformEr1();break;case4://二(2)this.transformEr2();break;case5://七(1)this.transformQi1();break;case6://七(2)this.transformQi2();break;case7://凸this.transformTu();break;}}Model.prototype.transformYi=function(){varblocks=this.blocks,block2=blocks[1];switch(this.dir){case1://横着的tran1();this.dir=2;break;case2://竖着的tran2();this.dir=1;break;}functiontran1(){//变成竖着的for(vari=0;i<blocks.length;i++){if(i==1)continue;block=blocks[i];if(i==0){block.y=block2.y+1;}elseif(i==2){block.y=block2.y-1;}elseif(i==3){block.y=block2.y-2;}//x方向改成一样block.x=block2.x;}}functiontran2(){//变成横着的for(vari=0;i<blocks.length;i++){if(i==1)continue;block=blocks[i];if(i==0){block.x=block2.x-1;}elseif(i==2){block.x=block2.x+1;}elseif(i==3){block.x=block2.x+2;}//y方向改成一样block.y=block2.y;}}}Model.prototype.transformEr1=function(){varblocks=this.blocks,block2=blocks[1];switch(this.dir){case1://竖着的tran1();this.dir=2;break;case2://横着的tran2();this.dir=3;break;case3://竖着的tran3();this.dir=4;break;case4://横着的tran4();this.dir=1;break;}functiontran1(){//变成横着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==0){block.x+=2;}elseif(i==1){block.x+=1;block.y+=1;}elseif(i==2){}elseif(i==3){block.x-=1;block.y+=1}}}functiontran2(){//竖着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==0){block.x-=1;block.y-=2;}elseif(i==1){block.y-=1;}elseif(i==2){block.x-=1;}elseif(i==3){block.y+=1}}}functiontran3(){//变成横着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==3){block.x+=2;}elseif(i==2){block.x+=1;block.y+=1;}elseif(i==1){}elseif(i==0){block.x-=1;block.y+=1}}}functiontran4(){//竖着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==3){block.x-=1;block.y-=2;}elseif(i==2){block.y-=1;}elseif(i==1){block.x-=1;}elseif(i==0){block.y+=1}}}}Model.prototype.transformEr2=function(){varblocks=this.blocks,block2=blocks[1];switch(this.dir){case1://竖着的tran1();this.dir=2;break;case2://横着的tran2();this.dir=3;break;case3://竖着的tran3();this.dir=4;break;case4://横着的tran4();this.dir=1;break;}functiontran1(){//变成横着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==0){block.x+=1;block.y-=1;}elseif(i==1){}elseif(i==2){block.x+=1;block.y+=1;}elseif(i==3){block.y+=2;}}}functiontran2(){//竖着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==0){block.x-=2;block.y-=1;}elseif(i==1){block.x-=1;}elseif(i==2){block.y-=1;}elseif(i==3){block.x+=1}}}functiontran3(){//变成横着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==3){block.x+=1;block.y-=1;}elseif(i==2){}elseif(i==1){block.x+=1;block.y+=1;}elseif(i==0){block.y+=2;}}}functiontran4(){//竖着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==3){block.x-=2;block.y-=1;}elseif(i==2){block.x-=1;}elseif(i==1){block.y-=1;}elseif(i==0){block.x+=1}}}}//七1变形Model.prototype.transformQi1=function(){varblocks=this.blocks,block2=blocks[1];switch(this.dir){case1://竖着的tran1();this.dir=2;break;case2://横着的tran2();this.dir=3;break;case3://竖着的tran3();this.dir=4;break;case4://横着的tran4();this.dir=1;break;}functiontran1(){//变成横着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==0){block.x+=2;}elseif(i==1){block.x+=1;block.y+=1;}elseif(i==2){block.y+=2;}elseif(i==3){block.x-=1;block.y+=1}}}functiontran2(){//竖着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==0){block.x-=1;block.y-=2;}elseif(i==1){block.y-=1;}elseif(i==2){block.x+=1;}elseif(i==3){block.y+=1}}}functiontran3(){//变成横着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==3){block.x+=2;}elseif(i==2){block.x+=1;block.y-=1;}elseif(i==1){}elseif(i==0){block.x-=1;block.y+=1}}}functiontran4(){//竖着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==3){block.x-=1;block.y-=2;}elseif(i==2){block.x-=2;block.y-=1;}elseif(i==1){block.x-=1;}elseif(i==0){block.y+=1;}}}}//七2变形Model.prototype.transformQi2=function(){varblocks=this.blocks,block2=blocks[1];switch(this.dir){case1://竖着的tran1();this.dir=2;break;case2://横着的tran2();this.dir=3;break;case3://竖着的tran3();this.dir=4;break;case4://横着的tran4();this.dir=1;break;}functiontran1(){//变成横着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==0){block.x+=1;block.y-=1;}elseif(i==1){}elseif(i==2){block.x-=1;block.y+=1;}elseif(i==3){block.y+=2;}}}functiontran2(){//竖着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==0){block.x-=2;block.y-=1;}elseif(i==1){block.x-=1;}elseif(i==2){block.y+=1;}elseif(i==3){block.x+=1;}}}functiontran3(){//变成横着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==3){block.x+=1;block.y-=1;}elseif(i==2){block.x+=2;}elseif(i==1){block.x+=1;block.y+=1;}elseif(i==0){block.y+=2;}}}functiontran4(){//竖着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==3){block.x-=2;block.y-=1;}elseif(i==2){block.x-=1;block.y-=2;}elseif(i==1){block.y-=1;}elseif(i==0){block.x+=1;}}}}//凸变形Model.prototype.transformTu=function(){varblocks=this.blocks,block2=blocks[1];switch(this.dir){case1://横着的tran1();this.dir=2;break;case2://竖着的tran2();this.dir=3;break;case3://横着的tran3();this.dir=4;break;case4://竖着的tran4();this.dir=1;break;}functiontran1(){//变成横着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==0){block.x+=1;}elseif(i==1){block.y-=1;}elseif(i==2){block.x-=1;block.y-=2;}elseif(i==3){block.x-=1;}}}functiontran2(){//竖着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==0){block.x+=1;block.y-=1;}elseif(i==1){}elseif(i==2){block.x-=1;block.y+=1}elseif(i==3){block.x+=1;block.y+=1}}}functiontran3(){//变成横着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==3){block.y-=1;}elseif(i==2){block.y+=1;}elseif(i==1){block.x-=1;}elseif(i==0){block.x-=2;block.y-=1}}}functiontran4(){//竖着的for(vari=0;i<blocks.length;i++){block=blocks[i];if(i==3){}elseif(i==2){block.x+=2;}elseif(i==1){block.x+=1;block.y+=1}elseif(i==0){block.y+=2;}}}}//移动Model.prototype.move=function(dir){varcur=this.game.currentModel,dis=1,blocks=this.blocks;if(dir=='r'||dir=='ld'){dis=1}elseif(dir=='l'){dis=-1;}elseif(dir=='d'){dis=3;}varstopMoveObj=this.stopMove(dir,dis),val=stopMoveObj.val,resDis=stopMoveObj.resDis;if(val){if(dir=='d'||dir=='ld'){//到底了[].push.apply(this.game.aliveModel,cur.blocks);//放到已到底的组合中this.game.renderArr.pop();//当前模型弹出this.game.clearBlock();//消除this.game.createModel();//绘制一个新图形}return;//如果返回true则不能再往这个方向移动}if(resDis>0){dis=resDis;}//更新每一个block的位置for(vari=0;i<blocks.length;i++){block=blocks[i];if(dir=='d'||dir=='ld'){block.y+=dis;}else{block.x+=dis;}}}//停止移动Model.prototype.stopMove=function(dir,dis){varcur=this.game.currentModel,blocks=this.blocks;varmaxX=this.game.maxX,maxY=this.game.maxY,res,temp;for(vari=0;i<blocks.length;i++){block=blocks[i];if(dir=='d'||dir=='ld'){if(block.y>=maxY-1){//到底了return{val:true};}}elseif(dir=='r'){if(block.x>=maxX-1){//到右边界了return{val:true};}}elseif(dir=='l'){if(block.x<=0){//到左边界了return{val:true};}}//碰撞检测temp=this.collide(block,dis,dir);if(temp.val){returntemp;}if(!res||res.resDis==0||(temp.resDis!=0&&temp.resDis<res.resDis)){res=temp;}}returnres;}//检查当前模型是否与其他存底的模型相触碰Model.prototype.collide=function(block,dis,dir){varaliveModel=this.game.aliveModel,item;varres={},val=false,resDis=0,maxY=this.game.maxY;if(dir=='r'){//向右判断for(vari=0;i<aliveModel.length;i++){item=aliveModel[i];if(!item)continue;if(item.y==block.y&&item.x==block.x+1){val=true;break;}}}elseif(dir=='l'){//向左判断for(vari=0;i<aliveModel.length;i++){item=aliveModel[i];if(!item)continue;if(item.y==block.y&&item.x==block.x-1){val=true;break;}}}else{//向下判断if(aliveModel.length>0){for(vari=0;i<aliveModel.length;i++){item=aliveModel[i];if(!item)continue;if(item.x==block.x){//下方有存在的方块if(item.y==block.y+1){val=true;break;}elseif(item.y<=block.y+Math.abs(dis)){vartemp=item.y-block.y-1;if(resDis==0||temp<resDis){resDis=temp;}}}else{//下发不存在方块if(maxY<=block.y+Math.abs(dis)){vartemp=maxY-block.y-1;if(resDis==0||temp<resDis){resDis=temp;}}}}}else{//第一个模型if(maxY<=block.y+Math.abs(dis)){vartemp=maxY-block.y-1;if(resDis==0||temp<resDis){resDis=temp;}}}}res.resDis=resDis;res.val=val;returnres;}//绘制Model.prototype.render=function(context){varctx=context;ctx.save();ctx.beginPath();//ctx.translate(this.x,this.y);varblocks=this.blocks,block,game=this.game,disX=game.disX,disY=game.disY;for(vari=0;i<blocks.length;i++){block=blocks[i];ctx.rect(block.x*disX+1,block.y*disY+1,disX-1,disY-1);}if(this.lineWidth){//线宽ctx.lineWidth=this.lineWidth;}if(this.fill){//是否填充this.fillStyle?(ctx.fillStyle=this.fillStyle):null;ctx.fill();}if(this.stroke){//是否描边this.strokeStyle?(ctx.strokeStyle=this.strokeStyle):null;ctx.stroke();}ctx.restore();returnthis;}//直线的构造functionLine(ctx,o){this.x=0,//x坐标this.y=0,//y坐标this.startX=0,//开始点x位置this.startY=0,//开始点y位置this.endX=0,//结束点x位置this.endY=0;//结束点y位置this.thin=false;//设置变细系数this.ctx=ctx;this.init(o);}Line.prototype.init=function(o){for(varkeyino){this[key]=o[key];}}Line.prototype.render=function(){innerRender(this);functioninnerRender(obj){varctx=obj.ctx;ctx.save()ctx.beginPath();ctx.translate(obj.x,obj.y);if(obj.thin){ctx.translate(0.5,0.5);}if(obj.lineWidth){//设定线宽ctx.lineWidth=obj.lineWidth;}if(obj.strokeStyle){ctx.strokeStyle=obj.strokeStyle;}//划线ctx.moveTo(obj.startX,obj.startY);ctx.lineTo(obj.endX,obj.endY);ctx.stroke();ctx.restore();}returnthis;}var_=util={//画直线drawLine:function(ctx,startX,startY,endX,endY){ctx.beginPath();ctx.moveTo(startX,startY);ctx.lineTo(endX,endY);ctx.stroke();ctx.closePath();},//获取属性值getStyle:function(obj,prop){varprevComputedStyle=document.defaultView?document.defaultView.getComputedStyle(obj,null):obj.currentStyle;returnprevComputedStyle[prop];},getRandom:function(min,max){returnparseInt(Math.random()*(max-min)+min);},//获取鼠标信息getOffset:function(e){return{x:e.offsetX,y:e.offsetY};},//循环each:function(arr,fn){varlen=arr.length;for(vari=0;i<len;i++){fn(arr[i],i);}},getDecimals:function(value){return(value!=Math.floor(value))?(value.toString()).split('.')[1].length:0;}}varclass2type={};_.each("BooleanNumberStringFunctionArrayDateRegExpObject".split(""),function(name){class2type["[object"+name+"]"]=name;});functiongetType(obj){returnobj==null?String(obj):class2type[Object.prototype.toString.call(obj)]||"undefined";}global.game=game;})(window)
以上是“怎么用JavaScript做俄罗斯方块游戏”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。