成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

HTML 5游戲制作之五彩連珠(尋路)

開(kāi)發(fā) 前端
其實(shí)Canvas也是html的一個(gè)元素而已,所以我們可以給Canvas加click事件。來(lái)查看click時(shí)鼠標(biāo)的坐標(biāo),這樣就等得出點(diǎn)擊了map的哪個(gè)位置。我們給game增加一個(gè)click方法,當(dāng)Canvas點(diǎn)擊時(shí)調(diào)用此方法。

上節(jié)主要做了動(dòng)畫(huà)的實(shí)現(xiàn),感覺(jué)還是比較有意思的。游戲的性能好不好,重繪應(yīng)該比較重要吧,菜鳥(niǎo)瞎想了下呵呵。

本節(jié)就要做對(duì)泡泡的操作,上節(jié)后面提到了點(diǎn)擊泡泡后泡泡要做出閃動(dòng)響應(yīng),那我們我們?nèi)绾潍@得被點(diǎn)擊了哪個(gè)泡泡呢?

其實(shí)Canvas也是html的一個(gè)元素而已,所以我們可以給Canvas加click事件。來(lái)查看click時(shí)鼠標(biāo)的坐標(biāo),這樣就等得出點(diǎn)擊了map的哪個(gè)位置。

我們給game增加一個(gè)click方法,當(dāng)Canvas點(diǎn)擊時(shí)調(diào)用此方法。

要實(shí)現(xiàn)的效果是: 當(dāng)Canvas時(shí)被點(diǎn)擊時(shí)有幾種可能:

1、沒(méi)點(diǎn)到map  那就不作響應(yīng);2、點(diǎn)到了泡泡,那該泡泡要做出響應(yīng)(閃);3、如果之前有點(diǎn)擊過(guò)其他的泡泡,則取消之前的泡泡的響應(yīng)(clicked.stop),如果之前的泡泡是自己,則不作響應(yīng)。并把clicked作為自己,以體后面的操作;4、如果點(diǎn)擊到的是空格,如果之前點(diǎn)擊了泡泡,那就嘗試移動(dòng)這個(gè)泡泡,如果clicked為null(之前沒(méi)泡泡)那就不作任何響應(yīng)。如果可以移動(dòng),則取消閃動(dòng),并清除clicked,開(kāi)始移動(dòng)。 

  1. onclick: function (e) {   
  2.     var px = e.offsetX - game.map.startX;   
  3.     var py = e.offsetY - game.map.startY;   
  4.     if (px < 0 || py < 0 || px > game.map.width || py > game.map.height) {   
  5.         return;   
  6.     }   
  7.     var x = parseInt(px / game.cellWidth);   
  8.     var y = parseInt(py / game.cellWidth);   
  9.    
  10.     var bubble = game.map.getBubble(x, y);   
  11.     if (bubble.color) {   
  12.         if (this.clicked) {   
  13.             //同一個(gè)泡不做反映   
  14.             if (this.clicked.x == x && this.clicked.y == y) {   
  15.                 return;   
  16.             }   
  17.             this.clicked.stop();   
  18.         }   
  19.         this.clicked = bubble;   
  20.         bubble.play();   
  21.     }   
  22.     else {   
  23.         if (this.clicked) {   
  24.             this.clicked.stop();   
  25.             //移動(dòng)clicked   
  26.             game.map.move(this.clicked, bubble);   
  27.         }   
  28.     }   
  29.     //console.log("x:" + x + " y:" + y);   
  30. }, 

尋路的代碼還沒(méi)寫(xiě),因?yàn)檫@個(gè)需要考慮怎么實(shí)現(xiàn)。 我絞盡腦汁終于想到了一個(gè)辦法。暫且撇開(kāi)游戲的代碼,單獨(dú)實(shí)現(xiàn)下兩點(diǎn)的尋路代碼。
先給定一個(gè)棋盤,假如如下:

1 1 1 1 1
0 0 1 0 1
0 0 1 0 1
1 0 0 1 1

要想從 最下面一行中間的點(diǎn)(2,3)移動(dòng)到左上角的(0,1),該如何設(shè)計(jì)呢?

一個(gè)棋子能否移動(dòng),要看他相鄰的4個(gè)子是否為0,如果是0則可以移動(dòng)。 所以我們可以通過(guò)遞歸來(lái)獲得所有相連的0的記錄。 這個(gè)記錄用樹(shù)結(jié)構(gòu)來(lái)存儲(chǔ),直到我們無(wú)法繼續(xù)探測(cè)為0的格子或到達(dá)目的地。 我們把當(dāng)前的棋子的格子設(shè)為 root,他相鄰的棋子是他的孩子。這樣的話,我們會(huì)得到一棵樹(shù)的結(jié)果如下:

是不是?這樣的畫(huà)我們就可以直接看到了整個(gè)路徑(2,3 -> 1,3 -> 1,2 -> 0,2 -> 0,1)。思路很清晰,只要遞歸構(gòu)建子節(jié)點(diǎn)就ok了。代碼如下:

  1. var map = [   
  2. [1, 1, 1, 1, 1],   
  3. [0, 0, 1, 0, 1],   
  4. [0, 0, 1, 0, 1],   
  5. [1, 0, 0, 1, 1]   
  6.     ];   
  7.     
  8.     var history = [];   
  9.     var goal = { "x": 0, "y": 1 }   
  10.     var goalNode = null;   
  11.     var getNode = function (x, y, parent) {   
  12.         if (x >= map.length || y >= map.length) {   
  13.             return;   
  14.         }   
  15.     
  16.         if (map[y][x] == 1) {   
  17.             return;   
  18.         }   
  19.     
  20.         var hasNode = false;   
  21.         history.forEach(function (n) {   
  22.             if (n.x == x && n.y == y) {   
  23.                 hasNode = true;   
  24.                 return;   
  25.             }   
  26.         });   
  27.     
  28.         if (hasNode) {   
  29.             return;   
  30.         }   
  31.         var node = { "x": x, "y": y, "parent": parent, child: [] };   
  32.         history.push(node);   
  33.     
  34.         if (node.x == goal.x && node.y == goal.y) {   
  35.             goalNode = node;   
  36.             return node;   
  37.         }   
  38.         if (x - 1 >= 0 && !map[y][x - 1]) {   
  39.             node.child.push(getNode(x - 1, y, node));   
  40.         }   
  41.         if (y - 1 >= 0 && !map[y - 1][x]) {   
  42.             node.child.push(getNode(x, y - 1, node));   
  43.         }   
  44.         if (x + 1 < map.length && !map[y][x + 1]) {   
  45.             node.child.push(getNode(x + 1, y), node);   
  46.         }   
  47.         if (y + 1 < map.length && !map[y + 1][x]) {   
  48.             node.child.push(getNode(x, y + 1, node));   
  49.         }   
  50.         return node;   
  51.     }   
  52.     console.log(getNode(2, 3));   
  53.     console.log(goalNode); 

我加了一個(gè)parent,就是指向父親的指針,那樣就不用再去遍歷這棵樹(shù)了。可以直接從goalNode的結(jié)果得到整個(gè)路徑:) 雖然偷懶,但也是要復(fù)出代價(jià)的,因?yàn)檫@樣走的路徑不是最短路線,比較傻,怎么選擇最優(yōu)路線呢? 最笨的方法就是 把所有的路徑都得到(深度優(yōu)先遍歷樹(shù)N遍- -)然后比較。這個(gè)顯然效率不高。開(kāi)始我也不知道效果會(huì)這么差,等一運(yùn)行(你運(yùn)行下就知道了),我發(fā)現(xiàn),是代碼寫(xiě)的不好(廢話)。因?yàn)槲覀兠看蔚呐袛囗槍ざ际?左上右下,這樣路徑總是這個(gè)方向探索,而最優(yōu)的路徑應(yīng)該是朝目標(biāo)點(diǎn)的方向探索。 由于是遞歸查找,所以,對(duì)當(dāng)前的node和目標(biāo)node進(jìn)行坐標(biāo)的方向判斷,然后調(diào)整判斷順序,這樣是得到的才是比較短的路徑。

  1. var child = [];   
  2. var left, top, right, buttom;   
  3. //最短路徑的粗略判斷就是首選目標(biāo)位置的大致方向   
  4. if (x - 1 >= 0 && map.isEmpty(x - 1, y))   
  5.     left = { "x": x - 1, "y": y };   
  6. if (x + 1 < map.length && map.isEmpty(x + 1, y))   
  7.     right = { "x": x + 1, "y": y };   
  8. if (y + 1 < map.length && map.isEmpty(x, y + 1))   
  9.     buttom = { "x": x, "y": y + 1 };   
  10. if (y - 1 >= 0 && map.isEmpty(x, y - 1))   
  11.     top = { "x": x, "y": y - 1 };   
  12.     
  13. if (x > x2) {   
  14.     if (y > y2)   
  15.         child = [left, top, right, buttom];   
  16.     else if (y < y2)   
  17.         child = [left, buttom, right, top];   
  18.     else 
  19.         child = [left, top, right, buttom];   
  20. }   
  21. else if (x < x2) {   
  22.     if (y > y2)   
  23.         child = [right, top, left, buttom];   
  24.     else if (y < y2)   
  25.         child = [right, buttom, left, top];   
  26.     else 
  27.         child = [right, top, left, buttom];   
  28. }   
  29. else if (x == x2) {   
  30.     if (y > y2)   
  31.         child = [top, left, right, buttom];   
  32.     else if (y < y2)   
  33.         child = [buttom, left, right, top];   
  34. }   
  35.     
  36. for (var i = 0; i < child.length; i++) {   
  37.     var c = child[i];   
  38.     if (c) node.child.push(getnode(c.x, c.y, node));   

代碼雖然寫(xiě)的比較傻,但這種方式不得不說(shuō)好就一個(gè)字:)

既然尋路已經(jīng)實(shí)現(xiàn)了,那么下面就交給map了,map來(lái)負(fù)責(zé)讓泡泡走起來(lái)。其實(shí)就是根據(jù)路徑給泡泡著色- - ,代碼也不復(fù)雜。

  1. move: function (bubble, target) {   
  2.     var path = this.search(bubble.x, bubble.y, target.x, target.y);   
  3.     if (!path) {   
  4.         //顯示不能移動(dòng)s   
  5.         alert("過(guò)不去");   
  6.         return;   
  7.     }   
  8.     //map開(kāi)始播放當(dāng)前泡的移動(dòng)效果   
  9.     //兩種實(shí)現(xiàn)方式,1、map按路徑染色,最后達(dá)到目的地 2、map生成一個(gè)臨時(shí)的bubble負(fù)責(zé)展示,到目的地后移除   
  10.     //console.log(path);   
  11.     var me = this;   
  12.     var name = "move_" + bubble.x + "_" + bubble.y;   
  13.     var i = path.length - 1;   
  14.     var color = bubble.color;   
  15.     game.play(name, function () {   
  16.         if (i < 0) {   
  17.             game.stop(name);   
  18.             return;   
  19.         }   
  20.         path.forEach(function (cell) {   
  21.             me.setBubble(cell.x, cell.y, null);   
  22.         });   
  23.         var currentCell = path[i];   
  24.         me.setBubble(currentCell.x, currentCell.y, color);   
  25.         i--;   
  26.    
  27.     }, 50);   
  28. },   
  29. search: function (x1, y1, x2, y2) {   
  30.    
  31.     var history = [];   
  32.     var goalCell = null;   
  33.     var me = this;   
  34.    
  35.     getCell(x1, y1, null);   
  36.     if (goalCell) {   
  37.         var path = [];   
  38.    
  39.         var cell = goalCell;   
  40.         while (cell) {   
  41.             path.push({ "x": cell.x, "y": cell.y });   
  42.             cell = cell.parent;   
  43.         }   
  44.    
  45.         return path;   
  46.     }   
  47.     return null;   
  48.    
  49.     function getCell(x, y, parent) {   
  50.         if (x >= me.bubbles.length || y >= me.bubbles.length)   
  51.             return;   
  52.         if (x != x1 && y != y2 && !me.isEmpty(x, y))   
  53.             return;   
  54.    
  55.         for (var i = 0; i < history.length; i++) {   
  56.             if (history[i].x == x && history[i].y == y)   
  57.                 return;   
  58.         }   
  59.    
  60.         var cell = { "x": x, "y": y, child: [], "parent": parent };   
  61.         history.push(cell);   
  62.    
  63.         if (cell.x == x2 && cell.y == y2) {   
  64.             goalCell = cell;   
  65.             return cell;   
  66.         }   
  67.    
  68.         var child = [];   
  69.         var left, top, right, buttom;   
  70.         //最短路徑的粗略判斷就是首選目標(biāo)位置的大致方向   
  71.         if (x - 1 >= 0 && me.isEmpty(x - 1, y))   
  72.             left = { "x": x - 1, "y": y };   
  73.         if (x + 1 < me.bubbles.length && me.isEmpty(x + 1, y))   
  74.             right = { "x": x + 1, "y": y };   
  75.         if (y + 1 < me.bubbles.length && me.isEmpty(x, y + 1))   
  76.             buttom = { "x": x, "y": y + 1 };   
  77.         if (y - 1 >= 0 && me.isEmpty(x, y - 1))   
  78.             top = { "x": x, "y": y - 1 };   
  79.    
  80.         if (x > x2) {   
  81.             if (y > y2)   
  82.                 child = [left, top, right, buttom];   
  83.             else if (y < y2)   
  84.                 child = [left, buttom, right, top];   
  85.             else 
  86.                 child = [left, top, right, buttom];   
  87.         }   
  88.         else if (x < x2) {   
  89.             if (y > y2)   
  90.                 child = [right, top, left, buttom];   
  91.             else if (y < y2)   
  92.                 child = [right, buttom, left, top];   
  93.             else 
  94.                 child = [right, top, left, buttom];   
  95.         }   
  96.         else if (x == x2) {   
  97.             if (y > y2)   
  98.                 child = [top, left, right, buttom];   
  99.             else if (y < y2)   
  100.                 child = [buttom, left, right, top];   
  101.         }   
  102.    
  103.         for (var i = 0; i < child.length; i++) {   
  104.             var c = child[i];   
  105.             if (c) cell.child.push(getCell(c.x, c.y, cell));   
  106.         }   
  107.         return cell;   
  108.     }   
  109. }, 

試玩地址:http://zhengliangjun.sinaapp.com/colorline.html

后面剩下的就是判斷如何消除、加分、防止誤操作之類的內(nèi)容了。

原文鏈接:http://www.cnblogs.com/mad/archive/2012/03/18/2404660.html

【編輯推薦】

  1. HTML 5游戲制作之五彩連珠(預(yù)覽)
  2. HTML 5游戲制作之五彩連珠(畫(huà)圖)
  3. HTML 5游戲制作之五彩連珠(設(shè)計(jì))
  4. HTML 5游戲制作之五彩連珠(動(dòng)畫(huà))
  5. HTML 5游戲制作之五彩連珠(試玩)
責(zé)任編輯:張偉 來(lái)源: 君之蘭的博客
相關(guān)推薦

2012-05-18 13:07:04

HTML5

2012-05-18 14:05:53

HTML5

2012-05-18 13:11:09

HTML5

2012-05-17 14:45:34

HTML5

2012-05-17 13:45:35

HTML5

2010-08-12 22:35:24

IBM培訓(xùn)

2011-11-30 15:14:32

HTML 5

2017-07-26 15:59:51

尋路算法Dijkstra游戲

2019-09-11 15:20:21

華為

2021-03-26 07:06:40

Windows 10Windows操作系統(tǒng)

2012-06-07 15:29:31

HTML5

2012-05-15 13:57:41

HTML5

2012-01-10 16:37:46

樂(lè)團(tuán)

2012-03-29 09:18:47

HTML5WEB

2020-04-22 10:01:26

Vim編輯器代碼

2019-09-12 10:10:10

Vim編輯器代碼

2013-08-27 14:20:09

游戲應(yīng)用圖標(biāo)ASO應(yīng)用商店優(yōu)化

2012-08-13 14:17:35

算法代碼

2012-05-30 13:49:52

HTML5

2014-12-30 17:13:51

HTML5
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 午夜成人免费视频 | 亚洲三区在线观看 | 色接久久 | 超碰免费在线观看 | 国产精品久久久久久久久久久久久久 | 性做久久久久久免费观看欧美 | 亚洲欧美日韩在线一区二区 | 国产一区二区免费电影 | 国产成人精品免费视频大全最热 | 亚洲 欧美 综合 | k8久久久一区二区三区 | 日本成人中文字幕 | 91麻豆精品国产91久久久久久久久 | 99re6在线视频| 日韩在线精品 | 瑞克和莫蒂第五季在线观看 | 99久久亚洲 | 久久久国产精品一区 | 久久综合影院 | 久久国产精品一区二区三区 | 一级片在线视频 | 日韩一区二区福利视频 | 黄网址在线观看 | japan21xxxxhd美女 日本欧美国产在线 | 一区二区国产精品 | 国产三级国产精品 | 中文字幕国产视频 | 国产精品久久久久久久岛一牛影视 | 天天干夜夜操 | 日韩精品免费一区二区在线观看 | 精品国产一区二区三区久久 | 亚洲国产片 | 亚洲免费在线 | 欧美激情亚洲 | 亚洲 欧美 另类 综合 偷拍 | 在线91 | 久久精品视频网站 | 亚洲日本免费 | 欧美激情视频一区二区三区在线播放 | 波多野结衣一区二区三区在线观看 | 91精品国产综合久久久久久蜜臀 |