JavaScript俄罗斯方块游戏开发

俄罗斯方块游戏,童年的回忆呀,相信大家都有玩过,今天我就带大家来讲解一下前端开发网页俄罗斯方块的开发方法。

这个游戏效果开发的代码多数重点在于JavaScript,在JavaScript的算法运用非常重要。

话不多说,打开编辑器,开始撸代码吧

这里声明一个对象存储俄罗斯方块的地图(或者游戏场地更为合适?)

eval的功能是把字符串变成实际运行时的JavaScript代码

这里代码变换之后相当于 var map = [0x801, 0x801, 0x801, 0x801, 0x801, 0x801, 0x801, 0x801, 0x801, 0x801, 0x801, 0x801, 0x801, 0x801, 0x801, 0x801, 0x801, 0x801, 0x801, 0x801, 0x801, 0x801, 0xfff];

声明一个锯齿数组存储7种俄罗斯方块的图案信息

俄罗斯方块在不同的旋转角度下会产生不同的图案,当然可以通过算法实现旋转图案生成,这里为了减少代码复杂性直接给出了不同旋转状态下的图案数据

很明显,第一个0x6600就是7种俄罗斯方块之中的正方形方块

0x6600二进制分四行表示如下:0110、0110、0000、0000

这就是正方形图案的表示,可以看出,这里统一采用一个16位数来存储4 * 4的俄罗斯方块图案

因为正方形图案旋转不会有形状的改变,所以此行只存储了一个图案数据

一个按键对象,存储的是按键键值(上,下,左,右)和函数之间的调用映射关系,之后通过eval可以做好调用映射

声明4个对象后面调用

dia存储选取的俄罗斯方块类型(一共七种俄罗斯方块类型)

pos是前台正在下落的俄罗斯方块图案(每一种俄罗斯方块类型有属于自己的图案,如果不清楚可以查看上文的锯齿数组)对象

bak里存储关于pos图案对象的备份,在需要的时候可以实现对于pos运动的撤销

run就是游戏开始执行

start()函数

在游戏场景上方产生一个新的俄罗斯方块

random产生0~6的随机数,~运算符在JavaScript依然是位取反运算,隐式实现了浮点数到整形的转换,这是一个很丑陋的取整实现方式,其作用是在七种基本俄罗斯方块类型之中随机选择一个

pos和bak两个对象分别为前后台,实现俄罗斯方块运动的备份和撤销,然后在特定的俄罗斯方块类型之中随机选择一个具体的图案

新生的俄罗斯方块不旋转,所以这里rotate参数为0

rotate()旋转函数,这里做的处理只不过是旋转旋转之后的俄罗斯方块具体图案,之后进行移位,根据X坐标把位置移动到场景里对应的地点

这里是根据输入的实参旋转参数 r 选择具体的俄罗斯方块图案,这里的 f ,就是上文之中的十六进制数

再把当前pos.s的值和r(也就是旋转角度)相加,最后和dia.length求余,实现了旋转循环

最后update更新场景

这是一个判断函数,判断有没有重叠

把俄罗斯方块图案每一行的二进制位与场景内的二进制位进行对比,如果结果非0的话,那么这就证明图案和场景之中的实体(比如墙或者是已经落底的俄罗斯方块)重合了

既然重合了,那么之前的运动就判断为非法的,所以在这个if语句里面调用之前备份的bak实现对于pos的恢复

如果没有重合,那么这里默认返回空

update函数,用于绘制场景的字符串并且写入到div之中完成游戏场景的更新

把pos备份到bak之中,slice(0)意为从0号开始到结束的数组,也就是全数组,这里不能直接赋值,否则只是建立引用关系,起不到数据备份的效果

第一个for循环,实现的是对于字符串的替换处理,就是把原始的01字符串转换成为方块字符串

第二个for循环,处理的是正在下落的俄罗斯方块的绘制,□是空格方块,这里也是隐式使用正则表达式

■是黑色方块  是空,这里实现的是替换div之中的文本,由数字替换成为两种方块或者空白

俄罗斯方块下落函数

pos就是当前的(前台)俄罗斯方块,这里y坐标++,就相当于下落

和实体场景进行位或并且赋值,如果最后赋值结果为0xfff,也就说明当前行被完全填充了,可以消行

首行添加,unshift的作用是在数组第0号元素之前添加新元素,新的元素作为数组首元素

如果最上面一行不是空了,俄罗斯方块垒满了,则游戏结束

如果是空的,重新产生下一个俄罗斯方块

move左右移动函数,t参数只能为2或者是0.5

这样实现左移右移(相当于移位运算)的方法很简陋,但是为了简短只能这样了

*=t在这里实现了左右移1位赋值的功能

左右移之后调用update更新,这里同样进行了重合判断,如果和左右墙重合的话,那么一样会撤销操作并且不更新场景

设置按键事件映射,这样按下键的时候就会触发对应的事件,具体来说就是触发对应的move,只有2和0.5

eval生成的JavaScript代码,在这里就被执行了

最后,开始游戏,执行设置俄罗斯方块下落定时器,500毫秒触发一次,调节这里的数字可以调整游戏之中俄罗斯方块下落的快慢

就这样,开发俄罗斯方块的代码就完成了

这这时可以运行玩一下

最后,全部实现代码整合如下:

<!doctype html> <html><head><title>俄罗斯方块</title> <div id="box" style="margin: 20px auto; text-align:center; width:252px;font:25px/25px 宋体;background:#FFF;color:#000;border:#999;"></div> <script> var author="LiJiaJing ",ContactAuthor=1853802745; var map=eval("\["+Array(23).join("0x801,")+"0xfff\]"); var tatris=\[\[0x6600\],\[0x2222,0xf00\],\[0xc600,0x2640\],\[0x6c00,0x4620\],\[0x4460,0x2e0,0x6220,0x740\],\[0x2260,0xe20,0x6440,0x4700\],\[0x2620,0x720,0x2320,0x2700\]\]; var keycom={"38":"rotate(1)","40":"down()","37":"move(2,1)","39":"move(0.5,-1)"}; var dia, pos, bak, run; function start(){ dia=tatris\[~~(Math.random()\*7)\]; bak=pos={fk:\[\],y:0,x:4,s:~~(Math.random()\*4)}; rotate(0); } function over(){ document.onkeydown=null; clearInterval(run); alert("GAME OVER"); } function update(t){ bak={fk:pos.fk.slice(0),y:pos.y,x:pos.x,s:pos.s}; if(t) return; for(var i=0,a2=""; i<22; i++) a2+=map\[i\].toString(2).slice(1,-1)+"<br/>"; for(var i=0,n; i<4; i++) if(/(\[^0\]+)/.test(bak.fk\[i\].toString(2).replace(/1/g,"□"))) a2=a2.substr(0,n=(bak.y+i+1)\*15-RegExp.$\_.length-4)+RegExp.$1+a2.slice(n+RegExp.$1.length); document.getElementById("box").innerHTML=a2.replace(/1/g,"■").replace(/0/g," "); } function is(){ for(var i=0; i<4; i++) if((pos.fk\[i\]&map\[pos.y+i\])!=0) return pos=bak; } function rotate(r){ var f=dia\[pos.s=(pos.s+r)%dia.length\]; for(var i=0; i<4; i++) pos.fk\[i\]=(f>>(12-i\*4)&15)<<pos.x; update(is()); } function down(){ ++pos.y; if(is()){ for(var i=0; i<4 && pos.y+i<22; i++) if((map\[pos.y+i\]|=pos.fk\[i\])==0xfff) map.splice(pos.y+i,1), map.unshift(0x801); if(map\[1\]!=0x801) return over(); start(); } update(); } function move(t,k){ pos.x+=k; for(var i=0; i<4; i++) pos.fk\[i\]\*=t; update(is()); } document.onkeydown=function(e){ eval(keycom\[(e?e:event).keyCode\]); }; var author="LiJiaJing ",ContactAuthor ="学习联系1853802745"; start(); run=setInterval("down()",400); </script></body></html>

订阅ID:qdkfmiji

咨询QQ:1853802745

☆学习是一种信仰

☆国内最具影响力在线教育学院

本文分享自微信公众号 - 前端研究所(WEBqdyjs)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )