




已阅读5页,还剩10页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
介绍如何用ActionScript制作绚丽的特效SilkOn February 12, 2011, in Action Script, by James 前几天看到推出一个用HTML5做的很漂亮的特效Silk,经过三天的研究,我现在介绍一下如何用ActionScript写一个Flash版本。效果图如下:点击查看线上效果 (键盘X清屏,S停止,按住Shift更改风向)下载源文件 SilkFlash.zip (4KB)老样子,我们先来分析一下这个效果里有什么关键的技术问题需要解决:波浪线的画法波浪线间的填充效果颜色的过渡光效一、波浪线的画法这个效果中很重要的一个亮点就是一层层平滑的波浪,相信细心的朋友一定注意到了这里面的随机事件,每一条线都是一条随机路径,难点不在于如何选取随机点的位置,而是如何用一条平滑的线将它们连接起来。如图1中左图是一条随机线中的各个随机点,如果用直线连接那么就是一条条的折线,显然不是我们要的波浪线;如果如中图那样用曲线来连接,难点就是如何来确定曲线的控制点;所以我采用的方法是如右图那样,用每两个点的中点来做实际连接的锚点,而采用原来的随机点作控制点,这样既能保证平滑又可以确保曲线与随机点的方向一致,不至于最后出来的波浪线走样儿。图1,波浪线的画法找到了锚点和控制点后,用我在这篇文章介绍过的drawPath来画线,这里我就不多罗嗦了。下面就是随机和计算波浪线控制点的代码:/用来存储锚点和控制点的数组var gpd:Vector. = new Vector.();for(var i:int=datas.length-1;i =0;i-)if(i 0)/各点都朝着前一个点运动,宏观就是整体形状的萎缩datasi.x += (datasi-1.x - datasi.x)/7;datasi.y += (datasi-1.y - datasi.y)/7;if(i datas.length-1)/计算中心点,并将其添加到数组中作为锚点坐标,实际随机点作为控制点坐标。var x2:Number = (datasi.x + datasi+1.x)/2;var y2:Number = (datasi.y + datasi+1.y)/2;var ax:Number = datasi+1.x;var ay:Number = datasi+1.y;if(i datas.length-2)gpd.push(ax);gpd.push(ay);gpd.push(x2);gpd.push(y2);二、波浪线间的填充效果波浪线做好后,每两段相邻的波浪线之间应该是连续填充的,否则丝绸就变成粗线条的麻布了。我刚看到这个效果的时候就在想这个问题,仔细观察后发现波浪线之间的填充色有很强的渐变,而且在一些极端区域甚至可以看到细线。这让我确定了之前的一个猜测,那就是波浪线之间的填充是若干条细线,而不是整块填充色。也就是说,在画两条相邻的波浪线时,同时将它们中间的若干条过渡线补充进去,这样当过渡线足够多就会形成填充。方案一旦确定,实施的代码其实很简单:/设置过渡线的数目为20条var number:Number =20;for(var i:int=0;i number;i+)var g:Vector. = new Vector.();for(var j:int=0;j 0xFFFF00(黄)- 0x00FF00(绿) - 0x00FFFF(蓝绿) - 0x0000FF(蓝) - 0xFF00FF(紫)所以RGB的变化规律是这样的,当R达到0xFF,开始增加G的值;当G增加到0xFF,开始减小R的值,减小到0后增加B的值;当B到达0xFF开始减小G的值,达到0值后增加R的值,然后减小B的值完成一个光谱循环。用程序描述就是下面的代码:var speed:Number = 0xFF/80;if(r 0)if(g =0xFF)r-=speed;else if(b=0xFF)r +=speed;else if(b=0)g+=speed;if(g 0)if(b =0xFF)g-=speed;else if(r =0xFF)g +=speed;else if(r=0)b+=speed;if(b 0)if(r =0xFF)b-=speed;else if(g=0xFF)b +=speed;else if(g=0)r+=speed;r = Math.max(Math.min(0xFF,r),0);g = Math.max(Math.min(0xFF,g),0);b = Math.max(Math.min(0xFF,b),0);colorTransform.color = (r16)+(g8)+b;四、光效为了弄清楚整个效果的点睛之笔,也就是光影效果,我确实费了好一阵功夫。我的思路是这样的,当所有的线条都画好后,由于波浪线的疏密会形成颜色的深浅,这一点无需质疑,只要将波浪线一条一条画上去自然会水到渠成。但是仔细观察后发现,原效果中线条密集的地方除了饱和的颜色之外,还有明显的白色高光。所以我坚信一定要用到BlendMode.ADD这个算法,因为只有这个方法会在两种颜色叠加时增加RGB的实际值。可是当我用BlendMode.ADD后发现效果与预期的相差甚远,像素感特别强,更别提什么平滑。我用了整整两个通宵来解决这个问题,修改透明度、颜色值、加高光层等等做过各种尝试,最后发现原因出现在一个小小的细节上。因为我用的是BitmapData位图绘制,在黑色的背景上有一层输出位图,我在初始化的时候将输出的位图定义成全透明的,这样绘制的波浪线实际上是在一张透明层上做图形叠加,所以结果很差。解决的方法就是将输出背景改为不透明黑色,这样得到的效果就和当初设想的一模一样!至于效果中其他的一些细节比如跟随线条的小星星等因为不是核心技术瓶颈,所以我就不一一解释。我写这个代码的目的就是想告诉Flash开发者,Flash和ActionScript都已经非常成熟,只要你在网页上见到的任何绚丽的效果,不管它是不是用Flash开发,基本上都可以用Flash作出一模一样甚至更好的结果。补充:老刘Ryan也做了一版,我们采用了不同的方法,在颜色过渡上他用的是mx.utils.HSBColor,在曲线生成上他用的perlin,都是原生的API,在执行效率上肯定要更高。10Comments 2,879 views 请留言 使用Drawing API和位图滤镜制作特效水珠挂壁On January 30, 2011, in Action Script, by James 先来看看本文要介绍的效果,点击开始或者暂停:这是一个水珠挂壁的例子,一串串的水珠在模糊的玻璃上流动,水珠滑过的地方露出背景的图案。这一个简单的画面里却有很多的技术细节,包括用drawPath绘制水珠边缘;用物理运动模拟水珠的不规则流动轨迹;利用beginBitmapFill结合尺寸缩放来制作水珠的透镜效果;利用数学计算来完成水珠的融合动作以及结合多种位图滤镜来处理滑痕、反光和阴影等等。下面我们就一一来分析如何使用这些技术来制作一个水珠挂壁的效果。一,绘制水珠:水珠的绘制难点在于多变的边缘,设想一下如果每一滴水珠都是圆形或者椭圆形,而且始终保持不变,那一定不符合现实生活中的样子。真实的水珠应该如图1这样,在重力、附着力和表面张力的相互作用下具有不规则的边缘。我们虽然不要求做到与现实中所看到的完全一样,但如果能抓住自然规律的特点,就会至少做到神似。图1,现实中的水珠边缘水珠虽然是流体,但是边缘变化则是波的特性,而非粒子的运动特点。所以如果用粒子系统来绘制水珠不仅需要大量的单位粒子,更让处理器难以忍受的是每两个粒子之间的引力斥力的大量计算。不然无法做到逼真的波传递的效果。所以这里我的思路是先确定一周为数不多的关键点,然后把它们用曲线连接,通过控制关键点的位置来影响整体的曲线形状,从而实现多变的水珠边缘。图2,利用关键点结合曲线定义水珠的边缘形状如图2所示,黑色的点就是关键点,绿色的线就是连接相邻关键点的曲线。这里我要介绍一个比moveTo,curveTo更快速的绘图函数drawPath,通过下面这个例子我们来看如何使用这个方法:var graphicsPathCommand:Vector. = new Vector.(4);/*定义每一次绘制动作是起笔还是落笔*/graphicsPathCommand0 = GraphicsPathCommand.MOVE_TO;graphicsPathCommand1 = GraphicsPathCommand.LIVE_TO;graphicsPathCommand2 = GraphicsPathCommand.LIVE_TO;graphicsPathCommand3 = GraphicsPathCommand.LIVE_TO;/*定义点坐标*/var datas:Vector. = new Vector.(8);/第一个点(10,10)的坐标datas0 = 10;datas1 = 10;/第二个点(20,20)的坐标datas2 = 20;datas3 = 20;/第三个点(20,30)的坐标datas4 = 20;datas5 = 30;/第四个点(10,10)的坐标datas6 = 10;datas7 = 10;/绘制graphics.drawPath(graphicsPathCommand,datas);这样三个点就被连接成一个闭合三角形。如果你对ActionScript的绘图API比较熟悉,那么就可以以此类推出代替curveTo来绘制曲线的写法,不同的是datas的数量要多出将近一倍,因为增加了曲线锚点的信息。如图3所示,左边的图表示graphicsPathCommand的顺序,右边的图表示datas的内容与顺序,除了添加关键点(黑色点)的坐标外还要添加每一个曲线锚点(蓝色点)的坐标。图3,绘制曲线的参数定义顺序从图中我们可以归纳出结论:在绘制曲线的时候,如果关键点个数为N,则graphicsPathCommand的元素个数为N+1,datas的元素个数为(2*N+1)*2。程序中的代码如下:graphicPathCommand = new Vector.(atomCount+1);datas = new Vector.(atomCount*4 + 2);for(var i:int=0;iatoms.length+1;i+)if(i=0)/起笔点为MoveTographicPathCommandi = GraphicsPathCommand.MOVE_TO;else/其他各点为CurveTographicPathCommandi = GraphicsPathCommand.CURVE_TO;/起笔点不需要锚点var atom:Atom = atoms0 as Atom;datas0 = x + atom.x;datas1 = y + atom.y;/每一个落笔点都有一对锚点坐标for(var i:int=1,j:int=2;i var nextAtom:Atom;if(i=atoms.length)nextAtom = atoms0 as Atom;elsenextAtom = atomsi as Atom;/anchorSize为锚点的偏移量var anchorX:Number = (atom.x + nextAtom.x)/2 * anchorSize;var anchorY:Number = (atom.y + nextAtom.y)/2 * anchorSize;datasj = x + anchorX;datasj+1 = y + anchorY;datasj+2 = x + nextAtom.x;datasj+3 = y + nextAtom.y;atom = nextAtom;/atoms.length+1;i+)二,水珠的透镜效果:水珠好比与一块凸透镜,透过它看到的图像应该是一个放大的背景图片。如果抓住并实现了这个自然规律,那么做出来的水珠就会显得非常的有立体感。所以这里牵涉到两个知识点,一是如何在水珠中绘制背景图片,二是如何控制绘制的缩放和位置。Graphics的绘图API可以指定绘制的内容,其中beginBitmapFill是用位图来绘制,这里我们需要的正是它。beginBitmapFill(bitmap:BitmapData, matrix:Matrix = null, repeat:Boolean = true, smooth:Boolean = false):void参数列表中的第二项是matrix,用它可以解决刚才提到的第二个问题,也就是缩放和位置的设定。在下面的代码中,缩放为150。因为缩放是以水珠的坐标为中心,所以填充背景的偏移应该是缩放后水珠坐标的增量的负数,所有缩放的偏移都可以这样计算。var matrix:Matrix = new Matrix();matrix.scale(1.5,1.5);matrix.tx = -pDrop.x*.5;matrix.ty = -pDrop.y*.5;dropShape.graphics.beginBitmapFill(backgroundSource,matrix);接下来,我们再给水珠加上滤镜,让它有反光和阴影,水珠的立体感便油然而生。下面就是作用在水珠上的两个位图滤镜:/*浮雕滤镜可以同时给水珠添加高光和反光,这些参数的意义是,浮雕的深度为1,角度为75度,高光颜色为黑色,高光透明度为0,反光颜色为白色,透明度为0.8,浮雕横纵向模糊度为4,强度为3,渲染品质为3*/dropBevelFilter = new BevelFilter(1,75,0,0,0xffffff,.8,4,4,3,3);/*阴影滤镜可以在水珠的下方加上一个挂壁的阴影效果,这个效果距离为4,角度为90度也就是垂直从上到下,颜色为黑色,透明度为1,模糊为4,强度为0.5,渲染品质默认为1*/dropShadowFilter = new DropShadowFilter(4,90,0,1,4,4,.5);三,水珠融合效果:水珠沿着玻璃流动时如果与其他水珠相接触或者流进其他水珠流动的轨迹内,则水珠会融合在一起成为新的水珠。这个看似复杂的情况其实很好解决。先来看水珠的大小是如何计算的。每一个水珠的大小都跟它的体积相关,而在密度相等的情况下,体积与质量成正比: 体积 质量密度。我们先给水珠设定一个质量参数mass,假设水珠在壁上的厚度一定,那么体积与面积成正比,再假设理想状态下(无重力无张力)水珠是一个圆形,由圆形面积公式可知,面积等于半径的平方乘以圆周率: S = * R * R,即半径与面积的开方成正比。所以最后我们得出结论:半径与质量的开方成正比。有了这个结论,在水珠融合的过程中,就可以直接通过质量的传递来解决水珠的显示大小:mass += pDrop.mass * .75;其他的问题相对来说比较好解决,用距离计算公式可以算出水珠的距离,如果过近或者垂直距离过近则发生融合,融合的时候质量小或者相对处于上方的水珠是被融合的水珠,表现为朝着融合的主体快速移动并减小质量,主体水珠表现为增加质量,最后质量等于两个水珠的质量和。代码如下:判断融合的代码:if(Math.sqrt(Math.pow(drop.x - pDrop.x,2) + Math.pow(drop.y - pDrop.y,2)=pDrop.mass)drop.merge(pDrop);return true;elsepDrop.merge(drop);return true;else if(Math.abs(drop.x - pDrop.x)5 & Math.abs(pDrop.y - drop.y)drop.y & pDrop.mass 90)pDrop.merge(drop);return true;else if(drop.y pDrop.y & drop.mass 90)drop.merge(pDrop);return true;融合主体:public function merge(pDrop:Drop):voidmass += pDrop.mass * .75;pDrop.beMerged(this);resetTimer();被融合水珠:public function beMerged(pDrop:Drop):voidisMerged = true;mergeParent = pDrop;resetAtoms();.if(isMerged)mass *= .8;vx = (mergeParent.x - x)/5;vy = (mergeParent.y - y) /5;vx *= .98;vy *= .98;x +=vx;y +=vy;四,流动算法:挂壁有两种状态:挂壁和流动。当质量相对小时,水珠与玻璃的附着力大于水珠的重力,水珠表现为挂壁而静止不动;当质量较大时,重力大于附着力,水珠便沿着玻璃向下流动。水珠向下流动的过程中由于附着力表现为对流体各个附着点的阻力,导致各个附着点的相对位置发生变化,宏观看来就是水珠的形状发生变化,形状变化导致水珠重心偏移,运动方向和速度发生变化,其变化周期不衡定。我们没有必要将变形和运动改变计算得与自然界中发生的一般无二,只要抓住两个特点即变形和变速,便可以描绘出流动的特征。水珠变形:刚才我们已经分析了如何使用关键点结合曲线来绘制水珠。所以只要改变关键点的位置便可以完成水珠的变形。下面代码表示了一个关键点的位置是如何计算的:/利用质量与半径的关系求出半径radius = Math.sqrt(mass / Math.PI);/求出理想状态下此关键点的角度var angle:Number = Math.PI *2 * (index+.5)/neighborCount) - Math.PI/2;/求出理想状态下角度与运动方向角的偏移量var angleDistance:Number = .5- Math.abs(pVAngle - angle)/2;/算出此关键点的目标坐标位置ax = radius * (1+Math.random() * angleDistance ) * Math.cos(angle+(pVAngle - angle)/30);ay = radius * (1+Math.random() * angleDistance ) * Math.sin(angle+(pVAngle - angle)/30);/朝着目标坐标运动x += (ax + mass/100 * (1- Math.random()*2) - x) / 3;y += (ay + mass/100 * (1- Math.random()*2) - y) / 3;图4,水珠的变形如图4所示,a,b,c,d,e为5个关键点,蓝色圆为已知半径在理想状态下的的范围,蓝色箭头为运动方向,A为运动方向角,B为关键点b与运动方向角的偏移量。则b点目标方向增量与B成正比,b点的离心半径偏移量与B成正比。红色点b即为b点的目标点,同理得出其他各点的目标点。从图上可以看出运动方向影响了水珠的形状。变速算法:水珠流动的特征可以用这样的规律来模拟,在某一个时间点算出一个速度组(vx,vy),然后用timer来算出下一个时间点。这样在每一个时间点都会改变速度,同时保证在两个时间点间的时间段内速度方向不变。代码如下:if(getTimer() - startTime timeStep)resetTimer();.private function resetTimer():voidstartTime = getTimer();/当水珠足够大时才开始流动if(mass 80)vx = .5 *(1-Math.random()*2);vy = .5 + Math.random()*5;/设置水珠流动速度上限vy = Math.min(vy,8);/计算下一个时间点timeStep = Math.random() * 1000+2000;五,滑痕效果:水珠流动时会在玻璃上留下一道滑痕,这条滑痕是本例的效率瓶颈,因为它是多重位图滤镜的相互作用的结果。我们先分析一下滑痕的特征,滑痕接近水珠的部分厚度比较大,所以有透镜效果;远离水珠的部分没有厚度和透镜效果,但是可以在玻璃上擦出一条干净透明的轨迹,随后这条轨迹慢慢消失。这样的安排虽然与自然规律相比显得比较极端,但是却可以描绘出很动感的流体画面。靠近水珠的透镜部分实际上是水珠的残影,由于我们需要同时保留残影清晰的边缘和它的渐行渐远的特性,所以不能使用卷积滤镜。这里使用的是一个数组来保存一定数量的历史残影位图,然后一次重绘。如下面的代码:for(var i:int=0;idropBitmapDatas.length;i+)var level:Number = (i/dropBitmapDatas.length);var bmd:BitmapData = dropBitmapDatasi as BitmapData;var cf:ColorTransform = new ColorTransform();cf.alphaOffset = -100 + 100 * level;bmd.colorTransform(bmd.rect,cf);dropBitmap.bitmapData.copyPi
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 民法学习课件
- 北京舞蹈考试题库及答案
- 结核病治疗方案
- 人工智能:新质生产力的技术引擎
- 打造新质生产力的人才磁场
- 乡镇过去五年进展工作总结及将来五年工作方案
- 新质生产力本质属性
- 幼儿园班级疫情防控活动方案
- 干部如何服务新质生产力发展
- 新质生产力看莞深智造
- 2024-2030年中国电解二氧化锰(EMD)行业市场发展趋势与前景展望战略分析报告
- 初中+物理运动的描述++人教版八年级物理上册+
- 计算机科学实习合同模板
- 人身损害三期评定规范
- 《我与地坛》教学设计 统编版高中语文必修上册
- 工业固废运输处置投标方案(技术标)
- 上海市语文新初一均衡分班试卷
- 中医培训课件:《放血疗法》
- KA-T 20.1-2024 非煤矿山建设项目安全设施设计编写提纲 第1部分:金属非金属地下矿山建设项目安全设施设计编写提纲
- 医务人员职业暴露的预防与处理应急预案
- 《古建筑构件制作(榫卯、斗拱)》课程标准
评论
0/150
提交评论