[Stage3D] Starlingで紙吹雪 (4)

Starling Framework を使って、紙吹雪の動きを作ったよ。 :boy:

starling_confetti4

小橋先生 :hakase: に、ドローコールが増えない方法を教えてもらったよ! :cake:
これで、紙吹雪が地面近くでフェードアウトし始めても、ドローコールが 1 増えない! :sun:

:caution: 要 Flash Player 11.8 以上

ConfettiクラスPaperクラスを作ってみたよ。 :bouzu:
紙が回転する動きは、MovieClipクラスTextureクラスTextureAtlasクラスを使ってるよ。 :girl:

Main.as
package {

  import flash.display.Sprite;
  import flash.display.StageScaleMode;
  import flash.display.StageAlign;

  import starling.core.Starling;

  [SWF(backgroundColor="#FFFFFF", width="800", height="600", frameRate="60")]

  public class Main extends Sprite {
    // プロパティ
    private var starling:Starling;

    // コンストラクタ
    public function Main() {
      stage.scaleMode = StageScaleMode.NO_SCALE;
      stage.align = StageAlign.TOP_LEFT;
      init();
    }

    // メソッド
    private function init():void {
      starling = new Starling(MainView, stage, null, null);
      starling.enableErrorChecking = true;
      starling.start();
    }

  }

}



import flash.geom.Rectangle;
import starling.core.Starling;
import starling.display.Sprite;
import starling.display.MovieClip;
import starling.textures.Texture;
import starling.textures.TextureAtlas;
import starling.events.Event;
import starling.events.ResizeEvent;

import starling.effects.Confetti;

internal class MainView extends Sprite {
  [Embed(source="assets/papers.png")]
  private var PapersTexture:Class;
  [Embed(source="assets/papers.xml", mimeType="application/octet-stream")]
  private var PapersAtlas:Class;
  // プロパティ
  private static var bw:uint = 800;
  private static var bh:uint = 600;
  private static var offset:uint = 60;
  private var confetti:Confetti;

  // コンストラクタ
  public function MainView() {
    addEventListener(Event.ADDED_TO_STAGE, init);
    addEventListener(Event.REMOVED_FROM_STAGE, remove);
  }

  // メソッド
  private function init(evt:Event):void {
    removeEventListener(Event.ADDED_TO_STAGE, init);
    var texture:Texture = Texture.fromBitmap(new PapersTexture());
    var atlas:TextureAtlas = new TextureAtlas(texture, XML(new PapersAtlas()));

    confetti = new Confetti(bw, bh, offset, [0.8, 0.6, 0.4], 3);
    addChild(confetti);
    confetti.x = 400;
    confetti.setup(texture, atlas);
    confetti.start();
    stage.addEventListener(ResizeEvent.RESIZE, resize);
  }
  private function remove(evt:Event):void {
    removeEventListener(Event.REMOVED_FROM_STAGE, remove);
    stage.removeEventListener(ResizeEvent.RESIZE, resize);
  }
  override public function dispose():void {
    removeEventListener(Event.ADDED_TO_STAGE, init);
    removeEventListener(Event.REMOVED_FROM_STAGE, remove);
    super.dispose();
  }
  private function resize(evt:ResizeEvent):void {
    var sw:uint = evt.width;
    var sh:uint = evt.height;
    Starling.current.viewPort = new Rectangle(0, 0, sw, sh);
    stage.stageWidth = sw;
    stage.stageHeight = sh;
  }

}

Confetti.as (starling.effects.Confetti.as)
package effects {

  import flash.utils.Timer;
  import flash.events.TimerEvent;

  import starling.display.Sprite;
  import starling.display.MovieClip;
  import starling.textures.Texture;
  import starling.textures.TextureAtlas;

  import org.libspark.betweenas3.BetweenAS3;
  import org.libspark.betweenas3.tweens.ITween;
  import org.libspark.betweenas3.events.TweenEvent;
  import org.libspark.betweenas3.easing.*;

  import starling.effects.Paper;

  public class Confetti extends Sprite {
    // プロパティ
    private var bw:uint = 800;
    private var bh:uint = 600;
    private var offset:uint = 60;
    private var scales:Array = [1];
    private var unit:uint = 2;
    private var timer:Timer;
    private static var interval:Number = 30;
    private static var time:Number = 0.3;
    private static var duration:Number = time*8;
    private var texture:Texture;
    private var atlas:TextureAtlas;
    private static var radian:Number = Math.PI/180;
    private var atlas:TextureAtlas;
    private static var ids:Array;

    // コンストラクタ
    public function Confetti(w:uint, h:uint, o:uint, s:Array, u:uint) {
      bw = w;
      bh = h;
      offset = o;
      if (s) scales = s;
      unit = u;
      init();
    }

    // メソッド
    private function init():void {
      ids = [0, 0, 1, 2, 3, 4, 5, 6, 7, 8];
      timer = new Timer(interval);
      timer.addEventListener(TimerEvent.TIMER, create, false, 0, true);

    }
    public function start():void {
      timer.start();
    }
    public function stop():void {
      if (timer) {
        timer.stop();
        timer.removeEventListener(TimerEvent.TIMER, create);
        timer = null;

      }
    }
    public function setup(t:Texture, ta:TextureAtlas):void {
      texture = t;
      atlas = ta;
    }
    private function create(evt:TimerEvent):void {
      for (var n:uint = 0; n < unit; n++) {
        var id:uint = ids[uint(Math.random()*ids.length)];
        var papers:MovieClip = new MovieClip(atlas.getTextures("paper" + id), 30);
        var scale:Number = scales[uint(Math.random()*scales.length)];
        var paper:Paper = new Paper(scale);
        fall(paper);

        paper.add();
      }
    }
    private function fall(paper:Paper):void {
      var px:Number = (Math.random() - 0.5)*bw;
      var a:Number = Math.random()*360;
      var ta:Number;
      if (Math.random() < 0.5) {
        ta = a - 360;
      } else {
        ta = a + 360;
      }
      paper.x = px;
      paper.y = - 25;
      paper.rotation = a*radian;
      addChild(paper);
      paper.alpha = 0.999;
      var itween:ITween = BetweenAS3.serial(
        BetweenAS3.parallel(
          BetweenAS3.to(paper, {y: bh - 25}, duration, Sine.easeIn),
          BetweenAS3.delay(
            BetweenAS3.to(paper, {alpha: 0}, time, Linear.easeNone),
          time*7),
          BetweenAS3.to(paper, {rotation: ta*radian}, duration, Quad.easeOut)
        ),
        BetweenAS3.func(remove, [paper])
      );
      itween.play();

    }
    private function remove(paper:Paper):void {
      paper.remove();
      removeChild(paper);
      paper = null;
    }
  }

  }

}

Paper.as (starling.effects.Paper.as)
package effects {

  import starling.core.Starling;
  import starling.display.Sprite;
  import starling.display.MovieClip;


  public class Paper extends Sprite {
    // プロパティ
    private var container:Sprite;
    private var content:MovieClip;
    private var scale:Number = 1;

    // コンストラクタ
    public function Paper(mc:MovieClip, s:Number = 1) {
      content = mc;
      scale = s;
      init();
    }

    // メソッド
    private function init():void {
      container = new Sprite();
      addChild(container);
      container.scaleX = container.scaleY = scale;
      content.currentFrame = Math.random()*18;
      container.addChild(content);
      content.pivotX = 10;
      content.pivotY = 10;

    }
    public function add():void {
      Starling.juggler.add(content);
    }
    public function remove():void {
      Starling.juggler.remove(content);
    }

  }

}