In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Stage3D FireBall

書籍「Stage3Dプログラミング」を参考に作成
クリックするとFireBall !!
Get Adobe Flash player
by matsu4512 05 Sep 2012
/**
 * Copyright matsu4512 ( http://wonderfl.net/user/matsu4512 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/7dMR
 */

package {

    import com.adobe.utils.AGALMiniAssembler;

    import flash.display.*;

    import flash.display3D.*;

    import flash.display3D.textures.*;

    import flash.events.*;

    import flash.geom.*;

    import flash.net.URLRequest;

    

    [SWF(width="500", height="500", frameRate="60")]

    public class Stage3D_10 extends Sprite {

        

        private var ctx:Context3D;

        private var WIDTH:Number = 500;

        private var HEIGHT:Number = 500;

        

        private var vertexParticle:VertexBuffer3D;

        private var indexParticle:IndexBuffer3D;

        private var textureParticle:Texture;

        private var transformVec:Vector.<Number>;

        private var colorVec:Vector.<Number>;

        private var particles:Vector.<Particle>=new Vector.<Particle>();

        private var balls:Vector.<FireBall> = new Vector.<FireBall>();

        

        // 頂点シェーダ

        private const VERTEX_SHADER:String =

            "mov vt0, va0 \n"+                

            "mul vt0.xy, vt0, vc4.ww \n"+    //サイズを乗算して拡大

            "add vt0.xy, vt0, vc4.xy \n"+    //位置を移動

            "m44 op, vt0, vc0 \n"+            //座標を表示範囲に正規化

            "mov v0, va1";

        

        // ピクセルシェーダ

        private const PIXEL_SHADER:String =

            "tex ft0, v0, fs0<2d,linear> \n"+    

            "mul oc, ft0, fc0";                

        

        

        public function Stage3D_10(){

            stage.scaleMode = StageScaleMode.NO_SCALE;

            stage.align = StageAlign.TOP_LEFT;

            var stage3d:Stage3D = stage.stage3Ds[0];

            stage3d.addEventListener(Event.CONTEXT3D_CREATE, context3DCreateHandler);

            stage3d.requestContext3D();

        }

        

        private function context3DCreateHandler(e:Event):void {

            ctx = Stage3D(e.target).context3D;

            ctx.configureBackBuffer(WIDTH, HEIGHT, 2, false);

            

            //頂点データ・インデックスデータ

            var vertices:Vector.<Number> = new <Number>[

                -0.5,  0.5, 0, 0,

                0.5,  0.5, 0, 1,

                0.5, -0.5, 1, 1,

                -0.5, -0.5, 0, 1];

            var indices:Vector.<uint> = new <uint>[0,1,2, 2,3,0];

            

            vertexParticle = ctx.createVertexBuffer(4, 4);

            vertexParticle.uploadFromVector(vertices, 0, 4);

            

            indexParticle = ctx.createIndexBuffer(6);

            indexParticle.uploadFromVector(indices, 0, 6);

            

            var screenMat:Matrix3D = new Matrix3D();

            screenMat.appendScale(1/(WIDTH/2), 1/(HEIGHT/2), 1);

            ctx.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, screenMat, true);

            

            transformVec = new <Number>[0, 0, 0, 1];

            colorVec = new <Number>[1, 1, 1, 1];

            

            //テクスチャ生成

            var sp:Sprite = new Sprite();

            var m:Matrix = new Matrix();

            m.createGradientBox(64, 64, 0, -32, -32);

            sp.graphics.beginGradientFill(GradientType.RADIAL, [0xFF8888, 0xFF8888], [0.5, 0], [0, 255], m);

            sp.graphics.drawCircle(0,0,64);

            sp.graphics.endFill();

            var bmpd:BitmapData = new BitmapData(64, 64, true, 0);

            bmpd.draw(sp, new Matrix(1,0,0,1,32,32));

            textureParticle = ctx.createTexture(64, 64, Context3DTextureFormat.BGRA, false);

            textureParticle.uploadFromBitmapData(bmpd);

            

            // 頂点シェーダをコンパイル;

            var vertexAssembly:AGALMiniAssembler = new AGALMiniAssembler();

            vertexAssembly.assemble(Context3DProgramType.VERTEX, VERTEX_SHADER);

            // ピクセルシェーダをコンパイル;

            var fragmentAssembly:AGALMiniAssembler = new AGALMiniAssembler();

            fragmentAssembly.assemble(Context3DProgramType.FRAGMENT, PIXEL_SHADER);

            

            var programPair:Program3D;

            // Program3Dのインスタンスを取得

            programPair = ctx.createProgram();

            // 頂点シェーダとピクセルシェーダのコードをGPUにアップロード

            programPair.upload(vertexAssembly.agalcode, fragmentAssembly.agalcode);

            // 使用するシェーダのペアを指定;

            ctx.setProgram(programPair);

            

            ctx.setVertexBufferAt(0, vertexParticle, 0, Context3DVertexBufferFormat.FLOAT_2);

            ctx.setVertexBufferAt(1, vertexParticle, 2, Context3DVertexBufferFormat.FLOAT_2);

            ctx.setTextureAt(0, textureParticle);

            

            ctx.setBlendFactors(Context3DBlendFactor.ONE, Context3DBlendFactor.ONE);

            stage.addEventListener(MouseEvent.CLICK, createBall);

            addEventListener(Event.ENTER_FRAME, onEnterFrame);

        }

        

        private function onEnterFrame(e:Event):void {

            i = balls.length;

            while(i--){

                var ball:FireBall = balls[i];

                createParticles(ball);

                ball.x += ball.vx;

                ball.y += ball.vy;

                ball.vy += 0.1;

                if(ball.x < 0){

                    ball.x = 0;

                    ball.vx *= -1;

                }

                if(ball.x > WIDTH){

                    ball.x = WIDTH;

                    ball.vx *= -1;

                }

                if(ball.y > HEIGHT+50) balls.splice(i,1);

            }

            

            var i:int = particles.length;

            while(i--){

                var p:Particle = particles[i];

                p.x += -p.vx;

                p.y += -p.vy;

                p.vx += p.ax;

                p.vy += p.ay;

                p.size -= 2;

                if(p.size <= 0){

                    particles.splice(i,1);

                }

            }

           
           

            ctx.clear();

            

            for (i = 0; i<particles.length; i++){

                p = particles[i];

                transformVec[0] = p.x;

                transformVec[1] = p.y;

                transformVec[3] = p.size;

                colorVec[0]     = p.r;

                colorVec[1]     = p.g;

                colorVec[2]     = p.b;

                ctx.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 4, transformVec);

                ctx.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, colorVec);

                ctx.drawTriangles(indexParticle);

            }

            

            ctx.present();

        }

        

        private function createBall(e:MouseEvent):void{

            balls.push(new FireBall(mouseX, mouseY, Math.random()*20-10, Math.random()*10-10, Math.random()*Math.random()*50+5));

        }

        

        private function createParticles(ball:FireBall):void {

            for (var i:int = 0; i<ball.N; i++){

                particles.push(new Particle(ball.x-WIDTH/2, -(ball.y-HEIGHT/2), Math.random()*10-5, Math.random()*10-5, 0, -Math.random()));

            }

        }

    }

}



class FireBall{

    public var x:Number, y:Number;

    public var vx:Number, vy:Number;

    public var N:int;

    

    public function FireBall(x:Number, y:Number, vx:Number, vy:Number, N:Number):void{

        this.x = x; this.y = y;

        this.vx = vx; this.vy = vy;

        this.N = N;

    }

}



class Particle{

    public var x:Number, y:Number;

    public var vx:Number, vy:Number;

    public var ax:Number, ay:Number;

    public var size:Number;

    public var r:Number, g:Number, b:Number;

    

    public function Particle(x:Number, y:Number, vx:Number, vy:Number, ax:Number, ay:Number){

        this.x = x; this.y = y;

        this.vx = vx; this.vy = vy;

        this.ax = ax; this.ay = ay;

        size = 50*Math.random()+20;

        r = Math.random();

        g = Math.random()*0.5;

        b = Math.random()*0.5;

    }

}