Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

How do I use JavaScript for a Russian block game?


May 30, 2021 Article blog


Table of contents


Russian blocks believe that everyone has played it, although there are many big games now, but it can be described as a good childhood memories, often can play tea and dinner without thinking

So you know how to make a Russian block yourself? This article teaches you how to make a Russian block game with JavaScript

The final game effect

 How do I use JavaScript for a Russian block game?1

Let's start with a framework for later use

Write an external framework

<!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>

The framework effect is as follows:

 How do I use JavaScript for a Russian block game?2

Add an internal canvas and draw a map

Start by creating line constructor 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;
	}

Set parameters, perform drawing and other related methods

The code is as follows:

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++){//20var 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++){//15var 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();//渲染
	}

At this point, the grid of the game area is drawn as follows:

 How do I use JavaScript for a Russian block game?3

Let's draw the model again

Model definition: one glyph, tian glyph, two glyphs 2 kinds, seven glyphs 2 kinds, convex glyphs and so on a total of 7 kinds.

 How do I use JavaScript for a Russian block game?4

Deformation definition: 1 glyph can be deformed 2 kinds, field glyphs can not be deformed, the other can be deformed 4 kinds.

The composition of the model: The model is made up of 4 small squares, each model has a number of blocks to access the 4 small blocks of x, y coordinates, and then draw out is the model.

Deformation of the model: When deforming, you can achieve the effect of deformation by simply switching the X-Y coordinates of each block.

Here's the constructor for the model

	//模型构造函数
	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];
		}
	}

Example

Add a way to create a seven-shaped shape (because there are four placements for the seven glyphs, there is a dir to distinguish and how to place them)

//创建七字形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;	
		}
	}

Create a seven-shaped try (incoming x, y is the first place to put)

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;

Write a deformation method (each deformation rotates 90 degrees counterclockwise as before, modifying each small block x, y to modify the line)

 How do I use JavaScript for a Russian block game?5 ------------------------ >>>  How do I use JavaScript for a Russian block game?6

How does this graphic on the left need to be changed to become the one on the right?

 How do I use JavaScript for a Russian block game?7 -------------------->>>  How do I use JavaScript for a Russian block game?8

It's easy to see if 1 is the corresponding 1, 2 or the corresponding 2, and so on, but X-Y has changed

1 block: as long as x plus 2 can be moved to the specified position;

2 blocks: x, y need to add 1

3 blocks: y plus 2 on it

4 blocks: x-1 and y-1

Everything else is the same, write about the deformation method

//七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;
				}
			}
		}
	}

Add w and up keys as deformation events, while moving left, right, and accelerating down also add good events

//按键的控制
	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();
		});
	}

Try the deformation next

 How do I use JavaScript for a Russian block game?9

Add a move method

//移动
	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;
			}
		}
	}

Add boundary judgment and collision detection (border detection is relatively simple, collision detection in fast-forwarding should pay attention to deal with, look at the code)

//停止移动
	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;
	}

 How do I use JavaScript for a Russian block game?10

After the end of the treatment

 How do I use JavaScript for a Russian block game?11

  1. Give the current game object an array of liveModels and access the four small squares corresponding to the current model (drawn when the render method is executed)
  2. In the renderArr array this model is to be removed
  3. Each bottom needs to be added to eliminate judgment, eligible to eliminate
  4. Draw a new model

Draws the bottom of the model square

//绘制存底的图形
	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();
	}

Eliminate lines, points, and drops

//消除行
	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;
			}
		});
	}

Move down automatically, update, display time, score

//显示分数
	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');
	}

Add an event to the Start and End buttons

	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
	}

The source code is as follows:

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)