@H_
772_22@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "
http://www.w3
.org/TR/xhtml1/DTD/xhtml1-transitiona
l.dtd">
<html xmlns="
http://www.w3
.org/1999/xhtml">
<head>
<meta
http-equiv="Content-Type" content="text/html; charset=utf-8" />
<
title>无标题文档</
title>
<style type="text/css">
#test
{
/*width:25px;*/
}
.t
{
width
:10px;
height
:10px;
border
:1px solid black;
float:left;
}
body
{
margin:0 auto;
width
:1000px;
height:600px;
}
/*游戏相关*/
#startGame
{
}
#li
nes
{
}
#level
{
}
#time
{
}
/*俄罗斯方块实体类*/
#tetris-area
{
width:auto;
height:auto;
BACkground:blue;
}
/*JS生成的CLASS,俄罗斯方块实体*/
#tetris
.block0,#tetris
.block1,#tetris
.block2,#tetris
.block3,#tetris
.block4,#tetris
.block5,#tetris
.block6
{
z-index
:1000;
font-size
:10px;
line-height
:1em;
position:absolute;
width
:13px;
height
:13px;
border:0.5px solid red;
BACkground:#000;
}
</style>
<script src="jquery.js"></script>
<script type="text/javascript">
//2维数组,用来存放俄罗斯方块的坐标
var xYAxis=[];
xYAxi
s.push([1,2],
[3,4]
);
//alert(xYAxis[1]
[0]);
//复制节点
/*$(document).ready(function(
E) {
for(i
=0;i<2;i++)
{
if(i==1)
{
// $("#test").append("<br>"
); //加上换行符
}
$(".t").clone().appendTo("#test"
);
}
//动态得到test(container)的宽度,包含两边的边框BORDER
$("#test").width(($(".t").width()+2)*2+1
);
}
);
*/
//获得区域的横坐标和纵坐标
function getArea(x,y,unit,id)
{
thi
s.x=x;
thi
s.y=y;
thi
S.Unit=unit; //每个单元的大小,单位为像素
thi
s.el=document.getElementById(id
); //得到ID对象
this
.board=[]; //面板,即在区域范围内的元素(俄罗斯方块)
/*创建2D范围矩阵*/
for(var y
=0;y<thi
s.y;y++)
{
this
.board.push(new Array()
);
for(var x
=0;x<thi
s.x;x++)
{
this
.board[y].push(0
);
}
}
/*从2D矩阵中消除元素*/
thi
s.destroy=function()
{
for(var y
=0;y<this
.board.length;y++)
{
for(var x
=0;x<this
.board[y].length;x++)
{
if(this
.board[y][x])
{
thi
s.e
l.removeChild(this
.board[y][x]
);
this
.board[y][x]
=0;
}
}
}
}
//添加元素
thi
s.addElement=function(el)
{
//得到起始元素的X开始坐标和Y开始坐标的位置(错误)
//得到X坐标的下落次数,和Y轴的左右移动的次数
var xBegin=parseInt(el
.offsetLeft/unit
);
var yBegin=parseInt(el
.offsetTop/unit
);
if(xBegin>
=0&&xBegin<=thi
s.x&&yBegin>
=0&&yBegin<=thi
s.y)
{
this
.board[yBegin][xBegin]=el; //确定元素的位置
}
}
//消掉所有的行
thi
s.removeFullLi
nes=function()
{
var li
nes=0;
for(var i=thi
s.y-1;i>0;i--)
{
if(thi
s.li
nesRelated(i))
{
thi
s.removeLi
nes(i
);
li
nes++;
y++;
}
}
return li
nes; //返回线条
}
//和线性有关的东西(判断是否满了)
thi
s.li
nesRelated=function(y)
{
for(var x
=0;x<thi
s.x;x++)
{
if(!this
.board[y][x])
{return
false;} //如果不为0的话,那么菜返回
falSE
}
return true;
};
//去掉行
thi
s.removeLi
nes=function(y)
{
for(var x
=0;x<thi
s.x;x++)
{
thi
s.e
l.removeChild(this
.board[y][x]
);
this
.board[y][x]
=0;
}
y--;
for(;y>0;y--)
{
/*今天暂时写到这里*/
/*继续于2014-12-21*/
for(var x
=0;x<thi
s.x;x++)
{
if(this
.board[y][x])
{
var el=this
.board[y][x];
e
l.style.top=el
.offsetTop+thi
S.Unit+"px";
this
.board[y+1][x]=el;
this
.board[y][x]
=0;
}
}
}
};
//活动区域
thi
s.getBlock=function(y,
X)
{
if(y<0)
{return 0;}
if(y<thi
s.y&&x<thi
s.X)
{
return this
.board[y][x];
}
else
{
throw "Area get failed!";
}
}
}
/*俄罗斯方块实体类*/
function Tetris()
{
var self =this; //自身
var operate=null;
thi
s.area=null;
thi
s.operate=null; //操作
thi
s.status=new State(
); //新建状态
/*初始化X,Y,单元为5或者20*/
thi
s.x=20;
thi
s.y=20;
thi
S.Unit=20;
thi
s.running=null; //是否在运行中
//俄罗斯方块实体ID
thi
s.id="tempid";
/*开始的时候暂停是
falSE的*/
thi
s.paused=
false;
//开始游戏
thi
s.start=function()
{
self.reset(
); //重新开始游戏
self.statu
s.start(
);
thi
s.area=new getArea(thi
s.x,thi
s.y,thi
S.Unit,"tetris-area"
); //获得Area对象,其中TEMPID是俄罗斯方块实体类ID
thi
s.operate=
new operateTetris(thi
s.area,self
);
//是否可以替换
if(thi
s.operate.mayPlace())
{
//alert
(1);
thi
s.operate.place(
);
}
else
{
self.gameOver(
);
}
}
//游戏结束
thi
s.gameOver=function()
{
self.statu
s.stopGame(
); //停止游戏
self
.operate.stopGame(
); //操作类停止游戏
}
/*重置游戏*/
thi
s.reset=function()
{
if(thi
s.operat
E)
{
self
.operate.destroy(
); //重新开始
self
.operate=null;
}
if(self.area)
{
self.area.destroy(
);
self.area=null;
}
//隐藏游戏结束
document.getElementById("game_over").style.display="none";
document.getElementById("next_operate").style.display="block"; //下一个操作
document.getElementById("keys_Press").style.display="block"; //显示按键
self.statu
s.reset(
);
self.paused=
false;
document.getElementById("tetris-pause").style.display="block"; //暂停按钮
}
/*暂停游戏*/
thi
s.pause=function()
{
if(self
.operate==null)
{
return ;
}
if(self.paused)
{
self
.operate.running=true;
/*这里还没写完2014-12-22*/
}
else
{
}
}
//上
thi
S.Up=function()
{
if(self
.operate&&self
.operate.isRunning()&&!self
.operate.isStopped())
{
if(self
.operate.mayRotate())
{
self
.operate.rotate(
);
self.statu
s.setActions(self.statu
s.getActions()+1
);
}
}
}
//下
thi
s.down=function()
{
if(self
.operate&&self
.operate.isRunning()&&!self
.operate.isStopped())
{
if(self
.operate.ma
ymoveDown())
{
self
.operate.moveDown(
);
self.statu
s.setActions(self.statu
s.getActions()+1
);
}
}
}
//左
thi
s.left=function()
{
if(self
.operate&&self
.operate.isRunning()&&!self
.operate.isStopped())
{
if(self
.operate.ma
ymoveLeft())
{
self
.operate.moveLeft(
);
self.statu
s.setActions(self.statu
s.getActions()+1
);
}
}
}
//右
thi
s.right=function()
{
if(self
.operate&&self
.operate.isRunning()&&!self
.operate.isStopped())
{
if(self
.operate.ma
ymoveRight())
{
self
.operate.moveRight(
);
self.statu
s.setActions(self.statu
s.getActions()+1
);
}
}
}
//开始游戏
document.getElementById("startGame")
.onclick=function()
{self.start()};
//} //Tetris是一个整体类,里面包含了很多方法。
var keyboard=new Keyboard(
); //创建键盘类实体
keyboard.set(keyboard.n,thi
s.start
);
keyboard.set(keyboard.up,thi
S.Up);
keyboard.set(keyboard.down,thi
s.down
);
keyboard.set(keyboard.left,thi
s.left
);
keyboard.set(keyboard.right,thi
s.right
);
document
.onkeydown=keyboard.event; //按下按键按钮的事件
/*键盘操作方法*/
function Keyboard()
{
thi
S.Up=38; //上
thi
s.down=40; //下
thi
s.left=37; //左
thi
s.right=39; //右
thi
s.n=78;
thi
s.p=80;
thi
s.r=82;
thi
s.space=32; //空格
thi
s.f12=123;
thi
s.escape=27; //退格键
thi
s.keys=[]; //键位集合
thi
s.funcs=[];
var self=this;
//设置键位
thi
s.set=function(key,fun
C)
{
thi
s.key
s.push(key
);
thi
s.func
s.push(func
);
}
thi
s.event=function(
E)
{
if(!
E){e=window.event;}
for(var i
=0;i<self.key
s.length;i++)
{
if(e.keyCode==self.keys[i])
{
self.funcs[i](
);
}
}
}
}
//具体的操作类
function OperateTetris(area,tetris)
{
var self=this; //当前对象
thi
s.area=area;
thi
s.tetris=tetris;
thi
s.types=null; //方块的类型;
thi
s.nextType=null; //下一个类型
//初始化X和Y
thi
s.x=null;
thi
s.y=null;
thi
s.position
=0; //初始位置
this
.board=[]; //用来填充HTML元素的
thi
s.elements=[];
thi
s.nextElements=[]; //下一个元素
thi
s.running=null; //是否在运行中
thi
s.stopped=null; //是否停止
thi
s.fallDownId=null; //往下掉落的
thi
s.speed=null; //速度
/*方块的组合方式,用数组进行组合(二维数组)
用0,1表示是否有方块存在,如果是0:不存在,1:存在,
以下的逻辑就可以非常的清楚了。*/
this
.blockComplex=[
[
[0,1],[1,1,[0,0] //_|
],[
[1,0],0] //L
],[
[0,0] //T
],0] //--
],1] //口
],0] //Z
]
];
thi
s.stopGame=function()
{
thi
s.running=
false;
}
/*一连串的GETTER方法
分别是速度,X,Y轴,运行和停止的GETTER方法*/
thi
s.getSpeed=function()
{
return thi
s.speed;
}
thi
s.getX=function()
{
return thi
s.x;
}
thi
s.getY=function()
{
return thi
s.y;
}
thi
s.isRunning=function()
{
return thi
s.running;
}
thi
s.isStopped=function()
{
return thi
s.stopped;
}
//重置(初始化)
thi
s.reset=function()
{
if(thi
s.fallDownId)
{
clearTimeout(thi
s.fallDownId
); //下落的时候去掉时间间隔
}
thi
s.types=thi
s.nextType;
thi
s.nextType=random(this
.blockComplex.length
);
thi
s.position
=0;
this
.board=[];
thi
s.elements=[];
thi
s.x=null;
thi
s.y=null;
thi
s.speed=200; //速度暂定为51
thi
s.running=
false;
thi
s.stopped=
false;
//移除下一个元素
for(var i
=0;i<thi
s.nextElement
s.length;i++)
{
document.getElementById("next_operate").removeChild(thi
s.nextElements[i]
);
}
thi
s.nextElements=[]; //下一个元素
}
//下一个类型,随机抽取
thi
s.nextType=random(this
.blockComplex.length
);
//重置
thi
s.reset(
);
/*判断是否替换*/
thi
s.mayPlace=function()
{
var isOperate=this
.blockComplex[thi
s.types];
/*area开始的坐标原点*/
var areaStartX=parseInt(thi
s.area.x-isOperate
[0].length
);
var areaStartY=1;
var lineFound=
false;
var li
nes=0;
for(var y=isOperate.length-1;y>
=0;y--)
{
for(var x
=0;x<isOperate[y].length;x++)
{
if(isOperate[y][x])
{
lineFound=true;
if(thi
s.area.getBlock(areaStartY,areaStartX+
X))
{return
false;}
}
}
if(lineFound)
{
li
nes++;
}
if(areaStartY-li
nes<0)
{
break;
}
}
return true;
}
/*替换*/
thi
s.place=function()
{
//初始化
var operate=this
.blockComplex[thi
s.types];
//区域开始X轴的位置
var AreaXStartPos=parseInt(thi
s.area.x-operate
[0].length
);
//区域开始Y轴的位置
//var AreaYStartPos=parseInt(thi
s.area.y-operate
[0]);
var AreaYStartPos=1; //因为X轴的位置可能变化,而Y轴总是从最上面下来的,所以是1
thi
s.x=AreaXStartPos; //把新的位置赋给X;
thi
s.y=AreaYStartPos; //把新的位置赋给y;
//构建空对象,并存入BOARD
/*y:行,x:列*/
//alert(operate
[0].length+" "+operate.length
);
this
.board=thi
s.createEmpty(operate
[0].length,operate.length
);
/*线条,往下掉落,初始化*/
var li
nes=0;
var foundLi
nes=
false;
//循环遍历,先遍历行,每一行再来遍历列
for(var yAxis=operate.length-1;yAxis>
=0;yAxis--)
{
for(var xAxis
=0;xAxis<=operate[yAxis].length;xAxis++)
{
if(operate[yAxis][xAxis])
{
var el=document.createElement("div"
);
e
l.className="block"+thi
s.types; //确定这个元素的CLASSNAME
//确定左边距和上边距
e
l.style.left=(thi
s.x+xAxis)*thi
s.area.unit+"px";
e
l.style.top=(thi
s.y+yAxis)*thi
s.area.unit+"px";
thi
s.area.e
l.appendChild(el
); //这个EL去APPEND主要的EL。
this
.board[yAxis][xAxis]=el;
thi
s.element
s.push(el
); //推入elements中
}
}
/*个人感觉这个功能应该是加速往下掉落的方法?不明觉厉*/
if(li
nes)
{
yAxis--;
}
if(foundLi
nes)
{
li
nes++;
}
}
thi
s.running=true;
thi
s.fallDownId=setTimeout(thi
s.fallDown,thi
s.speed
); //间隔时间,掉落下的
var nextOperate=this
.blockComplex[thi
s.nextType];
for(var y
=0;y<nextOperate.length;y++)
{
for(var x
=0;x<nextOperate[y].length;x++)
{
//创建元素
if(nextOperate[y][x])
{
/*先写到这里:2014-12-22*/
var el=document.createElement("div"
);
e
l.className="block"+thi
s.nextType;
e
l.style.left=(x*thi
s.area.unit)+"px";
e
l.style.top=(y*thi
s.area.unit)+"px";
document.getElementById("next_operate").appendChild(el
);
thi
s.nextElement
s.push(el
); //下一个元素
}
}
}
}
//创建空对象,即所有的都为0的对象,
并返回对象
thi
s.createEmpty=function(x,y)
{
var elements=[];
for(var y2
=0;y2<y;y2++)
{
element
s.push(new Array()
);
for(var x2
=0;x2<x;x2++)
{
elements[y2].push(0
);
}
}
return elements;
}
//下落(这是一个最关键的函数,决定了这个游戏的成败)
thi
s.fallDown=function()
{
if(self.isRunning())
{
if(self.ma
ymoveDown())
{
self.moveDown(
);
self.
fallDownId=setTimeout(self.
fallDown,self.speed
); //下落的间隔时间
}
else
{
for(var i
=0;i<self.element
s.length;i++)
{
self.area.addElement(self.elements[i]
);
}
var li
nes=self.area.removeFullLi
nes(
);
if(li
nes)
{
/*这里到时候再写*/
self.tetri
s.statu
s.setLi
nes(self.tetri
s.statu
s.getLi
nes()+li
nes);
}
self.reset(
);
if(self.mayPlace())
{
self.place(
);
}
else
{
self.tetri
s.gameOver(
);
}
}
}
else
{
}
}
//是否可以旋转俄罗斯方块
thi
s.mayRotate=function()
{
for(var y
=0;y<this
.board.length;y++)
{
for(var x
=0;x<this
.board[y].length;x++)
{
if(this
.board[y][x])
{
/新的X,Y的值/
var newY=thi
s.getY()+this
.board.length-1-x;
var newX=thi
s.getX()+y;
if(newY>thi
s.area.y)
{return
false;}
if(newX<0)
{return
false;}
if(newX>=thi
s.area.
X){return
false;}
if(thi
s.area.getBlock(newY,new
X))
{return
false;} //获得区域
}
}
}
return true;
}
//旋转俄罗斯方块
thi
s.rotate=function()
{
var puzzle=thi
s.createEmpty(this
.board.length,this
.board
[0].length
); //创建一个空的矩阵
for(var y
=0;y<this
.board.length;y++)
{
for(var x
=0;x<this
.board[y].length;x++)
{
//旋转,X轴和Y轴的坐标互换
if(this
.board[y][x])
{
var newY=puzzle.length-1-x;
var newX=y;
var el=this
.board[y][x]; //旋转前的对象
var moveY=newY-y;
var moveX=newX-x;
//长度是offsetTop或left加上偏移量
e
l.style.left=el
.offsetLeft+(moveX*thi
s.area.unit)+"px";
e
l.style.top=el
.offsetTop+(moveY*thi
s.area.unit)+"px";
puzzle[newY][newX]=el;
}
}
}
this
.board=puzzle;
}
//下落方法(进行判断)
thi
s.ma
ymoveDown=function()
{
for(var y
=0;y<this
.board.length;y++)
{
for(var x
=0;x<this
.board[y].length;x++)
{
if(this
.board[y][x])
{
if(thi
s.getY()+y+1>=thi
s.area.y)
{thi
s.stopGame=true;return
false;} //如果触底,那么就停止游戏
if(thi
s.area.getBlock(thi
s.getY()+y+1,thi
s.getX()+
X))
{thi
s.stopGame=true;return
false;}
}
}
}
return true;
}
//下落
thi
s.moveDown=function()
{
//用一个循环去控制下落
for(var i
=0;i<thi
s.element
s.length;i++)
{
thi
s.elements[i].style.top=thi
s.elements[i]
.offsetTop+thi
s.area.unit+"px";
}
thi
s.y++;
}
thi
s.ma
ymoveLeft=function()
{
/*可以向左移动(判断方法)*/
for(var y
=0;y<this
.board.length;y++)
{
for(var x
=0;x<this
.board[y].length;x++)
{
if(this
.board[y][x])
{
if(thi
s.getX()-1+x<0)
{
return
false;
}
if(thi
s.area.getBlock(thi
s.getY()+y,thi
s.getX()+x-1))
{return
false;}
}
}
}
return true;
}
//向左移动
thi
s.moveLeft=function()
{
/*向左移动(判断方法)*/
for(var i
=0;i<thi
s.element
s.length;i++)
{
thi
s.elements[i].style.left=thi
s.elements[i]
.offsetLeft-thi
s.area.unit+"px";
}
thi
s.x--;
}
/*是否可以向右移动*/
thi
s.ma
ymoveRight=function()
{
for(var y
=0;y<this
.board.length;y++)
{
for(var x
=0;x<this
.board[y].length;x++)
{
if(this
.board[y][x])
{
if(thi
s.getX()+1+x>=thi
s.area.
X){return
false;}
if(thi
s.area.getBlock(thi
s.getY()+y,thi
s.getX()+x+1))
{return
false;}
}
}
}
return true;
}
/*向右移动*/
thi
s.moveRight=function()
{
for(var i
=0;i<thi
s.element
s.length;i++)
{
thi
s.elements[i].style.left=thi
s.elements[i]
.offsetLeft+thi
s.area.unit+"px";
}
thi
s.x++;
}
/*摧毁方法*/
thi
s.destroy=function()
{
for(var i
=0;i<thi
s.element
s.length;i++)
{
thi
s.area.e
l.removeChild(thi
s.elements[i]
);
}
thi
s.elements=[];
this
.board=[];
thi
s.reset(
);
}
}
/*俄罗斯方块状态*/
function State()
{
/*初始化*/
thi
s.level;
thi
s.time;
thi
s.score;
thi
s.opeate;
thi
s.li
nes;
thi
s.apm; //不明觉厉
thi
s.actions; //动作
thi
s.el=
{
"li
nes":document.getElementById("li
nes"),"level":document.getElementById("level"),"time":document.getElementById("time"),"apm":document.getElementById("apm"),"operate":document.getElementById("operate")
}
thi
s.tim
EID=null;
var self=this;
//开始游戏
thi
s.start=function()
{
thi
s.reset(
); //重置
thi
s.tim
EID=se
Tinterval(thi
s.in
ctime,1500
);
}
/*停止游戏*/
thi
s.stopGame=function()
{
if(thi
s.tim
EID)
{
clearInterval(thi
s.tim
EID);
}
}
//重置
thi
s.reset=function()
{
thi
s.stopGame(
);
thi
s.level=1;
thi
s.time
=0;
thi
s.score
=0
thi
s.opeate
=0;
thi
s.li
nes=0;
/*以后可能加INNERHTML*/
thi
s.e
l.level=thi
s.level;
thi
s.e
l.time=thi
s.time;
thi
s.e
l.score=thi
s.score;
thi
s.el
.operate=thi
s.opeate;
thi
s.e
l.li
nes=thi
s.li
nes;
}
//和Se
Tinterval有关
thi
s.in
ctime=function()
{
self.time++;
self.e
l.time.innerHTML=self.time; //设置时间
self.actions=parseInt(self.actions/self.tim
E)*60;
thi
s.e
l.ap
m.innerHTML=self.apm;
}
/*设置分数*/
thi
s.setScore=function(i)
{
thi
s.score==i;
thi
s.e
l.score.innerHTML=thi
s.score;
}
/*设置等级*/
thi
s.setLevel=function(i)
{
thi
s.level=i;
thi
s.e
l.leve
l.innerHTML=thi
s.level; //设置内部HTML
};
thi
s.getLevel=function()
{
return thi
s.level;
}
//线条的SETTER方法
thi
s.setLi
nes=function(i)
{
thi
s.li
nes=i;
thi
s.e
l.li
nes.innerHTML=thi
s.li
nes;
}
thi
s.getLi
nes=function()
{
return thi
s.li
nes;
}
//设置动作
thi
s.setActions=function(i)
{
thi
s.actions=i;
//thi
s.e
l.action
s.innerHTML=thi
s.actions;
}
thi
s.getActions=function()
{
return thi
s.actions;
}
//设置apm
thi
s.setApm=function(i)
{
thi
s.apm=i;
thi
s.e
l.ap
m.innerHTML=thi
s.apm;
}
thi
s.getApm=function()
{
return thi
s.apm;
}
//控制下落操作的类
thi
s.setOperate=function(i)
{
thi
s.opeate=i;
thi
s.el
.operate=thi
s.operate;
}
thi
s.getOperate=function()
{
return thi
s.opeate;
}
}
//随机数,产生1~6的
function random(i)
{
return Math.floor(Math.random()*i
);
}
} /*Tetris是一个整体类,里面包含了很多方法*/
</script>
</head>
<body>
<div id="tetris">
<!--正方形 -->
<div id="test">
<div class="t"></div>
</div>
<!--长方形-->
<div id="rect">
<div class="r">
</div>
</div>
<!-- 俄罗斯方块实体类-->
<div id="tetris-area">
</div>
<!-- 下一个操作-->
<div id="next_operate"></div>
<!--游戏结束-->
<div id="game_over">Game Over</div>
<!-- 按键 -->
<div id="keys_Press">
</div>
<input type="button" id="startGame" value="Start" />
<!--线条 -->
<div id="li
nes"></div>
<!--等级 -->
<div id="level"></div>
<!--apm(不知道有什么作用) -->
<div id="apm"></div>
<!--时间 -->
<div id="time"></div>
<!--控制下落操作 -->
<div id="operate"></div>
<!-- 功能键(暂停)-->
<div id="tetris-pause">
</div>
<!-- 功能键(继续)-->
<div id="tetris-resume" style="display:none">
</div>
</div>
<script>
var tx=new Tetris(
);
tx.x=12;
tx.y=22;
tx.unit=14;
//tx.start(
); //开始游戏
</script>
</body>
</html>