forked from: forked from: [Pv3D] Meteor Attack

by smallflowergame forked from forked from: [Pv3D] Meteor Attack (diff: 189)
クリックしたところに隕石が降ってきて、クレーターができます。
お月さんかわいそうです(´;ω;`) 
もっと爆発した感じがだせるといいね。
Loaderめんどい・・・

追記
裏側だとクレーター見えないって言われたので改造。
クレーターにはPhongShaderのバンプマッピング使ってたため、
ライトが当たらないといけないのでライトも動かしてみた。
♥0 | Line 286 | Modified 2010-08-11 19:03:10 | MIT License | (replaced)
play

ActionScript3 source code

/**
 * Copyright smallflowergame ( http://wonderfl.net/user/smallflowergame )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/wT5R
 */

// forked from uwi's forked from: [Pv3D] Meteor Attack
// forked from aaharu's [Pv3D] Meteor Attack
/*
クリックしたところに隕石が降ってきて、クレーターができます。
お月さんかわいそうです(´;ω;`) 
もっと爆発した感じがだせるといいね。
Loaderめんどい・・・

追記
裏側だとクレーター見えないって言われたので改造。
クレーターにはPhongShaderのバンプマッピング使ってたため、
ライトが当たらないといけないのでライトも動かしてみた。
*/
package {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Shape;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Matrix;
    import flash.net.URLRequest;
    import org.libspark.betweenas3.BetweenAS3;
    import org.libspark.betweenas3.tweens.ITween;
    import org.papervision3d.events.InteractiveScene3DEvent;
    import org.papervision3d.lights.PointLight3D;
    import org.papervision3d.materials.BitmapMaterial;
    import org.papervision3d.materials.ColorMaterial;
    import org.papervision3d.materials.shaders.PhongShader;
    import org.papervision3d.materials.shaders.ShadedMaterial;
    import org.papervision3d.materials.special.ParticleMaterial;
    import org.papervision3d.objects.primitives.Sphere;
    import org.papervision3d.objects.special.ParticleField;
    import org.papervision3d.view.BasicView;
    import net.wonderfl.utils.SequentialLoader;
    import net.hires.debug.*;
    import org.papervision3d.core.math.*;
    import org.papervision3d.materials.shadematerials.*;
    
    [SWF(backgroundColor=0x000000)]
    public class Meteor extends BasicView {
        private var shader:PhongShader;
        private var light:PointLight3D = new PointLight3D();
        private var bumpBmpData:BitmapData;
        private var moonBmpData:BitmapData;
        private var mouseDownX:Number = 0;
        private var distanceX:Number = 0;
        private var radianX:Number = 0;
        private var rot:Number = 0;
        
        private var imageArray:Array = [];
        /**
         * constructor
         */
        public function Meteor() {
            super(0, 0, true, true);
//            camera.focus = 15;
//            stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
            
            SequentialLoader.loadImages(["http://assets.wonderfl.net/images/related_images/7/75/756d/756d4e45c50bca7ae7647c47568d8553aebd93a4", "http://assets.wonderfl.net/images/related_images/e/e9/e978/e978b55099c8d056d15861de179ca591eb5c157b"], imageArray, onMapComplete);
            //var loader:Loader = new Loader();
            //loader.load(new URLRequest("http://aaharuapp.appspot.com/data/changeBump/moonbump1k.jpg"));
            //loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onBumpComplete);
            addChild(new Stats());
            
        }
        
        /*
        private function onMouseDown(e:MouseEvent):void {
            mouseDownX = mouseX;
            stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
            stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
        }
        
        private function onMouseMove(e:MouseEvent):void {
            distanceX = mouseX - mouseDownX;
            radianX += distanceX / 180 * Math.PI;
            mouseDownX = mouseX;
        }
        
        private function onMouseUp(e:MouseEvent):void {
            stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
            stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
        }
        */
        
        /*private function onBumpComplete(e:Event):void {
            var bmpData:BitmapData = new BitmapData(e.target.loader.width, e.target.loader.height);
            bmpData.draw(e.target.loader);
            bumpBmpData = bmpData;
            
            var loader:Loader = new Loader();
            loader.load(new URLRequest("http://aaharuapp.appspot.com/data/changeBump/moonmap1k.jpg"));
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onMapComplete);
        }*/
        
        //private function onMapComplete(e:Event):void {
        private function onMapComplete():void {
            //var bmpData:BitmapData = new BitmapData(e.target.loader.width, e.target.loader.height);
            var loader1:Loader = imageArray.pop();
            var bmpData:BitmapData = new BitmapData(loader1.width, loader1.height);
            bmpData.draw(loader1);
            moonBmpData = bmpData;
            var loader2:Loader = imageArray.pop();
            bmpData = new BitmapData(loader2.width, loader2.height);
            bmpData.draw(loader2);
            bumpBmpData = bmpData;
            scene.addChild(light);
            
            shader = new PhongShader(light, 0xFFFFFF, 0x666666, 0, bumpBmpData);
            var material:ShadedMaterial = new ShadedMaterial(new BitmapMaterial(moonBmpData), shader);
            material.interactive = true;
            material.smooth = true;
            var sphere:Sphere = new Sphere(material, 100, 15, 15);
            sphere.addEventListener(InteractiveScene3DEvent.OBJECT_CLICK, onObjectClick);
            scene.addChild(sphere);
            
            var particles:ParticleField = new ParticleField(new ParticleMaterial(0xffffff, 1, 1), 200, 2, 500, 500, 500);
            scene.addChild(particles);
            
            _camera = new OperableSphereCamera(
                new Number3D(0, 0, 0),
                250,
                new Number3D(0, 0, 1),
                new Number3D(0, 1, 0),
                stage,
                0.01,
                0.01
            );
            startRendering();
        }
        
        private function onObjectClick(e:InteractiveScene3DEvent):void {
            var fsm : PhongMaterial = new PhongMaterial(light, 0x993333, 0, 0);
            var ball:Sphere = new Sphere(fsm, 10, 8, 8);
            scene.addChild(ball);
            var tween:ITween = BetweenAS3.tween(ball, {x: e.renderHitData.x * 0.9, y: e.renderHitData.y * 0.9, z: e.renderHitData.z * 0.9}, {x: e.renderHitData.x * 3.5, y: e.renderHitData.y * 3.5, z: e.renderHitData.z * 3.5});
            tween.play();
            tween.onComplete = function():void {
                ball.material = new ColorMaterial(0xffff99);
                var t2:ITween = BetweenAS3.parallel(
                    BetweenAS3.to(ball, {scaleX : 4.0, scaleY : 4.0, scaleZ : 4.0}),
                    BetweenAS3.to(ball.material, {fillAlpha : 0.0})
                    );
                t2.play();
                t2.onComplete = function():void {
                    scene.removeChild(ball);
                };
                fsm.destroy();
//                scene.removeChild(ball);
                var sp:Shape = new Shape();
                sp.graphics.beginFill(0xFFFFFF);
                sp.graphics.drawCircle(25, 25, 20);
                sp.graphics.endFill();
                sp.graphics.beginFill(0x000000);
                sp.graphics.drawCircle(25, 25, 17);
                sp.graphics.endFill();
                var bmpData:BitmapData = new BitmapData(50, 50, true, 0x00000000);
                bmpData.draw(sp);
                bumpBmpData.draw(bmpData, new Matrix(1, 0, 0, 1, e.x * 1000 - 25, e.y * 500 - 25));
                shader.bumpmap = bumpBmpData;
            }
        }
        
        override protected function onRenderTick(event:Event=null):void {
            /*
            rot += (radianX - rot) * 0.3;
            camera.x = light.x = 400 * Math.sin(rot);
            camera.z = light.z = 400 * Math.cos(rot);
            */
            super.onRenderTick(event);
        }
    }
}

import org.papervision3d.objects.*;
import org.papervision3d.core.math.*;

class PV3DUtils
{
    public static function rotate(x : Number3D, axis : Number3D, angle : Number) : Number3D
    {
        var nCos:Number    = Math.cos(angle);
        var nSin:Number    = Math.sin(angle);
        var scos:Number    = 1 - nCos;

        var sxy    :Number = axis.x * axis.y * scos;
        var syz    :Number = axis.y * axis.z * scos;
        var sxz    :Number = axis.x * axis.z * scos;
        var sz    :Number = nSin * axis.z;
        var sy    :Number = nSin * axis.y;
        var sx    :Number = nSin * axis.x;

        var nx : Number = (nCos + axis.x * axis.x * scos) * x.x + (-sz + sxy) * x.y + (sy + sxz) * x.z;
        var ny : Number = (sz + sxy) * x.x + (nCos + axis.y * axis.y * scos) * x.y + (-sx + syz) * x.z;
        var nz : Number = (-sy + sxz) * x.x + (sx + syz) * x.y + (nCos + axis.z * axis.z * scos) * x.z;

        x.x = nx; x.y = ny; x.z = nz;
        return x;
    }
    
    public static function rotateMulti(xs : Array, axis : Number3D, angle : Number) : void
    {
        var nCos:Number    = Math.cos(angle);
        var nSin:Number    = Math.sin(angle);
        var scos:Number    = 1 - nCos;

        var sxy    :Number = axis.x * axis.y * scos;
        var syz    :Number = axis.y * axis.z * scos;
        var sxz    :Number = axis.x * axis.z * scos;
        var sz    :Number = nSin * axis.z;
        var sy    :Number = nSin * axis.y;
        var sx    :Number = nSin * axis.x;

        for each(var x : Number3D in xs){
            var nx : Number = (nCos + axis.x * axis.x * scos) * x.x + (-sz + sxy) * x.y + (sy + sxz) * x.z;
            var ny : Number = (sz + sxy) * x.x + (nCos + axis.y * axis.y * scos) * x.y + (-sx + syz) * x.z;
            var nz : Number = (-sy + sxz) * x.x + (sx + syz) * x.y + (nCos + axis.z * axis.z * scos) * x.z;
            x.x = nx; x.y = ny; x.z = nz;
        }
    }
    
    public static function setLookAt(d : DisplayObject3D, front : Number3D, up : Number3D) : void
    {
        var X : Number3D = Number3D.cross(front, up);
        var look : Matrix3D = d.transform;
        look.n11 = X.x; look.n21 = X.y; look.n31 = X.z;
        look.n12 = -up.x; look.n22 = -up.y; look.n32 = -up.z;
        look.n13 = front.x; look.n23 = front.y; look.n33 = front.z;
    }    
}

import org.papervision3d.cameras.*;

class QCamera3D extends Camera3D
{
    public var _up : Number3D; // カメラの上の向きの単位ベクトル
    protected var _front : Number3D;
    private var _prevDir : Number3D;
    
    public function QCamera3D(up : Number3D, front : Number3D= null)
    {
        super();
        _up = null;
        init(up, front);
    }
    
    // prevDirからcurDirへ向ける回転を_upにかけるだけ。カメラ自体に操作はしない
    public function rotate(curDir : Number3D) : void
    {
        if(_prevDir != null){
            var n : Number3D = Number3D.cross(curDir, _prevDir);
//            if(n.moduloSquared > 0.00000001){
            if(n.moduloSquared != 0){
                n.normalize();
                var angle : Number = Math.acos(Number3D.dot(_prevDir, curDir));
                if(_front != null){
                        PV3DUtils.rotate(_front, n, angle);
                }
                   PV3DUtils.rotate(_up, n, angle);
            }
        }
        _prevDir = curDir.clone();
    }
    
    // カメラを_frontのほうへ向ける
    public function head() : void
    {
        if(_front != null){
                var Z : Number3D = _front.clone();
            Z.normalize();
            var X : Number3D = Number3D.cross(Z, _up);
            X.normalize();
            var Y : Number3D = Number3D.cross(Z, X);
            Y.normalize();

            var look : Matrix3D = this.transform;
            look.n11 = X.x*this.scaleX; look.n21 = X.y*this.scaleY; look.n31 = X.z*this.scaleZ;
            look.n12 = -Y.x*this.scaleX; look.n22 = -Y.y*this.scaleY; look.n32 = -Y.z*this.scaleZ;
            look.n13 = Z.x*this.scaleX; look.n23 = Z.y*this.scaleY; look.n33 = Z.z*this.scaleZ;
        }
    }
    
    public function init(up : Number3D = null, front : Number3D = null) : void
    {
        if(up != null){
            _up = up.clone();
            _up.normalize();
        }
        if(front != null){
            _front = front.clone();
            _front.normalize();
        }else{
            _front = null;
        }
        _prevDir = null;
    }
}

// 球面上を動き、球の中心を見るカメラ
class SphereCamera extends QCamera3D
{
    private var _O : Number3D; // 球の中心
    private var _R : Number; // 球の半径
    
    // O : 中心座標
    // R : 半径
    // front : カメラ正面の向きを表す単位ベクトル
    // up : カメラ上の向きを表す単位ベクトル
    public function SphereCamera(O : Number3D, R : Number, front : Number3D, up : Number3D) : void
    {
        super(up, front);
        _O = O;
        _R = R;
        move();
    }
    
    public function move(x : Number = 0, y : Number = 0) : void
    {
        if(x != 0 || y != 0){
        var X : Number3D = Number3D.cross(_up, _front);
        var axis : Number3D = new Number3D(X.x * -y + _up.x * x, X.y * -y + _up.y * x, X.z * -y + _up.z * x);
        var angle : Number = axis.modulo;
        axis.normalize();
        PV3DUtils.rotate(_front, axis, angle);
        PV3DUtils.rotate(_up, axis, angle);
        this.x = _front.x * -_R + _O.x;
        this.y = _front.y * -_R + _O.y;
        this.z = _front.z * -_R + _O.z;
        head();
        }
    }

}

import flash.display.*;
import flash.events.*;

class OperableSphereCamera extends SphereCamera
{
    private var _dx : Number;
    private var _dy : Number;
    private var _stage : DisplayObject;
    private var _prevX : Number = -1;
    private var _prevY : Number = -1;
    private var _down : Boolean = false;

    // O : 中心座標
    // R : 半径
    // front : カメラ正面の向きを表す単位ベクトル
    // up : カメラ上の向きを表す単位ベクトル
    // stage : マウスイベントをlistenするDisplayObject
    // dx : カメラ横への移動角度単位
    // dy : カメラ上への移動角度単位
    public function OperableSphereCamera(O : Number3D, R : Number, front : Number3D, up : Number3D, stage : DisplayObject, dx : Number, dy : Number) : void
    {
      super(O, R, front, up);
      _dx = dx;
      _dy = dy;
      _stage = stage;
      addCallback();
      move(0, 0.001);
    }
    
    public function addCallback() : void
    {
      _stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
      _stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
      _stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
    }
    
    public function removeCallback() : void
    {
      _stage.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
      _stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
      _stage.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
    }
    
    private function onMouseDown(e : MouseEvent) : void { _down = true; }
    private function onMouseUp(e : MouseEvent) : void { _down = false; }
    
    public function onEnterFrame(e : Event = null) : void
    {
      if(_down){
        if(_prevX != -1){
          this.move((_stage.mouseX - _prevX) * _dx, (_stage.mouseY - _prevY) * _dy);
        }
        _prevX = _stage.mouseX;
        _prevY = _stage.mouseY;
      }else{
        _prevX = -1;
        _prevY = -1;
      }
    }
}