21游戏网
您的当前位置:首页2小时完成HTML5拼图小游戏代码图文介绍

2小时完成HTML5拼图小游戏代码图文介绍

来源:21游戏网


上面我给出的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();
 } 
};

到这里,我们就实现了打乱和操作拼图块部分。

90~120min

最后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这个游戏引擎,实在是可以大幅提升开发效率。

显示全文