ConvolutionFilter应用矩阵卷积滤镜效果.卷积将输入图像的像素与相邻的像素合并以生成图像,利用它某一点的颜色跟周围颜色融合,做出好看的烟火效果.
效果图
ActionScript代码
先看下代码,再来分析:
单个烟火特效元件里的代码:
AS Codeimport flash.display.BitmapData; import flash.geom.Rectangle; import flash.filters.ConvolutionFilter; var matrixX:Number = 3; var matrixY:Number = 3; var matrix:Array = [1, 1, 1, 1, 30, 1, 1, 1, 1]; var divisor:Number = 38; var filter:ConvolutionFilter = new ConvolutionFilter (matrixX, matrixY, matrix, divisor); var _w:Number = 100; var _h:Number = 200; var bitsMax:Number = 100; var bitAry:Array = []; var rect:Rectangle = new Rectangle (0, 0, _w, _h); var bmp1:BitmapData = new BitmapData (rect.width, rect.height, false, 0x000000); this.createEmptyMovieClip ("yanhuo", 0).attachBitmap (bmp1, 1); var sd1:Sound = new Sound(this["yanhuo"]) var sd2:Sound = new Sound(this["yanhuo"]) sd1.attachSound("sound1") sd2.attachSound("sound2") var bomy:Number; function initBit () { var r:Number = Math.floor (Math.random () * 100) +155; var g:Number = Math.floor (Math.random () * 255); var b:Number = Math.floor (Math.random () * 255); var c:Number = RGB (r, g, b); bomy = 20 + Math.random () * 10; for (var i = 0; i < bitsMax; i++) { var d = Math.random () * 6.28; var d1 = Math.random (); bitAry[i] = {x:rect.width / 2, y:rect.height, vx:Math.sin (d) * d1 / 2, vy:Math.cos (d) * d1 / 2, life:Math.floor (Math.random () * 50) + 100, cc:(Math.random () > 0.9 ? 0xFFFFFF : c), step:1}; } sd1.start(0,1) this.onEnterFrame = render; } function RGB (r, g, b) { return r << 16 | g << 8 | b; } function render () { var bit:Object; var flag:Boolean = false var len:Number = bitAry.length; if (len == 0) { delete this.onEnterFrame; initBit (); return; } for (var i = 0; i < len; i++) { bit = bitAry[i]; if (bit.step == 1) { // 上升中 bit.y -= 5; if (bit.y <= bomy) { bit.step = 2; flag = true } if (Math.random () > 0.8) { bmp1.setPixel (Math.floor (bit.x + Math.random () * 2), Math.floor (bit.y + Math.random () * 5), 0xFFFFFF); } } else if (bit.step == 2) { // 爆炸过程 bit.vy += Math.random () / 100; bit.x += bit.vx; bit.y += bit.vy; bit.life--; if (bit.life == 0 || !rect.contains (bit.x, bit.y)) { bit.cc = 0x000000; bitAry.splice (i, 1); i--; bit.step = 3; } bmp1.setPixel (Math.round (bit.x), Math.round (bit.y), bit.cc); } } bmp1.applyFilter (bmp1, bmp1.rectangle, new Point (0, 0), filter); if(flag) { sd2.start(0,1) } }
下面我们来分析这段代码
首先是导入必须的类,包括BitmapData,Rectangle和ConvolutionFilter.然后定义了滤镜filter,如果不明白ConvolutionFilter类构造函数参数的意义,去看下Flash的帮助,这里的divisor是矩阵中所有元素之和,会调平总体色彩的强度.
接下来是定义BitmapData,定义粒子数组,以及定义声音.
函数initBit()完成的工作是要初始化粒子数组bitAry,每次放烟火时,指定了一种颜色,用变量c表示,为了让效果明显,r值取的都是大于155的.每个例子元素用一个Object对象表示,它含有x,y,vx,vy,life,cc,step几个属性,分别表示x,y坐标,爆炸后的水平速度,爆炸后的 垂直速度,生命值,颜色值和目前是第几步.其中step的可能值是1,2,3.其中1表示上升过程,2表示爆炸过程,3表示死亡了.定义完bitAry后,就会播放升空声音和指定onEnterFrame来渲染画面.
函数render()用来渲染画面的.如果粒子在上升过程中,则只在粒子周围随机绘制一些白点.在爆炸过程中,则会让每个粒子沿x,y方向以vx,vy的速度飞行,并且vy会一直增大,模拟加速下降的现象.如果粒子的生命期结束,或者超出了范围则把会从bitAry里删除掉它,否则会在bmp1里绘制这个点.当bitAry里没有元素后,会重新调用initBit(),演示下一次烟火效果.
主场景帧上的代码:
AS Codestop() var no:Number = 0 var id:Number var root:MovieClip = this function playMotion() { no++ root["yh" + no].initBit() if(no == 5) { clearInterval(id) } } id = setInterval(playMotion,100)
这段代码主要是为了让舞台上的5个元件播放烟火的效果有个时间差而已.
源文件下载
- FLA文件:yanhuo.fla
- SWF文件:yanhuo.swf