forked from: forked from: HANABI(初心者がアレンジしてみた)
♥0 |
Line 157 |
Modified 2010-09-16 09:31:40 |
MIT License
archived:2017-03-20 12:58:16
ActionScript3 source code
/**
* Copyright nayu ( http://wonderfl.net/user/nayu )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/jXjR
*/
// forked from Uwitch's forked from: HANABI(初心者がアレンジしてみた)
// forked from yanbaka's HANABI
/*
* 比較的短いコードでこれだけのことが出来ることに感動。
* wonderflらしくForkしてアレンジに挑戦。
* 解説付きがあったことは、初心者として多いに勉強になりました。
* Hiiragi氏には感謝です。
*
* 変更箇所のみコメントしてあります。
*
* 【変更点】
* ・花火の消え方の変更
* ・色の変化を色相環を周回するように変更
* ・時間経過で花火の発生間隔が変わるように変更
*/
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.PixelSnapping;
import flash.display.Sprite;
import flash.events.Event;
//import flash.events.TimerEvent;
import flash.filters.BlurFilter;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
//import flash.utils.Timer;
[SWF(width = "465", height = "465", backgroundColor = "0x000000", frameRate = "30")]
public class Hanabi extends Sprite
{
private const WIDTH:Number = 465;
private const HEIGH:Number = 465;
//_glowの効果を確認するために定数に置き換えただけで、数値そのものはオリジナルからいじってません
//要するに数値いじって遊びやすくしただけ
private const GLOW:Number = 4;
//花火の初期ディレイ(フレーム数指定)
private const IniD:Number = 45;
private var _particles:Array;
private var _canvas:BitmapData;
private var _glow:BitmapData;
private var _rect:Rectangle;
private var cTra:ColorTransform;
//色相情報(0:赤,60:黄,120:緑,180:シアン,240:青,300:マゼンタ の6つに分類しただけで単なるフラグ)
private var hue:int;
//色の変化スピード(色相環を一周する時間:フレーム数指定)
private var hueC:Number = 240;
private var sx:Number;
private var sy:Number;
//ディレイ,花火カウント,フレームカウント用
private var delay:Number = IniD;
private var cnt:int;
private var fcnt:uint;
public function Hanabi()
{
init();
}
private function init():void
{
_particles = [];
_canvas = new BitmapData(WIDTH, HEIGH, false, 0x0);
addChild(new Bitmap(_canvas)) as Bitmap;
_glow = new BitmapData(WIDTH/GLOW, HEIGH/GLOW, false, 0x0);
var bm:Bitmap = addChild(new Bitmap(_glow, PixelSnapping.NEVER, true)) as Bitmap;
bm.scaleX = bm.scaleY = GLOW;
bm.blendMode = BlendMode.ADD;
_rect = new Rectangle(0, 0, WIDTH, HEIGH);
//色相の0に合わせて、Rを0.9倍、GとBを0.8倍に変更
cTra = new ColorTransform(.9, .8, .8, 1.0);
//秒⇒フレーム毎の増減値に変換
hueC = (1 / (hueC / 6)) * 0.1;
//最初に一発だけ打ち上げる
hanabi();
this.stage.addEventListener(Event.ENTER_FRAME, enterframeHandler);
//Timerイベントの廃止
}
private function resetFunc():void
{
//Timerイベントからフレームイベントに変更
//色の変化を色相環を周回しているっぽく変更
//0.8⇔0.9と変化させる幅は変えず、RGBの値をシフトしながら増減させているだけ
switch ( hue ) {
case 0:
cTra.greenMultiplier += hueC;
break;
case 60:
cTra.redMultiplier -= hueC;
break;
case 120:
cTra.blueMultiplier += hueC;
break;
case 180:
cTra.greenMultiplier -= hueC;
break;
case 240:
cTra.redMultiplier += hueC;
break;
case 300:
cTra.blueMultiplier -= hueC;
break;
default :
}
if ( cTra.redMultiplier + cTra.greenMultiplier + cTra.blueMultiplier <= 2.5 || cTra.redMultiplier + cTra.greenMultiplier + cTra.blueMultiplier >= 2.6) {
hue = ( hue + 60 ) % 360;
}
if ( hanabishoot() == true ) {
hanabi();
}
}
//花火打ち上げのタイミングでtrueを返す
private function hanabishoot():Boolean {
var flag:Boolean;
if (delay <= fcnt++) {
if (cnt == -1) {
delay = IniD;
} else if (delay > 2) {
delay *= 0.96;
} else {
delay = 2;
}
fcnt = 0;
cnt ++;
if (cnt >= 180) {
delay = 120;
cnt = -1;
}
flag = true;
}
return flag;
}
private function hanabi():void
{
var i:int = 200;
sx = Math.random()*WIDTH;
sy = Math.random()*HEIGH/2;
while (i--) createParticle();
}
private function createParticle():void {
var p:Particle = new Particle();
p.x = sx;
p.y = sy;
var radius:Number = Math.sqrt(Math.random())*10;
var angle:Number = Math.random()*(Math.PI)*2;
p.vx = Math.cos(angle) * radius;
p.vy = Math.sin(angle) * radius;
_particles.push(p);
}
private function enterframeHandler(e:Event):void
{
//resetFuncをこっちで呼び出すようにお引越し
resetFunc();
update();
}
private function update():void {
_canvas.lock();
_canvas.applyFilter(_canvas, _rect, new Point(), new BlurFilter(1, 1));
_canvas.colorTransform(_rect, cTra);
var i:int = _particles.length;
while (i--) {
var p:Particle = _particles[i];
p.life --;
p.vy += 0.2;
p.vx *= 0.9;
p.vy *= 0.9;
p.x += p.vx;
p.y += p.vy;
_canvas.setPixel32(p.x, p.y, p.c);
//パーティクルがステージより上に出た場合は残すように変更
//速度による除去を廃止し、寿命で消えるように変更
if ((p.x > stage.stageWidth || p.x < 0) || p.life < 0)
{
this._particles.splice(i, 1);
}
}
_canvas.unlock();
_glow.draw(_canvas, new Matrix(1/GLOW, 0, 0, 1/GLOW));
}
}
}
class Particle
{
public var x:Number = 0;
public var y:Number = 0;
public var vx:Number = 0;
public var vy:Number = 0;
public var c:uint = 0xFFFFFFFF;
//パーティクルの寿命(37~53フレーム)
public var life:Number = 35 + Math.random() * 18;
public function Particle() {}
}