• Flash/Flex学习笔记(24):粒子效果


    粒子爆炸:

    仍然要用到以前的小球类,不过稍加改造

    view source

    print?

    01
    package {

    02
    import flash.display.Sprite;

    03

    04
    //小球 类

    05
    public class Ball extends Sprite {

    06

    07
    public var radius:uint;//半径

    08
    public var color:uint;//颜色

    09
    public var vx:Number=0;//x轴速度

    10
    public var vy:Number=0;//y轴速度

    11

    12
    public function Ball(r:Number=50,c:uint=0xff0000) {

    13
    this.radius=r;

    14
    this.color=c;

    15
    init();

    16
    }

    17

    18
    private function init():void {

    19
    graphics.beginFill(color);

    20
    graphics.drawCircle(0,0,radius);

    21
    graphics.endFill();

    22
    }

    23
    }

    24
    }

    增加了x,y轴的速度,其它没变

    原理:在舞台的某一区域放置大量小球实例,然后在某个时刻让其向四面八方运动即可(即改变每个小球在x,y轴上的坐标)

    问题:效率!让CPU在每帧对于大量对象进行重绘是很耗资源的,所以当小球跑出舞台边界时,得想办法通知CPU:这些小球不需要再处理了(反正也看不见)!否则纯属折腾CPU,下面的代码用一个数组存放所有对象实例的引用,然后在EnterFrame事件中不断检测,一旦有对象跑出边界了,就将其清除,不再理会了.

    view source

    print?

    01
    import fl.controls.Label;

    02
    import flash.text.TextFieldAutoSize;

    03

    04
    stage.scaleMode=StageScaleMode.NO_SCALE;

    05
    stage.align=StageAlign.TOP_LEFT;

    06

    07
    var Count:Number=1500;

    08
    var Radius:uint=30;

    09
    var CenterX:uint=stage.stageWidth/2;

    10
    var CenterY:uint=stage.stageHeight/2;

    11

    12
    var ArrBall:Array=new Array(Count);

    13

    14
    //让小球呈圆形随机分布

    15
    for (var i=0; i<ArrBall.length; i++) {

    16
    ArrBall[i]=new Ball(Math.random() * 5,Math.random() * 0xff0000);

    17
    var angle:Number=Math.random()*Math.PI*2;

    18
    var RadiusRnd:Number=Math.random()*Radius;

    19
    ArrBall[i].x=CenterX+Math.cos(angle)*RadiusRnd;

    20
    ArrBall[i].y=CenterY+Math.sin(angle)*RadiusRnd;

    21
    addChild(ArrBall[i]);

    22
    }

    23

    24
    var lbl1:Label = new Label();

    25
    lbl1.text="点击鼠标引爆这个球";

    26
    lbl1.autoSize=TextFieldAutoSize.CENTER;

    27

    28
    lbl1.x=stage.stageWidth/2-lbl1.width/2;

    29
    lbl1.y=50;

    30
    Mouse.cursor=MouseCursor.BUTTON;

    31
    addChild(lbl1);

    32

    33
    stage.addEventListener(MouseEvent.MOUSE_MOVE,MouseMoveHandler);

    34
    stage.addEventListener(MouseEvent.MOUSE_DOWN,MouseDownHandler);

    35

    36
    //文件鼠标跟随

    37
    function MouseMoveHandler(e:MouseEvent):void {

    38
    lbl1.x=mouseX+15;

    39
    lbl1.y=mouseY+15;

    40
    }

    41

    42
    function MouseDownHandler(e:MouseEvent):void {

    43
    //点击一次后,取消鼠标跟随,并移除lbl1,同时也取消鼠标点击事件(即本事件仅触发一次)

    44
    Mouse.cursor=MouseCursor.ARROW;

    45
    stage.removeEventListener(MouseEvent.MOUSE_MOVE,MouseMoveHandler);

    46
    lbl1.visible=false;

    47
    removeChild(lbl1);

    48
    stage.removeEventListener(MouseEvent.MOUSE_DOWN,MouseDownHandler);

    49

    50
    InitVelocity();//初始化粒子速度

    51

    52
    addEventListener(Event.ENTER_FRAME,EnterFrameHandler);

    53
    }

    54

    55
    function InitVelocity() {

    56
    for (var i=0; i<ArrBall.length; i++) {

    57
    ArrBall[i].vx = (Math.random()*2-1) * 30 ;//注意这里的小技巧: Math.random()*2-1即得到一个在-1到1之间分布的随机小数,即小球随机向左或向右的初始速度,然后再放大N倍,得到x轴最终速度

    58
    ArrBall[i].vy = (Math.random()*2-1) * 30;

    59
    }

    60

    61
    }

    62

    63

    64
    function EnterFrameHandler(e:Event):void {

    65
    for (i=ArrBall.length-1; i>=0; i--) {

    66
    var ball:Ball = ArrBall[i];     

    67
    ball.x += (ball.vx );

    68
    ball.y += (ball.vy );       

    69
    //检测边界,如果超出屏幕则移除该对象(注:从舞台上移除不再使用的对象,能使CPU占用率有效降低)       

    70
    if (ball.x < -ball.width/2 || ball.x > stage.stageWidth + ball.width/2 || ball.y< -ball.height/2 || ball.y > stage.stageHeight + ball.height/2){        

    71
    removeChild(ball);

    72
    ArrBall.splice(i,1);

    73
    }

    74

    75
    //如果数组已经为空,则清除EnterFrame事件

    76
    if (ArrBall.length==0){

    77
    removeEventListener(Event.ENTER_FRAME,EnterFrameHandler);

    78
    }

    79

    80
    //trace(ArrBall.length);

    81

    82

    83
    }

    84
    }

    粒子喷射:

    如果看过上篇Flash/Flex学习笔记(23):运动学原理 并动手实践过"自由落体运动"的朋友,对于这种粒子效果可能比较容易理解。

    原理:将所有粒子聚集于屏幕上某点(本例中为屏幕底部中心点),然后赋给一个随机向上的速度(这样就能向上喷射出),同时为了更效果更自然,还要加入随机的x轴方向速度(以实现喷射过程中的扩散),最后再加入重力加速度,以实现粒子的自由回落。

    效率:为了能最大限度的利用现有对象,当粒子跑出舞台边界时,重新用代码将其定位到发射点,以便下次继续喷射。

    交互:本例中为增强交互性,用鼠标的x轴位置模拟了风力影响。(在水平方向移动鼠标可看到喷射方向略有变化)

    view source

    print?

    01
    package {

    02
    import flash.display.Sprite;

    03
    import flash.display.StageAlign;

    04
    import flash.display.StageScaleMode;

    05
    import flash.events.Event;

    06
    public class Fountain extends Sprite {

    07
    private var count:int=3000;

    08
    private var wind:Number=0.0;

    09

    10
    private var gravity:Number=0.3;

    11
    private var balls:Array;

    12
    public function Fountain() {

    13
    init();

    14
    }

    15
    private function init():void {

    16
    stage.scaleMode=StageScaleMode.NO_SCALE;

    17
    stage.align=StageAlign.TOP_LEFT;

    18
    balls = new Array();

    19
    for (var i:int = 0; i < count; i++) {

    20
    var ball:Ball=new Ball(1,0xffffff);

    21
    ball.x=stage.stageWidth/2;

    22
    ball.y=stage.stageHeight;

    23
    ball.vx = (Math.random()*2-1) * 1.5 + wind;

    24
    ball.vy=-5+Math.random()*-10;

    25
    addChild(ball);

    26
    balls.push(ball);

    27
    }

    28
    addEventListener(Event.ENTER_FRAME, onEnterFrame);

    29
    }

    30
    private function onEnterFrame(event:Event):void {

    31
    wind = -1*(mouseX - stage.stageWidth/2)/200;

    32
    for (var i:Number = 0; i < balls.length; i++) {

    33
    var ball:Ball=Ball(balls[i]);

    34
    ball.vy+=gravity;

    35
    ball.x+=ball.vx;

    36
    ball.y+=ball.vy;

    37
    if (ball.x > stage.stageWidth + ball.radius || ball.x < -ball.radius || ball.y >stage.stageHeight + ball.radius || ball.y<-ball.radius) {

    38
    ball.x=stage.stageWidth/2;

    39
    ball.y=stage.stageHeight;

    40
    ball.vx = (Math.random()*2-1) * 1.5 + wind;

    41
    ball.vy=-5+Math.random()*-10;

    42
    }

    43
    }

    44
    }

    45
    }

    46
    }

    粒子跟随:

    除了利用边界检测移除粒子外,在实际开发中也经常利用时间来判断,比如一个对象在舞台上存活几秒后,便将其干掉。

    view source

    print?

    01
    stage.addEventListener(MouseEvent.MOUSE_MOVE,MouseMoveHandler);

    02

    03
    function MouseMoveHandler(e:MouseEvent):void{

    04
    var ball:Ball = new Ball(Math.random()*3,0x00ff00);

    05
    ball.x = mouseX;

    06
    ball.y = mouseY;

    07
    ball.vx = (Math.random()*2-1)*3;

    08
    ball.vy = (Math.random()*2-1)*3;

    09
    addChild(ball);

    10
    ball.addEventListener(Event.ENTER_FRAME,EnterFrameHandler);

    11
    }

    12

    13
    function EnterFrameHandler(e:Event):void{

    14
    var ball:Ball = e.target as Ball;

    15
    ball.x += ball.vx;

    16
    ball.y += ball.vy;

    17
    ball.count ++;

    18
    if (ball.count>=50){

    19
    ball.removeEventListener(Event.ENTER_FRAME,EnterFrameHandler);

    20
    removeChild(ball);      

    21
    }

    22
    }

    注:需要先在Ball类中增加一个public var count:uint=0;变量(用来辅助计时),上面的代码中用 if ball.count>=50做判断,相当于每个小球只让其播放50帧对应的时间就寿终正寝

    模拟布朗运动:

    view source

    print?

    01
    var Count:Number=200;

    02

    03
    //初始化

    04
    for (var i:Number=0; i<=Count; i++) {

    05
    var ball:Ball=new Ball(Math.random()*3,0x00ff00);

    06
    ball.x=Math.random()*stage.stageWidth;

    07
    ball.y=Math.random()*stage.stageHeight;

    08
    ball.vx=ball.vy=0;

    09
    addChild(ball);

    10
    ball.addEventListener(Event.ENTER_FRAME,EnterFrameHandler);

    11
    }

    12

    13
    function EnterFrameHandler(e:Event):void {

    14
    var ball:Ball=e.target as Ball;

    15
    //每一帧让其速度随机变化一点点

    16
    ball.vx += (Math.random()*2-1)*2;

    17
    ball.vy += (Math.random()*2-1)*2;

    18

    19
    ball.x+=ball.vx;

    20
    ball.y+=ball.vy;

    21

    22
    //超出边界后,先让其反向运动一次(即:退回原处),然后速度反向

    23
    if (ball.x>stage.stageWidth-ball.width/2||ball.x<ball.width/2) {

    24
    ball.x-=ball.vx;

    25
    ball.vx*=-1;

    26
    }

    27

    28
    if (ball.y>stage.stageHeight-ball.height/2||ball.y<ball.height/2) {

    29
    ball.y-=ball.vy;

    30
    ball.vy*=-1;

    31
    }

    32

    33
    //加入摩擦力因子,看起来更自然

    34
    ball.vx=ball.vx*0.9;

    35
    ball.vy=ball.vy*0.9;

    36
    }

  • 相关阅读:
    00. 以太坊私有链创世区块
    01. 以太坊部署智能合约
    IDEA 调试技巧
    CI/CD 容器服务准备
    Redis 存储机制及淘汰策略
    02. 最佳实践
    Spring 事务
    百度图片式的瀑布流
    线程
    Vue3+TS如何判断对象类型数组中包含某一个值
  • 原文地址:https://www.cnblogs.com/happysky97/p/1884532.html
Copyright © 2020-2023  润新知