标签:
试玩(没有考虑兼容低版本浏览器):
源码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>canvas版俄罗斯方块</title>
<style>
#canvas{
background: #000;
display: block;
margin: 0 auto;
}
</style>
</head>
<body>
<p style="text-align: center;">操作:↑变形;↓下移;←左移;→右移</p>
<canvas id="canvas" width="640" height="600">
您的浏览器不支持canvas!
</canvas>
<script>
/****************************
*后续可添加怪异变形,类似于L可变成Z
*改变速度
*积分随关卡递增
*初始化部分historyBlock
****************************/
var tetris = {
canvas : document.getElementById("canvas"),
ctx : this.canvas.getContext("2d"),
width : 500,
height : 600,
score : 0,
unit : 30,
historyBlock : [],
blockData : function(index, row, col){
var r = row || 1,
c = col || Math.floor((this.col - 3)/2) + 2,
block = [
[
{color: ‘red‘, status: 1, data: [{x: r, y:c-1}, {x: r+1, y:c-1}, {x: r+1, y:c}, {x: r+1, y:c+1}], center: {x: r, y: c}},
{color: ‘red‘, status: 2, data: [{x: r-1, y:c-1}, {x: r-1, y:c}, {x: r, y:c-1}, {x: r+1, y:c-1}], center: {x: r, y: c}},
{color: ‘red‘, status: 3, data: [{x: r-1, y:c-1}, {x: r-1, y:c}, {x: r-1, y:c+1}, {x: r, y:c+1}], center: {x: r, y: c}},
{color: ‘red‘, status: 4, data: [{x: r-1, y:c+1}, {x: r, y:c+1}, {x: r+1, y:c+1}, {x: r+1, y:c}], center: {x: r, y: c}}
],
[
{color: ‘green‘, status: 1, center: {x: r, y:c}, data: [{x: r, y:c+1}, {x: r+1, y:c-1}, {x: r+1, y:c}, {x: r+1, y:c+1}]},
{color: ‘green‘, status: 2, center: {x: r, y:c}, data: [{x: r-1, y:c-1}, {x: r, y:c-1}, {x: r+1, y:c-1}, {x: r+1, y:c}]},
{color: ‘green‘, status: 3, center: {x: r, y:c}, data: [{x: r, y:c-1}, {x: r-1, y:c-1}, {x: r-1, y:c}, {x: r-1, y:c+1}]},
{color: ‘green‘, status: 4, center: {x: r, y:c}, data: [{x: r-1, y:c}, {x: r-1, y:c+1}, {x: r, y:c+1}, {x: r+1, y:c+1}]}
],
[
{color: ‘blue‘, status: 1, center: {x: r, y:c}, data: [{x: r, y:c-1}, {x: r, y:c}, {x: r+1, y:c}, {x: r+1, y:c+1}]},
{color: ‘blue‘, status: 2, center: {x: r, y:c}, data: [{x: r+1, y:c-1}, {x: r, y:c-1}, {x: r, y:c}, {x: r-1, y:c}]}
],
[
{color: ‘orange‘, status: 1, center: {x: r, y:c}, data: [{x: r+1, y:c-1}, {x: r+1, y:c}, {x: r, y:c}, {x: r, y:c+1}]},
{color: ‘orange‘, status: 2, center: {x: r, y:c}, data: [{x: r-1, y:c}, {x: r, y:c}, {x: r, y:c+1}, {x: r+1, y:c+1}]}
],
[
{color: ‘yellow‘, status: 1, center: {x: r, y:c}, data: [{x: r, y:c-1}, {x: r, y:c}, {x: r+1, y:c-1}, {x: r+1, y:c}]}
],
[
{color: ‘aqua‘, status: 1, center: {x: r, y:c}, data: [{x: r, y:c-1}, {x: r, y:c}, {x: r, y:c+1}, {x: r-1, y:c}]},
{color: ‘aqua‘, status: 2, center: {x: r, y:c}, data: [{x: r+1, y:c}, {x: r, y:c}, {x: r, y:c+1}, {x: r-1, y:c}]},
{color: ‘aqua‘, status: 3, center: {x: r, y:c}, data: [{x: r, y:c-1}, {x: r, y:c}, {x: r, y:c+1}, {x: r+1, y:c}]},
{color: ‘aqua‘, status: 4, center: {x: r, y:c}, data: [{x: r, y:c-1}, {x: r, y:c}, {x: r+1, y:c}, {x: r-1, y:c}]}
],
[
{color: ‘indigo‘, status: 1, center: {x: r, y:c}, data: [{x: r, y:c-1}, {x: r, y:c}, {x: r, y:c+1}, {x: r, y:c+2}]},
{color: ‘indigo‘, status: 2, center: {x: r, y:c}, data: [{x: r-2, y:c}, {x: r-1, y:c}, {x: r, y:c}, {x: r+1, y:c}]}
]
]
return block[index];
},
init : function(){
var self = this;
self.row = Math.floor(self.height/self.unit);
self.col = Math.floor(self.width/self.unit);
self.curBlockIndex = Math.round(Math.random()*6);
self.curBlocks = self.blockData(self.curBlockIndex);
self.curBlock = self.curBlocks[0];
self.createNext().createMap().move();
self.addEvent("keydown", window, function(ev){
var ev = ev || window.event,
code = ev.keycode || ev.which;
if(self.handle[code]){
self.handle[code].call(self);
self.createMap();
}
ev.preventDefault();
})
return this;
},
createNext: function(){
var self = this;
self.nextBlockIndex = Math.round(Math.random()*6);
self.nextBlocks = self.blockData(self.nextBlockIndex, 4, self.col+3);
self.nextBlock = self.nextBlocks[0];
return this;
},
addEvent : function(ev, ele, callback){
if( ele.addEventListener ){
ele.addEventListener(ev,callback,false);
}else{
ele.attachEvent("on"+ev, callback);
}
},
createMap : function(){
var self = this;
self.ctx.clearRect(0, 0, self.canvas.width, self.canvas.height);
for (var i = 0; i < self.col; i++) {
for (var j = 0; j < self.row; j++) {
self.ctx.save();
self.ctx.strokeStyle = "#171814";
self.ctx.strokeRect(i*self.unit, j*self.unit, self.unit, self.unit);
self.ctx.stroke();
self.ctx.restore();
};
};
self.showText().createBlock();
return this;
},
createBlock : function(){
var self = this,
block = self.curBlock.data;
self.drawRect(self.historyBlock);
if(self.collide(40, true)){
block.map(function(val){
val.x--;
})
setTimeout(function(){
clearInterval(self.timer);
if(localStorage.getItem("score") === null){
localStorage.setItem("score", self.score);
}else if(localStorage.getItem("score") - self.score < 0 ){
localStorage.setItem("score", self.score);
alert("新纪录!"+self.score+"分!");
return;
}
alert("GAME OVER");
},100)
}
self.drawRect(block);
return this;
},
drawRect : function(block){
var self = this;
for (var i = 0; i < block.length; i++) {
self.ctx.save();
self.ctx.fillStyle = block[i].color || self.curBlock.color;
self.ctx.strokeStyle = ‘black‘;
self.ctx.fillRect((block[i].y - 1)*self.unit, (block[i].x - 1)*self.unit, self.unit, self.unit );
self.ctx.strokeRect((block[i].y - 1)*self.unit, (block[i].x - 1)*self.unit, self.unit, self.unit );
self.ctx.restore();
};
},
move : function(){
var self = this;
clearInterval(self.timer);
self.timer = setInterval(function(){
// 实时刷新数据 大坑!
var curBlock = self.curBlock,
data = self.curBlock.data;
if( self.collide() || data.some(function(val){
return val.x + 1 > self.row;
}) ){
clearInterval(self.timer);
self.historyBlock.push.apply(self.historyBlock, data.map(function(val){
val.color = curBlock.color;
return val;
}));
self.remove();
self.curBlockIndex = self.nextBlockIndex;
self.curBlocks = self.blockData(self.curBlockIndex);
self.curBlock = self.curBlocks[0];
self.createNext().createMap().move();
return false;
}
for (var i = 0; i < data.length; i++) {
data[i].x++;
};
self.curBlock.center.x++;
self.createMap();
}, 1000)
},
remove : function(){
var self = this,
count = {},
n = 0,
maxRow = 0,
delArr = [],
block = self.historyBlock;
for (var i = 0; i < block.length; i++) {
if(count[block[i].x]){
count[block[i].x].push(count[block[i].y]);
}else{
count[block[i].x] = [ count[block[i].y] ];
}
};
for (var attr in count) {
if(count[attr].length === self.col){
n++;
self.score += 100;
maxRow = attr > maxRow ? attr : maxRow;
for (var i = 0; i < block.length; i++) {
if(block[i].x == attr){
delArr = block.splice(i, 1);
i--;
}
};
}
};
block.forEach(function(val){
val.x < maxRow && (val.x += n);
})
},
collide : function(direction, isCreate){
var block = JSON.parse(JSON.stringify(this.curBlock)),
result = false,
self = this;
direction = direction || 40;
// direction:碰撞方向,默认下方
if(direction === 37){
self.mLeft(block);
}else if(direction === 38){
block = self.distortion(block);
}else if(direction === 39){
self.mRight(block);
}else if(direction === 40 && !isCreate){
// 非新增方块则往下移动一格
block.data.forEach(function(val){
val.x++;
})
}
result = block.data.some(function(val){
return (val.x > self.row || val.y < 1 || val.y > self.col);
})
if(result){
return result;
}else{
return block.data.some(function(val){
return self.historyBlock.some(function(value){
return (value.x === val.x && value.y === val.y);
})
})
}
},
mLeft : function(block){
if(block.data.every(function(val){
return val.y - 1 >= 1;
})){
block.data.forEach(function(val){
val.y--;
})
block.center.y--;
}
},
mRight : function(block){
var self = this;
if(block.data.every(function(val){
return val.y + 1 <= self.col;
})){
block.data.forEach(function(val){
val.y++;
})
block.center.y++;
}
},
distortion : function(block){
var self = this,
curRow = block.center.x,
curCol = block.center.y,
status = block.status + 1 > self.curBlocks.length ? 1 : block.status + 1;
self.curBlocks = self.blockData(self.curBlockIndex, block.center.x, block.center.y);
return self.curBlocks[status-1];
},
// 控制:上(变形)、右(右移)、下(下移)、左(左移)
handle : {
// 左键 code 37
37: function(){
var self = this;
if(!self.collide(37)){
self.mLeft(self.curBlock);
}
},
// 上键 code 38
38: function(){
var self = this;
if(!self.collide(38)){
self.curBlock = self.distortion(self.curBlock);
}
},
// 右键 code 39
39: function(){
var self = this;
if(!self.collide(39)){
self.mRight(self.curBlock);
}
},
// 下键 code 40
40: function(){
var self = this;
if(!self.collide()){
self.curBlock.data.forEach(function(val){
val.x++;
})
self.curBlock.center.x++;
}
}
},
showText: function(){
var self = this,
ctx = self.ctx;
ctx.save();
ctx.fillStyle = "green";
ctx.font = "20px Verdana";
ctx.fillText("Next:", self.width, 30);
ctx.fillText("Score:", self.width, 200);
ctx.fillText(self.score, self.width, 230);
ctx.fillText("作者:王美建", self.width, 580);
ctx.restore();
self.nextBlock.data.forEach(function(val){
val.color = self.nextBlock.color;
})
self.drawRect(self.nextBlock.data);
return this;
}
}
tetris.init();
</script>
</body>
</html>
持续优化中……
作者:古德God
出处:http://www.cnblogs.com/wangmeijian
本文版权归作者和博客园所有,欢迎转载,转载请标明出处。
如果您觉得本篇博文对您有所收获,请点击右下角的 [推荐],谢谢!
标签:
原文地址:http://www.cnblogs.com/wangmeijian/p/4772898.html