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 相关文章推荐
js innerHTML 的一些问题的解决方法
Jun 22 Javascript
js判断是否为数组的函数: isArray()
Oct 30 Javascript
js调用后台servlet方法实例
Jun 09 Javascript
jQuery :first选择器使用介绍
Aug 09 Javascript
jQuery构造函数init参数分析
May 13 Javascript
AngularJS中的过滤器使用详解
Jun 16 Javascript
javascript 中null和undefined区分和比较
Apr 19 Javascript
vue组件之间通信实例总结(点赞功能)
Dec 05 Javascript
超好用的jQuery分页插件jpaginate用法示例【附源码下载】
Dec 06 jQuery
抖音上用记事本编写爱心小程序教程
Apr 17 Javascript
深入学习Vue nextTick的用法及原理
Oct 08 Javascript
vscode+gulp轻松开发小程序的完整步骤
Oct 18 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
成本8450万,票房仅2亿,口碑两极分化,又一部DC电影扑街了
2020/04/09 欧美动漫
PHP生成自定义长度随机字符串的函数分享
2014/05/04 PHP
在WordPress中安装使用视频播放器插件Hana Flv Player
2016/01/04 PHP
浅谈PHP发送HTTP请求的几种方式
2017/07/25 PHP
PHP实用小技巧之调用录像的方法
2019/12/05 PHP
基于jquery的finkyUI插件与Ajax实现页面数据加载功能
2010/12/03 Javascript
Js中的onblur和onfocus事件应用介绍
2013/08/27 Javascript
正则表达式中特殊符号及正则表达式的几种方法总结(replace,test,search)
2013/11/26 Javascript
jQuery 顶部导航跟随滚动条滚动固定浮动在顶部
2014/06/06 Javascript
JavaScript实现按Ctrl键打开新页面
2014/09/04 Javascript
jquery+CSS实现的水平布局多级网页菜单效果
2015/08/24 Javascript
浅谈js中StringBuffer类的实现方法及使用
2016/09/02 Javascript
从零学习node.js之简易的网络爬虫(四)
2017/02/22 Javascript
原生JS实现幻灯片
2017/02/22 Javascript
详解angularJS动态生成的页面中ng-click无效解决办法
2017/06/19 Javascript
关于 angularJS的一些用法
2017/11/29 Javascript
p5.js绘制旋转的正方形
2019/10/23 Javascript
vue ajax 拦截原理与实现方法示例
2019/11/29 Javascript
[02:44]DOTA2英雄基础教程 克林克兹
2014/01/15 DOTA
Python解释执行原理分析
2014/08/22 Python
Python3中的真除和Floor除法用法分析
2016/03/16 Python
利用Python破解斗地主残局详解
2017/06/30 Python
详解python列表(list)的使用技巧及高级操作
2019/08/15 Python
Python使用贪婪算法解决问题
2019/10/22 Python
python线程信号量semaphore使用解析
2019/11/30 Python
python实现布隆过滤器及原理解析
2019/12/08 Python
python如何基于redis实现ip代理池
2020/01/17 Python
PyCharm永久激活方式(推荐)
2020/09/22 Python
keras的load_model实现加载含有参数的自定义模型
2020/06/22 Python
如何用Python进行时间序列分解和预测
2021/03/01 Python
CSS3实现闪烁动画效果的方法
2015/02/09 HTML / CSS
全球速卖通西班牙站:AliExpress西班牙
2017/10/30 全球购物
Yves Rocher伊夫·黎雪美国官网:法国始创植物美肌1959
2019/01/09 全球购物
在职人员函授期间自我评价分享
2013/11/08 职场文书
酒会开场白大全
2015/06/01 职场文书
RPM包方式安装Oracle21c的方法详解
2021/08/23 Oracle