您的位置:首页 > Web前端 > JavaScript

JS开发HTML5游戏《神奇的六边形》(六)

2015-11-17 00:00 1086 查看
摘要: 本文主要介绍如何使用青瓷引擎(www.zuoyouxi.com)开发一款魔性消除类HTML5游戏《神奇的六边形》

近期出现一款魔性的消除类HTML5游戏《神奇的六边形》,今天我们一起来看看如何通过开源免费的青瓷引擎(www.zuoyouxi.com)来实现这款游戏。



点击这里可进入游戏体验)
因内容太多,为方便大家阅读,所以分成部分来讲解。
本文为第六部分,主要包括:
15. 消除行

十五. 消除行

以下的行是可以被消除的:







逻辑实现
1. 打开Scripts/logic/board.js,将上述3类型的行建立数据结构:
var Board = qc.Tetris.Board = function() {
// 省略一堆代码
...

// 左斜的9条线,指明起始点坐标
self.xyLines = [
[0, -4],
[1, -4],
[2, -4],
[3, -4],
[4, -4],

[4, -3],
[4, -2],
[4, -1],
[4, 0]
];

// 横向9条线,指明起始点坐标和长度
self.yLines = [
[0, -4, 5],
[-1, -3, 6],
[-2, -2, 7],
[-3, -1, 8],
[-4, 0, 9],
[-4, 1, 8],
[-4, 2, 7],
[-4, 3, 6],
[-4, 4, 5]
];

// 右斜9条线,指明起始点坐标和长度
self.xLines = [
[-4, 0, 5],
[-3, -1, 6],
[-2, -2, 7],
[-1, -3, 8],
[0, -4, 9],
[1, -4, 8],
[2, -4, 7],
[3, -4, 6],
[4, -4, 5]
];
};


2. 实现putIn接口:
Board.prototype.putIn = function(pos, list, value) {
var self = this;
var pt = qc.Tetris.readPos(pos),
x = pt.x,
y = pt.y;

for (var i = 0; i < list.length; i++) {
var x0 = x + list[i][0],
y0 = y + list[i][1];

// 这个点应该是空的
var block = self.data[qc.Tetris.makePos(x0, y0)];
block.value = value;
}
};


3. 实现clearLine接口,干掉一行数据:
// 干掉一行
Board.prototype.clearLine = function(pts) {
var self = this;
pts.forEach(function(pos) {
self.data[pos].value = 0;
});
};


4. 实现getFullLines接口,将所有可以消除的行返回:
// 取得可以消除的行
Board.prototype.getFullLines = function() {
var self = this,
lines = [];

// 横向9条线
var pts = self.yLines;
for (var i = 0; i < pts.length; i++) {
var start = pts[i], end = [start[0] + start[2] - 1, start[1]];
var ok = true;
for (var x = start[0], y = start[1]; x <= end[0];) {
var pos = qc.Tetris.makePos(x, y);
if (self.data[pos].value === 0) {
// 不符合,不能消除
ok = false; break;
}

// 下一个点
x++;
}
if (ok) {
// 这条线可以消除,添加进来
lines.push('y' + qc.Tetris.makePos(start[0], start[1]));
}
}

// 右斜9条线
var pts = self.xLines;
for (var i = 0; i < pts.length; i++) {
var start = pts[i], end = [start[0], start[1] + start[2] - 1];
var ok = true;
for (var x = start[0], y = start[1]; y <= end[1];) {
var pos = qc.Tetris.makePos(x, y);
if (self.data[pos].value === 0) {
// 不符合,不能消除
ok = false; break;
}

// 下一个点
y++;
}
if (ok) {
// 这条线可以消除,添加进来
lines.push('x' + qc.Tetris.makePos(start[0], start[1]));
}
}

// 左斜的9条线
var pts = self.xyLines;
for (var i = 0; i < pts.length; i++) {
var start = pts[i], end = [start[1], start[0]];
var ok = true;
for (var x = start[0], y = start[1]; true;) {
var pos = qc.Tetris.makePos(x, y);
if (self.data[pos].value === 0) {
// 不符合,不能消除
ok = false; break;
}

// 下一个点
if (end[0] > start[0]) {
x++, y--;
if (x > end[0]) break;
}
else {
x--, y++;
if (x < end[0]) break;
}
}
if (ok) {
// 这条线可以消除,添加进来
lines.push('xy' + qc.Tetris.makePos(start[0], start[1]));
}
}

return lines;
};


界面实现

预先将所有的行创建出来,当行被删除时直接显示出来做动画表现。以下流程中,我们首先创建一个格子的预制,再创建一个行的预置。
1. 在board节点下,创建Image对象,设置属性如下图:



2.将新创建的block节点拖入Assets/prefab目录,创建预制。然后从场景中删除。
3. 在board节点下,创建Node对象,设置属性如下图:



4. 为节点挂载TweenAlpha动画组件,消失时需要淡出:



透明度从1变化到0

耗时0.5秒

变化的曲线是:先平缓的做变化,然后在快速变化为0

图片中from和to值设置反了,请手工设置下from=1,to=0

5. 在Scripts/ui下创建脚本Line.js,控制行的绘制和表现:
/**
* 消除一行的表现界面
*/
var LineUI = qc.defineBehaviour('qc.tetris.LineUI', qc.Behaviour, function() {
var self = this;

// 描述行的信息
self.flag = 'xy';
self.x = 0;
self.y = 0;
}, {
blockPrefab: qc.Serializer.PREFAB
});

Object.defineProperties(LineUI.prototype, {
/**
* 取得行标记
*/
key: {
get: function() {
return this.flag + qc.Tetris.makePos(this.x, this.y);
}
},

/**
* 取得本行的格子数量
*/
count: {
get: function() {
return this.gameObject.children.length;
}
}
});

/**
* 初始化行
*/
LineUI.prototype.init = function(flag, start, end) {
var self = this;
self.flag = flag;
self.x = start[0];
self.y = start[1];

// 创建一个格子
var createBlock = function(pos) {
var block = self.game.add.clone(self.blockPrefab, self.gameObject);
block.frame = 'white.png';
block.anchoredX = qc.Tetris.board.data[pos].x;
block.anchoredY = qc.Tetris.board.data[pos].y;
block.name = pos;
return block;
};

switch (flag) {
case 'xy':
for (var x = self.x, y = self.y; true;) {
createBlock(qc.Tetris.makePos(x, y));

// 下一个点
if (end[0] > start[0]) {
x++, y--;
if (x > end[0]) break;
}
else {
x--, y++;
if (x < end[0]) break;
}
}
break;

case 'y':
for (var x = start[0], y = start[1]; x <= end[0];) {
createBlock(qc.Tetris.makePos(x, y));
x++;
}
break;

case 'x':
for (var x = start[0], y = start[1]; y <= end[1];) {
createBlock(qc.Tetris.makePos(x, y));
y++;
}
}

// 初始时隐藏掉
self.gameObject.name = self.key;
self.gameObject.visible = false;
};

/**
* 播放消失的动画
*/
LineUI.prototype.playDisappear = function(index) {
var self = this,
o = self.gameObject,
ta = self.getScript('qc.TweenAlpha');

o.visible = true;
o.alpha = 1;

ta.delay = 0;
ta.resetToBeginning();
ta.onFinished.addOnce(function() {
// 隐藏掉
o.visible = false;
});
ta.playForward();
};


flag和x、y属性描述了行的信息(左斜行、水平行还是右斜行,起始点的坐标)

6. 将此脚本挂载到Line节点,并设置blockPrefab为第一步骤创建的格子预置:



7. 将line拖进Assets/prefab目录,创建预制。然后从场景中删除。
8. 在Scripts/ui创建脚本KillLineEffect.js,处理行消失表现的逻辑
/**
* 行消除的动画表现
*/
var KillLineEffect = qc.defineBehaviour('qc.tetris.KillLineEffect', qc.Behaviour, function() {
var self = this;

/**
* 所有的行
*/
self.lines = {};

/**
* 两行之间的播放延迟
*/
self.delay = 300;
}, {
delay: qc.Serializer.NUMBER,
linePrefab: qc.Serializer.PREFAB
});

/**
* 初始化:将用于表现的行全部创建出来放着
*/
KillLineEffect.prototype.awake = function() {
var self = this;

// 创建用于消除表现的格子行
var createLine = function(flag, start, end) {
var ob = self.game.add.clone(self.linePrefab, self.gameObject);
var line = ob.getScript('qc.tetris.LineUI');
line.init(flag, start, end);
self.lines[line.key] = line;
};
var pts = qc.Tetris.board.xyLines;
for (var i = 0; i < pts.length; i++) {
var start = pts[i], end = [start[1], start[0]];
createLine('xy', start, end);
}

var pts = qc.Tetris.board.yLines;
for (var i = 0; i < pts.length; i++) {
var start = pts[i], end = [start[0] + start[2] - 1, start[1]];
createLine('y', start, end);

}
var pts = qc.Tetris.board.xLines;
for (var i = 0; i < pts.length; i++) {
var start = pts[i], end = [start[0], start[1] + start[2] - 1];
createLine('x', start, end);
}
};

KillLineEffect.prototype.find = function(flag) {
return this.lines[flag];
};

KillLineEffect.prototype.play = function(index, flag, score) {
var self = this;
var line = self.find(flag);
var delay = index * self.delay;

var playFunc = function() {
// 冒出分数
var children = line.gameObject.children;
var pos = children[Math.round(children.length/2) - 1].name;
self.getScript('qc.tetris.FlyScore').play(pos, score);

// 消失动画
line.playDisappear();
};
if (delay <= 0) {
playFunc();
}
else {
self.game.timer.add(delay, playFunc);
}
};


在脚本初始化时,将所有行的数据构建出来,并隐藏掉

delay表示在多行消失时,其动画的间隔时间

在动画表现时,有分数表现,FlyScore下一章再补充

9. 将KillLineEffect挂载到board节点(棋盘),并设置linePrefab:



10. 运行工程,就可以看到这些“行”了:



11. 选中UIRoot节点,设置UIManager的Kill Line Effect Node属性(board节点,因为board挂载了KillLineEffect脚本):



下一篇:JS开发HTML5游戏《神奇的六边形》(五)

下一篇:JS开发HTML5游戏《神奇的六边形》(七)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息