HTML5 Canvas编写五彩连珠(5):寻路
上节主要做了动画的实现,感觉还是比较有意思的。游戏的性能好不好,重绘应该比较重要吧,菜鸟瞎想了下 呵呵。
本节就要做对泡泡的操作,上节后面提到了点击泡泡后泡泡要做出闪动响应,那我们我们如何获得被点击了哪个泡泡呢?
其实Canvas也是htML的一个元素而已,所以我们可以给Canvas加click事件。来查看click时鼠标的坐标,这样就等得出点击了map的哪个位置。
我们给game增加一个click方法,当Canvas点击时调用此方法。
要实现的效果是: 当Canvas时被点击时有几种可能:
1、没点到map 那就不作响应
2、点到了泡泡,那该泡泡要做出响应(闪)
3、如果之前有点击过其他的泡泡,则取消之前的泡泡的响应(clicked.stop),如果之前的泡泡是自己,则不作响应。并把clicked作为自己,以体后面的操作。
4、如果点击到的是空格,如果之前点击了泡泡,那就尝试移动这个泡泡,如果clicked为null(之前没泡泡)那就不作任何响应。如果可以移动,则取消闪动,并清除clicked,开始移动。
[javascript]
onclick: function (e) {
VAR px = e.offsetX - game.map.startX;
var py = e.offsetY - game.map.startY;
if (px 0 || py 0 || px >
game.map.width || py >
game.map.height) {
return;
}
var x = parseInt(px / game.cellWidth);
var y = parseInt(py / game.cellWidth);
var bubble = game.map.getBubble(x, y);
if (bubble.color) {
if (this.clicked) {
//同一个泡不做反映 if (this.clicked.x == x &
&
this.clicked.y == y) {
return;
}
this.clicked.stop();
}
this.clicked = bubble;
bubble.play();
}
else {
if (this.clicked) {
this.clicked.stop();
//移动clicked game.map.move(this.clicked, bubble);
}
}
//console.LOG("x:" + x + " y:" + y);
}
, onclick: function (e) {
var px = e.offsetX - game.map.startX;
var py = e.offsetY - game.map.startY;
if (px 0 || py 0 || px >
game.map.width || py >
game.map.height) {
return;
}
var x = parseInt(px / game.cellWidth);
var y = parseInt(py / game.cellWidth);
var bubble = game.map.getBubble(x, y);
if (bubble.color) {
if (this.clicked) {
//同一个泡不做反映 if (this.clicked.x == x &
&
this.clicked.y == y) {
return;
}
this.clicked.stop();
}
this.clicked = bubble;
bubble.play();
}
else {
if (this.clicked) {
this.clicked.stop();
//移动clicked game.map.move(this.clicked, bubble);
}
}
//console.log("x:" + x + " y:" + y);
}
,
寻路的代码还没写,因为这个需要考虑怎么实现。 我绞尽脑汁终于想到了一个办法。暂且撇开游戏的代码,单独实现下两点的寻路代码。
先给定一个棋盘,假如如下:
1 1 1 1 1
0 0 1 0 1
0 0 1 0 1
1 0 0 1 1
要想从 最下面一行中间的点(2,3)移动到左上角的(0,1),该如何设计呢?
一个棋子能否移动,要看他相邻的4个子是否为0,如果是0则可以移动。 所以我们可以通过递归来获得所有相连的0的记录。 这个记录用树结构来存储,直到我们无法继续探测为0的格子或到达目的地。 我们把当前的棋子的格子设为 root,他相邻的棋子是他的孩子。这样的话,我们会得到一棵树的结果如下:
是不是?这样的画我们就可以直接看到了整个路径(2,3 -> 1,3 -> 1,2 -> 0,2 -> 0,1)。思路很清晰,只要递归构建子节点就ok了。代码如下:
[javascript]
var map = [ [1, 1, 1, 1, 1], [0, 0, 1, 0, 1], [0, 0, 1, 0, 1], [1, 0, 0, 1, 1] ];
var history = [];
var goal = {
"x": 0, "y": 1 }
var goalNode = null;
var getNode = function (x, y, parent) {
if (x >
= map.length || y >
= map.length) {
return;
if (map[y][x] == 1) {
return;
}
var hasNode = false;
history.foreach(function (n) {
if (n.x == x &
&
n.y == y) {
hasNode = true;
return;
}
}
);
if (hasNode) {
return;
}
var node = {
"x": x, "y": y, "parent": parent, child: [] }
;
history.push(node);
if (node.x == goal.x &
&
node.y == goal.y) {
goalNode = node;
return node;
}
if (x - 1 >
= 0 &
&
!map[y][x - 1]) {
node.child.push(getNode(x - 1, y, node));
}
if (y - 1 >
= 0 &
&
!map[y - 1][x]) {
node.child.push(getNode(x, y - 1, node));
}
if (x + 1 map.length &
&
!map[y][x + 1]) {
node.child.push(getNode(x + 1, y), node);
}
if (y + 1 map.length &
&
!map[y + 1][x]) {
node.child.push(getNode(x, y + 1, node));
}
return node;
}
console.log(getNode(2, 3));
console.log(goalNode);
var map = [ [1, 1, 1, 1, 1], [0, 0, 1, 0, 1], [0, 0, 1, 0, 1], [1, 0, 0, 1, 1] ];
var history = [];
var goal = {
"x": 0, "y": 1 }
var goalNode = null;
var getNode = function (x, y, parent) {
if (x >
= map.length || y >
= map.length) {
return;
}
if (map[y][x] == 1) {
return;
}
var hasNode = false;
history.forEach(function (n) {
if (n.x == x &
&
n.y == y) {
hasNode = true;
return;
}
}
);
if (hasNode) {
return;
}
var node = {
"x": x, "y": y, "parent": parent, child: [] }
;
history.push(node);
if (node.x == goal.x &
&
node.y == goal.y) {
goalNode = node;
return node;
}
if (x - 1 >
= 0 &
&
!map[y][x - 1]) {
node.child.push(getNode(x - 1, y, node));
}
if (y - 1 >
= 0 &
&
!map[y - 1][x]) {
node.child.push(getNode(x, y - 1, node));
}
if (x + 1 map.length &
&
!map[y][x + 1]) {
node.child.push(getNode(x + 1, y), node);
}
if (y + 1 map.length &
&
!map[y + 1][x]) {
node.child.push(getNode(x, y + 1, node));
}
return node;
}
console.log(getNode(2, 3));
console.log(goalNode);
我加了一个parent,就是指向父亲的指针,那样就不用再去遍历这棵树了。可以直接从goalNode的结果得到整个路径:) 虽然偷懒,但也是要复出代价的,因为这样走的路径不是最短路线,比较傻,怎么选择最优路线呢? 最笨的方法就是 把所有的路径都得到(深度优先遍历树N遍- -)然后比较。这个显然效率不高。开始我也不知道效果会这么差,等一运行(你运行下就知道了),我发现,是代码写的不好(废话)。因为我们每次的判断顺寻都是 左上右下,这样路径总是这个方向探索,而最优的路径应该是朝目标点的方向探索。 由于是递归查找,所以,对当前的node和目标node进行坐标的方向判断,然后调整判断顺序,这样是得到的才是比较短的路径。
[javascript]
var child = [];
var left, top, right, buttom;
//最短路径的粗略判断就是首选目标位置的大致方向 if (x - 1 >
= 0 &
&
map.iSEMpty(x - 1, y)) left = {
"x": x - 1, "y": y }
;
if (x + 1 map.length &
&
map.isEmpty(x + 1, y)) right = {
"x": x + 1, "y": y }
;
if (y + 1 map.length &
&
map.isEmpty(x, y + 1)) buttom = {
"x": x, "y": y + 1 }
;
if (y - 1 >
= 0 &
&
map.isEmpty(x, y - 1)) top = {
"x": x, "y": y - 1 }
;
if (x >
x2) {
if (y >
y2) child = [left, top, right, buttom];
else if (y y2) child = [left, buttom, right, top];
else child = [left, top, right, buttom];
}
else if (x x2) {
if (y >
y2) child = [right, top, left, buttom];
else if (y y2) child = [right, buttom, left, top];
else child = [right, top, left, buttom];
}
else if (x == x2) {
if (y >
y2) child = [top, left, right, buttom];
else if (y y2) child = [buttom, left, right, top];
}
for (var i = 0;
i child.length;
i++) {
var c = child[i];
if (c) node.child.push(getnode(c.x, c.y, node));
}
var child = [];
var left, top, right, buttom;
//最短路径的粗略判断就是首选目标位置的大致方向 if (x - 1 >
= 0 &
&
map.isEmpty(x - 1, y)) left = {
"x": x - 1, "y": y }
;
if (x + 1 map.length &
&
map.isEmpty(x + 1, y)) right = {
"x": x + 1, "y": y }
;
if (y + 1 map.length &
&
map.isEmpty(x, y + 1)) buttom = {
"x": x, "y": y + 1 }
;
if (y - 1 >
= 0 &
&
map.isEmpty(x, y - 1)) top = {
"x": x, "y": y - 1 }
;
if (x >
x2) {
if (y >
y2) child = [left, top, right, buttom];
else if (y y2) child = [left, buttom, right, top];
else child = [left, top, right, buttom];
}
else if (x x2) {
if (y >
y2) child = [right, top, left, buttom];
else if (y y2) child = [right, buttom, left, top];
else child = [right, top, left, buttom];
}
else if (x == x2) {
if (y >
y2) child = [top, left, right, buttom];
else if (y y2) child = [buttom, left, right, top];
}
for (var i = 0;
i child.length;
i++) {
var c = child[i];
if (c) node.child.push(getnode(c.x, c.y, node));
}
代码虽然写的比较傻,但这种方式不得不说好就一个字:)
既然寻路已经实现了,那么下面就交给map了,map来负责让泡泡走起来。其实就是根据路径给泡泡着色- - ,代码也不复杂。
[javascript]
move: function (bubble, target) {
var path = this.seArch(bubble.x, bubble.y, target.x, target.y);
if (!path) {
//显示不能移动s alert("过不去");
return;
}
//map开始播放当前泡的移动效果
//两种实现方式,1、map按路径染色,最后达到目的地
2、map生成一个临时的bubble负责展示,到目的地后移除
//console.log(path);
var me = this;
var name = "move_" + bubble.x + "_" + bubble.y;
var i = path.length - 1;
var color = bubble.color;
game.play(name, function () {
if (i 0) {
game.stop(name);
return;
}
path.forEach(function (cell) {
me.setBubble(cell.x, cell.y, null);
}
);
var currentCell = path[i];
me.setBubble(currentCell.x, currentCell.y, color);
i--;
}
, 50);
}
, search: function (x1, y1, x2, y2) {
var history = [];
var goalCell = null;
var me = this;
getCell(x1, y1, null);
if (goalCell) {
var path = [];
var cell = goalCell;
while (cell) {
path.push({
"x": cell.x, "y": cell.y }
);
cell = cell.parent;
}
return path;
}
return null;
function getCell(x, y, parent) {
if (x >
= me.bubbles.length || y >
= me.bubbles.length) return;
if (x != x1 &
&
y != y2 &
&
!me.isEmpty(x, y)) return;
for (var i = 0;
i history.length;
i++) {
if (history[i].x == x &
&
history[i].y == y) return;
}
var cell = {
"x": x, "y": y, child: [], "parent": parent }
;
history.push(cell);
if (cell.x == x2 &
&
cell.y == y2) {
goalCell = cell;
return cell;
}
var child = [];
var left, top, right, buttom;
//最短路径的粗略判断就是首选目标位置的大致方向 if (x - 1 >
= 0 &
&
me.isEmpty(x - 1, y)) left = {
"x": x - 1, "y": y }
;
if (x + 1 me.bubbles.length &
&
me.isEmpty(x + 1, y)) right = {
"x": x + 1, "y": y }
;
if (y + 1 me.bubbles.length &
&
me.isEmpty(x, y + 1)) buttom = {
"x": x, "y": y + 1 }
;
if (y - 1 >
= 0 &
&
me.isEmpty(x, y - 1)) top = {
"x": x, "y": y - 1 }
;
if (x >
x2) {
if (y >
y2) child = [left, top, right, buttom];
else if (y y2) child = [left, buttom, right, top];
else child = [left, top, right, buttom];
}
else if (x x2) {
if (y >
y2) child = [right, top, left, buttom];
else if (y y2) child = [right, buttom, left, top];
else child = [right, top, left, buttom];
}
else if (x == x2) {
if (y >
y2) child = [top, left, right, buttom];
else if (y y2) child = [buttom, left, right, top];
}
for (var i = 0;
i child.length;
i++) {
var c = child[i];
if (c) cell.child.push(getCell(c.x, c.y, cell));
}
return cell;
}
}
,
move: function (bubble, target) {
var path = this.search(bubble.x, bubble.y, target.x, target.y);
if (!path) {
//显示不能移动s alert("过不去");
return;
}
//map开始播放当前泡的移动效果
//两种实现方式,1、map按路径染色,最后达到目的地
2、map生成一个临时的bubble负责展示,到目的地后移除
//console.log(path);
var me = this;
var name = "move_" + bubble.x + "_" + bubble.y;
var i = path.length - 1;
var color = bubble.color;
game.play(name, function ()
{
if (i 0) {
game.stop(name);
return;
}
path.forEach(function (cell) {
me.setBubble(cell.x, cell.y, null);
}
);
var currentCell = path[i];
me.setBubble(currentCell.x, currentCell.y, color);
i--;
}
, 50);
}
, search: function (x1, y1, x2, y2) {
var history = [];
var goalCell = null;
var me = this;
getCell(x1, y1, null);
if (goalCell) {
var path = [];
var cell = goalCell;
while (cell) {
path.push({
"x": cell.x, "y": cell.y }
);
cell = cell.parent;
}
return path;
}
return null;
function getCell(x, y, parent)
{
if (x >
= me.bubbles.length || y >
= me.bubbles.length) return;
if (x != x1 &
&
y != y2 &
&
!me.isEmpty(x, y)) return;
for (var i = 0;
i history.length;
i++) {
if (history[i].x == x &
&
history[i].y == y) return;
}
var cell = {
"x": x, "y": y, child: [], "parent": parent
}
;
history.push(cell);
if (cell.x == x2 &
&
cell.y == y2) {
goalCell = cell;
return cell;
}
var child = [];
var left, top, right, buttom;
//最短路径的粗略判断就是首选目标位置的大致方向 if (x - 1 >
= 0 &
&
me.isEmpty(x - 1, y)) left = {
"x": x - 1, "y": y }
;
if (x + 1 me.bubbles.length &
&
me.isEmpty(x + 1, y)) right = {
"x": x + 1, "y": y }
;
if (y + 1 me.bubbles.length &
&
me.isEmpty(x, y + 1)) buttom = {
"x": x, "y": y + 1 }
;
if (y - 1 >
= 0 &
&
me.isEmpty(x, y - 1)) top = {
"x": x, "y": y - 1 }
;
if (x >
x2)
{
if (y >
y2) child = [left, top, right, buttom];
else if (y y2) child = [left, buttom, right, top];
else child = [left, top, right, buttom];
}
else if (x x2) {
if (y >
y2) child = [right, top, left, buttom];
else if (y y2) child = [right, buttom, left, top];
else child = [right, top, left, buttom];
}
else if (x == x2) {
if (y >
y2) child = [top, left, right, buttom];
else if (y y2) child = [buttom, left, right, top];
}
for (var i = 0;
i child.length;
i++) {
var c = child[i];
if (c) cell.child.push(getCell(c.x, c.y, cell));
}
return cell;
}
}
,
看下动画效果http://jsfiddle.net/maddemon/khAJB/4/embedded/result/
后面剩下的就是判断如何消除、加分、防止误操作之类的内容了。
摘自 君之m
上节主要做了动画的实现,感觉还是比较有意思的。游戏的性能好不好,重绘应该比较重要吧,菜鸟瞎想了下 呵呵。
本节就要做对泡泡的操作,上节后面提到了点击泡泡后泡泡要做出闪动响应,那我们我们如何获得被点击了哪个泡泡呢?
其实Canvas也是html的一个元素而已,所以我们可以给Canvas加click事件。来查看click时鼠标的坐标,这样就等得出点击了map的哪个位置。
我们给game增加一个click方法,当Canvas点击时调用此方法。
要实现的效果是: 当Canvas时被点击时有几种可能:
1、没点到map 那就不作响应
2、点到了泡泡,那该泡泡要做出响应(闪)
3、如果之前有点击过其他的泡泡,则取消之前的泡泡的响应(clicked.stop),如果之前的泡泡是自己,则不作响应。并把clicked作为自己,以体后面的操作。
4、如果点击到的是空格,如果之前点击了泡泡,那就尝试移动这个泡泡,如果clicked为null(之前没泡泡)那就不作任何响应。如果可以移动,则取消闪动,并清除clicked,开始移动。
[javascript]
onclick: function (e) {
var px = e.offsetX - game.map.startX;
var py = e.offsetY - game.map.startY;
if (px 0 || py 0 || px >
game.map.width || py >
game.map.height) {
return;
}
var x = parseInt(px / game.cellWidth);
var y = parseInt(py / game.cellWidth);
var bubble = game.map.getBubble(x, y);
if (bubble.color) {
if (this.clicked) {
//同一个泡不做反映 if (this.clicked.x == x &
&
this.clicked.y == y) {
return;
}
this.clicked.stop();
}
this.clicked = bubble;
bubble.play();
}
else {
if (this.clicked) {
this.clicked.stop();
//移动clicked game.map.move(this.clicked, bubble);
}
}
//console.log("x:" + x + " y:" + y);
}
, onclick: function (e) {
var px = e.offsetX - game.map.startX;
var py = e.offsetY - game.map.startY;
if (px 0 || py 0 || px >
game.map.width || py >
game.map.height) {
return;
}
var x = parseInt(px / game.cellWidth);
var y = parseInt(py / game.cellWidth);
var bubble = game.map.getBubble(x, y);
if (bubble.color) {
if (this.clicked) {
//同一个泡不做反映 if (this.clicked.x == x &
&
this.clicked.y == y) {
return;
}
this.clicked.stop();
}
this.clicked = bubble;
bubble.play();
}
else {
if (this.clicked) {
this.clicked.stop();
//移动clicked game.map.move(this.clicked, bubble);
}
}
//console.log("x:" + x + " y:" + y);
}
,
寻路的代码还没写,因为这个需要考虑怎么实现。 我绞尽脑汁终于想到了一个办法。暂且撇开游戏的代码,单独实现下两点的寻路代码。
先给定一个棋盘,假如如下:
1 1 1 1 1
0 0 1 0 1
0 0 1 0 1
1 0 0 1 1
要想从 最下面一行中间的点(2,3)移动到左上角的(0,1),该如何设计呢?
一个棋子能否移动,要看他相邻的4个子是否为0,如果是0则可以移动。 所以我们可以通过递归来获得所有相连的0的记录。 这个记录用树结构来存储,直到我们无法继续探测为0的格子或到达目的地。 我们把当前的棋子的格子设为 root,他相邻的棋子是他的孩子。这样的话,我们会得到一棵树的结果如下:
是不是?这样的画我们就可以直接看到了整个路径(2,3 -> 1,3 -> 1,2 -> 0,2 -> 0,1)。思路很清晰,只要递归构建子节点就ok了。代码如下:
[javascript]
var map = [ [1, 1, 1, 1, 1], [0, 0, 1, 0, 1], [0, 0, 1, 0, 1], [1, 0, 0, 1, 1] ];
var history = [];
var goal = {
"x": 0, "y": 1 }
var goalNode = null;
var getNode = function (x, y, parent) {
if (x >
= map.length || y >
= map.length) {
return;
if (map[y][x] == 1) {
return;
}
var hasNode = false;
history.forEach(function (n) {
if (n.x == x &
&
n.y == y) {
hasNode = true;
return;
}
}
);
if (hasNode) {
return;
}
var node = {
"x": x, "y": y, "parent": parent, child: [] }
;
history.push(node);
if (node.x == goal.x &
&
node.y == goal.y) {
goalNode = node;
return node;
}
if (x - 1 >
= 0 &
&
!map[y][x - 1]) {
node.child.push(getNode(x - 1, y, node));
}
if (y - 1 >
= 0 &
&
!map[y - 1][x]) {
node.child.push(getNode(x, y - 1, node));
}
if (x + 1 map.length &
&
!map[y][x + 1]) {
node.child.push(getNode(x + 1, y), node);
}
if (y + 1 map.length &
&
!map[y + 1][x]) {
node.child.push(getNode(x, y + 1, node));
}
return node;
}
console.log(getNode(2, 3));
console.log(goalNode);
var map = [ [1, 1, 1, 1, 1], [0, 0, 1, 0, 1], [0, 0, 1, 0, 1], [1, 0, 0, 1, 1] ];
var history = [];
var goal = {
"x": 0, "y": 1 }
var goalNode = null;
var getNode = function (x, y, parent) {
if (x >
= map.length || y >
= map.length) {
return;
}
if (map[y][x] == 1) {
return;
}
var hasNode = false;
history.forEach(function (n) {
if (n.x == x &
&
n.y == y) {
hasNode = true;
return;
}
}
);
if (hasNode) {
return;
}
var node = {
"x": x, "y": y, "parent": parent, child: [] }
;
history.push(node);
if (node.x == goal.x &
&
node.y == goal.y) {
goalNode = node;
return node;
}
if (x - 1 >
= 0 &
&
!map[y][x - 1]) {
node.child.push(getNode(x - 1, y, node));
}
if (y - 1 >
= 0 &
&
!map[y - 1][x]) {
node.child.push(getNode(x, y - 1, node));
}
if (x + 1 map.length &
&
!map[y][x + 1]) {
node.child.push(getNode(x + 1, y), node);
}
if (y + 1 map.length &
&
!map[y + 1][x]) {
node.child.push(getNode(x, y + 1, node));
}
return node;
}
console.log(getNode(2, 3));
console.log(goalNode);
我加了一个parent,就是指向父亲的指针,那样就不用再去遍历这棵树了。可以直接从goalNode的结果得到整个路径:) 虽然偷懒,但也是要复出代价的,因为这样走的路径不是最短路线,比较傻,怎么选择最优路线呢? 最笨的方法就是 把所有的路径都得到(深度优先遍历树N遍- -)然后比较。这个显然效率不高。开始我也不知道效果会这么差,等一运行(你运行下就知道了),我发现,是代码写的不好(废话)。因为我们每次的判断顺寻都是 左上右下,这样路径总是这个方向探索,而最优的路径应该是朝目标点的方向探索。 由于是递归查找,所以,对当前的node和目标node进行坐标的方向判断,然后调整判断顺序,这样是得到的才是比较短的路径。
[javascript]
var child = [];
var left, top, right, buttom;
//最短路径的粗略判断就是首选目标位置的大致方向 if (x - 1 >
= 0 &
&
map.isEmpty(x - 1, y)) left = {
"x": x - 1, "y": y }
;
if (x + 1 map.length &
&
map.isEmpty(x + 1, y)) right = {
"x": x + 1, "y": y }
;
if (y + 1 map.length &
&
map.isEmpty(x, y + 1)) buttom = {
"x": x, "y": y + 1 }
;
if (y - 1 >
= 0 &
&
map.isEmpty(x, y - 1)) top = {
"x": x, "y": y - 1 }
;
if (x >
x2) {
if (y >
y2) child = [left, top, right, buttom];
else if (y y2) child = [left, buttom, right, top];
else child = [left, top, right, buttom];
}
else if (x x2) {
if (y >
y2) child = [right, top, left, buttom];
else if (y y2) child = [right, buttom, left, top];
else child = [right, top, left, buttom];
}
else if (x == x2) {
if (y >
y2) child = [top, left, right, buttom];
else if (y y2) child = [buttom, left, right, top];
}
for (var i = 0;
i child.length;
i++) {
var c = child[i];
if (c) node.child.push(getnode(c.x, c.y, node));
}
var child = [];
var left, top, right, buttom;
//最短路径的粗略判断就是首选目标位置的大致方向 if (x - 1 >
= 0 &
&
map.isEmpty(x - 1, y)) left = {
"x": x - 1, "y": y }
;
if (x + 1 map.length &
&
map.isEmpty(x + 1, y)) right = {
"x": x + 1, "y": y }
;
if (y + 1 map.length &
&
map.isEmpty(x, y + 1)) buttom = {
"x": x, "y": y + 1 }
;
if (y - 1 >
= 0 &
&
map.isEmpty(x, y - 1)) top = {
"x": x, "y": y - 1 }
;
if (x >
x2) {
if (y >
y2) child = [left, top, right, buttom];
else if (y y2) child = [left, buttom, right, top];
else child = [left, top, right, buttom];
}
else if (x x2) {
if (y >
y2) child = [right, top, left, buttom];
else if (y y2) child = [right, buttom, left, top];
else child = [right, top, left, buttom];
}
else if (x == x2) {
if (y >
y2) child = [top, left, right, buttom];
else if (y y2) child = [buttom, left, right, top];
}
for (var i = 0;
i child.length;
i++) {
var c = child[i];
if (c) node.child.push(getnode(c.x, c.y, node));
}
代码虽然写的比较傻,但这种方式不得不说好就一个字:)
既然寻路已经实现了,那么下面就交给map了,map来负责让泡泡走起来。其实就是根据路径给泡泡着色- - ,代码也不复杂。
[javascript]
move: function (bubble, target) {
var path = this.search(bubble.x, bubble.y, target.x, target.y);
if (!path) {
//显示不能移动s alert("过不去");
return;
}
//map开始播放当前泡的移动效果
//两种实现方式,1、map按路径染色,最后达到目的地
2、map生成一个临时的bubble负责展示,到目的地后移除
//console.log(path);
var me = this;
var name = "move_" + bubble.x + "_" + bubble.y;
var i = path.length - 1;
var color = bubble.color;
game.play(name, function () {
if (i 0) {
game.stop(name);
return;
}
path.forEach(function (cell) {
me.setBubble(cell.x, cell.y, null);
}
);
var currentCell = path[i];
me.setBubble(currentCell.x, currentCell.y, color);
i--;
}
, 50);
}
, search: function (x1, y1, x2, y2) {
var history = [];
var goalCell = null;
var me = this;
getCell(x1, y1, null);
if (goalCell) {
var path = [];
var cell = goalCell;
while (cell) {
path.push({
"x": cell.x, "y": cell.y }
);
cell = cell.parent;
}
return path;
}
return null;
function getCell(x, y, parent) {
if (x >
= me.bubbles.length || y >
= me.bubbles.length) return;
if (x != x1 &
&
y != y2 &
&
!me.isEmpty(x, y)) return;
for (var i = 0;
i history.length;
i++) {
if (history[i].x == x &
&
history[i].y == y) return;
}
var cell = {
"x": x, "y": y, child: [], "parent": parent }
;
history.push(cell);
if (cell.x == x2 &
&
cell.y == y2) {
goalCell = cell;
return cell;
}
var child = [];
var left, top, right, buttom;
//最短路径的粗略判断就是首选目标位置的大致方向 if (x - 1 >
= 0 &
&
me.isEmpty(x - 1, y)) left = {
"x": x - 1, "y": y }
;
if (x + 1 me.bubbles.length &
&
me.isEmpty(x + 1, y)) right = {
"x": x + 1, "y": y }
;
if (y + 1 me.bubbles.length &
&
me.isEmpty(x, y + 1)) buttom = {
"x": x, "y": y + 1 }
;
if (y - 1 >
= 0 &
&
me.isEmpty(x, y - 1)) top = {
"x": x, "y": y - 1 }
;
if (x >
x2) {
if (y >
y2) child = [left, top, right, buttom];
else if (y y2) child = [left, buttom, right, top];
else child = [left, top, right, buttom];
}
else if (x x2) {
if (y >
y2) child = [right, top, left, buttom];
else if (y y2) child = [right, buttom, left, top];
else child = [right, top, left, buttom];
}
else if (x == x2) {
if (y >
y2) child = [top, left, right, buttom];
else if (y y2) child = [buttom, left, right, top];
}
for (var i = 0;
i child.length;
i++) {
var c = child[i];
if (c) cell.child.push(getCell(c.x, c.y, cell));
}
return cell;
}
}
,
move: function (bubble, target) {
var path = this.search(bubble.x, bubble.y, target.x, target.y);
if (!path) {
//显示不能移动s alert("过不去");
return;
}
//map开始播放当前泡的移动效果
//两种实现方式,1、map按路径染色,最后达到目的地
2、map生成一个临时的bubble负责展示,到目的地后移除
//console.log(path);
var me = this;
var name = "move_" + bubble.x + "_" + bubble.y;
var i = path.length - 1;
var color = bubble.color;
game.play(name, function ()
{
if (i 0) {
game.stop(name);
return;
}
path.forEach(function (cell) {
me.setBubble(cell.x, cell.y, null);
}
);
var currentCell = path[i];
me.setBubble(currentCell.x, currentCell.y, color);
i--;
}
, 50);
}
, search: function (x1, y1, x2, y2) {
var history = [];
var goalCell = null;
var me = this;
getCell(x1, y1, null);
if (goalCell) {
var path = [];
var cell = goalCell;
while (cell) {
path.push({
"x": cell.x, "y": cell.y }
);
cell = cell.parent;
}
return path;
}
return null;
function getCell(x, y, parent)
{
if (x >
= me.bubbles.length || y >
= me.bubbles.length) return;
if (x != x1 &
&
y != y2 &
&
!me.isEmpty(x, y)) return;
for (var i = 0;
i history.length;
i++) {
if (history[i].x == x &
&
history[i].y == y) return;
}
var cell = {
"x": x, "y": y, child: [], "parent": parent
}
;
history.push(cell);
if (cell.x == x2 &
&
cell.y == y2) {
goalCell = cell;
return cell;
}
var child = [];
var left, top, right, buttom;
//最短路径的粗略判断就是首选目标位置的大致方向 if (x - 1 >
= 0 &
&
me.isEmpty(x - 1, y)) left = {
"x": x - 1, "y": y }
;
if (x + 1 me.bubbles.length &
&
me.isEmpty(x + 1, y)) right = {
"x": x + 1, "y": y }
;
if (y + 1 me.bubbles.length &
&
me.isEmpty(x, y + 1)) buttom = {
"x": x, "y": y + 1 }
;
if (y - 1 >
= 0 &
&
me.isEmpty(x, y - 1)) top = {
"x": x, "y": y - 1 }
;
if (x >
x2)
{
if (y >
y2) child = [left, top, right, buttom];
else if (y y2) child = [left, buttom, right, top];
else child = [left, top, right, buttom];
}
else if (x x2) {
if (y >
y2) child = [right, top, left, buttom];
else if (y y2) child = [right, buttom, left, top];
else child = [right, top, left, buttom];
}
else if (x == x2) {
if (y >
y2) child = [top, left, right, buttom];
else if (y y2) child = [buttom, left, right, top];
}
for (var i = 0;
i child.length;
i++) {
var c = child[i];
if (c) cell.child.push(getCell(c.x, c.y, cell));
}
return cell;
}
}
,
看下动画效果http://jsfiddle.net/maddemon/khAJB/4/embedded/result/
后面剩下的就是判断如何消除、加分、防止误操作之类的内容了。
摘自 君之m
觉得可用,就经常来吧! 欢迎评论哦! html5教程,巧夺天工,精雕玉琢。小宝典献丑了!
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: HTML5 Canvas编写五彩连珠(5):寻路
本文地址: https://pptw.com/jishu/586660.html