`
ivb411iv
  • 浏览: 15179 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

AS3.0打造随风吹散效果

 
阅读更多

AS3.0打造随风吹散效果
2010年07月29日
  在这篇教程中,我们会自定义一个类,它能将一张图片分解成1000多个碎片,并模拟被风吹散的效果。我使用了FlashDevelop来创建一个AS3项目。
  最终效果预览
  点击Flash舞台看风吹效果
  了解FlashDevelop
  FlashDevelop是一个Flash和Flex的代码编辑器。当你在使用Flash的时候你也可以用它来编辑类文件,或者直接用FlashDevelop来创建as3工程,而不需要使用Flash―这正是本教程要做的。
  因此,先下载FlashDevelop并安装它。不幸的是,FlashDevelop只能在Windows下运行。苹果系统可以选择FDT和FlexBuilder(ok,现在已经叫Flash Builder)但也不是免费的。你可以使用Flash,我也将解释使用Flash怎么做到。
  步骤1:创建一个项目
  打开FlashDevelop并点击Porject>New Project
  步骤2:建立
  选择ActionScript3>AS3 Project。输入项目名称“WindEffect”,选择一个文件夹保存项目。保证“Create Directory For Project”检查框被选择,然后单击OK按钮。
  如果你打算使用Flash CS3/CS4。那么就创建一个新的Flash文件,并且设置舞台的宽高为550x250px。设置背景色为白色。保存为“windEffect.fla”,然后随便你喜欢保存在什么地方。
  步骤3:找张图片
  如果是FlashDevelop,打开项目目录,复制或者拖一张windEffect.jpg图片到\bin\folder目录。
  如果是使用Flash ide,复制或者拖一张windEffect.jpg图片到windEffect.fla文件同目录下。
  步骤4:安装TweenLite(一个补间动画类库)
  我们要使用TweenLite来做补间动画。你可以在这里(http://www.greensock.com/tweenlite/)下载最新版。我已经把它包含在源文件中了。
  对于FlashDevelop来说,将greensock.swc复制到项目的\lib\folder\目录下。然后单击View>
  
  roject Manager。
  步骤5:外链库
  不过在FlashDevelop,单击lib文件夹旁边的“+”号展开它。然后右键单击greensock.swc并选择“Add To Library”。
  在Flash中,复制或者拖拽“com”目录到windEffect.fla同目录下。
  步骤6:文档类
  在FlashDevelop中,再次打开project  manager(参考步骤4),展开src文件夹,并且双击Main.as。在完成导入以及类定义之后,使用元数标签设置舞台属性
  [SWF (width = 550, height = 250, frameRate = 30, backgroundColor = 0)] 
  在init()方法中,注释“entry point”之后,添加如下代码:
  stage.scaleMode = StageScaleMode.NO_SCALE;        //不伸展舞台
  var effect:WindEffect = new WindEffect('windEffect.jpg');        //我们马上要创建WindEffect类
  addChild (effect);
  复制代码这就是Main文档类
  在Flash,在fla文件同目录下新建的Main.as文件。加入如下代码:
  package
  {
  import flash.display.Sprite;
  import flash.display.StageScaleMode;
  import flash.events.Event;
  public class Main extends Sprite
  {
  public function Main():void
  {
  if (stage) init();
  else addEventListener(Event.ADDED_TO_STAGE, init);
  }
  private function init(e:Event = null):void
  {
  removeEventListener(Event.ADDED_TO_STAGE, init);
  stage.scaleMode = StageScaleMode.NO_SCALE;        //don't stretch the stage
  var effect:WindEffect = new WindEffect ('windEffect.jpg');        //we will create the WindEffect class soon
  addChild (effect);
  }
  }
  }
  复制代码打开Flash,给文档类赋值“Main”
  (如果对文档类不太明白可以看这篇教程http://active.tutsplus.com/tutor ... ent-class-in-flash/)
  如果你现在试着去运行它。你将会得到一个错误,因为我们还没有创建WindEffect类。
  步骤7:创建WindEffect类
  在FlashDevelop中,单击View>
  
  roject Manager,右键单击src文件夹,并选择Add>New Class
  步骤8:设置类
  命名类名为 WindEffect,单击browse按钮选择flash.displaySprite为基类。单击OK完成。
  步骤9:导入其他类
  在package大括号内导入所有必须的类,在Import  flash.display.Sprite之下,类定义之前。并保存
  import com.greensock.easing.Strong;
  import com.greensock.TweenLite;
  import flash.display.Bitmap;
  import flash.display.BitmapData;
  import flash.display.Loader;
  import flash.events.Event;
  import flash.events.MouseEvent;
  import flash.geom.Point;
  import flash.geom.Rectangle;
  import flash.net.URLRequest;
  复制代码在Flash中,新建一个ActionScript文件,命名为“WindEffect.as”,并保存在项目根目录下。它和fla文件,com目录与Main.as文件在同一个目录中。
  添加如下代码:
  package
  {
  import com.greensock.easing.Strong;
  import com.greensock.TweenLite;
  import flash.display.Bitmap;
  import flash.display.BitmapData;
  import flash.display.Loader;
  import flash.display.Sprite;
  import flash.events.Event;
  import flash.events.MouseEvent;
  import flash.geom.Point;
  import flash.geom.Rectangle;
  import flash.net.URLRequest;
  public class WindEffect extends Sprite
  {
  public function WindEffect ()
  {
  }
  }
  }
  复制代码步骤10:加入变量
  加入一个私有的变量,名为“_pictureArray”。这是这个类中唯一的变量。它的主要作用是保存所有小sprite,每个笑sprite都记录着图像的某一块图形数据。
  在括号内添加如下代码:
  public class WindEffect extends Sprite
  {
  //这用来保存所有运动的碎片.
  private var _pictureArray:Array;
  }
  复制代码步骤11:添加构造
  在_pictureArray声明下面添加:
  public class WindEffect extends Sprite
  {
  //这用来保存所有运动的碎片.
  private var _pictureArray:Array;
  public function WindEffect ($url:String)
  {
  //我们在构造函数中调用载入图片方法。
  loadPicture ($url);
  }
  }
  复制代码步骤12:操纵图片
  在构造函数中调用loadPicture()方法。我们实例化一个Loader来加载windEffect.jpg。我们还添加一个COMPLKETE事件来侦听加载是否完成。
  在WindEffect()之后添加如下代码(注意,参数$url是从Main.as中传过来的图片的路径)
  private function loadPicture ($url:String):void
  {
  //创建Loader并侦听载入情况。
  //加载图片
  var loader:Loader = new Loader;
  loader.contentLoaderInfo.addEventListener (Event.COMPLETE, onLoadComplete);                //when it's loaded, call the onLoadComplete () function
  loader.load (new URLRequest ($url));
  }
  复制代码步骤13:载入
  当图片完全导入的时候,这个方法就被调用了。在loadPicture()下面添加如下代码,并保存。
  private function onLoadComplete (e:Event):void
  {
  //for testing
  addChild (e.target.content);
  }
  复制代码步骤14:测试
  接着按CTRL+Enter组合键进行测试,图片就会出现在舞台的左上角。
  现在,我们已经知道它能正常的加载,那么就删除addChild方法,并将它替换为如下代码:
  createEffect (e.target.content); 
  你的WindEffect类看起来应该是这样的:
  package
  {
  import com.greensock.easing.Strong;
  import com.greensock.TweenLite;
  import flash.display.Bitmap;
  import flash.display.BitmapData;
  import flash.display.Loader;
  import flash.display.Sprite;
  import flash.events.Event;
  import flash.events.MouseEvent;
  import flash.geom.Point;
  import flash.geom.Rectangle;
  import flash.net.URLRequest;
  [SWF (width = 550, height = 250, frameRate = 30, backgroundColor = 0)]
  public class WindEffect extends Sprite
  {
  private var _pictureArray:Array;
  public function WindEffect ($url:String)
  {
  loadPicture ($url);
  }
  private function loadPicture ($url:String):void
  {
  var loader:Loader = new Loader;
  loader.contentLoaderInfo.addEventListener (Event.COMPLETE, onLoadComplete);
  loader.load (new URLRequest ($url));
  }
  private function onLoadComplete (e:Event):void
  {
  createEffect (e.target.content);
  }
  }
  }
  复制代码步骤15:设置变量
  createEffect()方法将传递一个图像参数,它本质上是一个位图(Bitmap),之后它会被分解为1250块。
  首先,我们计算出让图像处在舞台正中央的x,y坐标。我们将坐标保存至局部变量centerWidth和centerHeight中
  因为图片的尺寸为300x100,所以我决定分割的比例是:横50,竖25。这样划分会有一个很好的性能,我们将它们保存至局部变量“numberOfColumns”与“numberOfRows”中。这样图片就被分割成1250块均等的矩形,然后我们把矩形的宽高保存至“sizeWidth”与“sizeHeight”中。“numberOfBoxes”变量用来保存矩形的数目。
  接着我们实例化_pictureArray数组,这样我们就能将那些矩形存进去。接下来的这些代码放在onLoadComplete()方法后面。
  private function createEffect ($bitmap:Bitmap):void
  {
  //居中x坐标
  var centerWidth:Number = (stage.stageWidth - $bitmap.width) * .5;
  //居中y坐标
  var centerHeight:Number = (stage.stageHeight - $bitmap.height) * .5;
  var numberOfColumns:uint = 50;
  var numberOfRows:uint = 25;
  var sizeWidth:uint = $bitmap.width / numberOfColumns;
  var sizeHeight:uint = $bitmap.height / numberOfRows;
  var numberOfBoxes:uint = numberOfColumns * numberOfRows;
  _pictureArray = [];
  }
  复制代码步骤16:嵌套循环
  在实例化_ pictureArray后,我们将使用嵌套循环来实现一个二维数组。第一层循环处理x坐标遍历所有列,第二层循环将处理y坐标,遍历所有行。
  在实例化_pictureArray后,将下面的代码放入createEffect()方法内,保存。
  for (var i:uint = 0; i bitmapdata
  var tempBitmapData:BitmapData = new BitmapData (sizeWidth, sizeHeight);
  //1 个临时的矩形 (x,y,width,height)
  //我们通过i*sizeWidth作为x坐标的参数,j*sizeHeight作为y坐标的参数。
  //还有sizeWidth以及sizeHeight作为宽与高的参数。
  var sourceRect:Rectangle = new Rectangle (i * sizeWidth, j * sizeHeight, sizeWidth, sizeHeight);
  trace (sourceRect);//测试
  复制代码步骤19:进一步测试
  测试影片。可以观察到每次迭代创建的矩形情况,以便调整。
  正如你所看到的,在第一个例子显示x=0,y=0下一个是x=0,y=4。这就是我们从图像上取下来的小图片的区域。接下来移除test函数。
  步骤20:BitmapData.copyPixels()
  然后,我们使用BitmapData.copyPixels ()方法依据soureceRect来复制图像上的图形数据。这个方法的参数是需要复制的目标位图图像,需要复制的矩形区域以及目标点(它表示将在其中放置新像素的矩形区域的左上角)。
  tempBitmapData.copyPixels ($bitmap.bitmapData, sourceRect, new Point);
  复制代码然后我们创建一个临时位图来放置我们刚才复制的BitmapData,接着再创建一个临时Sprite来放置临时位图。
  再然后我们把所有的Sprite都放入到_pictureArray中。在这之后,我们将Sprite以原有的坐标放置到舞台上,还原原始图像。
  最后根据centerWidth和centerHeight调整一下位置让整副图能在舞台上居中。
  添加下面的代码,并再次保存。
  //创建一个临时位图来放置我们复制的BitmapData数据
  var tempBitmap:Bitmap = new Bitmap (tempBitmapData);
  //创建一个临时的Sprite来放置上面的bitmap,以便有交互功能。
  var tempSprite:Sprite = new Sprite;
  //将bitmap放入Sprite的目的是产生交互,因为bitmap是没有交互功能的。
  tempSprite.addChild (tempBitmap);
  //将临时Sprite加入数组
  _pictureArray.push (tempSprite);
  //加入舞台
  //校对中心位置
  tempSprite.x = i * sizeWidth + centerWidth;
  tempSprite.y = j * sizeHeight + centerHeight;
  addChild (tempSprite);
  复制代码步骤21:第三次测试
  请继续测一次,你将看到图像被正确的饿放置到了舞台上。甚至看不出它已经被分割成了1250份。
  在嵌套循环的结束括号后面,我们加入如下代码:
  stage.addEventListener (MouseEvent.CLICK, blowWind); 
  复制代码我们为舞台增加一个鼠标点击(MouseEvent.CLICK)事件监听器。这将触发我们将在下一步创建的blowWind()函数,
  你的WindEffect类看起来应该像这样:
  package
  {
  import com.greensock.easing.Strong;
  import com.greensock.TweenLite;
  import flash.display.Bitmap;
  import flash.display.BitmapData;
  import flash.display.Loader;
  import flash.display.Sprite;
  import flash.events.Event;
  import flash.events.MouseEvent;
  import flash.geom.Point;
  import flash.geom.Rectangle;
  import flash.net.URLRequest;
  public class WindEffect extends Sprite
  {
  private var _pictureArray:Array;
  public function WindEffect ($url:String)
  {
  loadPicture ($url);
  }
  private function loadPicture ($url:String):void
  {
  var loader:Loader = new Loader;
  loader.contentLoaderInfo.addEventListener (Event.COMPLETE, onLoadComplete);
  loader.load (new URLRequest ($url));
  }
  private function onLoadComplete (e:Event):void
  {
  createEffect (e.target.content);
  }
  private function createEffect ($bitmap:Bitmap):void
  {
  var centerWidth:Number = (stage.stageWidth - $bitmap.width) * .5;
  var centerHeight:Number = (stage.stageHeight - $bitmap.height) * .5;
  var numberOfColumns:uint = 50;
  var numberOfRows:uint = 25;
  var sizeWidth:uint = $bitmap.width / numberOfColumns;
  var sizeHeight:uint = $bitmap.height / numberOfRows;
  var numberOfBoxes:uint = numberOfColumns * numberOfRows;
  _pictureArray = [];
  for (var i:uint = 0; i BitmapData = new BitmapData (sizeWidth, sizeHeight);
  var sourceRect:Rectangle = new Rectangle (i * sizeWidth, j * sizeHeight, sizeWidth, sizeHeight);
  tempBitmapData.copyPixels ($bitmap.bitmapData, sourceRect, new Point);
  var tempBitmap:Bitmap = new Bitmap (tempBitmapData);
  var tempSprite:Sprite = new Sprite;
  tempSprite.addChild (tempBitmap);
  _pictureArray.push (tempSprite);
  tempSprite.x = i * sizeWidth + centerWidth;
  tempSprite.y = j * sizeHeight + centerHeight;
  addChild (tempSprite);
  }
  }
  stage.addEventListener (MouseEvent.CLICK, blowWind);
  }
  }
  }
  复制代码步骤22:创建随风飘散的效果
  首先移除鼠标点击(MouseEvent.CLICK)事件监听器,因为我们只需要它触发一次。接着在createEffect()方法后添加如下代码:
  private function blowWind (e:MouseEvent):void
  {
  stage.removeEventListener (MouseEvent.CLICK, blowWind);
  }
  复制代码我们需要通过_pictureArray数组来控制所有加入数组中的的Sprite产生动画。
  TweenLite很胜任这项工作,可以用它来实现随风飘散的效果。
  它的参数是:1目标对象(MovieClip或者其它对象),2时间长度(单位秒),3对象,通过属性值,来存贮各种属性参数用于缓动.(如果你使用 TweenLite.from() 方法,这里的参数表示缓动的初始值)以及其他你需要应用补间的属性。
  举个例子:TweenLite.to (target, duration, {x:100, y:100, rotation:30, ease:Strong.easeIn, onComplete:trace, onCompleteParams:['hello']}).
  上面例子的最后两个参数用来响应当补间结束时的函数。OnComplete参数是补间结束时响应的函数名trace,onCompleteParams则传递一个字符串“hello”到trace函数中去。
  在移除事件监听器后加入如下代码:
  for (var i:uint = 0; i Sprite的x坐标移到舞台外部
  y:_pictureArray[ i ].y+ getRandomRange (-100,100,false)。这个意思是将目标对象的y坐标增加一个-100至100的随机值,扩展动画效果。
  rotation:getRandomRange (-90,90),将目标对象随机旋转,范围在-90度至90度之间。
  ease:Strong.easeIn,这是缓动类型,慢慢开始,突然加快。
  onComplete:removeSprite当补间动画结束时调用removeSprite方法将Sprite移除
  onCompleteParams:这是给removeSprite传递要被移除的Sprite。
  步骤23:removeSprite()方法
  这是TweenLite在补间动画结束的时候调用的方法。用与移除运动结束的Sprite。
  将下面的代码添加到blowWind()方法后面
  private function removeSprite ($sprite:Sprite):void
  {
  removeChild ($sprite);
  }
  复制代码步骤24:getRandomInRange()方法
  我想你肯定熟悉这个(如果不熟悉可以看这篇教程http://active.tutsplus.com/tutor ... ed-range-using-as3/)我的版本有一个选项能控制返回整数(int,uint)还是浮点(fractions)。
  添加如下代码。如果你使用FlashDevelop,你可以将它保存为一个自定义代码片段,这样就能很容的在其它类或者项目中使用。我已经将它定义为静态方法。
  public static function getRandomInRange ($min:Number, $max:Number, $rounded:Boolean = true):Number
  {
  if ($rounded) return Math.round (Math.random () * ($max - $min) + $min);
  else return Math.random () * ($max - $min) + $min;
  }
  复制代码好了,运行一下该影片。如果有什么错误,对照源文件中的WindEffect类检查一下。
  总结
  创建酷效果的关键是学习和掌握图像处理以及补间动画类,例如TweenLite。
  感谢阅读!
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics