注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

清风的博客

我为人人,人人为我。

 
 
 

日志

 
 

用位图结合卷积滤镜做礼花的方法  

2014-06-17 00:56:22|  分类: 【flash教程】 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

用位图结合卷积滤镜(ConvolutionFilter)来做逼真礼花效果的方法。

首先让我们来分析一下需要考虑的问题:
礼花的生命周期
绘制礼花的技巧
环境的反光效果
礼花的生命周期

一束礼花的生命周期基本分为升空,爆炸以及消亡这三个过程。

 升空过程:

礼花在地面发射升空时具有比较大的初速度,并向上做匀减速直线运动经过某一个时间后爆炸。这个时候的礼花表现为一个高亮的燃点,燃烧所产生的灰烬由于高速运动而在竖直下方形成一个快速抖动的尾巴。

升空时的减速加速度来自地心引力,所以运动方程可以表现为:

const GRAVITY:Number = 0.098; speedY += GRAVITY; x += speedX; y += speedY;

由于燃点是边运动边燃烧,所以会在升空过程中有细微的颤动,在代码中可以添加一对随机因子来实现:

const GRAVITY:Number = 0.098; speedY += GRAVITY; x += speedX + .6 * (1 - Math.random()*2); y += speedY + .6 * (1 - Math.random()*2);

这样燃点的速度会在上下左右各0.6个像素范围内做随机选择。

爆炸过程

燃点升空一段时间后会爆炸而形成漂亮的礼花,爆炸的特点是瞬间产生大量燃点然后朝各个方向以较大的初速度做抛物线运动,之所以抛物线也是因为地心加速度的影响。这个过程中的每一个燃点具备与升空时燃点基本相同的特征,同样需要不规则颤动并在运动相反方向留有尾巴。

爆炸的瞬间可以用如下代码来表示:

pieces = new Array(); for(var i:int=0;i<200;i++){ //这里加随机确定了燃点的运动带有空间感 var speed:Number = 2* Math.random(); //随机算出燃点的运动方向 var angle:Number = i/200 * Math.PI * 2; var xs:Number = speed * Math.cos(angle); var ys:Number = speed * Math.sin(angle); var piece:FireworkPiece = new FireworkPiece(pX,pY,xs,ys,255); pieces.push(piece); }
消亡过程

礼花爆炸后每一个燃点都会在燃烧一段时间后燃尽而消亡,从程序设计上可以理解为能量的衰减,用一个参数energy可以表示。

那么礼花的消亡过程其实就是energy的递减过程:

public function dimmer():void{ energy -= dimmerSpeed; energy = Math.max(0,energy); }

如果给递减的速度dimmerSpeed取随机值,那么每个燃点的消亡时间就会有所区别,最后的效果也会比较逼真。

绘制礼花的技巧

由于礼花是大量粒子的运动,所以需要用到位图绘制。绘制礼花需要考虑到燃点和残影的绘制。

燃点的绘制

因为燃点是燃烧的火药,所以应该有一个高亮的燃烧白点,围绕这个白点的应该是燃点的主色。我在这个例子中采用的是十字法: 如图1,白点在中心,主色以十字形排列在下面,形成一个燃点。而整个点的尺寸大小以及颜色透明通道由刚才提到的燃点的能量值energy决定。

var r:int = pEnergy/100; var c:Number = (pEnergy << 24) + pColor; var w:Number = (pEnergy << 24) + 0xffffff; //在使用setPixel或者setPixel32前后用lock()和unlock()控制BitmapData可以让绘制更为高效。 pBmd.lock(); for(var i:int = pI- r;i<=pI + r;i++){ pBmd.setPixel32(i,pJ,c); } for(var j:int=pJ-r;j<=pJ + r;j++){ pBmd.setPixel32(pI,j,c); } //白点的尺寸为十字的三分之一 for(var p:int = pI- r/3;p<=pI + r/3;p++){ for(var q:int = pJ- r/3;q<=pJ + r/3;q++){ pBmd.setPixel32(p,q,w); } } pBmd.unlock();

燃点的十字画法
图1. 燃点的十字画法
残影的绘制方法

礼花的每一个燃点的运动都有一个燃烧的尾巴,它可以清晰地表示礼花的升空以及爆炸过程,这个尾巴的特点是自燃点开始逐渐透明并且模糊。这里需要用到一个非常重要的位图处理滤镜——卷积滤镜 ( ConvolutionFilter)。

卷积滤镜是一种着色器,它可以制定一个像素间相互影响的规则,并利用这种规则在整个位图的每一个像素点进行计算。下面这个例子说明了如何使用卷积滤镜来制作残影:

        /*这个数组所表示的矩阵说明了某主像素点周围的其他点是如何影响它的颜色的,如这里的数值说明了某点的上下左右四个点对它的影响为1,而它本身并不对自己产生影响,这样这个点就会逐步与环境相融合,宏观的结果就是模糊*/ var matrix:Array = [0,1,0,1,0,1,0,1,0]; //矩阵的行列数目 var matrixX:Number = 3; var matrixY:Number = 3; //矩阵内各项值相加后的和,如果为0就取1 var divisor:Number = 4; /*这里需要注意到divisor后面的两个参数分别为bias和preserveAlpha bias的值影响了卷积的作用强度,值越大强度越小,这里需要燃烧以及残影消退的速度比较快,所以取-3 preserveAlpha指卷积过程是否保留透明通道不被计算在内,这里需要在计算颜色的同时也要计算透明,所以取false,否则位图最后会变成不透明的黑色*/ convolutionFilter = new ConvolutionFilter(matrixX,matrixY,matrix,divisor,-3,false);

下面是使用卷积滤镜的代码:

fwbitmap.bitmapData.applyFilter(fwbitmap.bitmapData,fwbitmap.bitmapData.rect,new Point(),convolutionFilter); //update里绘制新的燃点 update();

这样每次调用的时候位图都会先让自己模糊,然后在绘制新的清晰的燃点,最后的结果就是形成衰减的残影。

环境的反光效果

"那五彩缤纷的烟花映红了大地,映红了天空,这绚丽的色彩??" 正如作文中描写那样,礼花的亮度足以让天空和大地变色,如果没有环境的反光效果,礼花效果就不是完整和逼真的。

环境反光非常容易,只要在礼花爆炸的瞬间获取它的主颜色值,然后通过ColorTransform来修改环境的颜色通道即可:

var color:Number = fw.color; //通过位移计算出三个颜色通道的值 var r:Number = color >> 16; var g:Number = (color << 8) >> 16; var b:Number = (color << 16) >> 16; var cf:ColorTransform = skybitmap.transform.colorTransform; //用颜色通道的offset值来修改天空位图的颜色 cf.redOffset = r/5; cf.greenOffset = g/5; cf.blueOffset = b/5; skybitmap.transform.colorTransform = cf;

下面是反光淡出的代码:

var cf:ColorTransform = skybitmap.transform.colorTransform; cf.redOffset *=.99; cf.blueOffset *=.99; cf.greenOffset *=.99; skybitmap.transform.colorTransform = cf;

这样,一个高效漂亮的礼花效果就完成了,在这个例子里,没有用copyPixels,直接使用了setPixel32结合了卷积滤镜,完成了礼花的残影效果。如果有合适的礼花音效,可以给它添上声音,那样就更加完美了。
    点击鼠标即可开始或者暂停
 

  评论这张
 
阅读(92)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017