标签:
试玩(没有考虑兼容低版本浏览器):
源码:
<!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