如何用JavaScript做俄罗斯方块游戏?

2021-03-02 16:22:37 浏览数 (8870)

俄罗斯方块相信大家都玩过吧,虽然现在大型游戏众多,但它可谓是童年的美好回忆,经常能玩到茶饭不思

那么你知道如何自己做一个俄罗斯方块嘛?本篇文章就教你如何用 JavaScript 来做一个俄罗斯方块小游戏

最终游戏效果


一开始我们先搭个框架,以便后期使用

编写外部框架

<!DOCTYPE html>
<html>
	<head lang="en">
		<meta charset="UTF-8">
		<title></title>
		<style>
*{
    margin: 0;
    padding: 0;
}
#box{
	width:320px;
	height:450px;
	position:absolute;
	margin:0 auto;
	left:0;
	top:20px;
	right:0;
	bottom:0;
	background:gray;
	border-radius:10px;
}
#mainDiv{
	width:300px;
	height:400px;
	position:absolute;
	margin:0 auto;
	left:0;
	top:10px;
	right:0;
	bottom:0;
}
.bottom{
	width:600px;
    height:30px;
	position:absolute;
	bottom:1px;
	right:1px;
}
.bottom .button1{
	position: absolute;
    right: 55px;
    width: 50px;
    font-size: 14px;
}
.bottom .button2{
	position: absolute;
    right: 5px;
    width: 50px;
    font-size: 14px;
}
.bottom .span1{
	position: absolute;
    right: 155px;
    color: white;
    font-size: 8px;
}
.bottom .span2{
	position: absolute;
    right: 255px;
    color: white;
    font-size: 8px;
}
</style>
	</head>
	<body>
		<div id='box'>
			<div id='mainDiv'>
			</div>
			<div class='bottom'>
				<span id='score' class='span1'>分数:0</span>
				<span id='time' class='span2'>时间:0</span>
				<button onclick='start()' class='button1'>开始</button>
				<button onclick='stop()' class='button2'>结束</button>
			</div>
		</div>
		
	<script type="text/javascript" src='tetris.js'></script>
	<script type="text/javascript">
 
	
</script>
	</body>
</html>

框架效果如下:

微信截图_20210302101229

添加内部画布,以及绘制地图

首先创建线的构造函数Line

function Line(ctx,o){
		this.x=0,//x坐标
		this.y=0,//y坐标
		this.startX=0,//开始点x位置
		this.startY=0, //开始点y位置
		this.endX=0,//结束点x位置
		this.endY=0;//结束点y位置
		this.thin=false;//设置变细系数
		this.ctx=ctx;
		
		this.init(o);
	}
	Line.prototype.init=function(o){
		for(var key in o){
			this[key]=o[key];
		}
	}
	Line.prototype.render=function(){
		innerRender(this);
		
		function innerRender(obj){
			var ctx=obj.ctx;
			ctx.save()
			ctx.beginPath();
			ctx.translate(obj.x,obj.y);
			if(obj.thin){
				ctx.translate(0.5,0.5);
			}
			if(obj.lineWidth){//设定线宽
				ctx.lineWidth=obj.lineWidth;
			}
			if(obj.strokeStyle){
				ctx.strokeStyle=obj.strokeStyle;
			}
			//划线
		  	ctx.moveTo(obj.startX, obj.startY);
		  	ctx.lineTo(obj.endX, obj.endY);
		  	ctx.stroke();
		  	ctx.restore();
		}
	  	
	  	return this;
	}

设定参数、执行绘制等相关方法

代码如下:

function Game(el){
		this.renderArr=[];//待渲染对象存储数组
		this.aliveModel=[];//用来存到底的model组合
		
		this.score=0;//分数
		this.time=0;//时间
		this.moveCount=1;//计时控制器
	}
	
	Game.prototype.init=function(el,score,time){
		if(!el) return ;
		this.el=el;
		this.scoreEL=score;
		this.timeEL=time;
		var canvas = document.createElement('canvas');//创建画布
		canvas.style.cssText="background:darkgrey;border:1px solid grey;";//设置样式
		var W = canvas.width = 300; //设置宽度
		var H = canvas.height = 400;//设置高度
		
		el.appendChild(canvas);//添加到指定的dom对象中
		
		this.ctx = canvas.getContext('2d');
		this.canvas=canvas;
		this.w=W;
		this.h=H;
		
		this.disX=20;//每个格子的x方向大小
		this.disY=20;//每个格子的y方向大小
		this.maxX=15;//x方向格子总数
		this.maxY=20;//y方向格子总数
		
		this.control();//
		this.draw();//绘制
	}
	
	//绘制地图
	Game.prototype.createMap=function(){
		var renderArr = this.renderArr;
		var disX = this.disX;
		var disY = this.disY;
		var maxX=this.maxX;
		var maxY=this.maxY;
		var rectW = this.w;
		var rectH = this.h;
		var rect=null;
		var color;
		
		for(var i=1;i<maxY;i++){//20行
			var line = new Line(this.ctx,{
				x:0,
				y:0,
			 	startX:0,
			 	startY:i*disY,
			 	endX:this.w,
			 	endY:i*disY,
			 	thin:true,
			 	strokeStyle:'white',
			 	lineWidth:0.2
			})
			renderArr.push(line);
		}
		
		for(var i=1;i<maxX;i++){//15列
			var line = new Line(this.ctx,{
				x:0,
				y:0,
			 	startX:i*disX,
			 	startY:0,
			 	endX:i*disX,
			 	endY:this.h,
			 	thin:true,
			 	strokeStyle:'white',
			 	lineWidth:0.2
			})
			renderArr.push(line);
		}
	}
	
	Game.prototype.draw=function(){
		this.createMap();//绘制地图
		
		this.render();//渲染
	}

此时游戏区域的格子以及绘制如下:

微信截图_20210302101509

再来绘制模型

模型定义:分别是一字形、田字形、二字形2种、七字形2种、凸字形等共7种。

微信截图_20210302101649

变形定义:1字形可以变形2种、田字形不能变形,其他的都可以变形4种

模型的组成:模型是有4个小方块来组成,每个模型里面有数组blocks来存取4个小方块的x、y坐标,然后绘制出来就是模型了。

模型的变形:变形的时候就只要切换每个方块的X\Y坐标就可以达到变形的效果。

下面来创建模型的构造函数

	//模型构造函数
	function Model(o){
		this.blocks=[],//存储方块的数组,绘制的时候根据数组来绘制
		this.type=1,//模型的形状,默认是一字形(共7种)
		this.dir=1,//方向默认为1,总共4种,其中一字形为2种,田字形为1种,其他为4种
		this.x=0,//x坐标(只传入第一个x,根据这个x来生成其他的x)
		this.y=0,//y坐标(只传入第一个y,根据这个y来生成其他的y)
		
		this.init(o);
	}
	//初始化
	Model.prototype.init=function(o){
		for(var key in o){
			this[key]=o[key];
		}
	}

举例

添加一个创建七字形的方法(因为七字形有4种摆放方式,所以有dir来区分,怎么摆放)

//创建七字形1
	Model.prototype.createQi1=function(){
		var blocks=this.blocks,x=this.x,y=this.y;
		switch(this.dir){
			case 1://
				blocks.push({x:x,y:y});
				blocks.push({x:x,y:y-1});
				blocks.push({x:x,y:y-2});
				blocks.push({x:x+1,y:y-2});
				break;
			case 2://
				blocks.push({x:x+2,y:y});
				blocks.push({x:x+1,y:y});
				blocks.push({x:x,y:y});
				blocks.push({x:x,y:y-1});
				break;	
			case 3://
				blocks.push({x:x+1,y:y-2});
				blocks.push({x:x+1,y:y-1});
				blocks.push({x:x+1,y:y});
				blocks.push({x:x,y:y});
				break;	
			case 4://
				blocks.push({x:x-2,y:y-1});
				blocks.push({x:x-1,y:y-1});
				blocks.push({x:x,y:y-1});
				blocks.push({x:x,y:y});
				break;	
		}
	}

创建一个七字形试试(传入的x、y是第一个放个的位置)

var model = new Model({//创建1字
	x:6,y:6,fillStyle:'#0370BD',fill:true,game:this,type:5,dir:1
});
this.renderArr.push(model);
//当前的模型
this.currentModel=model;

编写变形方法(每一次变形都是按前一个模样逆时针旋转90度,修改每个小方块x、y来修改就行)

   ------------------------ >>> 

左边这个图形要变成右边的图形,需要怎么变更呢?

-------------------->>>   

标上号码就很容易明白,1还是对应的1,2还是对应的2,以此类推,只不过X\Y变了

1方块:只要x+2就可以移到指定的位置;

2方块:x、y都需要加1

3方块:y+2就可以

4方块:x-1和y+1即可

其他都是一样的道理,来写一下变形的方法

//七1变形
	Model.prototype.transformQi1=function(){
		var blocks = this.blocks,block2=blocks[1];
		switch(this.dir){
			case 1://竖着的
				tran1();
				this.dir=2;
				break;
			case 2://横着的
				tran2();
				this.dir=3;
				break;	
			case 3://竖着的
				tran3();
				this.dir=4;
				break;
			case 4://横着的
				tran4();
				this.dir=1;
				break;			
		}
 
		function tran1(){//变成横着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==0){
					block.x+=2;
				}else if(i==1){
					block.x+=1;
					block.y+=1;
				}else if(i==2){
					block.y+=2;
				}else if(i==3){
					block.x-=1;
					block.y+=1
				}
			}
		}
		
		function tran2(){//竖着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==0){
					block.x-=1;
					block.y-=2;
				}else if(i==1){
					block.y-=1;
				}else if(i==2){
					block.x+=1;
				}else if(i==3){
					block.y+=1
				}
			}
		}
		
		function tran3(){//变成横着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==3){
					block.x+=2;
				}else if(i==2){
					block.x+=1;
					block.y-=1;
				}else if(i==1){
					
				}else if(i==0){
					block.x-=1;
					block.y+=1
				}
			}
		}
		
		function tran4(){//竖着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==3){
					block.x-=1;
					block.y-=2;
				}else if(i==2){
					block.x-=2;
					block.y-=1;
				}else if(i==1){
					block.x-=1;
				}else if(i==0){
					block.y+=1;
				}
			}
		}
	}

给 w 和向上键添加为变形事件,同时左移动、右移动、下加速也添加好事件

//按键的控制
	Game.prototype.control=function(){
		var that=this;
		global.addEventListener('keydown',function(e){
			//if(!that.timmer) return ;
			switch (e.keyCode){
				case 87://w
				case 38://上
					that.currentModel.transform();//变形
					break;
				case 83://s
				case 40://下
					that.currentModel.move('d');//移动
					break;
				case 65://a
				case 37://左
					that.currentModel.move('l');//移动
					break;
				case 68://d
				case 39://右
					that.currentModel.move('r');//移动
					break;
			
			}
			//测试用,记得删除
			that.render();
		});
	}

接下来变形试试


添加移动方法

//移动
	Model.prototype.move=function(dir){
		var cur = this.game.currentModel,dis=1,blocks = this.blocks;
		if(dir=='r'||dir=='ld'){
			dis=1
		}else if(dir=='l'){
			dis=-1;
		}else if(dir=='d'){
			dis=3;
		}
		
		var stopMoveObj = this.stopMove(dir,dis),
			val=stopMoveObj.val,resDis=stopMoveObj.resDis;
		if(val) {
			if(dir=='d'||dir=='ld'){//到底了
				[].push.apply(this.game.aliveModel,cur.blocks);//放到已到底的组合中
				this.game.renderArr.pop();//当前模型弹出
				this.game.clearBlock();//消除
				this.game.createModel();//绘制一个新图形
			}
			
			return ;//如果返回true 则不能再往这个方向移动
		}
 
		if(resDis>0){
			dis=resDis;
		}
		//更新每一个block的位置
		for(var i=0;i<blocks.length;i++){
			block=blocks[i];
			if(dir=='d'||dir=='ld'){
				block.y+=dis;
			}else{
				block.x+=dis;
			}
		}
	}

加入边界判断和碰撞检测(边界检测比较简单、碰撞检测在快进的时候要注意处理一下,看代码吧)

//停止移动
	Model.prototype.stopMove=function(dir,dis){
		var cur = this.game.currentModel,blocks = this.blocks;
		
		var maxX = this.game.maxX,maxY = this.game.maxY,res,temp;
		for(var i=0;i<blocks.length;i++){
			block=blocks[i];
			if(dir=='d'||dir=='ld'){
				if(block.y>=maxY-1){//到底了
					return {val:true};
				}
			}else if(dir=='r'){
				if(block.x>=maxX-1){//到右边界了
					return {val:true};
				}
			}else if(dir=='l'){
				if(block.x<=0){//到左边界了
					return {val:true};
				}
			}
			//碰撞检测
			temp=this.collide(block,dis,dir);
			if(temp.val){
				return temp;
			}
			if(!res || res.resDis==0 || (temp.resDis!=0 && temp.resDis<res.resDis)){
				res=temp;
			}
		}
		
		return res;
	}
	//检查当前模型是否与其他存底的模型相触碰
	Model.prototype.collide=function(block,dis,dir){
		var aliveModel = this.game.aliveModel,item;
		var res={},val=false,resDis=0,maxY = this.game.maxY;
		
		if(dir=='r'){//向右判断
			for(var i=0;i<aliveModel.length;i++){
				item = aliveModel[i];
				if(!item) continue;
				if(item.y==block.y && item.x==block.x+1){
					val= true;
					break;
				}
			}
		}else if(dir=='l'){//向左判断
			for(var i=0;i<aliveModel.length;i++){
				item = aliveModel[i];
				if(!item) continue;
				if(item.y==block.y && item.x==block.x-1){
					val= true;
					break;
				}
			}
		}else {//向下判断
			if(aliveModel.length>0){
				for(var i=0;i<aliveModel.length;i++){
					item = aliveModel[i];
					if(!item) continue;
					if(item.x==block.x){//下方有存在的方块
						if(item.y==block.y+1){
							val= true;
							break;
						}else if(item.y<=block.y+Math.abs(dis)){
							var temp=item.y-block.y-1;
							if(resDis==0 || temp<resDis){
								resDis = temp;
							}
						}
					}else{//下发不存在方块
						if(maxY<=block.y+Math.abs(dis)){
							var temp=maxY-block.y-1;
							if(resDis==0 || temp<resDis){
								resDis = temp;
							}
						}
					} 
				}
			}else{//第一个模型
				if(maxY<=block.y+Math.abs(dis)){
					var temp=maxY-block.y-1;
					if(resDis==0 || temp<resDis){
						resDis = temp;
					}
				}
			}
		}
		res.resDis=resDis;
		res.val=val;
		return res;
	}


到底后的处理

微信截图_20210302102023

  1. 给当前的游戏对象的aliveModel数组,存取当前到底的模型所对应的4个小方块(执行render方法的时候就绘制出来) 
  2. 在renderArr数组中此模型要删除
  3. 每次触底需要加入消除判断,符合条件就消除
  4. 绘制一个新的模型

绘制触底的模型方块

//绘制存底的图形
	Game.prototype.aliveModelRender=function(){
		var context=this.ctx;
		var disX=this.disX,disY=this.disY;
		context.save();
		context.beginPath();
		_.each(this.aliveModel,function(item){
			if(item){
				context.rect(item.x*disX+1,item.y*disY+1,disX-1,disY-1);
				//context.fillStyle='';
				context.fill();
			}
		});
		context.restore();
	}

消除行、积分、以及下降

//消除行
	Game.prototype.clearBlock=function(){
		var maxX=this.maxX,aliveModel=this.aliveModel;
		//将y相同的放在一起
		var rowArr=[],rowObj={};
		_.each(aliveModel,function(item,index){
			if(item) {
				if(!rowObj[item.y]){
					rowObj[item.y]=[];
				}
				rowObj[item.y].push(index);
			}
		});
		
		var that=this;
		var keys = Object.keys(rowObj),row,num=0;
		_.each(keys,function(k){
			row = rowObj[k];
			if(row.length>=maxX){//消除这行
				_.each(row,function(r){
					aliveModel.splice(r,1,undefined);//先用undefined代替
				})
				
				num++;//行数计数器
				that.down(k,1);//清楚当前行
			}
		})
		
		//完成消除
		for(var i=0;i<aliveModel.length;i++){
			if(!aliveModel[i]) {
				console.log(123)
				aliveModel.splice(i,1);
			}
		}
		
		var score = 0;
		switch (num){
			case 1:
				score=100;//1行100分
				break;
			case 2:
				score=300;//2行300分
				break;
			case 3:
				score=600;//3行600分
				break;
			case 4:
				score=1000;//4行1000分
				break;
		}
		//积分
		this.calcuScore(score);
	}
	
	//消除后的下降
	Game.prototype.down=function(y,num){
		var aliveModel=this.aliveModel;
		_.each(aliveModel,function(item){
			if(item && item.y<y){
				item.y+=num;
			}
		});
	}

自动往下移动、更新、显示时间、分数

//显示分数
	Game.prototype.calcuScore=function(s){
		this.score+=s;
		this.scoreEL.innerText='分数:'+this.score;
	}
	//显示时间
	Game.prototype.calcuTime=function(){
		if(this.moveCount%4==0){
			this.time++;
			this.time_flag=false;
			this.timeEL.innerText='时间:'+this.time;
		}
		
		this.moveCount++;
	}
	//向下移动
	Game.prototype.move=function(dir){
		var curModel= this.currentModel;
		this.calcuTime();
		
		var endFlag = this.end();
		if(endFlag) {
			this.stop();
			this.hasEnd=true;
			return ;
		} 
		
		this.update();
		this.render();
	}
	//更新
	Game.prototype.update=function(){
		this.currentModel.move('ld');
	}

给开始、结束按钮加入事件

	var mainDiv = document.getElementById('mainDiv');
	var score= document.getElementById('score');
	var time= document.getElementById('time');
	
	game.init(mainDiv,score,time);
	
	function start(){
		game.start()
	}
	
	function stop(){
		game.stop()
	}
Game.prototype.start=function(){
		if(this.timmer) return ;
		if(this.hasEnd){//如果是结束则需要重新开始,暂停的话就继续游戏
			this.restart();
		}
		this.hasEnd=false;
		this.timmer = setInterval(this.move.bind(this),250);//开始定时任务
	}
	
	//重新开始
	Game.prototype.restart=function(){
		this.renderArr=[];//待渲染对象存储数组
		this.aliveModel=[];//用来存到底的model组合
		
		this.score=0;//分数
		this.time=0;//时间
		this.moveCount=1;//计时控制器
		
		this.clearCanvas();
		this.draw();
	}
	//停止任务	
	Game.prototype.stop=function(){
		if(!this.timmer) return ;
		clearInterval(this.timmer);//清除定时任务
		this.timmer=null;
	}
	//结束
	Game.prototype.end=function(){
		var aliveModel = this.aliveModel;
		for(var i=0;i<aliveModel.length;i++){
			item = aliveModel[i];
			if(item&&item.y==0){
				alert('结束了')
				return true;
			}
		}
		return false
	}

源码如下:

HTML

<!DOCTYPE html>
<html>
	<head lang="en">
		<meta charset="UTF-8">
		<title></title>
		<style>
*{
    margin: 0;
    padding: 0;
}
#box{
	width:320px;
	height:450px;
	position:absolute;
	margin:0 auto;
	left:0;
	top:20px;
	right:0;
	bottom:0;
	background:gray;
	border-radius:10px;
}
#mainDiv{
	width:300px;
	height:400px;
	position:absolute;
	margin:0 auto;
	left:0;
	top:10px;
	right:0;
	bottom:0;
}
.bottom{
	width:600px;
    height:30px;
	position:absolute;
	bottom:1px;
	right:1px;
}
.bottom .button1{
	position: absolute;
    right: 55px;
    width: 50px;
    font-size: 14px;
}
.bottom .button2{
	position: absolute;
    right: 5px;
    width: 50px;
    font-size: 14px;
}
.bottom .span1{
	position: absolute;
    right: 155px;
    color: white;
    font-size: 8px;
}
.bottom .span2{
	position: absolute;
    right: 255px;
    color: white;
    font-size: 8px;
}
</style>
	</head>
	<body>
		<div id='box'>
			<div id='mainDiv'>
			</div>
			<div class='bottom'>
				<span id='score' class='span1'>分数:0</span>
				<span id='time' class='span2'>时间:0</span>
				<button onclick='start()' class='button1'>开始</button>
				<button onclick='stop()' class='button2'>结束</button>
			</div>
		</div>
		
	<script type="text/javascript" src='tetris.js'></script>
	<script type="text/javascript">
	var mainDiv = document.getElementById('mainDiv');
	var score= document.getElementById('score');
	var time= document.getElementById('time');
	
	game.init(mainDiv,score,time);
	
	function start(){
		game.start()
	}
	
	function stop(){
		game.stop()
	}
	
</script>
	</body>
</html>

JS

;(function(global){
	var game= new Game();
	
	function Game(el){
		this.renderArr=[];//待渲染对象存储数组
		this.aliveModel=[];//用来存到底的model组合
		
		this.score=0;//分数
		this.time=0;//时间
		this.moveCount=1;//计时控制器
	}
	
	Game.prototype.init=function(el,score,time){
		if(!el) return ;
		this.el=el;
		this.scoreEL=score;
		this.timeEL=time;
		var canvas = document.createElement('canvas');//创建画布
		canvas.style.cssText="background:darkgrey;border:1px solid grey;";//设置样式
		var W = canvas.width = 300; //设置宽度
		var H = canvas.height = 400;//设置高度
		
		el.appendChild(canvas);//添加到指定的dom对象中
		
		this.ctx = canvas.getContext('2d');
		this.canvas=canvas;
		this.w=W;
		this.h=H;
		
		this.disX=20;//每个格子的x方向大小
		this.disY=20;//每个格子的y方向大小
		this.maxX=15;//x方向格子总数
		this.maxY=20;//y方向格子总数
		
		this.control();//
		this.draw();//绘制
	}
	
	//绘制地图
	Game.prototype.createMap=function(){
		var renderArr = this.renderArr;
		var disX = this.disX;
		var disY = this.disY;
		var maxX=this.maxX;
		var maxY=this.maxY;
		var rectW = this.w;
		var rectH = this.h;
		var rect=null;
		var color;
		
		for(var i=1;i<maxY;i++){//20行
			var line = new Line(this.ctx,{
				x:0,
				y:0,
			 	startX:0,
			 	startY:i*disY,
			 	endX:this.w,
			 	endY:i*disY,
			 	thin:true,
			 	strokeStyle:'white',
			 	lineWidth:0.2
			})
			renderArr.push(line);
		}
		
		for(var i=1;i<maxX;i++){//15列
			var line = new Line(this.ctx,{
				x:0,
				y:0,
			 	startX:i*disX,
			 	startY:0,
			 	endX:i*disX,
			 	endY:this.h,
			 	thin:true,
			 	strokeStyle:'white',
			 	lineWidth:0.2
			})
			renderArr.push(line);
		}
	}
	
	Game.prototype.draw=function(){
		this.createMap();//绘制地图
		this.createModel();//绘制一个图形
		this.render();//渲染
	}
	//渲染图形
	Game.prototype.render=function(){
		var context=this.ctx;
		this.clearCanvas();	
		_.each(this.renderArr,function(item){
			item && item.render(context);
		});
		
		this.aliveModelRender();
	}
	//绘制存底的图形
	Game.prototype.aliveModelRender=function(){
		var context=this.ctx;
		var disX=this.disX,disY=this.disY;
		context.save();
		context.beginPath();
		_.each(this.aliveModel,function(item){
			if(item){
				context.rect(item.x*disX+1,item.y*disY+1,disX-1,disY-1);
				//context.fillStyle='';
				context.fill();
			}
		});
		context.restore();
	}
	//消除行
	Game.prototype.clearBlock=function(){
		var maxX=this.maxX,aliveModel=this.aliveModel;
		//将y相同的放在一起
		var rowArr=[],rowObj={};
		_.each(aliveModel,function(item,index){
			if(item) {
				if(!rowObj[item.y]){
					rowObj[item.y]=[];
				}
				rowObj[item.y].push(index);
			}
		});
		
		var that=this;
		var keys = Object.keys(rowObj),row,num=0;
		_.each(keys,function(k){
			row = rowObj[k];
			if(row.length>=maxX){//消除这行
				_.each(row,function(r){
					aliveModel.splice(r,1,undefined);//先用undefined代替
				})
				
				num++;//行数计数器
				that.down(k,1);//清楚当前行
			}
		})
		
		//完成消除
		for(var i=0;i<aliveModel.length;i++){
			if(!aliveModel[i]) {
				console.log(123)
				aliveModel.splice(i,1);
			}
		}
		
		var score = 0;
		switch (num){
			case 1:
				score=100;//1行100分
				break;
			case 2:
				score=300;//2行300分
				break;
			case 3:
				score=600;//3行600分
				break;
			case 4:
				score=1000;//4行1000分
				break;
		}
		//积分
		this.calcuScore(score);
	}
	
	//消除后的下降
	Game.prototype.down=function(y,num){
		var aliveModel=this.aliveModel;
		_.each(aliveModel,function(item){
			if(item && item.y<y){
				item.y+=num;
			}
		});
	}
	
	Game.prototype.start=function(){
		if(this.timmer) return ;
		if(this.hasEnd){//如果是结束则需要重新开始,暂停的话就继续游戏
			this.restart();
		}
		this.hasEnd=false;
		this.timmer = setInterval(this.move.bind(this),250);//开始定时任务
	}
	
	//重新开始
	Game.prototype.restart=function(){
		this.renderArr=[];//待渲染对象存储数组
		this.aliveModel=[];//用来存到底的model组合
		
		this.score=0;//分数
		this.time=0;//时间
		this.moveCount=1;//计时控制器
		
		this.clearCanvas();
		this.draw();
	}
	//停止任务	
	Game.prototype.stop=function(){
		if(!this.timmer) return ;
		clearInterval(this.timmer);//清除定时任务
		this.timmer=null;
	}
	//结束
	Game.prototype.end=function(){
		var aliveModel = this.aliveModel;
		for(var i=0;i<aliveModel.length;i++){
			item = aliveModel[i];
			if(item&&item.y==0){
				alert('结束了')
				return true;
			}
		}
		return false
	}
	//显示分数
	Game.prototype.calcuScore=function(s){
		this.score+=s;
		this.scoreEL.innerText='分数:'+this.score;
	}
	//显示时间
	Game.prototype.calcuTime=function(){
		if(this.moveCount%4==0){
			this.time++;
			this.time_flag=false;
			this.timeEL.innerText='时间:'+this.time;
		}
		
		this.moveCount++;
	}
	//向下移动
	Game.prototype.move=function(dir){
		var curModel= this.currentModel;
		this.calcuTime();
		
		var endFlag = this.end();
		if(endFlag) {
			this.stop();
			this.hasEnd=true;
			return ;
		} 
		
		this.update();
		this.render();
	}
	//更新
	Game.prototype.update=function(){
		this.currentModel.move('ld');
	}
	//按键的控制
	Game.prototype.control=function(){
		var that=this;
		global.addEventListener('keydown',function(e){
			//if(!that.timmer) return ;
			switch (e.keyCode){
				case 87://w
				case 38://上
					that.currentModel.transform();//变形
					break;
				case 83://s
				case 40://下
					that.currentModel.move('d');//移动
					break;
				case 65://a
				case 37://左
					that.currentModel.move('l');//移动
					break;
				case 68://d
				case 39://右
					that.currentModel.move('r');//移动
					break;
			
			}
			//测试用,记得删除
			//that.render();
		});
	}
	
	Game.prototype.clearCanvas=function(){
		this.ctx.clearRect(0,0,parseInt(this.w),parseInt(this.h));//清理画布
	}
	//创建模型
	Game.prototype.createModel=function(){
		var type = _.getRandom(1,7);//type有7种
		var dir =0;
		if(type=='1'){//一字 只2种
			dir = _.getRandom(1,2);
		}else if(type=='2'){//一字 只有1种
			dir = 1;
		}else{//其他有4种
			dir = _.getRandom(1,4);
		}

		var model = new Model({//随机创建
			x:6,y:-1,fillStyle:'#0370BD',fill:true,game:this,type:type,dir:dir
		});
		this.renderArr.push(model);
		//当前的模型
		this.currentModel=model;
		/*
		model = new Model({//创建横向1字
			x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:1,dir:1
		});
		
		
		model = new Model({//创建田字
			x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:2,dir:1
		});
		
		model = new Model({//创建二字1
			x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:3,dir:4
		});
		
		model = new Model({//创建二字2
			x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:4,dir:1
		});
		
		model = new Model({//创建七字1
			x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:5,dir:4
		});
		
		model = new Model({//创建七字2
			x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:6,dir:4
		});
		
		model = new Model({//创建凸字
			x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:7,dir:4
		});
		*/
	}
	
	//模型构造函数
	function Model(o){
		this.blocks=[],//存储方块的数组,绘制的时候根据数组来绘制
		this.type=1,//模型的形状,默认是一字形(共7种)
		this.dir=1,//方向默认为1,总共4种,其中一字形为2种,田字形为1种,其他为4种
		this.x=0,//x坐标(只传入第一个x,根据这个x来生成其他的x)
		this.y=0,//y坐标(只传入第一个y,根据这个y来生成其他的y)
		
		this.init(o);
	}
	//初始化
	Model.prototype.init=function(o){
		for(var key in o){
			this[key]=o[key];
		}
		this.organ();
	}
	//组织图形
	Model.prototype.organ=function(){
		switch(this.type){
			case 1:
				this.createYi();//创建一字形
				break;
				
			case 2:
				this.createTian();//创建田字形
				break;
				
			case 3:
				this.createEr1();//创建字二形1
				break;
				
			case 4:
				this.createEr2();//创建二字形2
				break;
				
			case 5:
				this.createQi1();//创建七字形1
				break;
				
			case 6:
				this.createQi2();//创建七字形2
				break;	
			
			case 7:
				this.createTu();//创建凸字形
				break;		
		}
	}
	//创建一字形
	Model.prototype.createYi=function(){
		var blocks=this.blocks,x=this.x,y=this.y;
		switch(this.dir){
			case 1://横着的
				blocks.push({x:x,y:y});
				blocks.push({x:x+1,y:y});
				blocks.push({x:x+2,y:y});
				blocks.push({x:x+3,y:y});
				break;
			case 2://竖着的
				blocks.push({x:x,y:y});
				blocks.push({x:x,y:y-1});
				blocks.push({x:x,y:y-2});
				blocks.push({x:x,y:y-3});
				break;	
				
		}
	}
	//创建田字形
	Model.prototype.createTian=function(){
		var blocks=this.blocks,x=this.x,y=this.y;
		switch(this.dir){
			case 1://横着的
				blocks.push({x:x,y:y});
				blocks.push({x:x+1,y:y});
				blocks.push({x:x,y:y-1});
				blocks.push({x:x+1,y:y-1});
				break;
			case 2://竖着的
				blocks.push({x:x,y:y});
				blocks.push({x:x,y:y-1});
				blocks.push({x:x,y:y-2});
				blocks.push({x:x,y:y-3});;
				break;	
				
		}
	}
	//创建二字形1
	Model.prototype.createEr1=function(){
		var blocks=this.blocks,x=this.x,y=this.y;
		switch(this.dir){
			case 1://
				blocks.push({x:x,y:y});
				blocks.push({x:x,y:y-1});
				blocks.push({x:x+1,y:y-1});
				blocks.push({x:x+1,y:y-2});
				break;
			case 2://
				blocks.push({x:x+1,y:y});
				blocks.push({x:x,y:y});
				blocks.push({x:x,y:y-1});
				blocks.push({x:x-1,y:y-1});
				break;	
			case 3://
				blocks.push({x:x+1,y:y-2});
				blocks.push({x:x+1,y:y-1});
				blocks.push({x:x,y:y-1});
				blocks.push({x:x,y:y});
				break;	
			case 4://
				blocks.push({x:x-1,y:y-1});
				blocks.push({x:x,y:y-1});
				blocks.push({x:x,y:y});
				blocks.push({x:x+1,y:y});
				break;	
		}
	}
	//创建二字形2
	Model.prototype.createEr2=function(){
		var blocks=this.blocks,x=this.x,y=this.y;
		switch(this.dir){
			case 1://
				blocks.push({x:x,y:y});
				blocks.push({x:x,y:y-1});
				blocks.push({x:x-1,y:y-1});
				blocks.push({x:x-1,y:y-2});
				break;
			case 2://
				blocks.push({x:x+2,y:y-1});
				blocks.push({x:x+1,y:y-1});
				blocks.push({x:x+1,y:y});
				blocks.push({x:x,y:y});
				break;	
			case 3://
				blocks.push({x:x-1,y:y-2});
				blocks.push({x:x-1,y:y-1});
				blocks.push({x:x,y:y-1});
				blocks.push({x:x,y:y});
				break;	
			case 4://
				blocks.push({x:x,y:y});
				blocks.push({x:x+1,y:y});
				blocks.push({x:x+1,y:y-1});
				blocks.push({x:x+2,y:y-1});
				
				break;	
		}
	}
	
	//创建七字形1
	Model.prototype.createQi1=function(){
		var blocks=this.blocks,x=this.x,y=this.y;
		switch(this.dir){
			case 1://
				blocks.push({x:x,y:y});
				blocks.push({x:x,y:y-1});
				blocks.push({x:x,y:y-2});
				blocks.push({x:x+1,y:y-2});
				break;
			case 2://
				blocks.push({x:x+2,y:y});
				blocks.push({x:x+1,y:y});
				blocks.push({x:x,y:y});
				blocks.push({x:x,y:y-1});
				break;	
			case 3://
				blocks.push({x:x+1,y:y-2});
				blocks.push({x:x+1,y:y-1});
				blocks.push({x:x+1,y:y});
				blocks.push({x:x,y:y});
				break;	
			case 4://
				blocks.push({x:x-2,y:y-1});
				blocks.push({x:x-1,y:y-1});
				blocks.push({x:x,y:y-1});
				blocks.push({x:x,y:y});
				break;	
		}
	}
	
	//创建七字形2
	Model.prototype.createQi2=function(){
		var blocks=this.blocks,x=this.x,y=this.y;
		switch(this.dir){
			case 1://
				blocks.push({x:x,y:y});
				blocks.push({x:x,y:y-1});
				blocks.push({x:x,y:y-2});
				blocks.push({x:x-1,y:y-2});
				break;
			case 2://
				blocks.push({x:x+2,y:y-1});
				blocks.push({x:x+1,y:y-1});
				blocks.push({x:x,y:y-1});
				blocks.push({x:x,y:y});
				break;	
			case 3://
				blocks.push({x:x,y:y-2});
				blocks.push({x:x,y:y-1});
				blocks.push({x:x,y:y});
				blocks.push({x:x+1,y:y});
				break;	
			case 4://
				blocks.push({x:x,y:y});
				blocks.push({x:x+1,y:y});
				blocks.push({x:x+2,y:y});
				blocks.push({x:x+2,y:y-1});
				break;	
		}
	}
	//创建凸字形
	Model.prototype.createTu=function(){
		var blocks=this.blocks,x=this.x,y=this.y;
		switch(this.dir){
			case 1://
				blocks.push({x:x,y:y});
				blocks.push({x:x+1,y:y});
				blocks.push({x:x+2,y:y});
				blocks.push({x:x+1,y:y-1});
				break;
			case 2://
				blocks.push({x:x,y:y});
				blocks.push({x:x,y:y-1});
				blocks.push({x:x,y:y-2});
				blocks.push({x:x-1,y:y-1});
				
				break;	
			case 3://
				blocks.push({x:x+1,y:y-1});
				blocks.push({x:x,y:y-1});
				blocks.push({x:x-1,y:y-1});
				blocks.push({x:x,y:y});
				break;	
			case 4://
				blocks.push({x:x,y:y-2});
				blocks.push({x:x,y:y-1});
				blocks.push({x:x,y:y});
				blocks.push({x:x+1,y:y-1});
				break;	
		}
	}
	
	//变形
	Model.prototype.transform=function(){
		switch(this.type){
			case 1://一
				this.transformYi();
				break;
			case 2://田
				//无需变形
				break;	
			case 3://二(1)
				this.transformEr1();
				break;
			case 4://二(2)
				this.transformEr2();
				break;
			case 5://七(1)
				this.transformQi1();
				break;	
			case 6://七(2)
				this.transformQi2();
				break;
			case 7://凸
				this.transformTu();
				break;
		}
	}
	Model.prototype.transformYi=function(){
		var blocks = this.blocks,block2=blocks[1];
		switch(this.dir){
			case 1://横着的
				tran1();
				this.dir=2;
				break;
			case 2://竖着的
				tran2();
				this.dir=1;
				break;	
				
		}

		function tran1(){//变成竖着的
			for(var i=0;i<blocks.length;i++){
				if(i==1)continue;
				block=blocks[i];
				
				if(i==0){
					block.y=block2.y+1;
				}else if(i==2){
					block.y=block2.y-1;
				}else if(i==3){
					block.y=block2.y-2;
				}
				//x方向改成一样
				block.x=block2.x;
			}
		}
		
		function tran2(){//变成横着的
			for(var i=0;i<blocks.length;i++){
				if(i==1)continue;
				block=blocks[i];
				
				if(i==0){
					block.x=block2.x-1;
				}else if(i==2){
					block.x=block2.x+1;
				}else if(i==3){
					block.x=block2.x+2;
				}
				//y方向改成一样
				block.y=block2.y;
			}
		}
	}
	
	Model.prototype.transformEr1=function(){
		var blocks = this.blocks,block2=blocks[1];
		switch(this.dir){
			case 1://竖着的
				tran1();
				this.dir=2;
				break;
			case 2://横着的
				tran2();
				this.dir=3;
				break;	
			case 3://竖着的
				tran3();
				this.dir=4;
				break;
			case 4://横着的
				tran4();
				this.dir=1;
				break;			
		}

		function tran1(){//变成横着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==0){
					block.x+=2;
				}else if(i==1){
					block.x+=1;
					block.y+=1;
				}else if(i==2){
				}else if(i==3){
					block.x-=1;
					block.y+=1
				}
			}
		}
		
		function tran2(){//竖着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==0){
					block.x-=1;
					block.y-=2;
				}else if(i==1){
					block.y-=1;
				}else if(i==2){
					block.x-=1;
				}else if(i==3){
					block.y+=1
				}
			}
		}
		
		function tran3(){//变成横着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==3){
					block.x+=2;
				}else if(i==2){
					block.x+=1;
					block.y+=1;
				}else if(i==1){
				}else if(i==0){
					block.x-=1;
					block.y+=1
				}
			}
		}
		
		function tran4(){//竖着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==3){
					block.x-=1;
					block.y-=2;
				}else if(i==2){
					block.y-=1;
				}else if(i==1){
					block.x-=1;
				}else if(i==0){
					block.y+=1
				}
			}
		}
	}
	
	Model.prototype.transformEr2=function(){
		var blocks = this.blocks,block2=blocks[1];
		switch(this.dir){
			case 1://竖着的
				tran1();
				this.dir=2;
				break;
			case 2://横着的
				tran2();
				this.dir=3;
				break;	
			case 3://竖着的
				tran3();
				this.dir=4;
				break;
			case 4://横着的
				tran4();
				this.dir=1;
				break;			
		}

		function tran1(){//变成横着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==0){
					block.x+=1;
					block.y-=1;
				}else if(i==1){
				}else if(i==2){
					block.x+=1;
					block.y+=1;
				}else if(i==3){
					block.y+=2;
				}
			}
		}
		
		function tran2(){//竖着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==0){
					block.x-=2;
					block.y-=1;
				}else if(i==1){
					block.x-=1;
				}else if(i==2){
					block.y-=1;
				}else if(i==3){
					block.x+=1
				}
			}
		}
		
		function tran3(){//变成横着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==3){
					block.x+=1;
					block.y-=1;
				}else if(i==2){
				}else if(i==1){
					block.x+=1;
					block.y+=1;	
				}else if(i==0){
					block.y+=2;	
				}
			}
		}
		
		function tran4(){//竖着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==3){
					block.x-=2;
					block.y-=1;
				}else if(i==2){
					block.x-=1;
				}else if(i==1){
					block.y-=1;
				}else if(i==0){
					block.x+=1
				}
			}
		}
	}
	//七1变形
	Model.prototype.transformQi1=function(){
		var blocks = this.blocks,block2=blocks[1];
		switch(this.dir){
			case 1://竖着的
				tran1();
				this.dir=2;
				break;
			case 2://横着的
				tran2();
				this.dir=3;
				break;	
			case 3://竖着的
				tran3();
				this.dir=4;
				break;
			case 4://横着的
				tran4();
				this.dir=1;
				break;			
		}

		function tran1(){//变成横着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==0){
					block.x+=2;
				}else if(i==1){
					block.x+=1;
					block.y+=1;
				}else if(i==2){
					block.y+=2;
				}else if(i==3){
					block.x-=1;
					block.y+=1
				}
			}
		}
		
		function tran2(){//竖着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==0){
					block.x-=1;
					block.y-=2;
				}else if(i==1){
					block.y-=1;
				}else if(i==2){
					block.x+=1;
				}else if(i==3){
					block.y+=1
				}
			}
		}
		
		function tran3(){//变成横着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==3){
					block.x+=2;
				}else if(i==2){
					block.x+=1;
					block.y-=1;
				}else if(i==1){
					
				}else if(i==0){
					block.x-=1;
					block.y+=1
				}
			}
		}
		
		function tran4(){//竖着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==3){
					block.x-=1;
					block.y-=2;
				}else if(i==2){
					block.x-=2;
					block.y-=1;
				}else if(i==1){
					block.x-=1;
				}else if(i==0){
					block.y+=1;
				}
			}
		}
	}
	
	//七2变形
	Model.prototype.transformQi2=function(){
		var blocks = this.blocks,block2=blocks[1];
		switch(this.dir){
			case 1://竖着的
				tran1();
				this.dir=2;
				break;
			case 2://横着的
				tran2();
				this.dir=3;
				break;	
			case 3://竖着的
				tran3();
				this.dir=4;
				break;
			case 4://横着的
				tran4();
				this.dir=1;
				break;			
		}

		function tran1(){//变成横着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==0){
					block.x+=1;
					block.y-=1;
				}else if(i==1){
				}else if(i==2){
					block.x-=1;
					block.y+=1;
				}else if(i==3){
					block.y+=2;
				}
			}
		}
		
		function tran2(){//竖着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==0){
					block.x-=2;
					block.y-=1;
				}else if(i==1){
					block.x-=1;
				}else if(i==2){
					block.y+=1;
				}else if(i==3){
					block.x+=1;
				}
			}
		}
		
		function tran3(){//变成横着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==3){
					block.x+=1;
					block.y-=1;
				}else if(i==2){
					block.x+=2;
				}else if(i==1){
					block.x+=1;
					block.y+=1;
				}else if(i==0){
					block.y+=2;
				}
			}
		}
		
		function tran4(){//竖着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==3){
					block.x-=2;
					block.y-=1;
				}else if(i==2){
					block.x-=1;
					block.y-=2;
				}else if(i==1){
					block.y-=1;
				}else if(i==0){
					block.x+=1;
				}
			}
		}
	}
	
	
	//凸变形
	Model.prototype.transformTu=function(){
		var blocks = this.blocks,block2=blocks[1];
		switch(this.dir){
			case 1://横着的
				tran1();
				this.dir=2;
				break;
			case 2://竖着的
				tran2();
				this.dir=3;
				break;	
			case 3://横着的
				tran3();
				this.dir=4;
				break;
			case 4://竖着的
				tran4();
				this.dir=1;
				break;			
		}

		function tran1(){//变成横着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==0){
					block.x+=1;
				}else if(i==1){
					block.y-=1;
				}else if(i==2){
					block.x-=1;
					block.y-=2;
				}else if(i==3){
					block.x-=1;
				}
			}
		}
		
		function tran2(){//竖着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==0){
					block.x+=1;
					block.y-=1;
				}else if(i==1){
				}else if(i==2){
					block.x-=1;
					block.y+=1
				}else if(i==3){
					block.x+=1;
					block.y+=1
				}
			}
		}
		
		function tran3(){//变成横着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==3){
					block.y-=1;
				}else if(i==2){
					block.y+=1;
				}else if(i==1){
					block.x-=1;
				}else if(i==0){
					block.x-=2;
					block.y-=1
				}
			}
		}
		
		function tran4(){//竖着的
			for(var i=0;i<blocks.length;i++){
				block=blocks[i];
				if(i==3){
				}else if(i==2){
					block.x+=2;
				}else if(i==1){
					block.x+=1;
					block.y+=1
				}else if(i==0){
					block.y+=2;
				}
			}
		}
	}
	
	//移动
	Model.prototype.move=function(dir){
		var cur = this.game.currentModel,dis=1,blocks = this.blocks;
		if(dir=='r'||dir=='ld'){
			dis=1
		}else if(dir=='l'){
			dis=-1;
		}else if(dir=='d'){
			dis=3;
		}
		
		var stopMoveObj = this.stopMove(dir,dis),
			val=stopMoveObj.val,resDis=stopMoveObj.resDis;
		if(val) {
			if(dir=='d'||dir=='ld'){//到底了
				[].push.apply(this.game.aliveModel,cur.blocks);//放到已到底的组合中
				this.game.renderArr.pop();//当前模型弹出
				this.game.clearBlock();//消除
				this.game.createModel();//绘制一个新图形
			}
			
			return ;//如果返回true 则不能再往这个方向移动
		}

		if(resDis>0){
			dis=resDis;
		}
		//更新每一个block的位置
		for(var i=0;i<blocks.length;i++){
			block=blocks[i];
			if(dir=='d'||dir=='ld'){
				block.y+=dis;
			}else{
				block.x+=dis;
			}
		}
	}
	
	//停止移动
	Model.prototype.stopMove=function(dir,dis){
		var cur = this.game.currentModel,blocks = this.blocks;
		
		var maxX = this.game.maxX,maxY = this.game.maxY,res,temp;
		for(var i=0;i<blocks.length;i++){
			block=blocks[i];
			if(dir=='d'||dir=='ld'){
				if(block.y>=maxY-1){//到底了
					return {val:true};
				}
			}else if(dir=='r'){
				if(block.x>=maxX-1){//到右边界了
					return {val:true};
				}
			}else if(dir=='l'){
				if(block.x<=0){//到左边界了
					return {val:true};
				}
			}
			//碰撞检测
			temp=this.collide(block,dis,dir);
			if(temp.val){
				return temp;
			}
			if(!res || res.resDis==0 || (temp.resDis!=0 && temp.resDis<res.resDis)){
				res=temp;
			}
		}
		
		return res;
	}
	//检查当前模型是否与其他存底的模型相触碰
	Model.prototype.collide=function(block,dis,dir){
		var aliveModel = this.game.aliveModel,item;
		var res={},val=false,resDis=0,maxY = this.game.maxY;
		
		if(dir=='r'){//向右判断
			for(var i=0;i<aliveModel.length;i++){
				item = aliveModel[i];
				if(!item) continue;
				if(item.y==block.y && item.x==block.x+1){
					val= true;
					break;
				}
			}
		}else if(dir=='l'){//向左判断
			for(var i=0;i<aliveModel.length;i++){
				item = aliveModel[i];
				if(!item) continue;
				if(item.y==block.y && item.x==block.x-1){
					val= true;
					break;
				}
			}
		}else {//向下判断
			if(aliveModel.length>0){
				for(var i=0;i<aliveModel.length;i++){
					item = aliveModel[i];
					if(!item) continue;
					if(item.x==block.x){//下方有存在的方块
						if(item.y==block.y+1){
							val= true;
							break;
						}else if(item.y<=block.y+Math.abs(dis)){
							var temp=item.y-block.y-1;
							if(resDis==0 || temp<resDis){
								resDis = temp;
							}
						}
					}else{//下发不存在方块
						if(maxY<=block.y+Math.abs(dis)){
							var temp=maxY-block.y-1;
							if(resDis==0 || temp<resDis){
								resDis = temp;
							}
						}
					} 
				}
			}else{//第一个模型
				if(maxY<=block.y+Math.abs(dis)){
					var temp=maxY-block.y-1;
					if(resDis==0 || temp<resDis){
						resDis = temp;
					}
				}
			}
		}
		res.resDis=resDis;
		res.val=val;
		return res;
	}
	
	//绘制
	Model.prototype.render=function(context){
		var ctx=context;
		ctx.save();
		ctx.beginPath();
		//ctx.translate(this.x,this.y);
		var blocks = this.blocks,block,game=this.game,disX=game.disX,disY=game.disY;
		for(var i=0;i<blocks.length;i++){
			block=blocks[i];
			ctx.rect(block.x*disX+1,block.y*disY+1,disX-1,disY-1);
		}
		
		if(this.lineWidth){//线宽
			ctx.lineWidth=this.lineWidth;
		}
		if(this.fill){//是否填充
			this.fillStyle?(ctx.fillStyle=this.fillStyle):null;
			ctx.fill();
		}
		if(this.stroke){//是否描边
			this.strokeStyle?(ctx.strokeStyle=this.strokeStyle):null;
			ctx.stroke();
		}	
		ctx.restore();
		
		return this;
	}
	
	
	//直线的构造
	function Line(ctx,o){
		this.x=0,//x坐标
		this.y=0,//y坐标
		this.startX=0,//开始点x位置
		this.startY=0, //开始点y位置
		this.endX=0,//结束点x位置
		this.endY=0;//结束点y位置
		this.thin=false;//设置变细系数
		this.ctx=ctx;
		
		this.init(o);
	}
	Line.prototype.init=function(o){
		for(var key in o){
			this[key]=o[key];
		}
	}
	Line.prototype.render=function(){
		innerRender(this);
		
		function innerRender(obj){
			var ctx=obj.ctx;
			ctx.save()
			ctx.beginPath();
			ctx.translate(obj.x,obj.y);
			if(obj.thin){
				ctx.translate(0.5,0.5);
			}
			if(obj.lineWidth){//设定线宽
				ctx.lineWidth=obj.lineWidth;
			}
			if(obj.strokeStyle){
				ctx.strokeStyle=obj.strokeStyle;
			}
			//划线
		  	ctx.moveTo(obj.startX, obj.startY);
		  	ctx.lineTo(obj.endX, obj.endY);
		  	ctx.stroke();
		  	ctx.restore();
		}
	  	
	  	return this;
	}
	
	var _= util = {
		//画直线
		drawLine:function (ctx, startX, startY, endX, endY) {
		  	ctx.beginPath();
		  	ctx.moveTo(startX, startY);
		  	ctx.lineTo(endX, endY);
		  	ctx.stroke();
		  	ctx.closePath();
		},
		//获取属性值
		getStyle:function (obj, prop) {
			var prevComputedStyle = document.defaultView ? document.defaultView.getComputedStyle( obj, null ) : obj.currentStyle;
			return prevComputedStyle[prop];
		},
		getRandom:function(min,max){
			return parseInt(Math.random()*(max-min)+min);
		},
		//获取鼠标信息
		getOffset:function(e){
			return {
					x:e.offsetX,
					y:e.offsetY
				};
		},
		//循环
		each:function(arr,fn){
			var len = arr.length;
			for(var i=0;i<len;i++){
				fn(arr[i],i);
			}
		},
		getDecimals:function(value){
			return (value!=Math.floor(value))?(value.toString()).split('.')[1].length:0;
		}
		
		}
	
	var class2type={};	
	_.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(name) {
		class2type[ "[object " + name + "]" ] = name;
	});

	function getType( obj ) {
		return obj == null ?
			String( obj ) :
			class2type[ Object.prototype.toString.call(obj) ] || "undefined";
	}
	
	global.game=game;
})(window)