下面是俄罗斯方块的截图:
请到这里下载源码:
俄罗斯方块 在线演示 下载地址
下面是代码:
复制代码 代码如下:
<!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>
请到这里下载源码:
俄罗斯方块 在线演示 下载地址
下面是代码:
复制代码 代码如下:
<!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>
标签:
俄罗斯方块
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件!
如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
暂无“JS俄罗斯方块,包含完整的设计理念”评论...
更新动态
2024年11月15日
2024年11月15日
- 黄乙玲1988-无稳定的爱心肝乱糟糟[日本东芝1M版][WAV+CUE]
- 群星《我们的歌第六季 第3期》[320K/MP3][70.68MB]
- 群星《我们的歌第六季 第3期》[FLAC/分轨][369.48MB]
- 群星《燃!沙排少女 影视原声带》[320K/MP3][175.61MB]
- 乱斗海盗瞎6胜卡组推荐一览 深暗领域乱斗海盗瞎卡组分享
- 炉石传说乱斗6胜卡组分享一览 深暗领域乱斗6胜卡组代码推荐
- 炉石传说乱斗本周卡组合集 乱斗模式卡组最新推荐
- 佟妍.2015-七窍玲珑心【万马旦】【WAV+CUE】
- 叶振棠陈晓慧.1986-龙的心·俘虏你(2006复黑限量版)【永恒】【WAV+CUE】
- 陈慧琳.1998-爱我不爱(国)【福茂】【WAV+CUE】
- 咪咕快游豪礼放送,百元京东卡、海量欢乐豆就在咪咕咪粉节!
- 双11百吋大屏焕新“热”,海信AI画质电视成最大赢家
- 海信电视E8N Ultra:真正的百吋,不止是大!
- 曾庆瑜1990-曾庆瑜历年精选[派森][WAV+CUE]
- 叶玉卿1999-深情之选[飞图][WAV+CUE]