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 相关文章推荐
javascript利用控件对windows的操作实现原理与应用
Dec 23 Javascript
自动设置iframe大小的jQuery代码
Sep 11 Javascript
js设置和获取自定义属性的方法
Oct 20 Javascript
jQuery中hover方法搭配css的hover选择器,实现选中元素突出显示方法
May 08 jQuery
常见的浏览器Hack技巧整理
Jun 29 Javascript
webpack组织模块打包Library的原理及实现
Mar 10 Javascript
React从react-router路由上做登陆验证控制的方法
May 10 Javascript
解决vue中使用proxy配置不同端口和ip接口问题
Aug 14 Javascript
微信小程序框架的页面布局代码
Aug 17 Javascript
JavaScript使用表单元素验证表单的示例代码
Aug 20 Javascript
javascript实现画板功能
Apr 12 Javascript
详解小程序横屏方案对比
Jun 28 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
全国FM电台频率大全 - 8 黑龙江省
2020/03/11 无线电
苏联队长,苏联超人蝙蝠侠,这些登场的“山寨”英雄真的很严肃
2020/04/09 欧美动漫
解析PHP中的unset究竟会不会释放内存
2013/07/18 PHP
Zend Framework教程之资源(Resources)用法实例详解
2016/03/14 PHP
php实现产品加入购物车功能(1)
2020/07/23 PHP
Yii框架通过请求组件处理get,post请求的方法分析
2019/09/03 PHP
33个优秀的jQuery 教程分享(幻灯片、动画菜单)
2011/07/08 Javascript
在父页面调用子页面的JS方法
2013/09/29 Javascript
js弹窗返回值详解(window.open方式)
2014/01/11 Javascript
node.js中的fs.createWriteStream方法使用说明
2014/12/17 Javascript
angular.element方法汇总
2015/01/07 Javascript
字符串反转_JavaScript
2016/04/28 Javascript
Javascript基础_标记文字的实现方法
2016/06/14 Javascript
AngularJS中watch监听用法分析
2016/11/04 Javascript
JS实现一次性弹窗的方法【刷新后不弹出】
2016/12/26 Javascript
详解浏览器渲染页面过程
2017/02/09 Javascript
AngularJS2中一种button切换效果的实现方法(二)
2017/03/27 Javascript
深入浅析Vue不同场景下组件间的数据交流
2017/08/15 Javascript
JS实现的简单四则运算计算器功能示例
2017/09/27 Javascript
nodejs连接mysql数据库及基本知识点详解
2018/03/20 NodeJs
js动态获取时间的方法分析
2019/08/02 Javascript
[01:30]2016国际邀请赛中国区预选赛神秘商店火爆开启
2016/06/26 DOTA
python基础教程之类class定义使用方法
2014/02/20 Python
python2.7 mayavi 安装图文教程(推荐)
2017/06/22 Python
用python的requests第三方模块抓取王者荣耀所有英雄的皮肤实例
2017/12/14 Python
python+opencv实现移动侦测(帧差法)
2020/03/20 Python
Python+Dlib+Opencv实现人脸采集并表情判别功能的代码
2020/07/01 Python
filter使用python3代码进行迭代元素的实例详解
2020/12/03 Python
HTML5 Canvas 实现圆形进度条并显示数字百分比效果示例
2017/08/18 HTML / CSS
购买200个世界上最好的内衣品牌:Bare Necessities
2017/02/11 全球购物
校长竞聘演讲稿
2014/05/16 职场文书
小学运动会班级口号
2014/06/09 职场文书
银行竞聘上岗演讲稿
2014/09/12 职场文书
2014年群众路线教育实践活动整改措施
2014/09/24 职场文书
Vue的过滤器你真了解吗
2022/02/24 Vue.js
手写Spirit防抖函数underscore和节流函数lodash
2022/03/22 Javascript