您的位置:首页 > Web前端 > JavaScript

(难度:40%)纯js的俄罗斯方块游戏(含源码)

2014-06-06 23:27 489 查看
第一次写这么大的js程序, 代码量首破300的页面, 而且是纯js, 没用到任何库或框架...

断断续续写了四天终于弄好了, 除了觉得自己通过这个游戏, js进步了不少之外, 还培养了自己对代码的控制. 虽然没用到面向对象, 但我严格要求自己, 90%以上的函数不带注释不能超过10行, 一来易写而来容易更新维护.

html文件:

<body>
<div id='game'>
<div id='main'></div>
<div id='count'>
<h3>Sorce:</h3>
<div id='sorce'>0</div>
<h3>Next:</h3>
<div id='next'></div>
<div id='panel'>
<div class='button'><a href="#">START</a></div>
<div class='button'><a href="#">STOP</a></div>
</div>
</div>
</div>


css文件

#game{
margin:50px auto;
width: 960px;
}
#main{
border:3px solid black;
float: left;
}
#count{
width: 120px;
height: 190px;
padding: 5px 20px 10px 20px;
float: right;
border:3px solid black;
}
#next{
width: 60px;
height: 60px;
text-align: center;
}
#panel{
width: 120px;
height:205px;
margin-top: 20px;
padding: 5px 20px 10px 20px;
border:3px solid black;
float: right;
margin-right: -23px;
}
.cell{
background: white;
float: left;
width: 20px;
height: 20px;
}
._cell{
background: white;
float: left;
width: 15px;
height: 15px;
}
.button{
position: relative;
margin-top: 20px;
width: 120px;
height:40px;
border-radius: 10px;
background: black;
text-align: center;
line-height: 40px;
text-decoration: none;
cursor:pointer;
}
.button:hover{
background: orange;
}
.button a{
text-decoration: none;
color: white;
}


js文件

var row   = 24,
col   = 12,
len   = 20,
game  = document.getElementById('game'),
main  = document.getElementById('main'),
count = document.getElementById('count'),
next = document.getElementById('next'),
sorce = document.getElementById('sorce'),
_sorce= 0,
nextb = 0,
nextn = 0,
width = col*len,
height= row*len,
map   = [],
_map  = [],
bak   = [],
cur   = [],
timer = null,
cells = null,
_cells= null,
mark  = 0,
color = '#0cf',
_color= 'orange',
block = [[0x3300,0x3300,0x3300,0x3300],[0x3110,0x1700,0x2230,0x7400],
[0xf000,0x1111,0xf000,0x1111],[0x3220,0x7100,0x1130,0x4700],
[0x1320,0x6300,0x1320,0x6300],[0x2310,0x3600,0x2310,0x3600],
[0x2700,0x2320,0x7200,0x2620]];

init();
newBlock();
function start(e){
// event.preventDefault();
timer=setInterval(down,400);
}
function stop(e){
// event.preventDefault();
clearInterval(timer);
}
function init(){
var tmp;

main.style.width=width+"px";
main.style.height=height+"px";
game.style.width=width+200+"px";
game.style.height=height+"px";

cur={x:~~Math.random()*(col-8)+4,	//到右边的距离
y:-1,
b:~~(Math.random()*7),	//block编号
n:~~(Math.random()*4),}	//block状态
//新的方块
nextb=~~(Math.random()*7);
//新的状态
nextn=~~(Math.random()*4);
//不能连写
//document.createElement('div').cloneNode
var _cell=document.createElement('div');
_cell.className="_cell";
for (var i=0;i<4;i++)
for (var j=0;j<4;j++){
tmp=_cell.cloneNode(true)
next.appendChild(tmp);
// _cells.push(tmp)
}
_cells=document.querySelectorAll('._cell');
showNext();

var cell=document.createElement('div');
cell.className="cell";
for (var i=0;i<row;i++){
for (var j=0;j<col;j++){
tmp=cell.cloneNode(true);
tmp.id=i*row+j;
main.appendChild(tmp);
//Cannot call method 'push' of null
// cells.push(tmp);
}
}
cells=document.querySelectorAll(".cell");
//每行都初始化为100..001
//首尾为1是为了判断边界
//最后一行初始化为全1
var tmp="1"
for (var i=0;i<col;i++) tmp+='0';
tmp+='1'
mark=tmp=parseInt(tmp,2);
for (var i=0;i<row;i++){
map[i]=tmp;
}
tmp="1";
for (var i=1;i<col+2;i++) tmp+='1';
map[row]=parseInt(tmp,2);

document.onkeydown=function(e){
e=e?e:event;
// console.log(e.keyCode)
switch (e.keyCode){
case 37:move(1);break;	//左
case 38:rotate();break;	//上
case 39:move(-1);break;	//右
case 40:down();break;	//下
case 32:down();break;	//空格
}
}

tmp=document.querySelectorAll('.button');
tmp[0].onclick=start;
tmp[1].onclick=stop;

}
function newBlock(){
cur={
x:~~(Math.random()*(col-8)+4),
y:0,
b:nextb,	//block编号
n:nextn		//block状态
}
nextb=~~(Math.random()*7);
nextn=~~(Math.random()*4);
showNext();
bak={
x:cur.x,
y:0,
b:cur.b,
n:cur.n
}
update();
}
function down(){
if (isOver()){
return
}
cur.y++;
if (!canDown()){
//更新视图
for (var i=0;i<row;i++) map[i]=_map[i];
show();
if (matchLine()) show();
newBlock();
}
else{
update();
}
}
function move(dir){
bak={
x:cur.x
}
cur.x+=dir;
//bak.x=cur.x
// console.log(cur.x)
// console.log(bak.x)
//bak.x==cur.x
if (canDown()){
update();
}else{
// console.log(cur.x)
cur.x=bak.x;
// console.log(cur.x)
}
}
function rotate(){
bak={
n:cur.n
}
cur.n++;
cur.n%=4;
if (!canDown()) cur.n=bak.n;
else update();
}
function update(){
var tmp=block[cur.b][cur.n];
for (var i=0;i<row;i++) _map[i]=map[i];
for (var i=0;i<4;i++) _map[cur.y+i]|=((tmp>>(12-4*i)&0x000f)<<cur.x);
show();
}
function canDown(){
var tmp=block[cur.b][cur.n];
//cur.x<0, 移位结果出错
if (cur.x<0) return false;
//一个方块四行
for (var i=0;i<4;i++){
//每行与map的下一行进行或运算
// console.log(map[cur.y+1+i].toString(2))
if ( ( (tmp>>(12-4*i)&0x000f)<<cur.x ) & map[cur.y+i]) return false;
}
return true;
}
function matchLine(){
var upgreade=0;
var _mark=map[row];	//_mark全是1
for (var i=cur.y,j=0;j<4&&i<row;i++,j++){
// if (map[i]&0xffffffffff==0xffffffffff){
if ((map[i]&_mark)==_mark){
map.splice(i,1);
map.unshift(mark);
upgreade=1;
_sorce++;
}
}
sorce.innerHTML=_sorce;
return upgreade;
}
function show(){
// console.log(block[cur.b][cur.n].toString(2))
// console.log(cur.x)
for (var i=0;i<row;i++){
for (var j=0;j<col;j++)
if (_map[i]>>(col-j)&0x000000001){
cells[i*col+j].style.background=color;
}else{
cells[i*col+j].style.background='white';
}
// alert(i+" "+j+" "+cells[i*row+j].id)
// console.log(_map[i].toString(2))
}
}
function showNext(){
var tmp=block[nextb][nextn];
for (var i=0;i<4;i++)
for (var j=0;j<4;j++)
if (tmp>>(15-i*4-j)&0x0001)
_cells[i*4+j].style.background=_color;
else
_cells[i*4+j].style.background='white';
}
function isOver(){
if ((map[0]|0x000000000)!=mark){
clearInterval(timer);
alert("game over");
return true;
}
return false;
}
运行效果如下:



演示地址(点解START运行游戏):点击打开链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: