最近有朋友找我用js帮忙仿做一个别踩白块的小游戏程序,但他给的源代码较麻烦,而且没有注释,理解起来很无力,我就以自己的想法自己做了这个小游戏,主要是应用js对dom和数组的操作。
程序思路:如图:将游戏区域的css设置为相对定位、溢出隐藏;两块“游戏板”上分别排布着24块方格,黑色每行随机产生一个,“游戏板”向下滚动并交替显示,将每个操作板的黑块位置存入数组,每次点击时将数组pop出来进行比对(我觉得亮点在这……)。
这里是游戏的github地址,大家可以到里点击中部菜单最右边的的download zip按钮下载到桌面一试,html和js,无需服务器。
下载地址
以下是具体实现,关键部分有注释。
html部分:
别踩白块
//初始化一个boardb,使ab同时存在
css部分:
复制代码 代码如下:
*{margin: 0px;padding: 0px;box-sizing: border-box;} //简单的reset一下,并用box-sizing设置盒子尺寸将边框也计算进去,便于后面计算小方块位置
#gamezone{width: 302px;height: 602px;border: 1px solid green;margin: 20px auto;position: relative;overflow: hidden;} //游戏区域,多两个像素是为了除去边框外还有足够的300*600的空间
.square{width: 75px;height: 100px;float: left;border: 1px solid black;}
.squareblack{width: 75px;height: 100px;border: 1px solid black;float: left;background: black;}//每个小方块为75*100,并且设置黑色小方块的背景色。
js部分:
这里分函数介绍:
全局变量初始化
var loc=600;//黑块落地失败判定var count=0;//初始化击中黑块总数var locarr=[];//初始化游戏板上黑块位置的var order=(function(){var ord=a;return function(){if(ord=='boarda')ord='boardb';else ord='boarda';return ord;}})()
//用闭包函数使每次创建的游戏板的id为boarda与boardb,其实用一个全局变量也行,不过为了有点逼格。。。
每次点击判定结果的函数
function judge(){var num=this.id.substr(3)//获取元素的id号if(num!=locarr.pop()){ //与位置数组pop出的对比cleartimeout(timer);alert(你的得分为:+count+分!);return; //失败清除定时器,结算分数。}else{loc+=100; this.style.background=silver;count+=1;//成功将落地标志加方格的高度,将方格背景色改变一下,击中数+1}if(count!=0&&count%15==0){cleartimeout(timer);newtimer=50-count/15*5;timer=setinterval('fall()',newtimer);}//每击中15个后将速度加快一点,这个式子可自行定义。}
产生大框中小黑框位置的随机数,每次创建游戏板时调用此函数,根据产生数定义小黑块的位置
function generaterand(){var numarr=[];for(var j=0;j<6;j++){var num=math.floor(math.random()*4)+j*4;numarr.push(num);}return numarr;}
每次调用在游戏区域的上方生成一个待往下滚动的游戏板,并将其黑色的部分的数字push进locarr中
function drawboard(){var temarr=generaterand();//这里应用一个临时的位置数组,为了防止两块游戏板之间的位置冲突。locarr=temarr.concat(locarr);//将临时数组相连到全局位置数组中var board=document.createelement('div');board.setattribute('id',order());board.style.position=absolute;board.style.top='-600px';for(var i=0;i-1){ //判断当前创建的小方块的id序列是否属于临时位置数组ele.setattribute('class','squareblack')}else{ele.setattribute('class','square');}ele.addeventlistener('click',judge,false); //给每一个小方格添加点击判定函数judgeboard.appendchild(ele);}var gamezone=document.getelementbyid('gamezone');gamezone.appendchild(board);}
找到脚本中存在的两个游戏板,使其往下滚动
function fall(){gamezone=document.getelementbyid('gamezone');var boarda=document.getelementbyid('boarda');//因为ab两个游戏板全局一直存在,所以不需要定义找不到时的逻辑var anowtop=parseint(boarda.style.top);//因为获取到的top位置是xxxpx类型,所以用一个parseint()将其转换为整数便于处理。if(anowtop==595){ //这里数目为595而不是600是因为在这一帧删除后,下一帧正好600px,刚好使两块游戏板衔接完好。gamezone.removechild(boarda);drawboard();//删除游戏区域的游戏板,并在最上方新生成一个。}anowtop+=5;boarda.style.top=anowtop+px;var boardb=document.getelementbyid('boardb');var bnowtop=parseint(boardb.style.top);if(bnowtop==595){gamezone.removechild(boardb);drawboard();}bnowtop+=5;boardb.style.top=bnowtop+px;loc-=5;if(loc==0){cleartimeout(timer);alert(你的得分为:+count+分!);return;} //每一帧将落地判定减5,当落地判定为0时表示落地,结算分数。}
将主体调用写在window.onload函数里,使得页面的游戏区域加载完成后再调用函数。
window.onload=function(){drawboard();fall();var timer=setinterval('fall()',50);}
游戏扩展:
增加页面ui:因为一开始的html特别简单,所以ui也很好修改,设置按钮,点击触发开始函数。
改变游戏难度:修改setinterval的值,也可以对judge函数内的间隔数目进行修改,或将下落加速的表达式优化一下。
增加比分排行等:用ajax连接服务器,在游戏结束后将结果写入数据库,并引用数据中的排行榜。
改为街机模式:去除定时,修改judge函数,使其每次点击游戏板下落一个小方格的高度。设置总数,开始计时,结束计时。