forked from: 気体のような何か

by s8t1h12akj forked from 気体のような何か (diff: 1)
♥0 | Line 143 | Modified 2013-01-25 10:59:24 | MIT License
play

ActionScript3 source code

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

// forked from k0rin's 気体のような何か
// パーティクル祭りらしいので。
// クリックでピストン移動です。いろいろ怪しげです。
package {
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;
    
    [SWF(width = "465", height = "465", frameRate = "60", backgroundColor = "0x000000")]
    public class Gas10000 extends Sprite {
        private const W:int = stage.stageWidth;
        private const H:int = stage.stageHeight;
        
        private const NUMBER_OF_MOLECULES:int = 10000;
        private var molecules:Vector.<Molecule> = new Vector.<Molecule>();
        
        private var frameBuffer:BitmapData = new BitmapData(W, H, false, 0x00000000);
        private var colorTransform:ColorTransform;
        
        private var world:BitmapData = new BitmapData(W, H, true, 0x00000000);
        private const T:int = 10;
        
        private var map:Vector.<int> = new Vector.<int>(W * H);
        private const MAP_VOID:int = 0;
        private const MAP_WALL:int = 1;
        private const MAP_PISTON:int = 2;
        
        private const CYLINDER_X:int = W * 0.15;
        private const CYLINDER_Y:int = H / 2;
        private const CYLINDER_LENGTH:int = W * 0.7;
        private const CYLINDER_RADIUS:int = H * 0.15;
        
        private const PISTON_T:int = W * 0.07;
        private var pistonX:Number = CYLINDER_X + CYLINDER_LENGTH * 0.65;
        private var pistonVX:Number = 0;
        
        private var hud:Shape = new Shape();
        
        public function Gas10000() {
            drawSolid(MAP_WALL, 0xFFFFFFFF, 0, 0, T, H);
            drawSolid(MAP_WALL, 0xFFFFFFFF, W - T, 0, T, H);
            drawSolid(MAP_WALL, 0xFFFFFFFF, 0, 0, W, T);
            drawSolid(MAP_WALL, 0xFFFFFFFF, 0, H - T, W, T);
            
            drawSolid(MAP_WALL, 0xFFEEEEFF, CYLINDER_X, CYLINDER_Y - CYLINDER_RADIUS, T, CYLINDER_RADIUS * 2);
            drawSolid(MAP_WALL, 0xFFEEEEFF, CYLINDER_X, CYLINDER_Y - CYLINDER_RADIUS - T, CYLINDER_LENGTH, T);
            drawSolid(MAP_WALL, 0xFFEEEEFF, CYLINDER_X, CYLINDER_Y + CYLINDER_RADIUS    , CYLINDER_LENGTH, T);
            
            drawPiston();
            
            for (var i:int = 0; i < NUMBER_OF_MOLECULES; i++) {
                var x:int = Math.random() * W;
                var y:int = Math.random() * H;
                if (map[y * W + x] != MAP_VOID) {
                    i--;
                    continue;
                }
                // 動きが見えにくいので、酸素のようなものと窒素のようなものに分けてみる。
                molecules.push(new Molecule(x, y, i < NUMBER_OF_MOLECULES * 0.2 ? 0xFFFFFF : 0x99AAFF));
            }
            colorTransform = new ColorTransform(1, 1, 1, 1, -120, -120, -120);
            
            addChild(new Bitmap(frameBuffer));
            addChild(new Bitmap(world));
            addChild(hud);
            
            stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
            stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
            addEventListener(Event.ENTER_FRAME, enterFrameHandler);
        }
        
        private function drawSolid(attribution:int, color:uint, x:int, y:int, w:int, h:int):void {
            for (var iy:int = y; iy < y + h; iy++) {
                for (var ix:int = x; ix < x + w; ix++) {
                    map[iy * W + ix] = attribution;
                }
            }
            world.fillRect(new Rectangle(x, y, w, h), color);
        }
        
        private function drawPiston():void {
            drawSolid(MAP_PISTON, 0xFFEEEEFF, pistonX, CYLINDER_Y - CYLINDER_RADIUS, PISTON_T, CYLINDER_RADIUS * 2);
            drawSolid(MAP_WALL, 0xFF444466, pistonX + PISTON_T, CYLINDER_Y - T, W - pistonX - PISTON_T, T * 2);
        }
        private function erasePiston():void {
            drawSolid(MAP_VOID, 0x00000000, pistonX, CYLINDER_Y - CYLINDER_RADIUS, PISTON_T, CYLINDER_RADIUS * 2);
            drawSolid(MAP_VOID, 0x00000000, pistonX + PISTON_T, CYLINDER_Y - T, W - pistonX - PISTON_T, T * 2);
        }
        
        private var isMouseDown:Boolean = false;
        private function mouseDownHandler(event:MouseEvent):void {
            isMouseDown = true;
        }
        private function mouseUpHandler(event:MouseEvent):void {
            isMouseDown = false;
        }
        
        private function enterFrameHandler(event:Event):void {
            frameBuffer.colorTransform(frameBuffer.rect, colorTransform);
            frameBuffer.lock();
            for each(var m:Molecule in molecules) {
                if (map[int(m.y) * W + int(m.x + m.vx)]) {
                    if (map[int(m.y) * W + int(m.x + m.vx)] == MAP_PISTON) {
                        if (m.x < pistonX + PISTON_T / 2) {
                            m.x = pistonX;
                        }
                        if (m.x > pistonX + PISTON_T / 2) {
                            m.x = pistonX + PISTON_T;
                        }
                        pistonVX += m.vx * 0.008;
                    }
                    m.vx = -m.vx;
                }
                m.x += m.vx;
                if (map[int(m.y + m.vy) * W + int(m.x)]) {
                    m.vy = -m.vy;
                }
                m.y += m.vy;
                frameBuffer.setPixel(m.x, m.y, m.color);
            }
            frameBuffer.unlock();
            
            var g:Graphics = hud.graphics;
            g.clear();
            if (isMouseDown) {
                g.lineStyle(2, 0xFF0000);
                g.moveTo(pistonX + PISTON_T / 2, CYLINDER_Y);
                g.lineTo(mouseX, mouseY);
                pistonVX += (mouseX - pistonX) * 0.008;
                
                if (pistonVX > 5) { pistonVX = 5; };
                if (pistonVX < -5) { pistonVX = -5; };
            }
            
            erasePiston();
            pistonVX *= 0.7;
            pistonX += pistonVX;
            if (pistonX < CYLINDER_X + T + 5) {
                pistonX = CYLINDER_X + T + 5;
            }
            if (pistonX > W - T - PISTON_T) {
                pistonX = W - T - PISTON_T;
            }
            drawPiston();
        }
    }
}

class Molecule {
    public var x:Number;
    public var y:Number;
    public var vx:Number;
    public var vy:Number;
    public var color:uint;
    
    private static const SPEED_FACTOR:Number = 4;
    private static const MAX_SPEED:Number = 10;
    
    public function Molecule(x:Number, y:Number, color:uint) {
        this.x = x;
        this.y = y;
        this.color = color;
        
        // 正規分布
        var speed:Number = Math.sqrt( -2 * Math.log(1 - Math.random())) * SPEED_FACTOR;
        // すり抜け防止
        if (speed > MAX_SPEED) {
            speed = MAX_SPEED;
        }
        var angle:Number = 2 * Math.PI * Math.random();
        vx = Math.cos(angle) * speed;
        vy = Math.sin(angle) * speed;
    }
}