HTML5游戏制作之五彩连珠(动画)

上一节中,我们留下了一个flyin的方法没有介绍,这里想单独写一篇html5的动画实现。

成都创新互联成立10年来,这条路我们正越走越好,积累了技术与客户资源,形成了良好的口碑。为客户提供成都网站建设、做网站、网站策划、网页设计、申请域名、网络营销、VI设计、网站改版、漏洞修补等服务。网站是否美观、功能强大、用户体验好、性价比高、打开快等等,这些对于网站建设都非常重要,成都创新互联通过对建站技术性的掌握、对创意设计的研究为客户提供一站式互联网解决方案,携手广大客户,共同发展进步。

在第二节中我们实现了画一个泡泡,并且成功的擦除了泡泡,但当时也说了别把棋盘的线给擦掉了,所以做了偏移量。所以说html5 Canvas还是低级, 没有图层的概念,擦掉再想补回来,怎么补?  答案就是重绘。  没错,整个Canvas重绘,这样就能不用担心补哪里了。虽然带来了性能的损失,但绝对减少的编码难度。而且计算机的能力也不差这点损失。那么重绘的话,我们在Canvas是上所有的需要绘制的对象都应该有draw方法。这是必须的。另外,所有的元素都有个上下的概念,所以要先绘制下面的,再绘制上面的。 而这个上下就得靠 子元素的概念,这样在父元素绘制完毕后遍历其子元素绘制,就不用担心掩盖的问题。

如果想把ready区的3个泡“飞入”棋盘,就需要让Canvas在泡移动的时候进行重绘,泡泡不动时不需要重绘。泡泡的移动很容易实现,只要改变他的x,y坐标即可。如果想达到动画的效果,就得在改变坐标期间,定时重绘,可以使用setInterval来实现。

另外,我们不光飞入的动作需要重绘,游戏开始后玩家还要点击移动一个泡泡到另外一个格子,所以这里也要重绘。那绘制的信息这么多,整个重绘工作都要交给game来进行,game控制所有的父元素。 

  
 
 
 
  1. start: function () {   
  2.     this.map.init();   
  3.     this.ready.init();   
  4.     this.draw();   
  5.     this.canvas.onclick = this.onclick;   
  6. },   
  7. over: function () {   
  8.     alert("GAME OVER");   
  9. },   
  10. draw: function () {   
  11.     this.ctx.clearRect(0, 0, 400, 600);   
  12.     this.ctx.save();   
  13.     this.map.draw();   
  14.     this.ready.draw();   
  15.     this.ctx.restore();   
  16. },   
  17. play: function (action, interval) {   
  18.     var me = this;   
  19.     play = setInterval(function () {   
  20.         action();   
  21.         me.draw();   
  22.     }, interval || 1);   
  23. },   
  24. stop: function () {   
  25.     clearInterval(play);   
  26.     this.draw();   
  27.     //console.log(this.ready.bubbles.length);   
  28. }, 

game.start就是初始化所有的父元素,

game.over自然不必说,只是这里没有写具体代码,结束时应该无法继续操作泡泡。

game.draw 绘制所有的父元素。

game.play 就是重绘方法,需要重绘时掉用此方法。接收2个参数,***个是重绘时需要做的动作,interval是绘制的间隔时间。不同的动作可能间隔不一样。

可能这种实现是野路子,真正的重绘应该是游戏开始后就不听的调用重绘方法,而不是具体哪里调用,只是在具体的精灵(每个元素)Update自己状态就像我这里的action。  这里我们暂且这样实现,后面如果达不到需求再重构这个重绘的代码,毕竟核心的代码不变,只是改改机制 不是大问题。

game.stop 停止重绘,又调用了一次draw,是为了保证***的绘制没问题。

接下来考虑下flyin飞入的实现。知道起始和结束的xy坐标,飞入的路径不是问题,无非是x y的加加减减,那么动画方面,我们的game.play的action就是来加减ready.bubbles的xy坐标。飞入的逻辑并非这么简单,首先需要3个没染色空格,如果不足3个,那就GameOver了,所以map需要提供一个返回3个空格子的方法,另外,飞入之后ready区要重新生成新的泡泡,而这几个被飞的泡泡需要删除,并且map要对3个空格子进行染色。 这就完成了整个飞入效果。

其实还有一个逻辑就是 飞入完毕后检查是否有哪些泡泡可以被消除,这个我们后面再讲。

先看获取3个空格的方法: 

  
 
 
 
  1. getEmptyBubbles: function () {   
  2.     var empties = [];   
  3.     this.bubbles.forEach(function (row) {   
  4.         row.forEach(function (bubble) {   
  5.             if (!bubble.color) {   
  6.                 empties.push(new Bubble(bubble.x, bubble.y));   
  7.             }   
  8.         });   
  9.     });   
  10.     if (empties.length <= 3) {   
  11.         game.over();   
  12.         return [];   
  13.     }   
  14.    
  15.     var result = [];   
  16.     var useds = [];   
  17.     for (var i = 0; i < empties.length; i++) {   
  18.         if (result.length == 3) {   
  19.             break;   
  20.         }   
  21.         var isUsed = false;   
  22.         var ra = game.getRandom(empties.length);   
  23.         for (var m = 0; m < useds.length; m++) {   
  24.             isUsed = ra === useds[m];   
  25.             if (isUsed) break;   
  26.         }   
  27.         if (!isUsed) {   
  28.             result.push(empties[ra]);   
  29.             useds.push(ra);   
  30.         }   
  31.     }   
  32.     console.log(useds);   
  33.     return result;   
  34. },  

获取3个随机的空格还是挺多代码的。。。然后就是flyin的实现了。

首先定一个一个status,来存飞入的状态。3个都飞完毕才能做后面的逻辑。Bubble对象也为此增加了px和py俩个成员(即Bubble的实际坐标),这样才能控制每个像素的移动。 其实在计算飞入路径时我写了很久的代码,别看现在就这么几行,开发过程中还是颇费力。各种诡异的飞行。。。开始是按x++ y++递增飞行的,这样就是45°角飞行,但显然飞行线路(起始到结束的线)的倾斜度不是45°,那就会出现先飞完x或y,再走直线,很傻的。所以要用斜率来计算当前的y坐标。而x的坐标可以固定常熟移动。我画了一个斜率的公式,忘记的同学可以看看下。根据长宽的比率,就能计算当前的y值。

  
 
 
 
  1. flyin: function () {   
  2.     var emptys = game.map.getEmptyBubbles();   
  3.     if (emptys.length < 3) {   
  4.         //GAME OVER   
  5.         game.over();   
  6.         return;   
  7.     }   
  8.     var me = this;   
  9.     var status = [0, 0, 0];   
  10.     game.play(function () {   
  11.         if (status[0] && status[1] && status[2]) {   
  12.             game.stop();   
  13.             status = [0, 0, 0];   
  14.             me.bubbles = [];   
  15.             me.genrate();   
  16.             return;   
  17.         }   
  18.     
  19.         for (var i = 0; i < me.bubbles.length; i++) {   
  20.             if (status[i]) {   
  21.                 continue;   
  22.             }   
  23.             var target = emptys[i];   
  24.             var x2 = target.px + game.map.startX - me.startX;   
  25.             var y2 = target.py + game.map.startY - me.startY;   
  26.     
  27.             var current = me.bubbles[i];   
  28.     
  29.             var tmpWidth = 2;   
  30.             if (current.px < x2) {   
  31.                 current.py = ((y2 - current.py) / (x2 - current.px)) * tmpWidth + current.py;   
  32.                 current.px += tmpWidth;   
  33.             }   
  34.             else if (current.px > x2) {   
  35.                 current.py = ((y2 - current.py) / (current.px - x2)) * tmpWidth + current.py;   
  36.                 current.px -= tmpWidth;   
  37.             }   
  38.             else {   
  39.                 current.py += tmpWidth;   
  40.             }   
  41.             if (current.py > y2) {   
  42.                 current.py = y2;   
  43.             }   
  44.     
  45.             if (current.px > x2) {   
  46.                 current.px = x2;   
  47.             }   
  48.     
  49.     
  50.             if (current.px == x2 && current.py == y2) {   
  51.                 status[i] = 1;   
  52.                 current.x = target.x;   
  53.                 current.y = target.y;   
  54.                 game.map.addBubble(current);   
  55.                 console.log(1);   
  56.             }   
  57.         }   
  58.     });   
  59.     

既然我们已经实现了动画效果,那么接下来顺便再实现一个动画效果,就是点击泡泡时,泡泡要做出响应(就是忽闪忽闪的),要不然用户都不知道点了没有。所以Bubble也要增加一个闪动的action。

代码的意思是让间隔50毫秒,重绘一次光照的亮度,亮度值(外圆的半径)10和30之间来回荡。这样就亮了暗,暗了再亮。很有意思:)

  
 
 
 
  1. Bubble.prototype.play = function () {   
  2.     var me = this;   
  3.     var isUp = true;   
  4.     game.play("light_" + this.x + "_" + this.y, function () {   
  5.         if (isUp) {   
  6.             me.light++;   
  7.         }   
  8.     
  9.         if (!isUp) {   
  10.             me.light--;   
  11.         }   
  12.         if (me.light == 30) {   
  13.             isUp = false;   
  14.         }   
  15.         if (me.light == 10) {   
  16.             isUp = true;   
  17.         }   
  18.     }, 50);   
  19. };   
  20.     
  21. Bubble.prototype.stop = function () {   
  22.     //this.light = 10;   
  23.     var me = this;   
  24.     game.stop("light_" + this.x + "_" + this.y);   
  25.     game.play("restore_" + this.x + "_" + this.y, function () {   
  26.         if (me.light > 10) {   
  27.             me.light--;   
  28.         }   
  29.         else {   
  30.             me.light = 10;   
  31.             game.stop("restore_" + me.x + "_" + me.y);   
  32.         }   
  33.     }, 50);   
  34. }; 

细心的朋友可能会发现,在调用Game.stop的方法的参数上增加了一个参数。 这里我要说明下。如果没有参数的情况,game.play和stop会造成问题,因为用的都是一个interval,clear的话会打断其他的动画,所以我们把每个action都要传递一个name,这样就能让game粒度更细的控制每个action了。game的播放代码也做了响应的调整,如下:

  
 
 
 
  1. play: function (name, action, interval) {   
  2.     var me = this;   
  3.     this.actions[name] = setInterval(function () {   
  4.         action();   
  5.         me.draw();   
  6.     }, interval || 1);   
  7. },   
  8. stop: function (name) {   
  9.     clearInterval(this.actions[name]);   
  10.     this.draw();   
  11. }, 

效果演示地址:http://jsfiddle.net/maddemon/VtMSU/embedded/result/

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

【编辑推荐】

  1. HTML 5游戏制作之五彩连珠(预览)
  2. HTML 5游戏制作之五彩连珠(画图)
  3. HTML 5游戏制作之五彩连珠(设计)
  4. HTML 5游戏制作之五彩连珠(寻路)
  5. HTML 5游戏制作之五彩连珠(试玩)

标题名称:HTML5游戏制作之五彩连珠(动画)
标题网址:http://www.shufengxianlan.com/qtweb/news23/166623.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联