1、效果原理图片
2、直接上代码
1、index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>rasian square</title>
<style type="text/css">
*{margin: 0;padding: 0;}
table{display: block;margin: 20px auto;width: 200px;}
table,td{border: 1px solid #999999;border-collapse: collapse;}
td{width: 20px;height: 20px;line-height: 20px;text-align: center;}
.center{text-align: center;}
</style>
</head>
<body>
<div class="center">
得分:<span id="score">0</span>
</div>
<table></table>
<div class="center">
<button onclick="start()">开始</button>
<button onclick="reload()">重新开始</button>
<button onclick="rotate()">旋转</button>
</div>
<script type="text/javascript" src="./js/common.js"></script>
<script type="text/javascript" src="./js/data.js"></script>
<script type="text/javascript" src="./js/game.js"></script>
<script type="text/javascript" src="./js/block.js"></script>
<script type="text/javascript">
var rows = 20,
verticals = 10,
speed = 200,
datas = Array.prototype.slice.call(Object.keys(data)),
g = new Game(rows, verticals),
block,
fixedData = [],
scores = 0;
function start() {
block = new square[datas[Math.floor(Math.random()*datas.length)]](speed);
var timer = setInterval(function(){
//触底
for(var i = 0;i < 4;i++) {
if(block.body[i]["x"] >= rows - 1) {
fixedData = fixedData.concat(block.body);
clearInterval(block.move);
block = new square[datas[Math.floor(Math.random()*datas.length)]](speed);
};
for(var j = 0;j < fixedData.length; j++) {
//积累超出画布,游戏结束
if(block.body[i]["x"] + 1 == fixedData[j]["x"] && block.body[i]["y"] == fixedData[j]["y"] && block.body[i]["x"] < 0) {
clearInterval(block.move);
clearInterval(timer);
};
//碰到已有块
if(block.body[i]["x"] + 1 == fixedData[j]["x"] && block.body[i]["y"] == fixedData[j]["y"]) {
fixedData = fixedData.concat(block.body);
clearInterval(block.move);
block = new square[datas[Math.floor(Math.random()*datas.length)]](speed);
}
};
};
score();
var renderData = fixedData.concat(block.body);
g.render(renderData);
},speed);
};
function rotate() {
clearInterval(block.move);
block.rotate();
for(var i = 0;i < 4;i++) {
if(block.body[i]["y"] < 0 || block.body[i]["y"] >= verticals || block.body[i]["x"] >= rows) {
block.body = block.preBody;
};
};
block.move = setInterval(function(){block.down()}, speed);
};
function reload() {
window.location.reload();
};
function judgeLeftOrRight(direction) {
for(var i = 0;i < 4;i++) {
if(direction == 'left' ? block.body[i]["y"] <= 0 : block.body[i]["y"] >= verticals - 1 ) {
return true;
};
for(var j = 0;j < fixedData.length; j++) {
if(block.body[i]["x"] == fixedData[j]["x"] && (direction == 'left' ? block.body[i]["y"] - 1 : block.body[i]["y"] + 1) == fixedData[j]["y"]) {
return true;
}
};
};
return false;
};
function moveLeftOrRight(direction) {
clearInterval(block.move);
for(var i = 0;i < 4;i++) {
direction == 'left' ? block.body[i].y -= 1 : block.body[i].y += 1;
};
block.move = setInterval(function(){block.down()}, speed);
};
function score() {
var map = {};
for(var j = 0;j < fixedData.length; j++) {
var temp = fixedData[j]["x"];
if(map[temp]) {
map[temp] += 1;
}else{
map[temp] = 1;
}
};
for(key in map) {
if(map[key] == verticals) {
fixedData = fixedData.filter(function(item) {
return item.x != key;
});
for(var j = 0;j < fixedData.length; j++) {
if(fixedData[j]["x"] < key) {
fixedData[j]["x"] += 1;
}
};
scores += 100;
document.getElementById("score").innerHTML = scores;
}
};
};
document.onkeydown = function(event){
event = event || window.event;
if(event.keyCode == 37) { //left
if(!judgeLeftOrRight('left')) {
moveLeftOrRight('left');
}
} else if (event.keyCode == 39) { //right
if(!judgeLeftOrRight('right')) {
moveLeftOrRight('right');
}
} else if (event.keyCode == 32) { //space
rotate();
}
};
</script>
</body>
</html>
2、common.js 这个方法之前百度上面看到,就蛮用了
var util = (function () {
var class2type = {};
["Null", "Undefined", "Number", "Boolean", "String", "Object", "Function", "Array", "RegExp", "Date"].forEach(function (item) {
class2type["[object " + item + "]"] = item.toLowerCase();
})
function isType(obj, type) {
return getType(obj) === type;
}
function getType(obj) {
return class2type[Object.prototype.toString.call(obj)] || "object";
}
return {
isType: isType,
getType: getType
}
})();
//对象深,浅拷贝
function copy(obj, deep) {
if (obj === null || typeof obj !== "object") {
return obj;
}
var i, target = this.util.isType(obj, "array") ? [] : {}, value, valueType;
for (i in obj) {
value = obj[i];
valueType = this.util.getType(value);
if (deep && (valueType === "array" || valueType === "object")) {
target[i] = this.copy(value);
} else {
target[i] = value;
}
}
return target;
}
3、data.js
var data = {
/**
* ######
* ##
*下折线
**/
DLine : {
init: [
{x: -2, y: 4},
{x: -3, y: 4},
{x: -3, y: 5},
{x: -3, y: 6}
],
degree0_90: [
{x: -1, y: 0},
{x: 0, y: 1},
{x: 1, y: 0},
{x: 2, y: -1}
],
degree90_180: [
{x: 0, y: 1},
{x: 1, y: 0},
{x: 0, y: -1},
{x: -1, y: -2}
],
degree180_270: [
{x: 1, y: 0},
{x: 0, y: -1},
{x: -1, y: 0},
{x: -2, y: 1}
],
degree270_360: [
{x: 0, y: -1},
{x: -1, y: 0},
{x: 0, y: 1},
{x: 1, y: 2}
]
},
/**
* ##
* ######
*上折线
**/
ULine : {
init: [
{x: -3, y: 4},
{x: -3, y: 5},
{x: -3, y: 6},
{x: -4, y: 4}
],
degree0_90: [
{x: 0, y: 1},
{x: 1, y: 0},
{x: 2, y: -1},
{x: 1, y: 2}
],
degree90_180: [
{x: 1, y: 0},
{x: 0, y: -1},
{x: -1, y: -2},
{x: 2, y: -1}
],
degree180_270: [
{x: 0, y: -1},
{x: -1, y: 0},
{x: -2, y: 1},
{x: -1, y: -2}
],
degree270_360: [
{x: -1, y: 0},
{x: 0, y: 1},
{x: 1, y: 2},
{x: -2, y: 1}
]
},
/**
* ##
* ##
* ##
* ##
*直线
**/
Line : {
init: [
{x: -1, y: 4},
{x: -2, y: 4},
{x: -3, y: 4},
{x: -4, y: 4}
],
degree0_90: [
{x: -2, y: -1},
{x: -1, y: 0},
{x: 0, y: 1},
{x: 1, y: 2}
],
degree90_180: [
{x: -1, y: 2},
{x: 0, y: 1},
{x: 1, y: 0},
{x: 2, y: -1}
],
degree180_270: [
{x: 2, y: 1},
{x: 1, y: 0},
{x: 0, y: -1},
{x: -1, y: -2}
],
degree270_360: [
{x: 1, y: -2},
{x: 0, y: -1},
{x: -1, y: 0},
{x: -2, y: 1}
]
},
/**
* ##
* ######
*凸
**/
Raised : {
init: [
{x: -2, y: 3},
{x: -2, y: 4},
{x: -2, y: 5},
{x: -3, y: 4}
],
degree0_90: [
{x: -2, y: 1},
{x: -1, y: 0},
{x: 0, y: -1},
{x: 0, y: 1}
],
degree90_180: [
{x: 1, y: 2},
{x: 0, y: 1},
{x: -1, y: 0},
{x: 1, y: 0}
],
degree180_270: [
{x: 2, y: -1},
{x: 1, y: 0},
{x: 0, y: 1},
{x: 0, y: -1}
],
degree270_360: [
{x: -1, y: -2},
{x: 0, y: -1},
{x: 1, y: 0},
{x: -1, y: 0}
]
},
/**
* ####
* ####
*方块
**/
Square : {
init: [
{x: -2, y: 4},
{x: -2, y: 5},
{x: -3, y: 4},
{x: -3, y: 5}
],
degree0_90: [
{x: 0, y: 0},
{x: 0, y: 0},
{x: 0, y: 0},
{x: 0, y: 0}
],
degree90_180: [
{x: 0, y: 0},
{x: 0, y: 0},
{x: 0, y: 0},
{x: 0, y: 0}
],
degree180_270: [
{x: 0, y: 0},
{x: 0, y: 0},
{x: 0, y: 0},
{x: 0, y: 0}
],
degree270_360: [
{x: 0, y: 0},
{x: 0, y: 0},
{x: 0, y: 0},
{x: 0, y: 0}
]
},
/**
* ####
* ####
*左移块
**/
LSquare : {
init: [
{x: -2, y: 4},
{x: -2, y: 5},
{x: -3, y: 3},
{x: -3, y: 4}
],
degree0_90: [
{x: -1, y: 0},
{x: 0, y: -1},
{x: -1, y: 2},
{x: 0, y: 1}
],
degree90_180: [
{x: 1, y: 2},
{x: 0, y: 1},
{x: 1, y: 0},
{x: 0, y: -1}
],
degree180_270: [
{x: 1, y: -2},
{x: 0, y: -1},
{x: 1, y: 0},
{x: 0, y: 1}
],
degree270_360: [
{x: -1, y: 0},
{x: 0, y: 1},
{x: -1, y: -2},
{x: 0, y: -1}
]
},
/**
* ####
* ####
*右移块
**/
RSquare : {
init: [
{x: -2, y: 4},
{x: -2, y: 5},
{x: -3, y: 5},
{x: -3, y: 6}
],
degree0_90: [
{x: -1, y: 0},
{x: 0, y: -1},
{x: 1, y: 0},
{x: 2, y: -1}
],
degree90_180: [
{x: 0, y: 1},
{x: -1, y: 0},
{x: 0, y: -1},
{x: -1, y: -2}
],
degree180_270: [
{x: 1, y: 0},
{x: 0, y: 1},
{x: -1, y: 0},
{x: -2, y: 1}
],
degree270_360: [
{x: 0, y: -1},
{x: 1, y: 0},
{x: 0, y: 1},
{x: 1, y: 2}
]
}
};
4、game.js
function Game(rows, verticals) {
this.rows = rows;
this.verticals = verticals;
this.tds = [];
this.init();
}
Game.prototype = {
constructor: Game,
init: function() {
var table= document.getElementsByTagName('table')[0];
for(var i = 0; i < this.rows; i++) {
var tr = document.createElement('tr');
var tdsTr = [];
for(var j = 0;j < this.verticals; j++) {
var td = document.createElement('td');
tr.appendChild(td);
tdsTr.push(td);
};
table.appendChild(tr);
this.tds.push(tdsTr);
};
},
render: function(array) {
var self = this;
if(!util.isType(array, "array")) {
console.log('game render data must be array');
return;
};
for(var i = 0;i < self.tds.length;i++) {
for(var j = 0;j < self.tds[i].length;j++) {
self.tds[i][j].style.background = '';
}
};
for(var i = 0;i < array.length; i++) {
if(self.tds[array[i].x] && self.tds[array[i].x][array[i].y]) {
self.tds[array[i].x][array[i].y].style.background = '#999999';
}
};
}
}
5、block.js
;
var square = {};
Object.keys(data).forEach(function(obj) {
square[obj] = function(speed) {
this.speed = speed;
this.body = copy(data[obj]['init'],"deep");
this.degree0_90 = data[obj]["degree0_90"];
this.degree90_180 = data[obj]["degree90_180"];
this.degree180_270 = data[obj]["degree180_270"];
this.degree270_360 = data[obj]["degree270_360"];
this.preBody = '';
this.move = '';
this.state = 0;
this.init();
};
square[obj].prototype = {
constructor: square[obj],
init: function() {
var self = this;
self.move = setInterval(function() {
self.down();
}, self.speed);
},
down: function() {
var self = this;
self.preBody = copy(self.body,"deep");
self.body[0]["x"] += 1;
self.body[1]["x"] += 1;
self.body[2]["x"] += 1;
self.body[3]["x"] += 1;
// console.log('self.body');
// console.log(self.body);
},
rotate: function() {
var self = this;
self.body[0]["x"] += self['degree'+self.state+'_'+(self.state+90)][0]["x"];
self.body[0]["y"] += self['degree'+self.state+'_'+(self.state+90)][0]["y"];
self.body[1]["x"] += self['degree'+self.state+'_'+(self.state+90)][1]["x"];
self.body[1]["y"] += self['degree'+self.state+'_'+(self.state+90)][1]["y"];
self.body[2]["x"] += self['degree'+self.state+'_'+(self.state+90)][2]["x"];
self.body[2]["y"] += self['degree'+self.state+'_'+(self.state+90)][2]["y"];
self.body[3]["x"] += self['degree'+self.state+'_'+(self.state+90)][3]["x"];
self.body[3]["y"] += self['degree'+self.state+'_'+(self.state+90)][3]["y"];
self.state = self.state == 270 ? 0 : self.state + 90;
}
}
});
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。