F-siteで書籍いただきました記念 Hello World
5/30 F-siteセミナー にて
著者池田さま提供の『Flash3Dコンテンツ制作のためのPapervision3D入門』を
いただいたので、記念 Hello World。
/**
* Copyright yprops ( http://wonderfl.net/user/yprops )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/gH7B
*/
/*
5/30 F-siteセミナー にて
著者池田さま提供の『Flash3Dコンテンツ制作のためのPapervision3D入門』を
いただいたので、記念 Hello World。
*/
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.system.Security;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.easing.Back;
import org.libspark.betweenas3.easing.Elastic;
import org.papervision3d.core.math.Number3D;
import org.papervision3d.materials.BitmapFileMaterial;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.objects.primitives.Cube;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.view.BasicView;
public class Main extends Sprite
{
//consts----------------------
//カラー玉について
private static const BREAKCOUNT :uint = 6;
private static const BREAKRADIUS :Number = 300;
//props-----------------------
private var i :int;
private var view :BasicView;
private var cctrl :CamCtrl;
private var obi :ObjInfo;
private var obis :Vector.<ObjInfo>;
private var bfmtr :BitmapFileMaterial;
/// フロー記憶用
private var st :StepStack;
//initialize------------------
/// constractor
public function Main():void
{
//ビュー生成
view = new BasicView(1, 1, true, true);
view.opaqueBackground = true;
view.startRendering();
cctrl = new CamCtrl(view.cameraAsCamera3D, this);
addChildAt(view, 0);
//画像ロード
Security.loadPolicyFile("http://assets.wonderfl.net/crossdomain.xml");
BitmapFileMaterial.callback = beginFlow; //ロード終了時起動メソッド
bfmtr = new BitmapFileMaterial("http://assets.wonderfl.net/images/related_images/b/be/be9f/be9fae98834082473186ef205ca8aef91c8174fc", true);
bfmtr.doubleSided = false;
}
//flow methods-----------------
/// メインフロー構築、実行
private function beginFlow() :void {
obis = new Vector.<ObjInfo>();
st = new StepStack();
st.push(null, null, null, null, 500);
st.push(popFrameBall, null, Event.COMPLETE, this);
st.push(popColorBall, null, Event.COMPLETE, this);
st.push(stirAll, null, Event.COMPLETE, this);
st.push(popLastCube, null, Event.COMPLETE, this);
st.run();
}
/// 最初の玉を出して引っ込めるまで
private function popFrameBall() :void {
obi = new ObjInfo(new Sphere());
obi.st = new StepStack();
obi.st.push(view.scene.addChild, obi.obj);
obi.st.push(
obi.setTween,
BetweenAS3.tween(obi.obj, { scale :1.0 }, { scale :0.0 }, 1.5, Elastic.easeOut),
null, null, 1500
);
obi.st.push(
obi.setTween,
BetweenAS3.tween(obi.obj, { scale :0.1 }, { scale :1.0 }, 0.50, Back.easeIn),
null, null, 600
);
obi.st.push(view.scene.removeChild, obi.obj);
obi.st.push(dispatchEvent, new Event(Event.COMPLETE));
obi.st.run();
}
/// カラー玉出現
private function popColorBall() :void {
var rad :Number;
var pt :Number3D;
for (i = 0; i < Main.BREAKCOUNT; i++){
rad = Math.PI * 2 * i / Main.BREAKCOUNT;
pt = new Number3D(
Math.sin(rad) * Main.BREAKRADIUS,
0,
Math.cos(rad) * Main.BREAKRADIUS
);
obi = new ObjInfo(new Sphere(new ColorMaterial(getRndCol())));
obis.push(obi);
obi.st = new StepStack();
obi.st.push(view.scene.addChild, obi.obj);
obi.st.push(
obi.setTween,
BetweenAS3.parallel(
BetweenAS3.tween(obi.obj, { scale :1.0 }, { scale :0.0 }, 1.0, Elastic.easeOut),
BetweenAS3.tween(obi.obj, { x :pt.x, z :pt.z }, null, 0.5, Back.easeOut)
),
null, null, 1000
);
}
obis[obis.length - 1].st.push(dispatchEvent, new Event(Event.COMPLETE));
for each(obi in obis) obi.st.run();
}
/// かき混ぜてカラー玉引っ込む
private function stirAll() :void {
cctrl.beginStir();
for (i = 0; i < obis.length; i++) {
obi = obis[i];
obi.st = new StepStack();
obi.st.push(
obi.setTween,
BetweenAS3.parallel(
BetweenAS3.tween(obi.obj, { scale :0.0 }, null, 2.0, Back.easeIn),
BetweenAS3.tween(obi.obj, { x :0, z :0 }, null, 2.0, Elastic.easeIn)
),
null, null, 2000
);
obi.st.push(view.scene.removeChild, obi.obj);
}
obi.st.push(dispatchEvent, new Event(Event.COMPLETE));
for each(obi in obis) obi.st.run();
}
/// 最後のキューブ出す
private function popLastCube() :void {
obi = null;
obis = null;
cctrl.endStir();
obi = new ObjInfo(new Cube(new MaterialsList({all :bfmtr})));
obi.st = new StepStack();
obi.st.push(view.scene.addChild, obi.obj);
obi.st.push(
obi.setTween,
BetweenAS3.tween(obi.obj, { scale :1.0 }, { scale :0.0 }, 1.0, Elastic.easeOut),
null, null, 700
);
obi.st.run();
}
//tool methods-----------------------------------
/// 適当に色を返す
private function getRndCol() :uint {
var ptn :uint = Math.random() * 8;
var col :uint = ((ptn & 4)? 0xFF0000 : 0) + ((ptn & 2)? 0xFF00 : 0) + ((ptn & 1)? 0xFF : 0);
return (col == 0)? 0x333333 : col;
}
}
}
import flash.display.DisplayObject;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
import flash.events.TimerEvent;
import flash.utils.Timer;
import org.libspark.betweenas3.tweens.ITween;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.objects.DisplayObject3D;
/// 3Dオブジェクトと情報を含むコンテナ
class ObjInfo {
public var obj :DisplayObject3D;
public var st :StepStack;
public var tween :ITween;
public function ObjInfo(obj :DisplayObject3D) :void {
this.obj = obj;
}
public function setTween(tw :ITween) :void {
if (tween && tween.isPlaying) tween.stop();
tween = tw;
tween.play();
}
}
/// カメラ制御用
class CamCtrl {
private const PIH :Number = Math.PI / 2;
private const PI2 :Number = Math.PI * 2;
private var cam :Camera3D;
private var main :DisplayObject;
private var pitch :Number;
private var yaw :Number;
private var pitchSp :Number;
private var yawSp :Number;
private var stirPhase :uint;
public function CamCtrl(cam :Camera3D, main :DisplayObject) {
this.cam = cam;
this.main = main;
pitch = Math.PI * 0.4;
pitchSp = 0.005;
yaw = Math.random() * PI2;
yawSp = 0.01;
stirPhase = 0;
main.addEventListener(Event.ENTER_FRAME, update);
}
public function beginStir() :void {
stirPhase = 1;
}
public function endStir() :void {
stirPhase = 2;
}
public function endUpdate() :void {
main.removeEventListener(Event.ENTER_FRAME, update);
}
private function update(ev:Event) :void {
switch(stirPhase) {
//case 0:
case 1:
yawSp += 0.004;
break;
case 2:
yawSp -= 0.003;
if (yawSp <= 0.01) {
yawSp = 0.01;
pitchSp = 0;
stirPhase++;
}
break;
//case 3:
}
pitch = (pitch + pitchSp + PI2) % PI2;
yaw = (yaw + yawSp + PI2) % PI2;
cam.orbit(pitch, yaw, false);
}
}
//以下、フロー制御用------------------------------------------------
class StepStack extends EventDispatcher{
private var head :uint;
private var steps :Vector.<Step>;
private var crr :Step;
public function StepStack(){
this.steps = new Vector.<Step>();
}
public function get isRunning() :Boolean{ return (crr != null) }
public function get length() :uint { return steps.length;}
public function push(
fnc :Function = null, args :* = null,
completeEvent :String = null, completeEventDispatcher :IEventDispatcher = null,
postwait :uint = 0
) :void {
var ar :Array = (args is Array)? args : (args != null)? [args] : null;
steps.push(new Step(fnc,ar,completeEvent,completeEventDispatcher,postwait));
}
public function run() :void {
if (!steps) return;
head = 0;
next();
}
private function next(ev:Event = null) :void {
if (ev && ev.target && ev.target is Step) {
crr = ev.target as Step;
crr.removeEventListener(Event.COMPLETE, next);
}
if (head < steps.length) {
crr = steps[head];
head++;
crr.addEventListener(Event.COMPLETE, next);
crr.run();
}else {
crr = null;
dispatchEvent(new Event(Event.COMPLETE));
}
}
}
class Step extends EventDispatcher
{
private var method :Function;
private var args :Array;
private var cmpEvStr :String;
private var cmpEvDpt :IEventDispatcher;
private var ms :uint;
private var wt :Timer;
private var running :Boolean;
public function Step(
method :Function = null,
args :Array = null,
cmpEvStr :String = null,
cmpEvDpt :IEventDispatcher = null,
ms :uint = 0
)
{
this.method = method;
this.args = args;
this.cmpEvStr = cmpEvStr;
this.cmpEvDpt = cmpEvDpt;
this.ms = ms;
this.running = false;
}
internal function hasFin() :Boolean { return cmpEvDpt && cmpEvStr; }
internal function run() :void {
if (hasFin()) {
cmpEvDpt.addEventListener(cmpEvStr, fin);
}
running = true;
if(method != null) method.apply(null, args);
if (!hasFin()) fin(null);
}
private function fin(ev:Event) :void {
if (ms > 0 ) {
if (wt is StepTimer) {
removeListeners();
wt.removeEventListener(TimerEvent.TIMER_COMPLETE, fin);
}else {
wt = new StepTimer(ms);
wt.addEventListener(TimerEvent.TIMER_COMPLETE, fin);
wt.start();
return;
}
}else {
removeListeners();
}
running = false;
dispatchEvent(new Event(Event.COMPLETE));
}
private function removeListeners() :void {
if (hasFin()) cmpEvDpt.removeEventListener(cmpEvStr, fin);
}
}
class StepTimer extends Timer{
function StepTimer(delay:Number) :void {
super(delay, 1);
}
}