[Stage3D] Starlingで3D回転メニュー

Flash Player 11 から採用された Stage3D を学習するよ。 :bouzu:
Starling Framework を試しちゃうんだからね。 :girl:

starling_platemenu

Starling1.6から追加されたSprite3Dクラスで、回転メニューをやってみちゃうよ。 :boy:

:caution: 要 Flash Player 11.8 以上

This movie requires Flash Player 11.8.0

Main.as
package {

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

  import starling.core.Starling;

  [SWF(backgroundColor="#FFFFFF", width="600", height="480", 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 starling.core.Starling;
import starling.display.Sprite;
import starling.display.Sprite3D;
import starling.events.Event;
import starling.events.EnterFrameEvent;
import starling.events.Touch;
import starling.events.TouchEvent;
import starling.events.TouchPhase;

import a24.tween.Tween24;
import a24.tween.events.Tween24Event;


internal class MainView extends Sprite {
  // プロパティ
  private var container:Sprite3D;
  private var plates:Array;
  private static var max:uint = 5;
  private static var radian:Number = Math.PI/180;
  private var angle:Number = 0;
  private static var speed:Number = 0.5;

  // コンストラクタ
  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);
    stage.fieldOfView = 60*radian;
    stage.focalLength = 500;

    container = new Sprite3D();
    addChild(container);
    container.x = 300;
    container.y = 240;
    container.z = 750;

    var colors:Array = [0xF5F5F5, 0x3366CC, 0x339900, 0xFF9900, 0xCC0066];
    var tcolors:Array = [0x333333, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF];
    plates = [];
    for (var n:uint = 0; n < max; n++) {
      var plate:DoubleSidedPlate3D = new DoubleSidedPlate3D(colors[n], tcolors[n]);
      container.addChild(plate);

      plate.id = n;
      plate.x = 0;
      plate.y = - 140*(n - 2);
      plate.z = 0;
      plate.addEventListener(TouchEvent.TOUCH, touch);
      plates.push(plate);
    }
    addEventListener(EnterFrameEvent.ENTER_FRAME, update);
  }
  private function remove(evt:Event):void {
    removeEventListener(Event.REMOVED_FROM_STAGE, remove);
  }
  override public function dispose():void {
    removeEventListener(Event.ADDED_TO_STAGE, init);
    removeEventListener(Event.REMOVED_FROM_STAGE, remove);
    super.dispose();
  }
  private function update(evt:EnterFrameEvent):void {
    angle += speed;
    container.rotationY = angle*radian;
    for (var n:uint = 0; n < max; n++) {
      var plate:DoubleSidedPlate3D = plates[n];
      plate.update();
    }
  }
  private function touch(evt:TouchEvent):void {
    var plate:DoubleSidedPlate3D = DoubleSidedPlate3D(evt.target);
    var touch:Touch = evt.getTouch(plate);
    if (touch) {
      switch (touch.phase) {
        case TouchPhase.BEGAN :
          transit(plate.id);
          break;
      }
    }
  }
  private function transit(id:uint):void {
    enable(false);
    var fadeouts:Array = new Array();
    var fadeins:Array = new Array();
    var offset:int = 2 - Math.abs(2 - id);
    for (var n:uint = 0; n < max; n++) {
      var direction:int = (n == id) ? 0 : (n < id) ? 1 : - 1;
      var plate:DoubleSidedPlate3D = plates[n];
      var fadeout:Tween24 = Tween24.parallel(
        Tween24.tween(plate, 1, Tween24.ease.QuadIn).$$y(120*direction),
        Tween24.tween(plate, 1, Tween24.ease.QuadIn).rotationY(180*radian),
        Tween24.tween(plate, 0.4, Tween24.ease.Linear).fadeOut().delay(0.6)
      ).delay(0.2*(4 - Math.abs(n - id) - offset));

      fadeouts.push(fadeout);
      var fadein:Tween24 = Tween24.parallel(
        Tween24.tween(plate, 0.4, Tween24.ease.Linear).fadeIn(),
        Tween24.tween(plate, 1, Tween24.ease.QuadOut).$y(0),
        Tween24.prop(plate).rotationY(-180*radian),
        Tween24.tween(plate, 1, Tween24.ease.QuadOut).rotationY(0)
      ).delay(0.2*Math.abs(n - id));

      fadeins.push(fadein);
    }
    var atween:Tween24 = Tween24.serial(
      Tween24.parallel(fadeouts),
      Tween24.wait(0.4),
      Tween24.parallel(fadeins)
    );
    atween.addEventListener(Tween24Event.COMPLETE, complete, false, 0, true);
    atween.play();

  }
  private function complete(evt:Tween24Event):void {
    evt.target.removeEventListener(Tween24Event.COMPLETE, complete);
    enable(true);
  }
  private function enable(value:Boolean):void {
    for (var n:uint = 0; n < max; n++) {
      var plate:DoubleSidedPlate3D = plates[n];
      plate.touchable = value;
    }
  }

}


import flash.geom.Vector3D;
import starling.display.Sprite3D;
import starling.display.Quad;

import starling.controls.Label;

internal class DoubleSidedPlate3D extends Sprite3D {
  // プロパティ
  public var id:uint;
  private static var bw:uint = 320;
  private static var bh:uint = 120;
  private var color:uint = 0xFFFFFF;
  private var tcolor:uint = 0x000000;
  private var back:Sprite3D;
  private var front:Sprite3D;
  private var position:Vector3D = new Vector3D();

  // コンストラクタ
  public function DoubleSidedPlate3D(c:uint = 0xFFFFFF, tc:uint = 0x000000) {
    color = c;
    tcolor = tc;
    init();
  }

  // メソッド
  private function init():void {
    back = new Sprite3D();
    addChild(back);

    var bquad:Quad = new Quad(bw, bh, color);
    back.addChild(bquad);

    front = new Sprite3D();
    addChild(front);

    var fquad:Quad = new Quad(bw, bh, color);
    front.addChild(fquad);

    var label:Label = new Label(bw, 60, 48, Label.CENTER);
    front.addChild(label);

    label.textColor = tcolor;
    label.text = "Starling";
    label.y = 36;
    pivotX = bw/2;
    pivotY = bh/2;

    touchGroup = true;
  }
  public function update():void {
    stage.getCameraPosition(this, position);
    var direction:Boolean = position.z < 0;
    front.visible = direction;
    back.visible = !direction;
  }

}