怎么用JavaScript做俄罗斯方块游戏(javascript,开发技术)

时间:2024-05-02 19:58:52 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

最终游戏效果

怎么用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>

框架效果如下:

怎么用JavaScript做俄罗斯方块游戏

添加内部画布,以及绘制地图

首先创建线的构造函数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();//渲染 }

此时游戏区域的格子以及绘制如下:

怎么用JavaScript做俄罗斯方块游戏

再来绘制模型

模型定义:分别是一字形、田字形、二字形2种、七字形2种、凸字形等共7种。

怎么用JavaScript做俄罗斯方块游戏

变形定义: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来区分,怎么摆放)

//创建七字形1 Model.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来修改就行)

怎么用JavaScript做俄罗斯方块游戏 ------------------------ >>>怎么用JavaScript做俄罗斯方块游戏

左边这个图形要变成右边的图形,需要怎么变更呢?

怎么用JavaScript做俄罗斯方块游戏-------------------->>> 怎么用JavaScript做俄罗斯方块游戏

标上号码就很容易明白,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://w case38://上 that.currentModel.transform();//变形 break; case83://s case40://下 that.currentModel.move('d');//移动 break; case65://a case37://左 that.currentModel.move('l');//移动 break; case68://d case39://右 that.currentModel.move('r');//移动 break; } //测试用,记得删除 that.render(); }); }

接下来变形试试

怎么用JavaScript做俄罗斯方块游戏

添加移动方法

//移动 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; }

怎么用JavaScript做俄罗斯方块游戏

到底后的处理

怎么用JavaScript做俄罗斯方块游戏

  1. 给当前的游戏对象的aliveModel数组,存取当前到底的模型所对应的4个小方块(执行render方法的时候就绘制出来)

  2. 在renderArr数组中此模型要删除

  3. 每次触底需要加入消除判断,符合条件就消除

  4. 绘制一个新的模型

绘制触底的模型方块

//绘制存底的图形 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://w case38://上 that.currentModel.transform();//变形 break; case83://s case40://下 that.currentModel.move('d');//移动 break; case65://a case37://左 that.currentModel.move('l');//移动 break; case68://d case39://右 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({//创建二字1 x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:3,dir:4 }); model=newModel({//创建二字2 x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:4,dir:1 }); model=newModel({//创建七字1 x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:5,dir:4 }); model=newModel({//创建七字2 x: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();//创建字二形1 break; case4: this.createEr2();//创建二字形2 break; case5: this.createQi1();//创建七字形1 break; case6: this.createQi2();//创建七字形2 break; 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; } } //创建二字形1 Model.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; } } //创建二字形2 Model.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; } } //创建七字形1 Model.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; } } //创建七字形2 Model.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)
 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:怎么用JavaScript做俄罗斯方块游戏的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:JavaScript如何使用For实现循环语句下一篇:

16 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18