俄羅斯方塊相信大家都玩過(guò)吧,雖然現(xiàn)在大型游戲眾多,但它可謂是童年的美好回憶,經(jīng)常能玩到茶飯不思
那么你知道如何自己做一個(gè)俄羅斯方塊嘛?本篇文章就教你如何用 JavaScript 來(lái)做一個(gè)俄羅斯方塊小游戲
最終游戲效果
一開始我們先搭個(gè)框架,以便后期使用
編寫外部框架
<!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'>分?jǐn)?shù):0</span>
<span id='time' class='span2'>時(shí)間:0</span>
<button onclick='start()' class='button1'>開始</button>
<button onclick='stop()' class='button2'>結(jié)束</button>
</div>
</div>
<script type="text/javascript" src='tetris.js'></script>
<script type="text/javascript">
</script>
</body>
</html>
框架效果如下:
添加內(nèi)部畫布,以及繪制地圖
首先創(chuàng)建線的構(gòu)造函數(shù)Line
function Line(ctx,o){
this.x=0,//x坐標(biāo)
this.y=0,//y坐標(biāo)
this.startX=0,//開始點(diǎn)x位置
this.startY=0, //開始點(diǎn)y位置
this.endX=0,//結(jié)束點(diǎn)x位置
this.endY=0;//結(jié)束點(diǎn)y位置
this.thin=false;//設(shè)置變細(xì)系數(shù)
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){//設(shè)定線寬
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;
}
設(shè)定參數(shù)、執(zhí)行繪制等相關(guān)方法
代碼如下:
function Game(el){
this.renderArr=[];//待渲染對(duì)象存儲(chǔ)數(shù)組
this.aliveModel=[];//用來(lái)存到底的model組合
this.score=0;//分?jǐn)?shù)
this.time=0;//時(shí)間
this.moveCount=1;//計(jì)時(shí)控制器
}
Game.prototype.init=function(el,score,time){
if(!el) return ;
this.el=el;
this.scoreEL=score;
this.timeEL=time;
var canvas = document.createElement('canvas');//創(chuàng)建畫布
canvas.style.cssText="background:darkgrey;border:1px solid grey;";//設(shè)置樣式
var W = canvas.width = 300; //設(shè)置寬度
var H = canvas.height = 400;//設(shè)置高度
el.appendChild(canvas);//添加到指定的dom對(duì)象中
this.ctx = canvas.getContext('2d');
this.canvas=canvas;
this.w=W;
this.h=H;
this.disX=20;//每個(gè)格子的x方向大小
this.disY=20;//每個(gè)格子的y方向大小
this.maxX=15;//x方向格子總數(shù)
this.maxY=20;//y方向格子總數(shù)
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();//渲染
}
此時(shí)游戲區(qū)域的格子以及繪制如下:
再來(lái)繪制模型
模型定義:分別是一字形、田字形、二字形2種、七字形2種、凸字形等共7種。
變形定義:1字形可以變形2種、田字形不能變形,其他的都可以變形4種。
模型的組成:模型是有4個(gè)小方塊來(lái)組成,每個(gè)模型里面有數(shù)組blocks來(lái)存取4個(gè)小方塊的x、y坐標(biāo),然后繪制出來(lái)就是模型了。
模型的變形:變形的時(shí)候就只要切換每個(gè)方塊的X\Y坐標(biāo)就可以達(dá)到變形的效果。
下面來(lái)創(chuàng)建模型的構(gòu)造函數(shù)
//模型構(gòu)造函數(shù)
function Model(o){
this.blocks=[],//存儲(chǔ)方塊的數(shù)組,繪制的時(shí)候根據(jù)數(shù)組來(lái)繪制
this.type=1,//模型的形狀,默認(rèn)是一字形(共7種)
this.dir=1,//方向默認(rèn)為1,總共4種,其中一字形為2種,田字形為1種,其他為4種
this.x=0,//x坐標(biāo)(只傳入第一個(gè)x,根據(jù)這個(gè)x來(lái)生成其他的x)
this.y=0,//y坐標(biāo)(只傳入第一個(gè)y,根據(jù)這個(gè)y來(lái)生成其他的y)
this.init(o);
}
//初始化
Model.prototype.init=function(o){
for(var key in o){
this[key]=o[key];
}
}
舉例
添加一個(gè)創(chuàng)建七字形的方法(因?yàn)槠咦中斡?種擺放方式,所以有dir來(lái)區(qū)分,怎么擺放)
//創(chuàng)建七字形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;
}
}
創(chuàng)建一個(gè)七字形試試(傳入的x、y是第一個(gè)放個(gè)的位置)
var model = new Model({//創(chuàng)建1字
x:6,y:6,fillStyle:'#0370BD',fill:true,game:this,type:5,dir:1
});
this.renderArr.push(model);
//當(dāng)前的模型
this.currentModel=model;
編寫變形方法(每一次變形都是按前一個(gè)模樣逆時(shí)針旋轉(zhuǎn)90度,修改每個(gè)小方塊x、y來(lái)修改就行)
------------------------ >>>
左邊這個(gè)圖形要變成右邊的圖形,需要怎么變更呢?
-------------------->>>
標(biāo)上號(hào)碼就很容易明白,1還是對(duì)應(yīng)的1,2還是對(duì)應(yīng)的2,以此類推,只不過(guò)X\Y變了
1方塊:只要x+2就可以移到指定的位置;
2方塊:x、y都需要加1
3方塊:y+2就可以
4方塊:x-1和y+1即可
其他都是一樣的道理,來(lái)寫一下變形的方法
//七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 和向上鍵添加為變形事件,同時(shí)左移動(dòng)、右移動(dòng)、下加速也添加好事件
//按鍵的控制
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');//移動(dòng)
break;
case 65://a
case 37://左
that.currentModel.move('l');//移動(dòng)
break;
case 68://d
case 39://右
that.currentModel.move('r');//移動(dòng)
break;
}
//測(cè)試用,記得刪除
that.render();
});
}
接下來(lái)變形試試
添加移動(dòng)方法
//移動(dòng)
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();//當(dāng)前模型彈出
this.game.clearBlock();//消除
this.game.createModel();//繪制一個(gè)新圖形
}
return ;//如果返回true 則不能再往這個(gè)方向移動(dòng)
}
if(resDis>0){
dis=resDis;
}
//更新每一個(gè)block的位置
for(var i=0;i<blocks.length;i++){
block=blocks[i];
if(dir=='d'||dir=='ld'){
block.y+=dis;
}else{
block.x+=dis;
}
}
}
加入邊界判斷和碰撞檢測(cè)(邊界檢測(cè)比較簡(jiǎn)單、碰撞檢測(cè)在快進(jìn)的時(shí)候要注意處理一下,看代碼吧)
//停止移動(dòng)
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};
}
}
//碰撞檢測(cè)
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;
}
//檢查當(dāng)前模型是否與其他存底的模型相觸碰
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{//下發(fā)不存在方塊
if(maxY<=block.y+Math.abs(dis)){
var temp=maxY-block.y-1;
if(resDis==0 || temp<resDis){
resDis = temp;
}
}
}
}
}else{//第一個(gè)模型
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;
}
到底后的處理
- 給當(dāng)前的游戲?qū)ο蟮腶liveModel數(shù)組,存取當(dāng)前到底的模型所對(duì)應(yīng)的4個(gè)小方塊(執(zhí)行render方法的時(shí)候就繪制出來(lái))
- 在renderArr數(shù)組中此模型要?jiǎng)h除
- 每次觸底需要加入消除判斷,符合條件就消除
- 繪制一個(gè)新的模型
繪制觸底的模型方塊
//繪制存底的圖形
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++;//行數(shù)計(jì)數(shù)器
that.down(k,1);//清楚當(dāng)前行
}
})
//完成消除
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;
}
});
}
自動(dòng)往下移動(dòng)、更新、顯示時(shí)間、分?jǐn)?shù)
//顯示分?jǐn)?shù)
Game.prototype.calcuScore=function(s){
this.score+=s;
this.scoreEL.innerText='分?jǐn)?shù):'+this.score;
}
//顯示時(shí)間
Game.prototype.calcuTime=function(){
if(this.moveCount%4==0){
this.time++;
this.time_flag=false;
this.timeEL.innerText='時(shí)間:'+this.time;
}
this.moveCount++;
}
//向下移動(dòng)
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');
}
給開始、結(jié)束按鈕加入事件
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){//如果是結(jié)束則需要重新開始,暫停的話就繼續(xù)游戲
this.restart();
}
this.hasEnd=false;
this.timmer = setInterval(this.move.bind(this),250);//開始定時(shí)任務(wù)
}
//重新開始
Game.prototype.restart=function(){
this.renderArr=[];//待渲染對(duì)象存儲(chǔ)數(shù)組
this.aliveModel=[];//用來(lái)存到底的model組合
this.score=0;//分?jǐn)?shù)
this.time=0;//時(shí)間
this.moveCount=1;//計(jì)時(shí)控制器
this.clearCanvas();
this.draw();
}
//停止任務(wù)
Game.prototype.stop=function(){
if(!this.timmer) return ;
clearInterval(this.timmer);//清除定時(shí)任務(wù)
this.timmer=null;
}
//結(jié)束
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('結(jié)束了')
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'>分?jǐn)?shù):0</span>
<span id='time' class='span2'>時(shí)間:0</span>
<button onclick='start()' class='button1'>開始</button>
<button onclick='stop()' class='button2'>結(jié)束</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=[];//待渲染對(duì)象存儲(chǔ)數(shù)組
this.aliveModel=[];//用來(lái)存到底的model組合
this.score=0;//分?jǐn)?shù)
this.time=0;//時(shí)間
this.moveCount=1;//計(jì)時(shí)控制器
}
Game.prototype.init=function(el,score,time){
if(!el) return ;
this.el=el;
this.scoreEL=score;
this.timeEL=time;
var canvas = document.createElement('canvas');//創(chuàng)建畫布
canvas.style.cssText="background:darkgrey;border:1px solid grey;";//設(shè)置樣式
var W = canvas.width = 300; //設(shè)置寬度
var H = canvas.height = 400;//設(shè)置高度
el.appendChild(canvas);//添加到指定的dom對(duì)象中
this.ctx = canvas.getContext('2d');
this.canvas=canvas;
this.w=W;
this.h=H;
this.disX=20;//每個(gè)格子的x方向大小
this.disY=20;//每個(gè)格子的y方向大小
this.maxX=15;//x方向格子總數(shù)
this.maxY=20;//y方向格子總數(shù)
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();//繪制一個(gè)圖形
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++;//行數(shù)計(jì)數(shù)器
that.down(k,1);//清楚當(dāng)前行
}
})
//完成消除
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){//如果是結(jié)束則需要重新開始,暫停的話就繼續(xù)游戲
this.restart();
}
this.hasEnd=false;
this.timmer = setInterval(this.move.bind(this),250);//開始定時(shí)任務(wù)
}
//重新開始
Game.prototype.restart=function(){
this.renderArr=[];//待渲染對(duì)象存儲(chǔ)數(shù)組
this.aliveModel=[];//用來(lái)存到底的model組合
this.score=0;//分?jǐn)?shù)
this.time=0;//時(shí)間
this.moveCount=1;//計(jì)時(shí)控制器
this.clearCanvas();
this.draw();
}
//停止任務(wù)
Game.prototype.stop=function(){
if(!this.timmer) return ;
clearInterval(this.timmer);//清除定時(shí)任務(wù)
this.timmer=null;
}
//結(jié)束
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('結(jié)束了')
return true;
}
}
return false
}
//顯示分?jǐn)?shù)
Game.prototype.calcuScore=function(s){
this.score+=s;
this.scoreEL.innerText='分?jǐn)?shù):'+this.score;
}
//顯示時(shí)間
Game.prototype.calcuTime=function(){
if(this.moveCount%4==0){
this.time++;
this.time_flag=false;
this.timeEL.innerText='時(shí)間:'+this.time;
}
this.moveCount++;
}
//向下移動(dòng)
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');//移動(dòng)
break;
case 65://a
case 37://左
that.currentModel.move('l');//移動(dòng)
break;
case 68://d
case 39://右
that.currentModel.move('r');//移動(dòng)
break;
}
//測(cè)試用,記得刪除
//that.render();
});
}
Game.prototype.clearCanvas=function(){
this.ctx.clearRect(0,0,parseInt(this.w),parseInt(this.h));//清理畫布
}
//創(chuàng)建模型
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({//隨機(jī)創(chuàng)建
x:6,y:-1,fillStyle:'#0370BD',fill:true,game:this,type:type,dir:dir
});
this.renderArr.push(model);
//當(dāng)前的模型
this.currentModel=model;
/*
model = new Model({//創(chuàng)建橫向1字
x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:1,dir:1
});
model = new Model({//創(chuàng)建田字
x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:2,dir:1
});
model = new Model({//創(chuàng)建二字1
x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:3,dir:4
});
model = new Model({//創(chuàng)建二字2
x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:4,dir:1
});
model = new Model({//創(chuàng)建七字1
x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:5,dir:4
});
model = new Model({//創(chuàng)建七字2
x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:6,dir:4
});
model = new Model({//創(chuàng)建凸字
x:5,y:4,fillStyle:'#0370BD',fill:true,game:this,type:7,dir:4
});
*/
}
//模型構(gòu)造函數(shù)
function Model(o){
this.blocks=[],//存儲(chǔ)方塊的數(shù)組,繪制的時(shí)候根據(jù)數(shù)組來(lái)繪制
this.type=1,//模型的形狀,默認(rèn)是一字形(共7種)
this.dir=1,//方向默認(rèn)為1,總共4種,其中一字形為2種,田字形為1種,其他為4種
this.x=0,//x坐標(biāo)(只傳入第一個(gè)x,根據(jù)這個(gè)x來(lái)生成其他的x)
this.y=0,//y坐標(biāo)(只傳入第一個(gè)y,根據(jù)這個(gè)y來(lái)生成其他的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();//創(chuàng)建一字形
break;
case 2:
this.createTian();//創(chuàng)建田字形
break;
case 3:
this.createEr1();//創(chuàng)建字二形1
break;
case 4:
this.createEr2();//創(chuàng)建二字形2
break;
case 5:
this.createQi1();//創(chuàng)建七字形1
break;
case 6:
this.createQi2();//創(chuàng)建七字形2
break;
case 7:
this.createTu();//創(chuàng)建凸字形
break;
}
}
//創(chuàng)建一字形
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;
}
}
//創(chuàng)建田字形
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;
}
}
//創(chuàng)建二字形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;
}
}
//創(chuàng)建二字形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;
}
}
//創(chuàng)建七字形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;
}
}
//創(chuàng)建七字形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;
}
}
//創(chuàng)建凸字形
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://田
//無(wú)需變形
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;
}
}
}
}
//移動(dòng)
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();//當(dāng)前模型彈出
this.game.clearBlock();//消除
this.game.createModel();//繪制一個(gè)新圖形
}
return ;//如果返回true 則不能再往這個(gè)方向移動(dòng)
}
if(resDis>0){
dis=resDis;
}
//更新每一個(gè)block的位置
for(var i=0;i<blocks.length;i++){
block=blocks[i];
if(dir=='d'||dir=='ld'){
block.y+=dis;
}else{
block.x+=dis;
}
}
}
//停止移動(dòng)
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};
}
}
//碰撞檢測(cè)
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;
}
//檢查當(dāng)前模型是否與其他存底的模型相觸碰
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{//下發(fā)不存在方塊
if(maxY<=block.y+Math.abs(dis)){
var temp=maxY-block.y-1;
if(resDis==0 || temp<resDis){
resDis = temp;
}
}
}
}
}else{//第一個(gè)模型
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;
}
//直線的構(gòu)造
function Line(ctx,o){
this.x=0,//x坐標(biāo)
this.y=0,//y坐標(biāo)
this.startX=0,//開始點(diǎn)x位置
this.startY=0, //開始點(diǎn)y位置
this.endX=0,//結(jié)束點(diǎn)x位置
this.endY=0;//結(jié)束點(diǎn)y位置
this.thin=false;//設(shè)置變細(xì)系數(shù)
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){//設(shè)定線寬
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);
},
//獲取鼠標(biāo)信息
getOffset:function(e){
return {
x:e.offsetX,
y:e.offsetY
};
},
//循環(huán)
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)