案例11——用遮障制作聚光灯效果及冷却动画

遮障(mask)在flash中有着相当广~泛地运用,马斯克(即mask的英译,对不起,贫道发音不太标准)这东西是马克思的好兄弟,为什么呢?因为他们名字看起来很相似。马斯克这个属性来源于DisplayObject类,所以包括我们最熟悉的MovieClip以及Sprite在内的继承于DisplayObject的显示对象来说都继承了此属性。那么马斯克应该怎样使用呢?举个例子吧:

  1. var SP1:Sprite;
  2. var SP2:Sprite;
  3. SP1.mask = SP2;
复制代码

我将SP1的mask值设置为SP2,则SP2将作为SP1的遮障层。若你为某个显示对象(就是继承了DisplayObject的类啦,包括MovieClip和Sprite,bitmap等)设置了mask的值后,遮障层(sp2)部分与被遮障层(sp1)将同时被置为不可见状态,不过在这两者的重叠部分你将会在遮障层区域中看见被遮障层中对应位置的图像,如图所示:

如果把被遮障层SP1比作一张桌子,那么当我们给他设置了遮障(mask)后它就被盖上了一层桌布,桌子上的东东都看不见了,此时遮障层SP2就扮演了一个透视镜的角色,我们只能在SP2的区域中窥探到SP1的样子。因此,对于作为遮障的对象(SP2)来说,它无论取什么颜色,什么外观都无所谓,因为它自己是不可见的,它只负责透视被他遮障的显示对象,那么对我们有用的仅是遮障层的形状和大小,它越大,我们能看到的区域也越大。
      理论说得再多也是虚的,作为新时代理论联系实际的新青年来说我们需要动手练习才能理解新的知识,没错,让我们先小试一把牛刀看看遮障的效果:

  1. package
  2. {
  3.         import flash.display.Sprite;
  4.         import flash.events.Event;
  5.         import flash.events.MouseEvent;
  6.         
  7.         public class SimpleMaskTest extends Sprite
  8.         {
  9.                 private var SP1:Sprite;
  10.                 private var SP2:Sprite;
  11.                 
  12.                 public function SimpleMaskTest()
  13.                 {
  14.                         init();
  15.                 }
  16.                 
  17.                 private function init():void{
  18.                         initSprites();
  19.                         SP1.mask = SP2;
  20.                         SP1.x = 50;
  21.                         SP1.y = 50;
  22.                         
  23.                         addChild(SP1);
  24.                         addChild(SP2);
  25.                         SP1.addEventListener(MouseEvent.CLICK, onClick);//用以测试遮障是否会屏蔽鼠标事件
  26.                         addEventListener(Event.ENTER_FRAME, onEF);//移动遮障
  27.                 }
  28.                 
  29.                 private function initSprites():void{
  30.                         SP1 = new Sprite();
  31.                         SP1.graphics.lineStyle(2);
  32.                         SP1.graphics.beginFill(0xffff00);
  33.                         SP1.graphics.drawRect(0, 0, 300, 200);
  34.                         SP1.graphics.endFill();
  35.                         
  36.                         SP2 = new Sprite();
  37.                         SP2.graphics.beginFill(0); //取什么颜色都无所谓,因为它不会显示出来
  38.                         SP2.graphics.drawCircle(0, 0, 50);
  39.                         SP2.graphics.endFill();
  40.                 }
  41.                 
  42.                 private function onClick(event:MouseEvent):void{
  43.                         trace("SP1 was clicked"); //正常trace出信息,证明遮障不会屏蔽鼠标事件
  44.                 }
  45.                 
  46.                 private function onEF(event:Event):void{
  47.                         SP2.x = mouseX;
  48.                         SP2.y = mouseY;
  49.                 }
  50.         }
  51. }
复制代码

编译运行一下后我们发现遮障层的确成了一个透视镜:
<ignore_js_op>1.jpg<ignore_js_op>2.jpg 

       相信现在大家对遮障的效果应该有了一定的了解了,我在代码中对被遮障层监听了一个鼠标点击事件(CLICK),这是为了探索遮障层是否会屏蔽被遮障层接收鼠标事件,事实证明,设置了mask的显示对象它的鼠标事件是不会被遮障层所屏蔽掉的。
       OK,接下来让我们开始做一些好玩的东东吧,在很多游戏中我们会玩到一些关卡是漆黑一片的,只有主角周围很小的一片圆形范围可见,这叫做聚光灯效果,在电视里演唱会上我们也能看到这样的效果哦。
结果预览:http://www.iamsevent.com/upload/spotlight.swf
了解了遮障的使用后我们自然而然地就会想到这种效果一定跟马斯克同学有关,holy shit,你太聪明了,一猜就猜中了,let`s 看代码先:

  1. package
  2. {
  3.         import flash.display.Bitmap;
  4.         import flash.display.Sprite;
  5.         import flash.events.Event;
  6.         import flash.events.MouseEvent;
  7.         
  8.         [SWF(backgroundColor="0x000000")]
  9.         public class SimpleMaskTest extends Sprite
  10.         {
  11.                 private var SP1:Bitmap;
  12.                 private var SP2:Sprite;
  13.                 [Embed(source="mm.jpg")]
  14.                 private var imgResource:Class;
  15.                 
  16.                 public function SimpleMaskTest()
  17.                 {
  18.                         init();
  19.                 }
  20.                 
  21.                 private function init():void{
  22.                         initSprites();
  23.                         SP1.mask = SP2;
  24.                         
  25.                         addChild(SP1);
  26.                         addChild(SP2);
  27.                         addEventListener(Event.ENTER_FRAME, onEF);//移动遮障
  28.                 }
  29.                 
  30.                 private function initSprites():void{
  31.                         SP1 = new imgResource() as Bitmap;
  32.                         SP1.width = stage.stageWidth;
  33.                         SP1.height = stage.stageHeight;
  34.                         
  35.                         SP2 = new Sprite();
  36.                         SP2.graphics.beginFill(0); //取什么颜色都无所谓,因为它不会显示出来
  37.                         SP2.graphics.drawCircle(0, 0, 50);
  38.                         SP2.graphics.endFill();
  39.                 }
  40.                 
  41.                 private function onEF(event:Event):void{
  42.                         SP2.x = mouseX;
  43.                         SP2.y = mouseY;
  44.                 }
  45.         }
  46. }
复制代码

这段代码与上一段不同的地方仅在于我们把舞台背景改成了黑色,让人有一种身处黑夜的Feeling,有没有?!还有我们把鼠标事件去掉了,因为不需要它来测试了。此外我们还把SP1改成了bitmap类型让它不再显示一块黄色矩形,而是一个漂亮的MM图片哦。运行一下,看到下图运行结果:
<ignore_js_op>3.jpg 

2010-11-10 10:49:39 上传
下载附件 (16.16 KB)
 


这图是不是有点邪恶?告诉你,我不是故意窥探这块区域的,我是有意的 
      聚光灯效果很容易做吧?回去自己动手来做一个吧。这帖子字数快超了,稍候再介绍下放大镜效果……see you later.......

 

管理员审核速度有点慢的说,毕竟值班管理员只有一个嘛,等了我好久,好了,审核既然通过了就开始介绍放大镜效果吧。
       在ActionScript 3 讨论区有位兄弟在几个礼拜前发过一个放大镜效果的帖子(传送门) ,不过这帖子里只给出了一个源码,也没多加解释,很多兄弟看不懂,也没地方问就搁浅了,帖子人气不足。不过这个例子非常典型,将“视角移动”以及“遮障”两个概念联系起来使用,而且这样子的放大镜效果在游戏中使用得也非常多,我这里就一步步地给各位分析一下放大镜效果的制作流程吧,先看最终效果:
<ignore_js_op>4.jpg 
在线预览:http://www.iamsevent.com/upload/magnifier.swf
感觉还算不错吧?你也可以做出来哦~
        第一步,添加大图,并提供视角移动:
在我的案例5——视角移动中已详细介绍了视角移动的方法,若你还不会的话赶紧去补补吧。假如我们想让放大镜放大倍数为2,那就让底层大图的长与宽为舞台的两倍即可。我们先把这步完成:

  1. [SWF(width="600",height="500")]
  2.         public class FangDaJing extends Sprite
  3.         {
  4.                 private var pic_bit:BitmapData;
  5.                 private var big:Bitmap;      //大图
  6.                 
  7.                 public function FangDaJing()
  8.                 {
  9.                         init();
  10.                 }
  11.                 private function init():void{
  12.                         var loader:Loader =new Loader();
  13.                         loader.contentLoaderInfo.addEventListener(Event.COMPLETE,loader_handler);
  14.                         var url:URLRequest =new URLRequest("mm.jpg");
  15.                         loader.load(url);
  16.                 }
  17.                 
  18.                 private function loader_handler(evt:Event):void{
  19.                         pic_bit =evt.target.content.bitmapData;
  20.                         //大图
  21.                         big =new Bitmap(pic_bit);
  22.                         big.width = 2 * stage.stageWidth;
  23.                         big.height = 2 * stage.stageHeight;
  24.                         this.addChild(big);
  25.                         stage.addEventListener(MouseEvent.MOUSE_MOVE,move_handler);
  26.                 }
  27.                 
  28.                 private function move_handler(evt:MouseEvent):void{
  29.                         big.x = mouseX / stage.stageWidth * (stage.stageWidth - big.width);
  30.                         big.y = mouseY / stage.stageHeight  * (stage.stageHeight - big.height);
  31.                 }
复制代码

这样就行了,大图会随着鼠标的移动调整视角,这样做能够保证鼠标移到角落能看到图片的角落部分,移到中间能看到中间部分,即在图片为一倍大小的情况下鼠标所停留的区域(假如是以鼠标为圆心的一个小圆区域)与二倍大小情况下鼠标停留的区域一致,献上两张图帮助理解:
<ignore_js_op>5.jpg <ignore_js_op>6.jpg 
我们看到,由于大图在不停地调整自己的位置,所以保证了鼠标所在的可视区域相对于整张图片的位置在一倍视角和二倍视角下都是一致的。
      第二步,盖上遮障:
接下来我们要用遮障来实现透视镜的效果,控制我们的可视区域。在init函数中加上滤镜的初始化代码:

  1.                 //滤镜
  2.                         _mask =new Sprite();
  3.                         _mask.graphics.beginFill(0xff0000); //你也许听我说,对于滤镜来说取什么颜色都无所谓就把这句去掉了,事实上这句是不可缺少的,不信你去掉试试
  4.                         _mask.graphics.drawCircle(0,0,50);
  5.                         _mask.graphics.endFill();
复制代码

接下来要记得在大图的width,height设置代码后面给大图加上遮障,并把遮障加到舞台上去:

  1. big.mask =_mask;
  2. this.addChild(_mask);
复制代码

最后我们在鼠标移动处理函数move_handler中让滤镜跟着鼠标跑,以鼠标为圆心:

  1.                 private function move_handler(evt:MouseEvent):void{
  2.                         big.x = mouseX / stage.stageWidth * (stage.stageWidth - big.width);
  3.                         big.y = mouseY / stage.stageHeight  * (stage.stageHeight - big.height);
  4.                         _mask.x = stage.mouseX;
  5.                         _mask.y  = stage.mouseY;
  6.                 }
复制代码

编译运行一下应该会看到大图中除遮障所在区域外的部分显示的都是舞台的灰颜色:
<ignore_js_op>7.jpg 
      第三步,加上一倍大小的图片(就叫他小图吧)。为了不让遮障以外部分显示一片舞台的灰色,我们给舞台上放上小图,使遮障以外部分显示一倍大小的图片,而遮障以内的放大镜部分显示的则是两倍大小的图片,这样就能给人一种放大镜的感觉了。给出全部代码:

  1. [SWF(width="600",height="500")]
  2.         public class FangDaJing extends Sprite
  3.         {
  4.                 private var pic_bit:BitmapData;
  5.                 private var small:Bitmap;    //小图
  6.                 private var big:Bitmap;      //大图
  7.                 private var _mask:Sprite;    //遮罩
  8.                 private var bounds:Shape;    //用以绘制放大镜边框
  9.                 
  10.                 private const scaling:Number =2;
  11.                 
  12.                 public function FangDaJing()
  13.                 {
  14.                         init();
  15.                 }
  16.                 private function init():void{
  17.                         var loader:Loader =new Loader();
  18.                         loader.contentLoaderInfo.addEventListener(Event.COMPLETE,loader_handler);
  19.                         var url:URLRequest =new URLRequest("mm.jpg");
  20.                         loader.load(url);
  21.                 }
  22.                 
  23.                 private function loader_handler(evt:Event):void{
  24.                         pic_bit =evt.target.content.bitmapData;
  25.                         
  26.                         //滤镜
  27.                         _mask =new Sprite();
  28.                         _mask.graphics.beginFill(0xff0000);
  29.                         _mask.graphics.drawCircle(0,0,50);
  30.                         _mask.graphics.endFill();
  31.                         
  32.                         bounds = new Shape();
  33.                         bounds.graphics.lineStyle(2);
  34.                         bounds.graphics.drawCircle(0,0,50);
  35.                         
  36.                         //大图
  37.                         big =new Bitmap(pic_bit);
  38.                         big.width = 2 * stage.stageWidth;
  39.                         big.height = 2 * stage.stageHeight;
  40.                         big.mask =_mask;
  41.                         
  42.                         //小图
  43.                         small =new Bitmap(pic_bit);
  44.                         small.width =stage.stageWidth;
  45.                         small.height =stage.stageHeight;
  46.                                                 
  47.                         this.addChild(_mask);     //作为滤镜则加在前在后则没有关系
  48.                         this.addChild(small);     //小图必须加载在大图的前面
  49.                         this.addChild(big);
  50.                         this.addChild(bounds);
  51.                         
  52.                         Mouse.hide();//用来隐藏鼠标
  53.                         stage.addEventListener(MouseEvent.MOUSE_MOVE,move_handler);
  54.                 }
  55.                 
  56.                 private function move_handler(evt:MouseEvent):void{
  57.                         big.x = mouseX / stage.stageWidth * (stage.stageWidth - big.width);
  58.                         big.y = mouseY / stage.stageHeight  * (stage.stageHeight - big.height);
  59.                         _mask.x = bounds.x = stage.mouseX;
  60.                         _mask.y = bounds.y = stage.mouseY;
  61.                 }
复制代码

这些代码都是在我文章一开头提到的那位几周前发了题为《放大镜效果》帖子的兄弟的代码基础上改进的,版权属于这位兄弟所有。在这段代码里我加上了一个bounds变量用以绘制放大镜的圆形边缘,因为在mask中使用lineStyle代码没有意义,身为遮障的它根本不可见,需要另加一个显示对像来画出一个圆形边框显示它,不要忘了在move_handler中随时改变bounds的坐标使之跟着mask跑。另外我还使用了一句Mouse.hide()来隐藏鼠标,要是你不想隐藏就去掉这句吧。
最后奉上源码文件,不想敲代码的、有钱的同学可以下去看看哦。 <ignore_js_op> src.rar (155.94 KB, 下载次数: 316)

在讲怎样做冷却动画之前,有必要先提一下flash中的“深度”问题。在flash中,对于像sprite等能够添加子显示对象的类来说,它其中的子项们存在个深度关系,早一些被addChild的子项要比晚addChild的子项深度要高(所在索引号要小一些)。越晚被Addchild进来的子项在屏幕上显示得越前面,它可能会盖住一些与其重合并且深度比其高(也就是比他早被Addchid进来)的子项,看下面一个例子:

  1.         public class DeepthTest extends Sprite
  2.         {
  3.                 public function DeepthTest()
  4.                 {
  5.                         var shape1:Shape = new Shape();
  6.                         shape1.graphics.beginFill(0xffff00);
  7.                         shape1.graphics.drawRect(0, 0, 100, 100);
  8.                         shape1.graphics.endFill();
  9.                         shape1.x = shape1.y = 40;
  10.                         addChild(shape1);
  11.                         
  12.                         var shape2:Shape = new Shape();
  13.                         shape2.graphics.beginFill(0x00ff00);
  14.                         shape2.graphics.drawRect(0, 0, 50, 50);
  15.                         shape2.graphics.endFill();
  16.                         shape2.x = shape2.y = 65;
  17.                         addChild(shape2);
  18.                 }
  19.         }
复制代码

运行结果如图:
<ignore_js_op>2.jpg 
我们看到,当两个显示对象被添加到同一父容器中时,越晚被添加上的子项显示得越前面,可能会遮挡住比它早添加进父容器的对象。所以,深度与一个显示对象的显示层次有着直接关系,在AddChild时需注意先后关系。如有需要,可使用setChildIndex()方法来即时设置子项的深度。
    好了,接下来进入正题,讲讲我们很多玩家期待了解的技能冷却时间读取的原理,在游戏中当我们释放过一个技能之后该技能会进入冷却时间,技能图标被蒙上一片半透明的黑色或者红色,且随着冷却时间的读取,这层半透明遮障会顺时针地一点点被抹去,所以很多人技能冷却时间称为“转圈”。
    既然这样,我们先要解决的问题就是如何画出一个转圈的效果。当当当当~我为大家隆重介绍今天的主角方法graphics.beginFill以及graphics.lineTo。我已经能够听到殿下列位爱卿开始议论纷纷了,这两个方法不是很一般,用得很多的么,它们能够画圈么?画圈我都用graphics.drawCircle的。NONONO,用它一次画一整个圆圈是没问题,若你想顺时针一点点地画圆就不能够用它了。使用graphics.lineTo可以绘制一条线,而调用graphics.beginFill之后使用graphics的其他绘图API(如lineTo,drawRect等)画出的图形若存在封闭区域则此封闭区域内会被自动填充上色。比如,我们写一句graphics.drawRect绘制一个矩形,绘制出来的结果将是一个矩形边框,其中并没有被填色,要想让此矩形区域中被填色,就必须在graphics.drawRect前加上graphics.beginFill,相信这一点对各位来说都不会陌生。那么我们就可以利用beginFill的这一特点来满足我们逐渐绘图的需要。要使用lineTo来绘图的话就必须想办法让我们画出的一条条线段能够构成一个封闭区域,这样才能让beginFill这个粉刷匠来进行填充,先给出两幅示意图:
<ignore_js_op>3.JPG 
我们先调用一次lineTo(10,0),因为显示对象中绘画点起始位置默认是停在(0,0)点的,所以执行这条语句后将从(0,0)点开始画线,第一次画到(10,0)点,之后我们的绘画点就跑到了(10,0)点,再次调用lingTo(12,6),将绘制一条由(10,0)至(12,6)的线段,若你在第一次lineTo()前写了beginFill方法,你就会发现在你画了两次线后,以这两条线以及绘画起始点(0,0)和终点(12,6)之间连线构成的三角形被自动填充了,事实上我们并没有画过第三条线,不过flashPlayer会认为你这两条线已能够构成一个封闭区域,就自作主张地给你把第三条不存在的线加上并进行了填充。
既然这样,那我们想一点点地画圆就可以使用这个特性,用一个个小三角形慢慢拼成一个圆吧,当每个三角形足够小时,视觉上看起来这个由它们拼起来的圆边缘还算是平滑。在你的FB中输入如下代码:

  1.         public class CDTime extends Sprite
  2.         {
  3.                 private var circle:Sprite;
  4.                 private var currentAngle:Number; //当前已绘画到的角度
  5.                 private var speed:Number;   //每帧改变的角度值
  6.                 private var radius:Number;  //要画的圆半径
  7.                 
  8.                 public function CDTime()
  9.                 {
  10.                         circle = new Sprite();
  11.                         currentAngle = 0;
  12.                         speed = 1;
  13.                         radius = 100;
  14.                         circle.x = stage.stageWidth / 2;
  15.                         circle.y = stage.stageHeight / 2;
  16.                         addChild(circle);
  17.                         circle.graphics.beginFill(0xffff00);
  18.                         circle.graphics.lineTo( radius, 0 );
  19.                         addEventListener(Event.ENTER_FRAME, onEF);
  20.                 }
  21.                 
  22.                 private function onEF(event:Event):void{
  23.                         currentAngle += speed;
  24.                         if( currentAngle <= 360 ){
  25.                                 var toX:Number = radius * Math.cos( currentAngle * Math.PI / 180 );//由于cos函数中传入的参数为弧度值,所以我们需要把角度转为弧度
  26.                                 var toY:Number = radius * Math.sin( currentAngle * Math.PI / 180 );
  27.                                 circle.graphics.lineTo( toX, toY );
  28.                         }else{
  29.                                 removeEventListener(Event.ENTER_FRAME, onEF);
  30.                         }
  31.                 }
  32.         }
复制代码

运行上面的代码,我们将看到一个圆正慢慢被绘制:
<ignore_js_op>4.jpg 
   看看代码,其实该说的原理我都说了,只需要在一开始就开启填充功能beginFill,并把绘画点画到圆的圆周上面(即从(0,0)点到(radius,0)),之后我们就可以使用enterFrame来逐帧地画圆了,绘画点将游历完整一圈圆周后回到起始点,此时结束对enterFrame的监听,完成绘画工作。
  学会了逐渐绘制圆形的方法后我们用上mask的知识,在前面我们讲过,遮障层只有实体部分,即有被填充,有像素的部分才能起到遮障的作用,若你遮障层什么东西都没画或者只有drawCircle而没有使用过beginFill填充过则此区域不算是实体部分,不能透视到被遮障层。所以我们在遮障层使用这种慢慢画圆的方式,圆被填充了多少被遮障层就能露出来多少。好了,知道了方法,接下来要做的就剩实现它了,首先我们制作一个独立对象Ability:
Ability.as

  1.         public class Ability extends Sprite
  2.         {
  3.                 private var icon:Bitmap;
  4.                 private var CDMask:Shape;
  5.                 private var currentAngle:Number; //当前已绘画到的角度
  6.                 private var speed:Number;   //每帧改变的角度值
  7.                 private var radius:Number;
  8.                 
  9.                 public function Ability( icon:BitmapData )
  10.                 {
  11.                         super();
  12.                         this.icon = new Bitmap(icon);
  13.                         addChild( this.icon );
  14.                         addEventListener(MouseEvent.CLICK, startCD);
  15.                 }
  16.                 
  17.                 private function startCD(event:MouseEvent):void{
  18.                         CDMask = new Shape();
  19.                         addChild( CDMask );
  20.                         icon.mask = CDMask;
  21.                         currentAngle = 0;
  22.                         speed = 1;
  23.                         radius = this.width / 2;
  24.                         CDMask.x = this.width / 2;
  25.                         CDMask.y = this.height / 2;
  26.                         
  27.                         CDMask.graphics.beginFill(0);
  28.                         CDMask.graphics.lineTo( radius, 0 );
  29.                         CDMask.addEventListener(Event.ENTER_FRAME, onEF);
  30.                 }
  31.                 
  32.                 private function onEF(event:Event):void{
  33.                         currentAngle += speed;
  34.                         if( currentAngle <= 360 ){
  35.                                 var toX:Number = radius * Math.cos( currentAngle * Math.PI / 180 );//由于cos函数中传入的参数为弧度值,所以我们需要把角度转为弧度
  36.                                 var toY:Number = radius * Math.sin( currentAngle * Math.PI / 180 );
  37.                                 CDMask.graphics.lineTo( toX, toY );
  38.                         }else{
  39.                                 icon.mask = null;
  40.                                 CDMask.removeEventListener(Event.ENTER_FRAME, onEF);
  41.                                 removeChild( CDMask );
  42.                         }
  43.                 }
  44.         }
复制代码

大致思想就是当该技能类被点击后进入冷却时间,给技能图标icon加上一层遮障,此遮障内部在不停地顺时针绘制圆形,随着圆形的绘制,被遮障的图标层露出来的部分将会顺时针方向逐渐增多。
    之后,在主应用里用上这个类:
CDTime.as

  1.         public class CDTime extends Sprite
  2.         {
  3.                 [Embed(source="Whirlwind.jpg")]
  4.                 private var imgResource:Class;
  5.                 private var ability:Ability;
  6.                 
  7.                 private var circle:Sprite;
  8.                 private var currentAngle:Number; //当前已绘画到的角度
  9.                 private var speed:Number;   //每帧改变的角度值
  10.                 private var radius:Number;
  11.                 
  12.                 public function CDTime()
  13.                 {
  14.                         ability = new Ability( new imgResource().bitmapData );
  15.                         ability.x = stage.stageWidth / 2;
  16.                         ability.y = stage.stageHeight / 2;
  17.                         addChild(ability);
  18.                 }
  19.                 
  20.         }
复制代码

我们可以看到运行结果如图所示:
<ignore_js_op>5.jpg

这效果和我们理想的效果还有差距,第一,图标没有变灰;第二,在转圈的时候mask覆盖范围不够广,图标四个角落里一直看不见;好吧,让我们逐一解决。
我们之前讲过,在显示对象被遮障后会显示其显示对象底下的东西,那么我们就给图标icon底下加一层灰色的背景就行了呗,于是在Ability构造函数中添加代码:

  1.                 public function Ability( icon:BitmapData )
  2.                 {
  3.                         super();
  4.                         this.icon = new Bitmap(icon);
  5.                         this.background = new Bitmap(icon);
  6.                         this.background.filters = [new ColorMatrixFilter(
  7.                                 [1,0,0,0,0,  
  8.                                         1,0,0,0,0,  
  9.                                         1,0,0,0,0,  
  10.                                         0,0,0,1,0 
  11.                                 ])];                        //灰度滤镜,死记住这个用法就行了
  12.                         addChild( background );
  13.                         addChild( this.icon );
  14.                         addEventListener(MouseEvent.CLICK, startCD);
  15.                 }
复制代码

在让图像变灰色这里我们使用了滤镜功能,对于滤镜的使用比较简单,我这里就不想多讲什么了,网上搜一搜资料很多的,你也可以不用滤镜而直接用一个灰色版本的技能图片(可以叫美术提供给你也可以你自己PS一个)来代替。值得注意的是这两句addChild语句次序不能弄反了,原因就在于我上面讲的深度问题,若灰色背景被addChild晚了它就会处于最前面一层,将彩色层给挡住了。这样第一个问题就解决了,之后解决第二个问题,为了扩大遮障层的范围,我们需要加大radius的值,找到它的赋值语句并改为:

  1. radius = Math.sqrt( this.width / 2 * this.width / 2 + this.height / 2 * this.height / 2 );
复制代码

我们这样就把原来radius等于图标的一半宽改成了图标对角线的一半,这样就足以覆盖全部图标区域了。最后,为了避免bug的发生,我们在技能类Ability被按下进入冷却时间后使之不能再次被点击,在startCD()函数第一行加上:

  1. removeEventListener(MouseEvent.CLICK, startCD);
复制代码

在进度读取完毕后使之可被点击,在onEF的else中加上:

  1. addEventListener(MouseEvent.CLICK, startCD);
复制代码

这样再来测试一下效果感觉就比较完美了:
<ignore_js_op>6.jpg 

2010-11-11 00:45:41 上传
下载附件 (13.91 KB)
 


在线预览:http://www.iamsevent.com/upload/CDTime.swf
      在这个案例中我们把speed设置成了每秒改变的角度,但是在实际应用中会直接用到时间值而非角度值,给一个技能设置了几秒的冷却时间,让你转一圈的时间等于它设置的冷却时间,此时就需要用的类似

原文地址:https://www.cnblogs.com/keng333/p/2712318.html