Beautifl - Flash Gallery

Thumbnail : 5k boxs
5k boxs
shen_0_ 2013-04-22 MIT License

再生するにはFlash Playerが必要です。デスクトップのブラウザでご覧ください。

package {



    import flash.display.Bitmap;

    import flash.display.BitmapData;

    import flash.display.Shape;

    import flash.display.Sprite;

    import flash.display.Stage3D;

    import flash.display.StageAlign;

    import flash.display.StageScaleMode;

    import flash.display3D.Context3D;

    import flash.display3D.Context3DProgramType;

    import flash.display3D.Context3DRenderMode;

    import flash.display3D.Context3DTextureFormat;

    import flash.display3D.Context3DVertexBufferFormat;

    import flash.display3D.IndexBuffer3D;

    import flash.display3D.VertexBuffer3D;

    import flash.display3D.textures.Texture;

    import flash.events.Event;

    import flash.geom.Matrix3D;

    import net.hires.debug.Stats;



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







    public class Boxes extends Sprite {



        public static const NUM_PARTICLE:int=7000;

        public static const SIZE:int=5;



        public static const W:int=460;

        public static const H:int=460;

        public static const COLS:int=W / SIZE;

        public static const ROWS:int=H / SIZE;



        public static const REST:int=3;

        public static const SPEED:Number=SIZE / REST; //moving speed

        public static const SPEED_No_SQRT:Number=SPEED * SPEED * 0.5;



        private var nets:Array=[];

        private var boxList:Array=[];



        ///////////////////stage3D

        public static const COLOR_ORANGE:uint=0x9B8553;

        public static const COLOR_GRAY:uint=0xaaaaaa;



        private var context:Context3D;

        private var program:ShaderProgram;

        private var iBuffer:IndexBuffer3D;

        private var vBuffer:VertexBuffer3D;

        private var uvBuffer:VertexBuffer3D;

        private var rotBmp:BitmapData;

        private var texture:Texture;

        private var ortho:Matrix3D=new Matrix3D();

        private var r_rot_steps:Vector.<Number>=Vector.<Number>([0, 0, 0, 0]);



        private var vb:Vector.<Number>=new Vector.<Number>();

        private var uvb:Vector.<Number>=new Vector.<Number>();

        private var ib:Vector.<uint>=new Vector.<uint>();

        private const vunit:int=4;

        private const uvunit:int=2;



        public function Boxes() {

            Wonderfl.disable_capture();
            stage.align=StageAlign.TOP_LEFT;
            stage.scaleMode=StageScaleMode.NO_SCALE;





            rotBmp=new BitmapData(16, 4, true, 0);

            const ox:Number=0.5;

            var sp:Shape=new Shape();

            sp.graphics.lineStyle(0, COLOR_GRAY * 0.7);

            sp.graphics.beginFill(COLOR_GRAY);

            sp.graphics.drawRect(ox, ox, 3, 3);

            sp.graphics.endFill();



            sp.graphics.lineStyle(0, COLOR_ORANGE);

            sp.graphics.beginFill(COLOR_ORANGE);

            sp.graphics.drawRect(ox + 4, ox, 3, 3);

            sp.graphics.endFill();



            sp.graphics.lineStyle(0, COLOR_ORANGE, 0.5);

            sp.graphics.beginFill(COLOR_ORANGE);

            sp.graphics.drawRect(ox + 8, ox, 3, 3);

            sp.graphics.endFill();

            rotBmp.draw(sp);



            var rotBM:Bitmap=new Bitmap(rotBmp);

            rotBM.x=100;



            var i:int, j:int;

            for (j=0; j < ROWS; j++) {

                nets[j]=[];

                for (i=0; i < COLS; i++) {

                    nets[j][i]=null;

                }

            }



            //obstacle

            for (i=0; i < 20; i++) {

                createObstacle(Math.random() * 90, 10 + Math.random() * 50, 20 * Math.random());

            }



            stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, createContext3D);

            stage.stage3Ds[0].requestContext3D(Context3DRenderMode.AUTO);



            addChild(new Stats());

            addChild(rotBM);

        }



        private function createContext3D(e:Event):void {

            context=(e.target as Stage3D).context3D;

            context.removeEventListener(Event.CONTEXT3D_CREATE, createContext3D);



            context.configureBackBuffer(W, H, 0, false);

            context.setRenderToBackBuffer();

            context.enableErrorChecking=true;



            //program

            program=new ShaderProgram(context, new VertexShader(), new FragmentShader());

            ortho=MatrixUtil.ortho(W, H, false);



            //index, vertex, uv

            const part:Number=0.25;

            const count:int=ROWS * COLS;

            for (var i:int=0; i < count; i++) {

                vb.push(0, 0, 0, 0);

                vb.push(0, 0, 0, 0);

                vb.push(0, 0, 0, 0);

                vb.push(0, 0, 0, 0);



                uvb.push(0, 0);

                uvb.push(part, 0);

                uvb.push(part, 1);

                uvb.push(0, 1);



                ib.push(i * 4 + 0, i * 4 + 1, i * 4 + 2, i * 4 + 0, i * 4 + 2, i * 4 + 3);

            }





            vBuffer=context.createVertexBuffer(vb.length / vunit, vunit);

            vBuffer.uploadFromVector(vb, 0, vb.length / vunit);



            uvBuffer=context.createVertexBuffer(uvb.length / uvunit, uvunit);

            uvBuffer.uploadFromVector(uvb, 0, uvb.length / uvunit);



            iBuffer=context.createIndexBuffer(ib.length);

            iBuffer.uploadFromVector(ib, 0, ib.length);



            r_rot_steps[0]=part;



            //texture

            texture=context.createTexture(16, 4, Context3DTextureFormat.BGRA, false);

            texture.uploadFromBitmapData(rotBmp);

            context.setTextureAt(0, texture);





            //setting

            context.setProgram(program.program);

            context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, ortho, true);

            context.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 4, r_rot_steps);





            //enter frame

            stage.addEventListener(Event.ENTER_FRAME, loop);

            stage.addEventListener(Event.RESIZE, resize);



        }



        private function resize(e:Event):void {

            context.configureBackBuffer(stage.stageWidth, stage.stageHeight, 0, false);

        }





        private function loop(e:Event):void {

            context.clear(0.1, 0.1, 0.1);

            boxsLoop();



            const len:int=boxList.length;

            var index:int=0;

            var id:int=0;



            for each (var box:Box in boxList) {

                var oldX:Number=box.x;

                var oldY:Number=box.y;

                id=box.getFixed() ? 0 : 2;



                vb[index++]=oldX;

                vb[index++]=oldY;

                vb[index++]=id;

                index++;



                vb[index++]=oldX + SIZE;

                vb[index++]=oldY;

                vb[index++]=id;

                index++;



                vb[index++]=oldX + SIZE;

                vb[index++]=oldY + SIZE;

                vb[index++]=id;

                index++;



                vb[index++]=oldX;

                vb[index++]=oldY + SIZE;

                vb[index++]=id;

                index++;

            }



            vBuffer.uploadFromVector(vb, 0, len * vunit);



            context.setVertexBufferAt(0, vBuffer, 0, Context3DVertexBufferFormat.FLOAT_2);

            context.setVertexBufferAt(1, vBuffer, 2, Context3DVertexBufferFormat.FLOAT_2);

            context.setVertexBufferAt(2, uvBuffer, 0, Context3DVertexBufferFormat.FLOAT_2);



            context.drawTriangles(iBuffer, 0, 2 * len);



            if (false && captureTime-- == 0) {

                var cc:BitmapData=new BitmapData(465, 465, false, 0);

                context.drawToBitmapData(cc);

                cc.draw(stage);

                addChild(new Bitmap(cc));

            }



            context.present();

        }



        private var captureTime:int=5 * 60;



        //loop

        private var nums:int=NUM_PARTICLE;



        private function boxsLoop():void {

            var box:Box, tx:int, ty:int, bool:Boolean;

            var len:int=boxList.length;



            for (var i:int=0; i < len; i++) {

                box=boxList[i];



                if (box.getFixed()) {

                    continue;

                }



                if (box.getSleep()) {

                    if (box.rest < 1) {

                        continue;

                    } else {

                        box.rest--;

                    }

                }





                if (!box.needMoving) {



                    tx=box.cx;

                    ty=box.cy;

                    bool=true;



                    if (ty < ROWS - 1) {

                        if (isEmpty(tx, ty + 1)) {

                            box.setGoto(tx, ty + 1);

                            bool=false;



                        } else {

                            if (tx > 0 && isEmpty(tx - 1, ty) && isEmpty(tx - 1, ty + 1)) {

                                box.setGoto(tx - 1, ty);

                                bool=false;



                            } else if (tx < COLS - 1 && isEmpty(tx + 1, ty) && isEmpty(tx + 1, ty + 1)) {

                                box.setGoto(tx + 1, ty);

                                bool=false;



                            }

                        }

                    }



                    if (bool) {

                        box.setSleep(true);

                    }



                }





                if (box.needMoving) {

                    box.move();

                }



            }



            trace("debug:", debug);

            debug=0;



            if (nums > 0) {

                for (i=5; i > 0; i--) {



                    var randX:int=Math.random() * COLS

                    if (!getBox(randX, 0)) {

                        nums--;

                        createBox(randX, 0);



                    }

                }

            }

        }

        private var debug:Number=0;



        //public



        public function setCheckBox(x:int, y:int, box:Box):void {

            nets[y][x]=box;

        }



        public function wakeOther(x:int, y:int):void {

            //wake.wake.wake

            //wake.move.wake

            var box:Box=getBox(x - 1, y); //x-1,y



            if (box)

                box.setSleep(false);



            box=getBox(x + 1, y); //x+1,y



            if (box)

                box.setSleep(false);



            box=getBox(x, y - 1); //x,y-1



            if (box)

                box.setSleep(false);



            box=getBox(x - 1, y - 1); //x-1,y-1



            if (box)

                box.setSleep(false);



            box=getBox(x + 1, y - 1); //x+1,y-1



            if (box)

                box.setSleep(false);



        }







        //check this position box;



        private function getBox(x:int, y:int):Box {

            if (x > -1 && y > -1 && x < COLS && y < ROWS) {

                return nets[y][x];

            }



            return null;

        }







        private function isEmpty(x:int, y:int):Boolean {

            if (x > -1 && y > -1 && x < COLS && y < ROWS) {

                return !(nets[y][x]);

            }



            return false;

        }







        //create



        private function createObstacle(x:int, y:int, len:int):void {

            for (var i:int=0; i < len; i++) {

                createBox(x + i, y, true);

            }

        }







        private function createBox(x:int, y:int, isFixed:Boolean=false):Box {

            if (!isEmpty(x, y)) {

                return null;

            }

            var box:Box=new Box(this, x, y);

            box.setFixed(isFixed);



            boxList.push(box);

            setCheckBox(x, y, box);

            return box;

        }

    }

}







import flash.geom.Point;





class Box {



    public var x:Number=0;

    public var y:Number=0;

    public var cx:int=0;

    public var cy:int=0;

    public var toX:int=0;

    public var toY:int=0;



    public var needMoving:Boolean=false;

    public var rest:int=0;



    private var _sleep:Boolean=false;

    private var _fixed:Boolean=false;

    private var _v:Point=new Point();

    private var world:Boxes=null;





    public function Box(world:Boxes, x:int, y:int) {

        this.world=world;

        setPos(x, y);

    }



    //set/get fixed

    public function getFixed():Boolean {

        return _fixed;

    }



    public function setFixed(bool:Boolean):void {

        if (bool != _fixed) {

            _fixed=bool;

        }

    }





    //sleep

    public function getSleep():Boolean {

        return _sleep;

    }





    public function setSleep(bool:Boolean):void {

        if (_sleep != bool) {

            _sleep=bool;

            if (bool) {

                rest=Boxes.REST;

            }

        }

    }



    public function setPos(xa:int, ya:int):void {

        cx=xa;

        cy=ya;

        x=xa * Boxes.SIZE;

        y=ya * Boxes.SIZE;

    }







    public function setGoto(xa:int, ya:int):void {

        world.setCheckBox(xa, ya, this);

        toX=xa;

        toY=ya;

        needMoving=false;

        _v.x=0;

        _v.y=0;



        //set the moving speed

        if (toX != cx || toY != cy) {

            needMoving=true;

            var v:int=toX - cx;

            if (v != 0) {

                _v.x=Boxes.SPEED * v / Math.abs(v);

            }

            v=toY - cy;



            if (v != 0) {

                _v.y=Boxes.SPEED * v / Math.abs(v);

            }

        }

    }



    public function move():void {

        var tx:Number=this.x - toX * Boxes.SIZE;

        var ty:Number=this.y - toY * Boxes.SIZE;

        if ((tx * tx + ty * ty) < Boxes.SPEED_No_SQRT) {

            world.setCheckBox(cx, cy, null);

            setPos(toX, toY);

            needMoving=false;

            _v.x=0;

            _v.y=0;

        } else {

            this.x+=_v.x;

            this.y+=_v.y;

        }



        world.wakeOther(cx, cy);

    }

}



//Stage3D

import com.adobe.utils.AGALMiniAssembler;

import flash.display3D.Context3D;

import flash.display3D.Context3DProgramType;

import flash.display3D.Program3D;

import flash.geom.Matrix3D;







class ShaderProgram {



    public var program:Program3D=null;



    public function ShaderProgram(context:Context3D, vsh:AGALMiniAssembler, fsh:AGALMiniAssembler) {

        program=context.createProgram();

        program.upload(vsh.agalcode, fsh.agalcode);

    }

}





class VertexShader extends AGALMiniAssembler {

    private var src:String=

        "m44 op, va0, vc0 \n" +

        "mov v0, va2 \n" +

        "mul vt0.x, va1.x, vc4.x \n" + //offset = base frame% x step

        "add v0.x, va2.x, vt0.x \n" + //new u = u + offset

        "";



    public function VertexShader() {

        assemble(Context3DProgramType.VERTEX, src);

    }

}



class FragmentShader extends AGALMiniAssembler {

    private var src:String=

        "mov ft0, v0\n" +

        "tex ft1, ft0.xy, fs0 <2d,repeat,nearest>\n" +

        "mov oc, ft1\n";



    public function FragmentShader() {

        assemble(Context3DProgramType.FRAGMENT, src);

    }

}



class MatrixUtil {

    public static function ortho(w:int, h:int, rev:Boolean):Matrix3D {

        var m:Matrix3D=new Matrix3D();

        m.appendTranslation(-w * 0.5, -h * 0.5, 0);

        m.appendScale(2 / w, rev ? 2 / h : -2 / h, 1);



        return m;



    }

}