[Stage3D] Starlingでページ開き (6)

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

starling_book6

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="#EEEEEE", width="600", height="400", 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;


internal class MainView extends Sprite {
  // プロパティ
  private var book:Sprite3D;
  private var sheet:Sheet3D;
  private var container:Sprite3D;
  private var current:Paper3D;
  private var papers:Array;
  private var id:uint = 0;
  private static var radian:Number = Math.PI/180;
  private var opened:Boolean = false;
  private var angle:Number = 0;
  private var speed:Number = 5;
  private var count:uint = 0;

  // コンストラクタ
  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;

    book = new Sprite3D();
    addChild(book);
    book.x = 300 + 400;
    book.y = 200;
    book.z = 0;

    book.rotationX = - 45*radian;
    sheet = new Sheet3D(Sheet3D.LEFT, "paper");
    book.addChild(sheet);
    sheet.x = - 300;

    container = new Sprite3D();
    book.addChild(container);
    container.x = - 300;

    var paper1:Paper3D = new Paper3D(Paper3D.LEFT, "back1", 0x333399, "front1", 0x3399CC);
    container.addChild(paper1);
    paper1.update();
    var paper2:Paper3D = new Paper3D(Paper3D.LEFT, "back2", 0x669900, "front2", 0x99CC00);
    paper1.contain(paper2);
    paper2.update();
    var paper3:Paper3D = new Paper3D(Paper3D.LEFT, "back3", 0xFF9900, "front3", 0xFFCC00);
    paper2.contain(paper3);
    paper3.update();
    var paper4:Paper3D = new Paper3D(Paper3D.LEFT, "back4", 0xCC0066, "front4", 0xFF6699);
    paper3.contain(paper4);
    paper4.update();
    papers = [paper1, paper2, paper3, paper4];
    addEventListener(TouchEvent.TOUCH, touch);
  }
  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 touch(evt:TouchEvent):void {
    var touch:Touch = evt.getTouch(book);
    if (touch) {
      switch (touch.phase) {
        case TouchPhase.BEGAN :
          start();
          break;
      }
    }
  }
  private function start():void {
    if (!opened) {
      open();
    } else {
      close();
    }
  }
  private function open():void {
    current = papers[id];
    addEventListener(EnterFrameEvent.ENTER_FRAME, update);
  }
  private function update(evt:EnterFrameEvent):void {
    if (angle < 180) {
      angle += speed;
      current.rotationY = - angle*radian;
      count ++;
    } else {
      if (id < 3) {
        angle = 0;
        id ++;
        current = papers[id];
      } else {
        opened = true;
        removeEventListener(Event.ENTER_FRAME, update);
      }
    }
    for (var n:uint = 0; n < 4; n++) {
      var paper:Paper3D = papers[n];
      paper.update();
    }
    var percent:Number = count/144;
    book.x = 300 + 400*(1 - percent);
    book.z = 500*percent;

  }
  private function close():void {
    opened = false;
    angle = 0;
    id = 0;
    for (var n:uint = 0; n < 4; n++) {
      var paper:Paper3D = papers[n];
      paper.rotationY = 0;
      paper.update();
      paper.hide();
    }
    count = 0;
    book.x = 300 + 400;
    book.y = 200;
    book.z = 0;
  }

}


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

internal class Paper3D extends Sprite3D {
  // プロパティ
  private var back:Sheet3D;
  private var backtxt:String = "";
  private var backcolor:uint = 0x333333;
  private var front:Sheet3D;
  private var fronttxt:String = "";
  private var frontcolor:uint = 0x999999;
  private var side:String = LEFT;
  private var child:Sprite3D;
  public static const LEFT:String = "left";
  public static const RIGHT:String = "right";
  private var position:Vector3D = new Vector3D();
  private static var radian:Number = Math.PI/180;

  // コンストラクタ
  public function Paper3D(s:String = LEFT, bt:String = "", bc:uint = 0x333333, ft:String = "", fc:uint = 0x999999) {
    side = s;
    backtxt = bt;
    backcolor = bc;
    fronttxt = ft;
    frontcolor = fc;
    init();
  }

  // メソッド
  private function init():void {
    var reverse:String;
    switch (side) {
      case LEFT :
        reverse = RIGHT;
        break;
      case RIGHT :
        reverse = LEFT;
        break;
    }
    back = new Sheet3D(side, backtxt, backcolor);
    addChild(back);

    front = new Sheet3D(reverse, fronttxt, frontcolor);
    addChild(front);

    front.rotationY = 180*radian;
    child = new Sprite3D();
    addChild(child);
    child.x = - 200;

    child.rotationY = 180*radian;
    hide();
  }
  public function contain(sprite:Sprite3D):void {
    child.addChild(sprite);
  }
  public function show():void {
    child.visible = true;
    //addChild(child);
  }
  public function hide():void {
    child.visible = false;
    //addChildAt(child, 0);
  }
  public function update():void {
    stage.getCameraPosition(this, position);
    var direction:Boolean = position.z < 0;
    front.visible = !direction;
    back.visible = direction;
    if (!direction) {
      show();
    } else {
      hide();
    }
  }

}


import starling.display.Sprite3D;
import starling.display.Quad;

import starling.controls.Label;

internal class Sheet3D extends Sprite3D {
  // プロパティ
  private static var bw:uint = 200;
  private static var bh:uint = 250;
  private var txt:String = "";
  private var color:uint = 0x666666;
  private var quad:Quad;
  private var label:Label;
  private var side:String = LEFT;
  public static const LEFT:String = "left";
  public static const RIGHT:String = "right";

  // コンストラクタ
  public function Sheet3D(s:String = LEFT, t:String = "", c:uint = 0x666666) {
    side = s;
    txt = t;
    color = c;
    init();
  }

  // メソッド
  private function init():void {
    quad = new Quad(bw, bh, color);
    addChild(quad);
    label = new Label(bw, 40, 40, Label.CENTER);
    addChild(label);
    label.textColor = 0xFFFFFF;
    label.text = txt;
    switch (side) {
      case LEFT :
        quad.pivotX = bw;
        quad.pivotY = bh/2;
        label.pivotX = bw;
        label.pivotY = 24;
        break;
      case RIGHT :
        quad.pivotX = 0;
        quad.pivotY = bh/2;
        label.pivotX = 0;
        label.pivotY = 24;
        break;
    }
  }

}