JS俄罗斯方块,包含完整的设计理念


Posted in Javascript onDecember 11, 2010

下面是俄罗斯方块的截图:
JS俄罗斯方块,包含完整的设计理念
请到这里下载源码:

俄罗斯方块 在线演示 下载地址
下面是代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" > 
<head> 
<title></title> 
<script type="text/javascript"> 
/********************************************js俄罗斯方块源码***********************************************/ 
//作者:高山流水 QQ:21243468 
//创建日期:2009-08-06 
//版权声明:该作品由高山流水创作,转载请注明出处,谢谢合作! 
//游戏设计说明: 
//1.由于该游戏属于二维游戏,所以布置好网格是写好该游戏的关键,无论是游戏窗口还是预览窗口、 
//方块集虚拟map等都用到了网格的概念,这样做的好处可以避免频繁的获取元素的位置,另外还可以对方块集的移动 
//进行精确的定位和变形。这里比较重要的一点就是提前定义好方块集的map,比如对于L方块集,应定义一个三乘三的正方形 
//网格,然后根据L的每一个形状,确定方块集中的每个方块在正方形网格中的位置,另外还需要保存方块集在map 
//(游戏窗口或者预览窗)中的位置,这样任意时刻,通过方块集的位置,和方块在正方形网格中的位置,就可以确定 
//方块集中的每一个方块在map中的位置。 
//2.该游戏主要用到了一些OOP的思想。比如定义一个基类base,方块集类继承自base类,其中还有对象的封装,属性, 
//枚举的定义等,当然还有事件,委托,attribute,垃圾收集器等,因为时间关系,就不做代码演示了,各位有兴趣可以自己 
//扩展一下,加深对js OOP的理解。 
//3.js内置对象的扩展:比如Array.prototype.removeAt等 
/********************************************js俄罗斯方块源码**********************************************/ 
var Sys = null; 
function sys() { } 
sys.prototype = { 
GameMap: [], 
PreviewMap: [], 
BlocksObj: [], 
Timer: null, 
HorizontalNum: 10, //游戏map的水平格数 
VerticalNum: 18, //游戏map的竖直格数 
IsGameOver: false, //判断游戏是否结束 
ScoreStrategy: [100, 300, 500, 800], //得分策略 
LevelScores: [100, 20000, 40000, 60000, 80000, 100000, 120000, 140000, 160000, 200000], //分数等级 
IsPlay: false, //游戏进行中 
IsFirstPlay: true, //是否第一次玩 
SmallGridNum: 6, //预览map的格子数,为正方形 
DirectionEnum: { left: 0, right: 1, up: 2, down: 3 }, //方向的枚举 
Speeds: [1000, 900, 800, 700, 600, 500, 400, 300, 200, 100], //速度,或者说级别 
CurrentSpeed: 1000, //当前级别或者说速度 
TypeEnum: { none: 0, block: 1, blocks: 2 }, //类型 
BlocksEnum: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], //0为LL,1为LR,2为T,3为ZL,4为ZR,5为I,6为F,7为长T 
BlocksStateNum: [4, 4, 4, 2, 2, 2, 1, 4, 4, 2], //对应BlocksEnum中每个方块集的变形个数,即有多少种变形 
BlocksShapeMaps: [ //方块形状集的集合 
[ //方块集的虚拟map集合,对应BlocksEnum,比如该map是L的map 
[[[2, 1]], [[0, 2], [1, 2], [2, 2]]], //L中的其中一个变形 
[[[1, 0]], [[1, 1]], [[1, 2], [2, 2]]], 
[[[0, 1], [1, 1], [2, 1]], [[0, 2]]], 
[[[1, 0], [2, 0]], [[2, 1]], [[2, 2]]] 
], 
[ 
[[[2, 0]], [[2, 1]], [[1, 2], [2, 2]]], 
[[[0, 1]], [[0, 2], [1, 2]], [[2, 2]]], 
[[[0, 0], [1, 0]], [[0, 1]], [[0, 2]]], 
[[[0, 1], [1, 1], [2, 1]], [[2, 2]]] 
], 
[ 
[[[0, 0], [1, 0], [2, 0]], [[1, 1]]], 
[[[1, 0]], [[0, 1], [1, 1]], [[1, 2]]], 
[[[1, 1]], [[0, 2], [1, 2], [2, 2]]], 
[[[0, 0]], [[0, 1], [1, 1]], [[0, 2]]] 
], 
[ 
[[[0, 0]], [[0, 1], [1, 1]], [[1, 2]]], 
[[[1, 1], [2, 1]], [[0, 2], [1, 2]]] 
], 
[ 
[[[1, 0]], [[0, 1], [1, 1]], [[0, 2]]], 
[[[0, 1], [1, 1]], [[1, 2], [2, 2]]] 
], 
[ 
[[[0, 0]], [[0, 1]], [[0, 2]], [[0, 3]]], 
[[[0, 3]], [[1, 3]], [[2, 3]], [[3, 3]]] 
], 
[ 
[[[0, 0], [0, 1]], [[1, 0], [1, 1]]] 
], 
[ 
[[[0, 0], [1, 0], [2, 0]], [[1, 1]], [[1, 2]]], 
[[[2, 0]], [[0, 1], [1, 1], [2, 1]], [[2, 2]]], 
[[[1, 0]], [[1, 1]], [[0, 2], [1, 2], [2, 2]]], 
[[[0, 0]], [[0, 1], [1, 1], [2, 1]], [[0, 2]]] 
], 
[ 
[[[0, 1], [1, 1], [2, 1]], [[0, 2]], [[2, 2]]], 
[[[1, 0], [2, 0]], [[2, 1]], [[1, 2], [2, 2]]], 
[[[0, 1], [2, 1]], [[0, 2], [1, 2], [2, 2]]], 
[[[1, 0], [2, 0]], [[1, 1]], [[1, 2], [2, 2]]] 
], 
[ 
[[[0, 0], [1, 0]], [[1, 1]], [[1, 2], [2, 2]]], 
[[[2, 0]], [[0, 1], [1, 1], [2, 1]], [[0, 2]]] 
], 
], 
ColorEnum: [[0, 0], [-28, 0], [-56, 0], [-84, 0], [-112, 0], [-140, 0], [-168, 0], [0, 0], [-28, 0], [-56, 0]], //颜色的枚举,对应BlocksEnum 
CreateGameMap: function() { //创建游戏map 
for (var i = 0; i < this.VerticalNum; i++) { 
this.GameMap.push([]); 
for (var j = 0; j < this.HorizontalNum; j++) { 
this.GameMap[i][j] = {}; 
this.GameMap[i][j][Sys.TypeEnum.blocks] = null; 
} 
} 
}, 
GetBlocks: function() { //获取GameMap里的方块集 
for (var i = 0; i < this.BlocksObj.length; i++) { 
if (this.BlocksObj[i].isInGameMap) { 
return this.BlocksObj[i]; 
} 
} 
return null; 
}, 
AllowBlocksMove: function() { //是否允许方块集移动 
var blocksItem = this.GetBlocks(); 
var itemPosArray = this._getBlocksItemPosArray(blocksItem, false); 
return this.NoBlocksInthePlace(itemPosArray, blocksItem) && this.CheckBoundary(itemPosArray, blocksItem); 
}, 
GetMaxAndMinItemPosArray: function(itemPosArray) { //获取最大最小方块位置集合 
itemPosArray.ItemPosXArray.sorts(); 
itemPosArray.ItemPosYArray.sorts(); 
return { maxItemPosX: itemPosArray.ItemPosXArray[itemPosArray.ItemPosXArray.length - 1], maxItemPosY: itemPosArray.ItemPosYArray[itemPosArray.ItemPosYArray.length - 1], minItemPosX: itemPosArray.ItemPosXArray[0], minItemPosY: itemPosArray.ItemPosYArray[0] }; 
}, 
NoBlocksInthePlace: function(itemPosArray, blocksItem) { //检测游戏方格中是否已经有方块 
return this._isOverMapChild(itemPosArray, blocksItem) ? false : true; 
}, 
CheckBoundary: function(itemPosArray, blocksItem) { //是否到达边界了 
var maxAndMinItemPosArray = this.GetMaxAndMinItemPosArray(itemPosArray); 
var isNotToBoundary = false; 
switch (blocksItem.currentDirectionEnum) { 
case this.DirectionEnum.left: 
isNotToBoundary = (maxAndMinItemPosArray.minItemPosX > 0) 
break; 
case this.DirectionEnum.right: 
isNotToBoundary = (maxAndMinItemPosArray.maxItemPosX < this.HorizontalNum - 1) 
break; 
case this.DirectionEnum.down: 
isNotToBoundary = (maxAndMinItemPosArray.maxItemPosY < this.VerticalNum - 1); 
break; 
} 
return isNotToBoundary; 
}, 
_isOverMapChild: function(itemPosArray, blocksItem) { //检测是否会覆盖某个游戏方格中的元素 
var isOverMapChild = false; 
for (var i = 0; i < itemPosArray.ItemPosYArray.length; i++) { 
var itemX = itemPosArray.ItemPosXArray[i]; 
var itemY = itemPosArray.ItemPosYArray[i]; 
if (blocksItem.currentDirectionEnum == this.DirectionEnum.left) { 
itemX--; 
} 
else if (blocksItem.currentDirectionEnum == this.DirectionEnum.right) { 
itemX++; 
} 
else if (blocksItem.currentDirectionEnum == this.DirectionEnum.down) { 
itemY++; 
} 
if (this.GameMap[itemY] && this.GameMap[itemY][itemX] && this.GameMap[itemY][itemX][this.TypeEnum.blocks] != null) { 
isOverMapChild = true; 
break; 
} 
} 
return isOverMapChild; 
}, 
_getBlocksItemPosArray: function(blocksItem, isRelative) { //获取方块集的位置集合,isRelative=true获取的是方块相对方块集map的位置,否则是方块相对游戏map的位置 
var itemPosXArray = []; 
var itemPosYArray = []; 
for (var i = 0; i < blocksItem.blocks.length; i++) { 
if (isRelative) { 
itemPosXArray.push(blocksItem.blocks[i].x); 
itemPosYArray.push(blocksItem.blocks[i].y); 
} 
else { 
itemPosXArray.push(blocksItem.blocks[i].x + blocksItem.x); 
itemPosYArray.push(blocksItem.blocks[i].y + blocksItem.y); 
} 
} 
return { ItemPosXArray: itemPosXArray, ItemPosYArray: itemPosYArray }; 
}, 
GetBlocksInitPos: function(blocks) { //获取方块的初始位置 
var blocksItem = null; 
if (!blocks) 
blocksItem = this.GetBlocks(); 
else 
blocksItem = blocks; 
var itemPosArray = this._getBlocksItemPosArray(blocksItem, true); 
itemPosArray.ItemPosXArray = itemPosArray.ItemPosXArray.filter(); 
itemPosArray.ItemPosYArray = itemPosArray.ItemPosYArray.filter(); 
var childsNumX = itemPosArray.ItemPosXArray.length; 
var childsNumY = itemPosArray.ItemPosYArray.length; 
var maxAndMinItemPosArray = this.GetMaxAndMinItemPosArray(itemPosArray); 
if (blocks) //获取方块集在预览map中的初始位置 
return { x: (this.SmallGridNum - childsNumX - 1) / 2 + 0.5 - maxAndMinItemPosArray.minItemPosX, y: (this.SmallGridNum - childsNumY - 1) / 2 + 0.5 - maxAndMinItemPosArray.minItemPosY }; 
else //获取方块集在游戏map中的初始位置 
return { x: parseInt((this.HorizontalNum - childsNumX - 1) / 2) + 1 - maxAndMinItemPosArray.minItemPosX, y: -(childsNumY + maxAndMinItemPosArray.minItemPosY) }; 
}, 
GetNextActiviteBrocks: function() { //获取下一个活动的方块集 
for (var i = 0; i < this.BlocksObj.length; i++) { 
if (this.BlocksObj[i].isInGameMap) { 
this.BlocksObj.removeAt(i); 
} 
} 
this.BlocksObj[0].isInGameMap = true; 
var itemPos = this.GetBlocksInitPos(); 
this.BlocksObj[0].x = itemPos.x; 
this.BlocksObj[0].y = itemPos.y; 
this.BlocksObj[0].AddToMap(false, false); 
this.CreateBlocks(); 
}, 
PlayGame: function() { //启动游戏 
this.IsPlay = true; 
this.NaturalMove(); 
if (!this.IsFirstPlay) { 
return; 
} 
this.GetNextActiviteBrocks(); 
}, 
AddToGameMapGrid: function() { //加入到游戏map网格中 
var blocks = this.GetBlocks(); 
blocks.UseGrid(this.GameMap, blocks); 
}, 
GetScore: function() { //分数处理 
var rowIndexArray = []; 
for (var i = 0; i < this.VerticalNum; i++) { //获取满行的行数 
var entireRow = true; 
for (var j = 0; j < this.HorizontalNum; j++) { 
if (this.GameMap[i][j][this.TypeEnum.blocks] == null) { 
entireRow = false; 
break; 
} 
} 
if (entireRow) 
rowIndexArray.push(i); 
} 
if (rowIndexArray.length > 0) { 
this._FreeMapGrid(rowIndexArray); 
document.getElementById("score").innerText = this.ScoreStrategy[rowIndexArray.length - 1] + parseInt(document.getElementById("score").innerText); 
this.CheckTheLevel(); 
} 
}, 
CheckTheLevel: function() { //检测是否进入下一个级别 
var currentScore = parseInt(document.getElementById("score").innerText); 
var speedList = document.getElementById("speed"); 
var currentLevel = parseInt(speedList.options[speedList.selectedIndex].text) - 1; 
var levelScore = this.LevelScores[currentLevel]; 
if (currentScore >= levelScore) { 
if (currentLevel < this.LevelScores.length) { 
var element = document.getElementById("gameOver"); 
element.innerText = "恭喜你通过第" + (speedList.selectedIndex + 1) + "关"; 
element.style.display = "block"; 
this.PauseGame(); 
document.getElementById("btnStart").disabled = true; 
document.getElementById("speed").disabled = true; 
this._goToNextLevel.delay(3000); 
} 
else { 
this._finishAllTheLevel(element); 
} 
} 
}, 
_goToNextLevel: function() { //进入下一个级别,速度加快 
Sys.IsPlay = true; 
document.getElementById("btnStart").disabled = false; 
var speedList = document.getElementById("speed"); 
speedList.disabled = false; 
speedList.options[speedList.selectedIndex + 1].selected = true; 
Sys.CurrentSpeed = Sys.Speeds[speedList.selectedIndex + 1]; 
Sys.NaturalMove(); 
document.getElementById("gameOver").style.display = "none"; 
}, 
_finishAllTheLevel: function() { //完成所有的游戏级别 
this.PauseGame(); 
}, 
_FreeMapGrid: function(rowIndexArray) { //从游戏map中释放满行的网格 
var gameMap = this.GameMap; 
var startIndex = rowIndexArray[0]; 
var len = rowIndexArray.length; 
var maxIndex = startIndex + len - 1; 
for (var i = startIndex; i <= maxIndex; i++) { 
for (var j = 0; j < this.HorizontalNum; j++) { 
if (gameMap[i][j][this.TypeEnum.blocks] != null) { 
document.getElementById("map").removeChild(gameMap[i][j][this.TypeEnum.blocks].domElement); 
gameMap[i][j][this.TypeEnum.blocks] = null; 
} 
} 
} 
this.ResetMapGrid(rowIndexArray); 
}, 
ResetMapGrid: function(rowIndexArray) { //重置游戏网格 
var gameMap = this.GameMap; 
var maxIndex = rowIndexArray[0]; 
var len = rowIndexArray.length; 
for (var i = maxIndex - 1; i >= 0; i--) { 
for (var j = 0; j < this.HorizontalNum; j++) { 
if (gameMap[i][j][this.TypeEnum.blocks] != null) { 
this._resetMapElement(gameMap[i][j][this.TypeEnum.blocks].domElement, len); 
gameMap[i + len][j][this.TypeEnum.blocks] = gameMap[i][j][this.TypeEnum.blocks]; 
gameMap[i][j][this.TypeEnum.blocks] = null; 
} 
} 
} 
}, 
_resetMapElement: function(element, len) { //重置dom元素,比如共有满行两行,则之上的元素均需下降两个 
element.style.top = (parseInt(element.style.top) + 28 * len) + "px"; 
}, 
InitSpeed: function() { //初始化游戏级别 
var speedList = document.getElementById("speed"); 
if (speedList.options.length == 0) { 
for (var i = 0; i < this.Speeds.length; i++) { 
var varItem = new Option(i + 1, this.Speeds[i]); 
speedList.options.add(varItem); 
} 
} 
this.SetSpeedSelected(); 
}, 
SetSpeedSelected: function() { //选中级别 
var speedList = document.getElementById("speed"); 
for (var i = 0; i < speedList.options.length; i++) { 
if (speedList.options[i].value == this.CurrentSpeed) { 
speedList.options[i].selected = true; 
break; 
} 
} 
}, 
GameOver: function() { //游戏结束 
this.IsGameOver = true; 
this.PauseGame(); 
var element = document.getElementById("gameOver"); 
element.innerText = "Game Over!"; 
element.style.display = "block"; 
document.getElementById("btnStart").value = "try again"; 
}, 
PauseGame: function() { //暂停游戏 
this.IsPlay = false; 
clearInterval(this.Timer); 
}, 
CreateBlocks: function() { //创建方块集 
var currentNum = this.BlocksEnum.length.getRandom(); 
var blocks = new Blocks(0, 0, this.BlocksStateNum[currentNum], currentNum, this.ColorEnum[currentNum]); 
blocks.Init(); 
if (this.BlocksObj.length == 3) 
Sys.BlocksObj.pop(); 
Sys.BlocksObj.push(blocks); 
}, 
NaturalMove: function() { //自然下落 
this.Timer = setInterval("Moving()", Sys.CurrentSpeed); 
} 
} 
function Base() { } //定义base类 
Base.prototype.AddToMap = function(isAddToPreviewMap, isMoving) { //添加方块集到map中 
for (var i = 0; i < this.blocks.length; i++) { 
var element = null; 
if (!this.isInGameMap) { //如果方块集是在预览map中 
element = document.createElement("DIV"); 
document.getElementById("PreviewMap").appendChild(element); 
this.blocksElement.push(element); 
this.blocks[i].domElement = element; 
} 
else 
element = this.blocksElement[i]; 
if (!isAddToPreviewMap && !isMoving) //由预览map移动到游戏map时 
document.getElementById("map").appendChild(element); 
element.style.position = "absolute"; 
element.style.left = ((this.x + this.blocks[i].x) * 28) + "px"; //设置元素所在的map的位置 
element.style.top = ((this.y + this.blocks[i].y) * 28) + "px"; 
element.style.backgroundPositionX = this.color[0]; 
element.style.backgroundPositionY = this.color[1]; 
} 
} 
Base.prototype.UseGrid = function(map, blocksItem) { //方块集加入到游戏map中 
for (var i = 0; i < blocksItem.blocks.length; i++) { 
var itemX = blocksItem.x + blocksItem.blocks[i].x; 
var itemY = blocksItem.y + blocksItem.blocks[i].y; 
if (blocksItem.y < 0) { 
Sys.GameOver(); 
return; 
} 
map[itemY][itemX] = {}; 
map[itemY][itemX][this.type] = blocksItem.blocks[i]; 
} 
} 
function Block(x, y) { //定义方块结构体 
this.x = x; 
this.y = y; 
this.type = Sys.TypeEnum.block; 
this.domElement = null; 
} 
function Blocks(x, y, state, blocksEnum, colorEnum) { //方块集类 
this.x = x; 
this.y = y; 
this.state = state; 
this.blocksEnum = blocksEnum; //方块类型(比如L,I,田字形,Z等) 
this.color = colorEnum; 
this.type = Sys.TypeEnum.blocks; //废弃属性 
this.blocks = []; //方块集下的方块的集合 
this.blocksElement = []; //方块集下的方块的对应dom元素集 
this.currentState = 0; //当前的状态,比如L有四种类型的变形 
this.isInGameMap = false; //是否在游戏map中 
this.currentDirectionEnum = Sys.DirectionEnum.down; //默认方向向下 
} 
Blocks.prototype = new Base(); //继承base类 
Blocks.prototype.Init = function() {//初始化blocks 
var blocksPoses = Sys.BlocksShapeMaps[this.blocksEnum]; 
this.currentState = Sys.BlocksStateNum[this.blocksEnum].getRandom(); //随机获取方块集的状态 
var blocksPos = blocksPoses[this.currentState]; //获取方块集的map 
for (var i = 0; i < blocksPos.length; i++) { 
for (var j = 0; j < blocksPos[i].length; j++) { 
var block = new Block(blocksPos[i][j][0], blocksPos[i][j][1]); 
this.blocks.push(block); 
} 
} 
var itemPos = Sys.GetBlocksInitPos(this); //获取初始位置,也就是说在预览map中的位置 
this.x = itemPos.x; 
this.y = itemPos.y; 
this.AddToMap(true, false); //加入到预览map中 
} 
Blocks.prototype.ChangeShape = function() {//方块变换形状 
var gameMap = Sys.GameMap; 
var allowChangeShape = true; 
var blocksPoses = Sys.BlocksShapeMaps[this.blocksEnum]; 
var num = Sys.BlocksStateNum[this.blocksEnum]; 
var currentState1 = -1; 
this.currentState == num - 1 ? currentState1 = 0 : currentState1 = this.currentState + 1; 
var blocksPos = blocksPoses[currentState1]; 
var k = 0; 
for (var i = 0; i < blocksPos.length; i++) { //主要是检测方块集的下一个变形是否合理 
for (var j = 0; j < blocksPos[i].length; j++) { 
var block = this.blocks[k]; 
var itemX = this.x + blocksPos[i][j][0]; 
var itemY = this.y + blocksPos[i][j][1]; 
if ((itemX > Sys.HorizontalNum - 1) || (itemX < 0) || (itemY > Sys.VerticalNum - 1) || itemY >= 0 && gameMap[itemY][itemX] != null && gameMap[itemY][itemX][Sys.TypeEnum.blocks] != null) { 
allowChangeShape = false; 
break; 
} 
k++; 
} 
} 
if (allowChangeShape)//如果允许变形 
{ 
this.currentState == num - 1 ? this.currentState = 0 : this.currentState++; //设置下一个变形的状态 
k = 0; 
for (var i = 0; i < blocksPos.length; i++) { 
for (var j = 0; j < blocksPos[i].length; j++) { 
var block = this.blocks[k]; 
block.x = blocksPos[i][j][0]; 
block.y = blocksPos[i][j][1]; 
k++; 
} 
} 
this.AddToMap(false, true); //变形后加入到游戏map中 
} 
} 
Blocks.prototype.BlocksMoveDown = function(isMoving) { //方块集下落 
this.currentDirectionEnum = Sys.DirectionEnum.down; 
if (!Sys.AllowBlocksMove()) { //如果不允许移动 
Sys.AddToGameMapGrid(); //固定方块集在游戏map中的位置 
Sys.GetScore(); //得分处理 
Sys.GetNextActiviteBrocks(); //获取下一个方块集 
} 
else { //下落一格 
this.y++; 
this.AddToMap(false, isMoving); 
} 
} 
Number.prototype.getRandom = function() {//获取0至number之间的随机数 
var num = this; 
var i = this + 1; 
while (i >= num) { 
i = Math.round(Math.random() * 10); 
} 
return i; 
} 
Array.prototype.sorts = function() { return this.sort(compare); } //数组排序,按照升序排序 
function compare(a, b) { return a - b; } //定义排序规则 
Array.prototype.removeAt = function(dx) { //清除指定索引的数组元素 
if (isNaN(dx) || dx > this.length) { return false; } 
for (var i = 0, n = 0; i < this.length; i++) { 
if (this[i] != this[dx]) 
this[n++] = this[i]; 
} 
this.length -= 1; 
} 
Array.prototype.filter = function() { //清除数组中的重复值 
var arr = []; 
for (var i = 0; i < this.length; i++) { 
if (!arr.contains(this[i])) 
arr.push(this[i]); 
} 
return arr; 
} 
Array.prototype.contains = function(item) { //检测数组是否包含某元素 
for (var i = 0; i < this.length; i++) { 
if (this[i] == item) 
return true; 
} 
return false; 
} 
Function.prototype.delay = function(time) { var timer = setTimeout(this, time); } //函数延迟time毫秒执行 
window.onload = InitGame; 
function InitGame() {//初始化游戏 
Sys = new sys(); 
Sys.BlocksObj = []; 
Sys.InitSpeed(); //初始化游戏速度 
Sys.CreateGameMap(); //创建游戏map 
Sys.CreateBlocks(); //创建方块集 
} 
function GameStart(element) { 
if (element.value == "start") { //开始游戏 
element.value = "pause"; 
Sys.PlayGame(); 
Sys.IsFirstPlay = false; 
} 
else if (element.value == "pause") { //暂停游戏 
element.value = "start" 
Sys.PauseGame(); 
} 
else { //游戏结束后重新开始 
window.location.reload(); 
} 
} 
function Moving() {//移动 
Sys.GetBlocks().BlocksMoveDown(false); 
} 
function ChangeSpeed(e) {//切换级别 
var speedlist = document.getElementById("speed"); 
Sys.CurrentSpeed = speedlist.options[speedlist.selectedIndex].value; 
if (!Sys.IsGameOver) { 
clearInterval(Sys.Timer); 
this.NaturalMove(); 
} 
} 
function keyDown(e) { //按键操作 
if (Sys.IsGameOver || !Sys.IsPlay) return; 
var blocks = Sys.GetBlocks(); 
if (e.keyCode == 37) { //向左 
blocks.currentDirectionEnum = Sys.DirectionEnum.left; 
if (Sys.AllowBlocksMove()) 
blocks.x--; 
if (blocks.x != 0) 
blocks.AddToMap(false, true); 
} 
else if (e.keyCode == 38) { //向上 
blocks.currentDirectionEnum = Sys.DirectionEnum.up; 
blocks.ChangeShape(); 
} 
else if (e.keyCode == 39) { //向右 
blocks.currentDirectionEnum = Sys.DirectionEnum.right; 
var oldX = blocks.x; 
if (Sys.AllowBlocksMove()) 
blocks.x++; 
if (blocks.x != oldX) 
blocks.AddToMap(false, true); 
} 
else if (e.keyCode == 40) //向下 
{ 
blocks.currentDirectionEnum = Sys.DirectionEnum.down; 
blocks.BlocksMoveDown(true); 
} 
} 
</script> 
<style type="text/css"> 
body 
{ 
background-color:#ffffff; 
overflow:hidden; 
font-size:14px; 
} 
.gameZone 
{ 
position:absolute; 
left:0px; 
top:0px; 
width:100%; 
height:550px; 
background-Color:white; 
} 
.mask 
{ 
position:absolute; 
left:100px; 
top:0px; 
width:300px; 
height:20px; 
background-color:White; 
border:solid 0px; 
z-index:5; 
} 
.map 
{ 
position:absolute; 
left:100px; 
top:20px; 
width:280px; 
height:504px; 
background-image:url(images/tetris_grid.gif); 
border:solid 3px green; 
} 
.gameOver 
{ 
position:absolute; 
left:100px; 
top:20px; 
width:280px; 
height:504px; 
font-weight:800; 
font-size:xx-large; 
color:Red; 
text-align:center; 
border:solid 3px; 
line-height:420px; 
display:none; 
filter: Alpha(Opacity=80); 
background-color:pink; 
} 
.map div 
{ 
BACKGROUND-IMAGE: url(images/tetris.gif); 
WIDTH: 28px; 
BACKGROUND-REPEAT: no-repeat; 
POSITION: absolute; 
HEIGHT: 28px 
} 
.PreviewMap 
{ 
position:absolute; 
left:400px; 
top:20px; 
width:168px; 
height:168px; 
background-color:pink; 
border:solid 2px green; 
} 
.PreviewMap div 
{ 
BACKGROUND-IMAGE: url(images/tetris.gif); 
WIDTH: 28px; 
BACKGROUND-REPEAT: no-repeat; 
POSITION: absolute; 
HEIGHT: 28px 
} 
.start 
{ 
position:absolute; 
left:400px; 
top:240px; 
width:168px; 
height:40px; 
} 
.scoreSpeed 
{ 
position:absolute; 
left:400px; 
top:200px; 
width:190px; 
height:40px; 
} 
.score 
{ 
color:pink; 
font-weight:bold; 
width:20px; 
height:20px; 
background-color:blue; 
padding-left:10px; 
padding-right:10px; 
font-size:medium; 
} 
.speed 
{ 
color:pink; 
font-weight:bold; 
width:20px; 
height:20px; 
background-color:blue; 
padding-left:5px; 
padding-right:5px; 
font-size:medium; 
} 
.copyright 
{ 
position:absolute; 
left:400px; 
top:280px; 
word-break:break-all; 
width:160px; 
height:225px; 
border:solid 2px green; 
padding:5px; 
} 
</style> 
</head> 
<body onkeydown="keyDown(event)"> 
<div class="gameZone"> 
<div id="mask" class="mask"></div> 
<div id="map" class="map"></div> 
<div id="gameOver" class="gameOver"></div> 
<div id="PreviewMap" class="PreviewMap"></div> 
<div id="scoreSpeed" class="scoreSpeed">得分:<span id="score" class="score">0</span></div> 
<div id="start" class="start"> 
<input type="button" id="btnStart" value="start" onclick="GameStart(this);" />  
级别:<select id="speed" onchange="ChangeSpeed();"></select> 
</div> 
<div id="copyright" class="copyright"> 
<b><center>版权所有</center></b><br /> 
此俄罗斯方块由高山流水开发,欢迎各位使用, 
如有bug或者好的意见,请给我留言,谢谢支持! 
另如需转载,请注明出处!<br /> 
<font color=red><b>顺便,宣传一下我的MVC qq群:45660795,欢迎加入!</b></font> 
<br /><br /> 
作者:<a href="http://www.cnblogs.com/JackFeng/" target="_blank">高山流水</a><br /> 
QQ:21243468 
</div> 
</div> 
</body> 
</html>
Javascript 相关文章推荐
jQuery使用手册之三 CSS操作
Mar 24 Javascript
基于Jquery的淡入淡出的特效基础练习
Dec 13 Javascript
js函数名与form表单元素同名冲突的问题
Mar 07 Javascript
js改变鼠标的形状和样式的方法
Mar 31 Javascript
js计算时间差代码【包括计算,天,时,分,秒】
Apr 26 Javascript
Bootstrap中文本框的宽度变窄并且加入一副验证码图片的实现方法
Jun 23 Javascript
js实现手机发送验证码功能
Mar 13 Javascript
Vue2.0表单校验组件vee-validate的使用详解
May 02 Javascript
Angular 4 指令快速入门教程
Jun 07 Javascript
从源码里了解vue中的nextTick的使用
Nov 22 Javascript
JavaScript实现shuffle数组洗牌操作示例
Jan 03 Javascript
vue组件讲解(is属性的用法)模板标签替换操作
Sep 04 Javascript
用于节点操作的API,颠覆原生操作HTML DOM节点的API
Dec 11 #Javascript
JavaScript下利用fso判断文件是否存在的代码
Dec 11 #Javascript
jQuery ul标签下拉菜单演示代码
Dec 11 #Javascript
基于jquery的修改当前TAB显示标题的代码
Dec 11 #Javascript
Wordpress ThickBox 添加“查看原图”效果代码
Dec 11 #Javascript
Wordpress ThickBox 点击图片显示下一张图的修改方法
Dec 11 #Javascript
基于jQuery的history历史记录插件
Dec 11 #Javascript
You might like
五个PHP程序员工具
2008/05/26 PHP
提高define性能的php扩展hidef的安装和使用
2011/06/14 PHP
学习php分页代码实例
2013/10/24 PHP
不一样的文字闪烁 轮番闪烁
2009/11/11 Javascript
js判断undefined变量类型使用typeof
2013/06/03 Javascript
js克隆对象、数组的常用方法介绍
2013/09/26 Javascript
jQuery中阻止冒泡事件的方法介绍
2014/04/12 Javascript
使用jquery解析XML的方法
2014/09/05 Javascript
跟我学习javascript的定时器
2015/11/19 Javascript
轻松搞定jQuery.noConflict()
2016/02/15 Javascript
js 动态生成json对象、时时更新json对象的方法
2016/12/02 Javascript
微信小程序 本地数据读取实例
2017/04/27 Javascript
vue-router 源码之实现一个简单的 vue-router
2018/07/02 Javascript
vue element upload组件 file-list的动态绑定实现
2019/10/11 Javascript
原生JavaScript实现留言板
2021/01/10 Javascript
python 切片和range()用法说明
2013/03/24 Python
zbar解码二维码和条形码示例
2014/02/07 Python
python使用7z解压apk包的方法
2015/04/18 Python
Python中的time模块与datetime模块用法总结
2016/06/30 Python
Tensorflow的可视化工具Tensorboard的初步使用详解
2018/02/11 Python
tensorflow实现简单的卷积网络
2018/05/24 Python
python 读取修改pcap包的例子
2019/07/23 Python
django认证系统实现自定义权限管理的方法
2019/08/28 Python
win10下python2和python3共存问题解决方法
2019/12/23 Python
django rest framework 自定义返回方式
2020/07/12 Python
Python生成pdf目录书签的实例方法
2020/10/29 Python
为智能设备设计个性化保护套网站:caseable
2017/01/05 全球购物
Sephora丝芙兰菲律宾官方网站:购买化妆品和护肤品
2017/04/05 全球购物
暑假实习求职信范文
2013/09/22 职场文书
护理中职生求职信范文
2014/02/24 职场文书
兴趣小组活动总结
2014/05/05 职场文书
幼儿园大班教师个人工作总结
2015/02/05 职场文书
中秋节感想
2015/08/10 职场文书
中秋节祝酒词
2015/08/12 职场文书
小学家庭教育心得体会
2016/01/14 职场文书
python中Tkinter 窗口之输入框和文本框的实现
2021/04/12 Python