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的链式调用浅析
Dec 03 Javascript
js实现拖拽 闭包函数详细介绍
Nov 25 Javascript
json属性名为什么要双引号(个人猜测)
Jul 31 Javascript
javascript实现简易计算器的代码
May 31 Javascript
node.js中 stream使用教程
Aug 28 Javascript
基于Javascript实现的不重复ID的生成器
Dec 25 Javascript
Vue2.0 多 Tab切换组件的封装实例
Jul 28 Javascript
Angular实现可删除并计算总金额的购物车功能示例
Dec 26 Javascript
Vue 将后台传过来的带html字段的字符串转换为 HTML
Mar 29 Javascript
浅谈Webpack打包优化技巧
Jun 12 Javascript
CSS3 动画卡顿性能优化的完美解决方案
Sep 20 Javascript
解决vue动态路由异步加载import组件,加载不到module的问题
Jul 26 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地址引用(php地址引用的效率问题)
2012/03/23 PHP
PHP+mysql防止SQL注入的方法小结
2019/04/27 PHP
对象特征检测法判断浏览器对javascript对象的支持
2009/07/25 Javascript
JS简单实现元素复制示例附图
2013/11/19 Javascript
node.js中的path.basename方法使用说明
2014/12/09 Javascript
jQuery实现锚点scoll效果实例分析
2015/03/10 Javascript
jquery UI Datepicker时间控件的使用方法(加强版)
2015/11/07 Javascript
Bootstrap每天必学之折叠(Collapse)插件
2016/04/25 Javascript
jQuery获取file控件中图片的宽高与大小
2016/08/04 Javascript
Html5 js实现手风琴效果
2020/04/17 Javascript
jQuery实现动态生成表格并为行绑定单击变色动作的方法
2017/04/17 jQuery
JS中将多个逗号替换为一个逗号的实现代码
2017/06/23 Javascript
BootStrap Fileinput上传插件使用实例代码
2017/07/28 Javascript
vue 使用鼠标滚动加载数据的例子
2019/10/31 Javascript
JavaScript实现模态对话框实例
2020/01/13 Javascript
VUE 实现element upload上传图片到阿里云
2020/08/12 Javascript
[04:40]2016国际邀请赛中国区预选赛全程TOP10镜头集锦
2016/07/01 DOTA
python3使用PyMysql连接mysql数据库实例
2017/02/07 Python
python验证码识别的示例代码
2017/09/21 Python
Python中几种属性访问的区别与用法详解
2018/10/10 Python
浅谈numpy生成数组的零值问题
2018/11/12 Python
python实现剪切功能
2019/01/23 Python
Python values()与itervalues()的用法详解
2019/11/27 Python
python如何使用jt400.jar包代码实例
2019/12/20 Python
Python实现UDP程序通信过程图解
2020/05/15 Python
HTML5地理定位与第三方工具百度地图的应用
2016/11/17 HTML / CSS
Merrell迈乐澳大利亚网站:购买户外登山鞋
2017/05/28 全球购物
VisionPros美国站:加拿大在线隐形眼镜和眼镜零售商
2020/02/11 全球购物
旅游管理专业学生求职信
2013/09/28 职场文书
平面设计师的工作职责
2013/11/21 职场文书
创意活动策划书
2014/01/15 职场文书
中文专业求职信
2014/06/20 职场文书
领导班子四风对照检查材料范文
2014/09/27 职场文书
领导班子四风查摆对照检查材料思想汇报
2014/10/05 职场文书
2014年德育工作总结
2014/11/20 职场文书
会计岗位工作总结
2015/08/12 职场文书