#21 Hanabi 2 ( flash on 2009-9-13 )

by krogue
#21 Hanabi 2
* 
* 花火がいくつかの層から出来ていることを意識してみました。
* 今度は曲がらず、はじけます。はじける瞬間が好きです。
* すぐに消えるのがすこし寂しいです。
* 
* P.S. 寒くなってきましたね。風邪を引かないように注意してください。
* 
* 操作:
* ・クリック:花火を打ち上げる(同じ位置に連続では上がりません)
* 
* @author krogue
♥2 | Line 144 | Modified 2009-09-13 16:06:06 | MIT License
play

ActionScript3 source code

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

/**
 * #21 Hanabi 2
 * 
 * 花火がいくつかの層から出来ていることを意識してみました。
 * 今度は曲がらず、はじけます。はじける瞬間が好きです。
 * すぐに消えるのがすこし寂しいです。
 * 
 * P.S. 寒くなってきましたね。風邪を引かないように注意してください。
 * 
 * 操作:
 * ・クリック:花火を打ち上げる(同じ位置に連続では上がりません)
 * 
 * @author krogue
 */
package
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    
    [SWF(width="465", height="465", backgroundColor="0", frameRate="60")]
    public class Main extends Sprite
    {
        private var hanabi:Hanabi;
        private var isMouseDown:Boolean = false;
        
        public function Main()
        {
            addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
        }
        
        private function addedToStageHandler(event:Event):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
            initialize();
            addEventListener(Event.ENTER_FRAME, enterFrameHandler);
        }
        
        private function enterFrameHandler(event:Event):void
        {
            update();
        }
        
        private function initialize():void
        {
            hanabi = addChild(new Hanabi()) as Hanabi;
            stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
            stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
        }
        
        private function update():void
        {
            if (isMouseDown)
                hanabi.shoot(mouseX, mouseY);
            hanabi.update();
        }
        
        private function mouseDownHandler(event:MouseEvent):void
        {
            isMouseDown = true;
        }
        
        private function mouseUpHandler(event:MouseEvent):void
        {
            isMouseDown = false;
        }
    }
}

import __AS3__.vec.Vector;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.geom.ColorTransform;
import flash.geom.Point;

class Hanabi extends Sprite
{
    private var particles:Vector.<Particle> = new Vector.<Particle>();
    private var bitmap:Bitmap = addChild(new Bitmap()) as Bitmap;
    private var lastPoint:Point = new Point(-465, -465);
    
    public function Hanabi()
    {
        bitmap.bitmapData = new BitmapData(465, 465, false, 0x000000);
    }
    
    public function update():void
    {
        var bmd:BitmapData = bitmap.bitmapData;
        bmd.lock();
        bmd.colorTransform(bmd.rect, new ColorTransform(0.9, 0.9, 0.9));
        for (var i:int = particles.length - 1; i >= 0; i--)
        {
            var p:Particle = particles[i];
            p.x += Math.cos(p.radians);
            p.y += Math.sin(p.radians);
            bmd.setPixel(p.x, p.y, p.color);
            if (!bmd.rect.contains(p.x, p.y))
                particles.splice(i, 1);
            else if (--p.life <= 0)
            {
                particles.splice(i, 1);
                if (p.level < 3)
                    shootHelper(p.x, p.y, p.level + 1);
            }
        }
        bmd.unlock();
    }
    
    public function shoot(x:Number, y:Number):void
    {
        // 前回の場所の近くには発射しない
        if (Point.distance(lastPoint, new Point(x, y)) < 30)
            return;
        lastPoint.x = x;
        lastPoint.y = y;
        shootHelper(x, y, 1);
    }
    
    private function shootHelper(x:Number, y:Number, level:int):void
    {
        // レベルごとに発射数・生存時間・色を変える
        var n:int = 4;
        var life:int = 100;
        var color:uint = 0x0000FF;
        switch (level)
        {
            case 1:
            {
                n = 4;
                life = 100;
                color = 0x0000FF;
                break;
            }
            case 2:
            {
                n = 6;
                life = 80;
                color = 0x00FFFF;
                break;
            }
            case 3:
            {
                n = 8;
                life = 40;
                color = 0x00FF00;
                break;
            }
        }
        
        // 最大数を超える時は発射しない
        if (particles.length + n > 3000)
             return;
        for (var i:int = 0; i < n; i++)
        {
            var p:Particle = new Particle();
            p.x = x;
            p.y = y;
            p.radians = i * 2 * Math.PI / n;
            p.level = level;
            p.life = life;
            p.color = color;
            particles.push(p);
        }
    }
}

class Particle
{
    public var x:Number;
    public var y:Number;
    public var radians:Number;
    public var level:int;
    public var life:int;
    public var color:uint;
}