canvas版2048,PC端上下左右控制,并支持移動(dòng)端滑動(dòng)控制(發(fā)現(xiàn)canvas做這種小游戲真是方便?。?/h3>
首先用一個(gè)center標(biāo)簽顯示Score,然后用一個(gè)canvas標(biāo)簽繪制游戲畫面
<center id="score" style="font:bold 25px Arial,Microsoft Yahei"></center><br/>
<canvas id="canvas" width="500" height="500"></canvas>
然后設(shè)置canvas的樣式
canvas{
display: block;
margin: 0 auto;
border-radius: 10px;
background-color: #bbada0;
}
設(shè)置后的canvas看起來像這樣
然后進(jìn)行地圖的初始化以及一些數(shù)據(jù)結(jié)構(gòu)定義
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
//初始化地圖
var map = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]];
//不同數(shù)字的顏色信息
var num_color = {0:"#ccc0b3",2:"#eee4da",4:"#ede0c8",8:"#f2b179",16:"#f59563",32:"#f67c5f",64:"#ec6544",128:"#e44d29",256:"#edcf72",512:"#c8a145",1024:"#a8832b",2048:"#86aa9c"};
//不同數(shù)字的大小信息
var num_size = {0:"60",2:"60",4:"60",8:"60",16:"60",32:"60",64:"60",128:"50",256:"50",512:"50",1024:"40",2048:"40"};
//不同數(shù)字的偏移量(為了將數(shù)字畫在方塊中心)
var offsetx = {0:53,2:53,4:53,8:53,16:34,32:35,64:35,128:28,256:28,512:28,1024:24,2048:25};
//上下左右鍵的code對(duì)應(yīng)的方向信息
var keycom = {'38':[0,-1],'40':[0,1],'37':[-1,0],'39':[1,0]}
//space表示當(dāng)前剩余的空格塊數(shù),score表示當(dāng)前的分?jǐn)?shù)
var space=16,score=0;
formap函數(shù)用來遍歷地圖中4×4的方格并執(zhí)行操作
function formap(func){
for(var i=0;i<4;i++)
for(var j=0;j<4;j++){
func(i,j);
}
}
produce函數(shù)用來在地圖的空白處隨機(jī)生成一個(gè)方塊,并重繪地圖,這里“~~”操作是為了取整
function produce(){
var cot = ~~(Math.random()*space);
var k = 0;
formap(function(i,j){
if(map[i][j]==0){
if(cot==k){
map[i][j]=2;
draw();
}
k+=1;
}
});
space-=1;
}
draw函數(shù)用來繪制地圖,包括每個(gè)小方格的繪制和Score的更新
function draw(){
formap(function(i,j){
var num = map[i][j];
ctx.fillStyle = num_color[num];
ctx.fillRect(j*120+20,i*120+20,100,100);
if(num!=0){
ctx.font = "bold "+num_size[num]+"px Arial,Microsoft Yahei";
ctx.fillStyle = (num<=4)?"#776e65":"white";
ctx.fillText(String(map[i][j]),j*120+offsetx[num],i*120+70+num_size[num]/3);
}
});
document.getElementById("score").innerText="Score: "+String(score);
}
move函數(shù)用來處理方塊的移動(dòng)
function move(dir){
//用來調(diào)整不同方向的遍歷方式
function modify(x,y){
tx=x,ty=y;
if(dir[0]==0)tx=[ty,ty=tx][0];
if(dir[1]>0)tx=3-tx;
if(dir[0]>0)ty=3-ty;
return [tx,ty];
}
//根據(jù)移動(dòng)的方向,將地圖中對(duì)應(yīng)行/列中的數(shù)字一個(gè)個(gè)壓入棧中,如果第一次遇到棧頂數(shù)字和待入棧數(shù)字相等,則棧頂數(shù)字乘2,最后用棧中數(shù)字更新地圖中的對(duì)應(yīng)行/列
for(var i=0;i<4;i++){
var tmp = Array();
var isadd = false;
for(var j=0;j<4;j++){
var ti=modify(i,j)[0],tj=modify(i,j)[1];
if(map[ti][tj]!=0){
if(!isadd&&map[ti][tj]==tmp[tmp.length-1])score+=(tmp[tmp.length-1]*=2),isadd=true,space+=1;
else tmp.push(map[ti][tj]);
}
}
for(var j=0;j<4;j++){
var ti=modify(i,j)[0],tj=modify(i,j)[1];
map[ti][tj] = isNaN(tmp[j])?0:tmp[j];
}
}
produce();
if(space==0)alert("game over");
draw();
}
隨機(jī)生成兩個(gè)方塊,開始游戲
produce();produce();
監(jiān)聽鍵盤的上下左右事件,并調(diào)用move方法
document.onkeydown=function(e){
dir = keycom[(e?e:event).keyCode];
move(dir);
};
監(jiān)聽移動(dòng)端屏幕的touch事件,判斷滑動(dòng)方向,并調(diào)用move方法
var sx,sy,dx,dy,ex,ey;
canvas.ontouchstart=function(event){
var touch = event.touches[0];
sx=touch.clientX,sy=touch.clientY;
}
canvas.ontouchmove=function(event){
var touch = event.touches[0];
ex=touch.clientX,ey=touch.clientY;
dx=ex-sx,dy=ey-sy;
//禁止默認(rèn)的滑動(dòng)事件
event.preventDefault();
}
canvas.ontouchend=function(event){
//根據(jù)橫縱坐標(biāo)位移判斷滑動(dòng)方向
if(dy<-50&&Math.abs(dy/dx)>2)move([0,-1]);
if(dy>50&&Math.abs(dy/dx)>2)move([0,1]);
if(dx<-50&&Math.abs(dx/dy)>2)move([-1,0]);
if(dx>50&&Math.abs(dx/dy)>2)move([1,0]);
}
像這樣,一個(gè)簡(jiǎn)單的web版2048游戲就做好啦~~
完整代碼已上傳到我的github上
<center id="score" style="font:bold 25px Arial,Microsoft Yahei"></center><br/>
<canvas id="canvas" width="500" height="500"></canvas>
canvas{
display: block;
margin: 0 auto;
border-radius: 10px;
background-color: #bbada0;
}

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
//初始化地圖
var map = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]];
//不同數(shù)字的顏色信息
var num_color = {0:"#ccc0b3",2:"#eee4da",4:"#ede0c8",8:"#f2b179",16:"#f59563",32:"#f67c5f",64:"#ec6544",128:"#e44d29",256:"#edcf72",512:"#c8a145",1024:"#a8832b",2048:"#86aa9c"};
//不同數(shù)字的大小信息
var num_size = {0:"60",2:"60",4:"60",8:"60",16:"60",32:"60",64:"60",128:"50",256:"50",512:"50",1024:"40",2048:"40"};
//不同數(shù)字的偏移量(為了將數(shù)字畫在方塊中心)
var offsetx = {0:53,2:53,4:53,8:53,16:34,32:35,64:35,128:28,256:28,512:28,1024:24,2048:25};
//上下左右鍵的code對(duì)應(yīng)的方向信息
var keycom = {'38':[0,-1],'40':[0,1],'37':[-1,0],'39':[1,0]}
//space表示當(dāng)前剩余的空格塊數(shù),score表示當(dāng)前的分?jǐn)?shù)
var space=16,score=0;
function formap(func){
for(var i=0;i<4;i++)
for(var j=0;j<4;j++){
func(i,j);
}
}
function produce(){
var cot = ~~(Math.random()*space);
var k = 0;
formap(function(i,j){
if(map[i][j]==0){
if(cot==k){
map[i][j]=2;
draw();
}
k+=1;
}
});
space-=1;
}
function draw(){
formap(function(i,j){
var num = map[i][j];
ctx.fillStyle = num_color[num];
ctx.fillRect(j*120+20,i*120+20,100,100);
if(num!=0){
ctx.font = "bold "+num_size[num]+"px Arial,Microsoft Yahei";
ctx.fillStyle = (num<=4)?"#776e65":"white";
ctx.fillText(String(map[i][j]),j*120+offsetx[num],i*120+70+num_size[num]/3);
}
});
document.getElementById("score").innerText="Score: "+String(score);
}
function move(dir){
//用來調(diào)整不同方向的遍歷方式
function modify(x,y){
tx=x,ty=y;
if(dir[0]==0)tx=[ty,ty=tx][0];
if(dir[1]>0)tx=3-tx;
if(dir[0]>0)ty=3-ty;
return [tx,ty];
}
//根據(jù)移動(dòng)的方向,將地圖中對(duì)應(yīng)行/列中的數(shù)字一個(gè)個(gè)壓入棧中,如果第一次遇到棧頂數(shù)字和待入棧數(shù)字相等,則棧頂數(shù)字乘2,最后用棧中數(shù)字更新地圖中的對(duì)應(yīng)行/列
for(var i=0;i<4;i++){
var tmp = Array();
var isadd = false;
for(var j=0;j<4;j++){
var ti=modify(i,j)[0],tj=modify(i,j)[1];
if(map[ti][tj]!=0){
if(!isadd&&map[ti][tj]==tmp[tmp.length-1])score+=(tmp[tmp.length-1]*=2),isadd=true,space+=1;
else tmp.push(map[ti][tj]);
}
}
for(var j=0;j<4;j++){
var ti=modify(i,j)[0],tj=modify(i,j)[1];
map[ti][tj] = isNaN(tmp[j])?0:tmp[j];
}
}
produce();
if(space==0)alert("game over");
draw();
}
produce();produce();
document.onkeydown=function(e){
dir = keycom[(e?e:event).keyCode];
move(dir);
};
var sx,sy,dx,dy,ex,ey;
canvas.ontouchstart=function(event){
var touch = event.touches[0];
sx=touch.clientX,sy=touch.clientY;
}
canvas.ontouchmove=function(event){
var touch = event.touches[0];
ex=touch.clientX,ey=touch.clientY;
dx=ex-sx,dy=ey-sy;
//禁止默認(rèn)的滑動(dòng)事件
event.preventDefault();
}
canvas.ontouchend=function(event){
//根據(jù)橫縱坐標(biāo)位移判斷滑動(dòng)方向
if(dy<-50&&Math.abs(dy/dx)>2)move([0,-1]);
if(dy>50&&Math.abs(dy/dx)>2)move([0,1]);
if(dx<-50&&Math.abs(dx/dy)>2)move([-1,0]);
if(dx>50&&Math.abs(dx/dy)>2)move([1,0]);
}
