

上面我给出的getRandomBlockList里的代码就是在实现打乱算法和检测是否可还原算法。
还有一种打乱方式,大家可以尝试尝试:和复原拼图一样,将空白块一步一步地与周围的拼图随机交换顺序。这个打乱算法较上一种而言,不会出现无法复原的现象,而且可以根据打乱的步数设定游戏难度。
在完成打乱拼图块后,如期而至的是显示拼图块:
function showBlock() {
for (var i = 0, l = blockList.length; i < l; i++) {
var b = blockList[i];
/** 根据序号计算拼图块位置 */
var y = (i / 3) >>> 0, x = i % 3;
b.setLocation(x, y);
gameLayer.addChild(b);
}
}显示了拼图块后,我们要做的就是添加操作拼图块的功能。于是需要拓展Block类,为其添加事件监听器onClick方法:
Block.prototype.onClick = function (e) {
var self = e.currentTarget;
if (isGameOver) {
return;
}
var checkList = new Array();
/** 判断右侧是否有方块 */
if (self.locationX > 0) {
checkList.push(Block.getBlock(self.locationX - 1, self.locationY));
}
/** 判断左侧是否有方块 */
if (self.locationX < 2) {
checkList.push(Block.getBlock(self.locationX + 1, self.locationY));
}
/** 判断上方是否有方块 */
if (self.locationY > 0) {
checkList.push(Block.getBlock(self.locationX, self.locationY - 1));
}
/** 判断下方是否有方块 */
if (self.locationY < 2) {
checkList.push(Block.getBlock(self.locationX, self.locationY + 1));
}
for (var i = 0, l = checkList.length; i < l; i++) {
var checkO = checkList[i];
/** 判断是否是空白拼图块 */
if (checkO.index == 8) {
steps++;
updateStepsTxt();
Block.exchangePosition(self, checkO);
break;
}
}
};首先,我们在这里看到了isGameOver全局变量的作用,即在游戏结束后,阻断点击拼图块后的操作。
在点击了拼图块后,我们先获取该拼图块周围的拼图块,并将它们装入checkList,再遍历checkList,当判断到周围有空白拼图块后,即周围有index属性等于8的拼图块后,先更新操作步数,然后将这两个拼图块交换位置。具体交换拼图块位置的方法详见如下代码:
Block.exchangePosition = function (b1, b2) {
var b1x = b1.locationX, b1y = b1.locationY,
b2x = b2.locationX, b2y = b2.locationY,
b1Index = b1y * 3 + b1x,
b2Index = b2y * 3 + b2x;
/** 在地图块数组中交换两者位置 */
blockList.splice(b1Index, 1, b2);
blockList.splice(b2Index, 1, b1);
/** 交换两者显示位置 */
b1.setLocation(b2x, b2y);
b2.setLocation(b1x, b1y);
/** 判断游戏是否结束 */
Block.isGameOver();
};还有就是Block.getBlock静态方法,用于获取给定的“数组位置”下的拼图块:
Block.getBlock = function (x, y) {
return blockList[y * 3 + x];
};在Block.exchangePosition中,我们通过Block.isGameOver判断玩家是否已将拼图复原:
Block.isGameOver = function () {
var reductionAmount = 0, l = blockList.length;
/** 计算还原度 */
for (var i = 0; i < l; i++) {
var b = blockList[i];
if (b.index == i) {
reductionAmount++;
}
}
/** 计算是否完全还原 */
if (reductionAmount == l) {
/** 游戏结束 */
gameOver();
}
};到这里,我们就实现了打乱和操作拼图块部分。
最后30min用于细枝末节上的处理,如显示拼图缩略图、显示&更新时间和步数,以及添加游戏结束画面,这些就交给如下冗长而简单的代码来完成吧:
function showThumbnail() {
var thumbnail = new LBitmap(imgBmpd);
thumbnail.scaleX = 130 / imgBmpd.width;
thumbnail.scaleY = 130 / imgBmpd.height;
thumbnail.x = (LGlobal.width - 100) /2;
thumbnail.y = 410;
overLayer.addChild(thumbnail);
}
function addTimeTxt () {
timeTxt = new LTextField();
timeTxt.stroke = true;
timeTxt.lineWidth = 3;
timeTxt.lineColor = "#54D9EF";
timeTxt.color = "#FFFFFF";
timeTxt.size = 18;
timeTxt.x = 20;
timeTxt.y = 450;
overLayer.addChild(timeTxt);
updateTimeTxt();
}
function updateTimeTxt () {
timeTxt.text = "时间:" + getTimeTxt(time);
}
function getTimeTxt () {
var d = new Date(time);
return d.getMinutes() + " : " + d.getSeconds();
};
function addStepsTxt () {
stepsTxt = new LTextField();
stepsTxt.stroke = true;
stepsTxt.lineWidth = 3;
stepsTxt.lineColor = "#54D9EF";
stepsTxt.color = "#FFFFFF";
stepsTxt.size = 18;
stepsTxt.y = 450;
overLayer.addChild(stepsTxt);
updateStepsTxt();
}
function updateStepsTxt () {
stepsTxt.text = "步数:" + steps;
stepsTxt.x = LGlobal.width - stepsTxt.getWidth() - 20;
}
function onFrame () {
if (isGameOver) {
return;
}
/** 获取当前时间 */
var currentTime = (new Date()).getTime();
/** 计算使用的时间并更新时间显示 */
time = currentTime - startTime;
updateTimeTxt();
}
function gameOver () {
isGameOver = true;
var resultLayer = new LSprite();
resultLayer.filters = [new LDropShadowFilter()];
resultLayer.graphics.drawRoundRect(3, "#BBBBBB", [0, 0, 350, 350, 5], true,"#DDDDDD");
resultLayer.x = (LGlobal.width - resultLayer.getWidth()) / 2;
resultLayer.y = LGlobal.height / 2;
resultLayer.alpha = 0;
overLayer.addChild(resultLayer);
var title = new LTextField();
title.text = "游戏通关"
title.weight = "bold";
title.stroke = true;
title.lineWidth = 3;
title.lineColor = "#555555";
title.size = 30;
title.color = "#FFFFFF";
title.x = (resultLayer.getWidth() - title.getWidth()) / 2;
title.y = 30;
resultLayer.addChild(title);
var usedTimeTxt = new LTextField();
usedTimeTxt.text = "游戏用时:" + getTimeTxt(time);
usedTimeTxt.size = 20;
usedTimeTxt.stroke = true;
usedTimeTxt.lineWidth = 2;
usedTimeTxt.lineColor = "#555555";
usedTimeTxt.color = "#FFFFFF";
usedTimeTxt.x = (resultLayer.getWidth() - usedTimeTxt.getWidth()) / 2;
usedTimeTxt.y = 130;
resultLayer.addChild(usedTimeTxt);
var usedStepsTxt = new LTextField();
usedStepsTxt.text = "所用步数:" + steps;
usedStepsTxt.size = 20;
usedStepsTxt.stroke = true;
usedStepsTxt.lineWidth = 2;
usedStepsTxt.lineColor = "#555555";
usedStepsTxt.color = "#FFFFFF";
usedStepsTxt.x = usedTimeTxt.x;
usedStepsTxt.y = 180;
resultLayer.addChild(usedStepsTxt);
var hintTxt = new LTextField();
hintTxt.text = "- 点击屏幕重新开始 -";
hintTxt.size = 23;
hintTxt.stroke = true;
hintTxt.lineWidth = 2;
hintTxt.lineColor = "#888888";
hintTxt.color = "#FFFFFF";
hintTxt.x = (resultLayer.getWidth() - hintTxt.getWidth()) / 2;
hintTxt.y = 260;
resultLayer.addChild(hintTxt);
LTweenLite.to(resultLayer, 0.5, {
alpha : 0.7,
y : (LGlobal.height - resultLayer.getHeight()) / 2,
onComplete : function () {
/** 点击界面重新开始游戏 */
stageLayer.addEventListener(LMouseEvent.MOUSE_UP, function () {
gameLayer.removeAllChild();
overLayer.removeAllChild();
stageLayer.removeAllEventListener();
startGame();
});
}
});
}Ok,2h下来,整个游戏就搞定咯~不得不表扬一下lufylegend这个游戏引擎,实在是可以大幅提升开发效率。
