怎么用Javascript实现俄罗斯方块游戏
这篇文章主要介绍“怎么用Javascript实现俄罗斯方块游戏”,在日常操作中,相信很多人在怎么用Javascript实现俄罗斯方块游戏问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么用Javascript实现俄罗斯方块游戏”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
本俄罗斯方块代码采用 JavaScript 脚本代码写成,简单易懂;
全代码采用静态类及静态变量成员组成;
全脚本通过实现代码全局配置 OLSFK.Options = {...}
定义方块起始坐标及定义各自的旋转点;
从初始化俄罗斯方块界面开始,再监听键盘事件;以及左右,向下及旋转动作判断,重新渲染方块位置;
判断是否消行,以及相应的加级判断,执行速度,加分操作来执行;
***以判断是否当前级别大于所定义的***级别来判断是否结束;
代码说明讲解
OLSFK.Options={//相关参数width:12,//界面横向方块数height:20,//界面纵向方块数boxWidth:'16px',curLevel:1,speed:1000,//setInterval,setTimeoutdirect:{//可以设定是ASDW,还是←↓→Down:40,/*runspeed*/Left:37,Right:39,Rotate:38},Move:true,//是否正在移动Eventing:false,Levels:{1:1000,2:900,3:800,4:700,5:600,6:500,7:400,8:300,9:200,10:100},curBlock:4,//当前移动的图形名称nextBlock:0,GampMap:newObject(),Timer:null,deline:0,Score:0,Deling:false,Start:false,lineNum:10,//删除几行了,加级ScoreNum:40//消一行加分}
direct 表示 使用键盘方位键来操作方块的移动方向;
使用哪种方向键按自由喜欢配置,比如字母键的A, S, D, W; 或右边小数字键盘的数字键各自的键盘编码;
比如 上(旋转)、下、左、右 方向键的编码分别为:38、40、37、39;
Levels:表示级别配置,本配置共分为10级,每个级别所对应的下落速度,即定时执行间隔;
curBlock:表示当前活动的方块;
nextBlock:表示接下来执行的方块索引,并显示界面右上角的预览框中;
GampMap:用于保存在根据定义行列数形成的游戏表格中保存每个格的数据信息;
OLSFK.Options.GampMap[x+'_'+y]=0;
对象表格为: id: "box_"+x+"_"+y;
初始化数据为 ‘0’; 表示该表格还未占用;当有占用时,设置值为 ‘1’;
Timer:为定时执行器;setTimeout 定时执行方块下落的的频率;定时时间越小,速度越快;
Deling:当正在执行消行操作时,下次暂不显示并下落;
lineNum:表示消超过 10 行,加一级;
ScoreNum:表示每消一行所加的分数;
OLSFK.ReItems=function(cur){//key旋转点switch(cur){case1:OLSFK.Items[1]={//长块LongBlock1:{x:4,y:0},2:{x:5,y:0},3:{x:6,y:0},4:{x:7,y:0},5:{x:5,y:0}//旋转点};break;//....}}
该方法用于恢复方块的初始设置;
OLSFK.Next={//key旋转点//长块LongBlock1:{1:{x:0,y:1},2:{x:1,y:1},3:{x:2,y:1},4:{x:3,y:1}},//...}
为不了不与游戏方块的设置冲突,独立出来下次随机方块的对象配置;
OLSFK.Items={//key旋转点//长块LongBlock1:{1:{x:4,y:0},2:{x:5,y:0},3:{x:6,y:0},4:{x:7,y:0},5:{x:5,y:0}},//方块Box2:{1:{x:4,y:0},2:{x:5,y:0},3:{x:4,y:1},4:{x:5,y:1},5:{x:0,y:0}},//凸块TuBlock3:{1:{x:4,y:1},2:{x:5,y:0},3:{x:5,y:1},4:{x:6,y:1},5:{x:5,y:1}},//L块LBlock4:{1:{x:5,y:0},2:{x:5,y:1},3:{x:5,y:2},4:{x:6,y:2},5:{x:5,y:2}},5:{//反向L块FLBlock1:{x:5,y:2},2:{x:6,y:2},3:{x:6,y:1},4:{x:6,y:0},5:{x:6,y:2}},//Z块ZBlock6:{1:{x:4,y:0},2:{x:5,y:0},3:{x:5,y:1},4:{x:6,y:1},5:{x:5,y:0}},7:{//反向Z块FZBlock1:{x:4,y:1},2:{x:5,y:1},3:{x:5,y:0},4:{x:6,y:0},5:{x:5,y:1}}}
方块共分为:长条块,方块,凸块(T块),L块,反L块,Z块,反Z块几种;
共7种方块,以1,2,3,4,5,6,7 索引键表示,方块是四个小块组成,每块都有各自的坐标,1-4表示组成该块的初始坐标位置,5表示旋转点;
OLSFK.Init=function(){//初始化界面//...}
俄罗斯方块的界面初始化方法;将在 window.onload 中调用执行;
varw=OLSFK.Options.width;varh=OLSFK.Options.height;vartotal=w*h;varx=0,y=0;for(vari=0;i<total;i++){OLSFK.Options.GampMap[x+'_'+y]=0;Lib.Tag('SPAN',{id:"box_"+x+"_"+y,name:"cbox",style:{width:OLSFK.Options.boxWidth,height:OLSFK.Options.boxWidth,border:"2pxoutset#669",background:"#ddd",float:"left",overflow:"hidden"},innerHTML:" ",className:"cssbox"},back);varend=i+1;x++;if(end>=w&&end%w==0){x=0;y++;Lib.Tag('DIV',{style:{clear:"both"}},back);}}
通过设置的 Options.width, Options.height 列数与行数,以及设置的小方格宽度,初始化了一个宽:Options.width列,高为 Options.height 的表格界面出来;
Lib.Tag 用于创建标签对象;
Lib.Tag=function(TAG,json,pnode){//...}
TAG为标签名,比如: div, span 等;
json为设置标签样式 style;
pnode 是该创建所在的父容器;
OLSFK.Init = function() {} 还创建主游戏区域旁边的下次随机方块预览区,当前级别,及分数,以及操作“开始”,“暂停”按钮等;
游戏初始入口点
window.onload=function(){if(window.isIE){document.attachEvent("onkeydown",function(e){if(OLSFK.Options.Start){varE=OLSFK.KeyCode();OLSFK.EventFunc(E);}});document.attachEvent("onkeyup",function(e){if(!OLSFK.Options.Move&&OLSFK.Options.Start){OLSFK.Options.Move=true;OLSFK.Options.Eventing=false;OLSFK.Options.Timer=setTimeout(function(){OLSFK.play();},OLSFK.Options.Levels[OLSFK.Options.curLevel]);}});}else{document.addEventListener("keydown",function(e){if(OLSFK.Options.Start){varE=OLSFK.KeyCode();OLSFK.EventFunc(E);}},false);document.addEventListener("keyup",function(e){if(!OLSFK.Options.Move&&OLSFK.Options.Start){OLSFK.Options.Move=true;OLSFK.Options.Eventing=false;OLSFK.Options.Timer=setTimeout(function(){OLSFK.play();},OLSFK.Options.Levels[OLSFK.Options.curLevel]);}},false);}OLSFK.Init();}
主要是监听键盘事件,根据 键盘事件 返回的按钮编码与 OLSFK.Options.direct 设置方向键匹配来操作方块的移动,旋转等;
keydown 用于操作下落方块的移动方向,旋转等;并重新绘制方块位置;
keyup 后继续按本级速度向下落;
OLSFK.Options.Levels[OLSFK.Options.curLevel]
表示当前级别对应的速度,即定时器间隔执行时间(毫秒);
OLSFK.EventFunc=function(code){switch(code){caseOLSFK.Options.direct.Left://LEFTif(!OLSFK.Options.Deling){clearTimeout(OLSFK.Options.Timer);OLSFK.Options.Eventing=true;OLSFK.Options.Move=false;OLSFK.Left();}break;//...}}
该方法是 监听 keydown 事件执行的动作;code 为按键 编码;
当判断未在消行动作时,清除定时器,OLSFK.Options.Eventing 设置为事件中 true,OLSFK.Options.Move 为 false 表示停止移动;
进入 向左移动方法 OLSFK.Left();
OLSFK.Left=function(){varblock=OLSFK.Items[OLSFK.Options.curBlock];if(block){varflag=true;for(vari=1;i<=4;i++){varx=block[i].x;vary=block[i].y;if(x-1<0){flag=false;break;}if(OLSFK.Options.GampMap[(x-1)+'_'+y]==1&&!OLSFK.isMe(x-1,y)){flag=false;break;}}if(flag){for(vari=1;i<=4;i++)//清除图形{varitm=block[i];varbox=Lib.Getid('box_'+itm.x+'_'+itm.y);box.style.background='#ddd';OLSFK.Options.GampMap[itm.x+'_'+itm.y]=0;}for(vari=1;i<=5;i++){varx=block[i].x;vary=block[i].y;OLSFK.Items[OLSFK.Options.curBlock][i]={x:(x-1),y:y};}OLSFK.draw();}}}
var block = OLSFK.Items[OLSFK.Options.curBlock]; 表示获取当前移动方块;
if(OLSFK.Options.GampMap[(x-1)+'_'+y]==1&&!OLSFK.isMe(x-1,y)){flag=false;break;}
判断该方块四个小方块左边是否有被占用的方块,也即:OLSFK.Options.GampMap[(x-1)+'_'+y] 为 1; 并且该位置块不属于方块自己的;
当左边方向无占用格时,清除当前方块四个小方块位置,重新绘制方块新坐标位置;并重置 相应的 OLSFK.Options.GameMap [x+y] 相应格的值;
当按钮 keyup 时,继承正常向下落;
OLSFK.isMe 代码:
OLSFK.isMe=function(x,y){varblock=OLSFK.Items[OLSFK.Options.curBlock];if(block){for(vari=1;i<=4;i++){if(block[i].x==x&&block[i].y==y){returntrue;}}}returnfalse;}
即指定的 x,y (参数值) 是否还在当前方块四个坐标内;
OLSFK.Right () 与 Left() 一样;
旋转方块代码;
OLSFK.Rotate=function(){varblock=OLSFK.Items[OLSFK.Options.curBlock];if(block){varflag=true;varR=block[5];for(vari=1;i<=4;i++){varx=block[i].x;vary=block[i].y;if(R.x==x&&R.y==y){}else{varnson=newObject();nson.x=R.x+R.y-y;nson.y=R.y-R.x+x;if(nson.x<0||nson.y<0||nson.x>=OLSFK.Options.width||nson.y>=OLSFK.Options.height){flag=false;break;}if(OLSFK.Options.GampMap[nson.x+'_'+nson.y]==1&&!OLSFK.isMe(nson.x,nson.y)){flag=false;break;}}}if(flag){for(vari=1;i<=4;i++)//清除图形{varitm=block[i];varbox=Lib.Getid('box_'+itm.x+'_'+itm.y);box.style.background='#ddd';OLSFK.Options.GampMap[itm.x+'_'+itm.y]=0;}varPnt=1;for(vari=1;i<=4;i++){varx=block[i].x;vary=block[i].y;if(R.x==x&&R.y==y){Pnt=i;}else{varnson=newObject();nson.x=R.x+R.y-y;nson.y=R.y-R.x+x;OLSFK.Items[OLSFK.Options.curBlock][i]={x:nson.x,y:nson.y};}}OLSFK.Items[OLSFK.Options.curBlock][5]=OLSFK.Items[OLSFK.Options.curBlock][Pnt];OLSFK.draw();}}}
var R = block[5]; 就是获取旋转点;
就开始对方块四个小块以旋转点为中心,逆时针旋转(并不全是 90 度);当当前块不为旋转点时,旋转公式;
varnson=newObject(); nson.x=R.x+R.y-y; nson.y=R.y-R.x+x;
这个公式要这样看;
ResultX=RotateX+(RotateY-CurrentY); ResultY=RotateY-(RotateX-CurrentX);//Y的偏移量,就是X的增加值;//反之同
当旋转四周都无占用物时;清除当前图形,重绘旋转后的图形位置;
重置OLSFK.Options.GampMap[itm.x+'_'+itm.y] 各个方块的占用值;
OLSFK.Random=function(){if(OLSFK.Options.nextBlock!=0){OLSFK.Options.curBlock=OLSFK.Options.nextBlock;varblock=OLSFK.Next[OLSFK.Options.nextBlock];if(block){for(vari=1;i<=4;i++){varitm=block[i];varbox=Lib.Getid('cur_'+itm.x+'_'+itm.y);box.style.background='#ddd';//OLSFK.Options.GampMap[itm.x+'_'+itm.y]=0;}}}else{OLSFK.Options.curBlock=Math.floor(Math.random()*7+1);}OLSFK.Options.nextBlock=Math.floor(Math.random()*7+1);OLSFK.drawNext();}
随机生成下次预下落的方块;并显示到右上角的预览表格里;
OLSFK.play=function(speed){varblock=OLSFK.Items[OLSFK.Options.curBlock];if(block&&OLSFK.Options.Move){varflag=true;for(vari=1;i<=4;i++){varx=block[i].x;vary=block[i].y;if(y+1>=OLSFK.Options.height){flag=false;break;}if(OLSFK.Options.GampMap[x+'_'+(y+1)]==1&&!OLSFK.isMe(x,y+1)){flag=false;break;}}if(flag){for(vari=1;i<=4;i++)//清除图形{varitm=block[i];varbox=Lib.Getid('box_'+itm.x+'_'+itm.y);box.style.background='#ddd';OLSFK.Options.GampMap[itm.x+'_'+itm.y]=0;}for(vari=1;i<=5;i++){varx=block[i].x;vary=block[i].y;OLSFK.Items[OLSFK.Options.curBlock][i]={x:x,y:(y+1)};}OLSFK.draw();varS=OLSFK.Options.Levels[OLSFK.Options.curLevel];if(speed){S=50;}OLSFK.Options.Timer=setTimeout(function(){OLSFK.play();},S);}else{OLSFK.ReItems(OLSFK.Options.curBlock);OLSFK.newRun();}}}
OLSFK.play 正常下落的方法,也得判断下落一格是否有被占用的格,如果没有,清除当前方块,绘制方块新位置;
当方块不能再下落时(flag = false),重置当前方块坐标配置; OLSFK.ReItems(OLSFK.Options.curBlock);
进入 OLSFK.newRun(); 新下落方块下落过程准备;
OLSFK.newRun=function(){clearTimeout(OLSFK.Options.Timer);OLSFK.DelFunc();if(OLSFK.Options.deline>=10){OLSFK.Options.deline=0;OLSFK.Options.curLevel++;OLSFK.Element.CurLevel.setHTML("级:"+OLSFK.Options.curLevel);}OLSFK.Element.Score.setHTML("分:"+OLSFK.Options.Score);if(OLSFK.Options.curLevel<=OLSFK.Options.lineNum){OLSFK.Random();//判断是否结束OLSFK.ChkEnd();}else{OLSFK.Options.Move=false;OLSFK.Options.Start=false;OLSFK.Options.Eventing=false;OLSFK.Options.Deling=false;Lib.Getid('spn').innerHTML='GameIsOver!YouWintheGame!';Lib.Getid('dobtn').innerHTML='开始';}}
当下落结束时,清除定时器,暂停新方块下落,检测是否有可消除的行;减了多少行;
每减去一行 加分OLSFK.Options.Score += OLSFK.Options.ScoreNum;
这个方法在 :
OLSFK.DelFunc=function(){OLSFK.Options.Deling=true;OLSFK.Options.Move=false;OLSFK.Options.Eventing=false;varFn=0;for(vari=OLSFK.Options.height-1;i>=0;i--){Fn=0;for(varj=0;j<OLSFK.Options.width;j++){if(OLSFK.Options.GampMap[j+'_'+i]==1){Fn++;}}if(Fn==OLSFK.Options.width){OLSFK.Options.deline++;OLSFK.Options.Score+=OLSFK.Options.ScoreNum;OLSFK.DelLine(i);i++;}}OLSFK.Options.Deling=false;OLSFK.Options.Move=true;OLSFK.Options.Eventing=true;}
中执行;
减完一行,就重置该行以上所有行往下降一行;并重置 :
OLSFK.Options.GampMap[x+'_'+y] = OLSFK.Options.GampMap[x+'_'+(y-1)];
该减行为上行的数据;
if(Fn==OLSFK.Options.width){OLSFK.Options.deline++;OLSFK.Options.Score+=OLSFK.Options.ScoreNum;OLSFK.DelLine(i);i++;}
该判断表示该行上所有格都被占用到;
回到 newRun 上,当判断消行超过几行时,即加级;
if(OLSFK.Options.curLevel<=OLSFK.Options.lineNum) { OLSFK.Random();//判断是否结束OLSFK.ChkEnd(); }
如果级数小于配置的总级数,则进入 OLSFK.random();
设置当前下落方块,并随机生成下次下落方块并预览右上角表格上;
OLSFK.ChkEnd=function(){varblock=OLSFK.Items[OLSFK.Options.curBlock];if(block&&OLSFK.Options.Move){varflag=true;for(vari=1;i<=4;i++){varx=block[i].x;vary=block[i].y;if(OLSFK.Options.GampMap[x+'_'+y]==1){flag=false;break;}}}if(flag){OLSFK.draw();//定时往下掉OLSFK.Options.Timer=setTimeout(function(){OLSFK.play();},OLSFK.Options.Levels[OLSFK.Options.curLevel]);}else{OLSFK.Options.Move=false;OLSFK.Options.Start=false;OLSFK.Options.Eventing=false;OLSFK.Options.Deling=false;Lib.Getid('spn').innerHTML='GameIsOver';Lib.Getid('dobtn').innerHTML='开始';}}
当当前下落的方块进入表格上有被占用的格子,即被卡住,游戏结束;
反之 则 setTimeout 开始新方块的下落动作;
其他方法说明
OLSFK.Event=function(){if(window.isIE)returnwindow.event;func=OLSFK.Event.caller;while(func!=null){vararg0=func.arguments[0];if(arg0){returnarg0;}func=func.caller;}returnnull;}OLSFK.KeyCode=function(){returnOLSFK.Event().keyCode||OLSFK.Event().which;}
OLSFK.Event = function();
这是一种获取当前事件的方法,可以比较兼容获取当前的事件;
俄罗斯方块 JavaScript 代码
http://files.cnblogs.com/editor/OLSFK.rar
到此,关于“怎么用Javascript实现俄罗斯方块游戏”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注恰卡编程网网站,小编会继续努力为大家带来更多实用的文章!
推荐阅读
-
JavaScript闭包用多会造成内存泄露吗
-
javascript中文乱码如何解决
-
PHP学习第十五天——JavaScript入门DOM对象:二
-
Node.js基本内容和知识点
简单的说node.js就是运行在服务端的JavaScript,起初段定位是后端开发语言,由于技术的不够成熟,一般小型项目...
-
PHP与Node.js:一个史诗般开发者的分享
-
JavaScript 中 find() 和 filter() 方法的区别
JavaScript在ES6上有很多数组方法,每种方法都有独特的用途和好处。在开发应用程序时,大多使用数组方法来获...
-
js怎么跟php结合使用
-
简单说说Node.js和JavaScript
Node.js是一个开源和跨平台的JavaScript运行时环境,在浏览器之外运行V8JavaScript引擎(...
-
前端开发工程师专业技能简历范文
-
JavaScript怎么实现淘宝网图片的局部放大功能