[Haxe/CreateJS] ParticleEmitterJS と戯れた

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

つい先日話題になった ParticleEmitterJS と戯れてみました。( デモ )

ParticleEmitterJS の Haxe 用 extern クラス

どなたか作っていないかと思い探したのですが、見つからなかったので用意しました。
Haxe/CreateJS な人は下記コードをご自由にどうぞ。( ParticleEmitterJS 0.5.0 対応版 )

ParticleEmitter.hx

package createjs;
import createjs.easeljs.Point;
import createjs.easeljs.DisplayObject;
@:native("createjs.ParticleEmitter")
extern class ParticleEmitter extends DisplayObject {
    public function new(image:Dynamic):Void;
    public function reset():Void;
    public var accelerationX:Int;
    public var accelerationY:Int;
    public var angle:Float;
    public var angleVar:Float;
    public var autoRemoveOnFinished:Bool;
    public var debugMode:Bool;
    public var duration:Float;
    public var emissionRate:Float;
    public var emitterType:Int;
    public var endColor:Array<Int>;
    public var endColorVar:Array<Int>;
    public var endOpacity:Array<Int>;
    public var endSize:Float;
    public var endSizeVar:Float;
    public var endSpin:Float;
    public var endSpinVar:Float;
    public var image:Dynamic;
    public var life:Float;
    public var lifeVar:Float;
    public var maxParticles:Float;
    public var position:Point;
    public var positionVarX:Float;
    public var positionVarY:Float;
    public var radialAcceleration:Float;
    public var radialAccelerationVar:Float;
    public var speed:Float;
    public var speedVar:Float;
    public var startColor:Array<Int>;
    public var startColorVar:Array<Int>;
    public var startOpacity:Float;
    public var startSize:Float;
    public var startSizeVar:Float;
    public var startSpin:Float;
    public var startSpinVar:Float;
    public var state:Int;
    public var tangentalAcceleration:Float;
    public var tangentalAccelerationVar:Float;
}

ParticleEmitterState.hx

package createjs;
@:native("createjs.ParticleEmitterState")
extern class ParticleEmitterState {
    public var Created:Int;
    public var Running:Int;
    public var Finished:Int;
}

ParticleEmitterType.hx

package createjs;
@:native("createjs.ParticleEmitterType")
extern class ParticleEmitterType {
    public static var Emit:Int;
    public static var OneShot:Int;
}

デモ

実装例は以下の通り。

エミッタのパラメータ調整は、ParticleEmitterJS 作者が提供しているエディタを使用すると簡単です。

Main.hx

package ;

import js.Dom.Image;
import js.Lib;
import createjs.easeljs.Point;
import createjs.easeljs.Ticker;
import createjs.ParticleEmitterType;
import createjs.ParticleEmitter;
import createjs.easeljs.Stage;
import createjs.easeljs.Ticker;

class Main {

    private var stage:Stage;

    private var particleImage:Image;

    private var emitter:ParticleEmitter;

    private var rad:Float = 0;

    public static function main():Void {
        new Main();
    }

    public function new() {
        Lib.window.onload = initHandler;
    }

    private function initHandler(_):Void {
//        particleImage = cast Lib.document.createElement("Image"); ///NG : Doesn't work in Firefox
//        particleImage = new Image(); //NG : js.Dom.Image cannot be constructed
        particleImage = untyped __js__("new Image()");
        particleImage.onload = initCanvas;
        particleImage.src = "hirai.png";
    }

    private function initCanvas(_):Void {
        stage = new Stage(cast Lib.document.getElementById("canvas"));
        stage.compositeOperation = "lighter";

        handleResize(null);
        Lib.window.onresize = handleResize;

        Ticker.setFPS(60);
        Ticker.useRAF = true;
        Ticker.addListener(update);

        var canvas:Dynamic = stage.canvas;
        addParticleEmitter(canvas.width * 0.5, canvas.height * 0.5);
    }

    private function addParticleEmitter(x, y):Void {
        emitter = new ParticleEmitter(particleImage);
        emitter.position = new Point(x, y);
        emitter.emitterType = ParticleEmitterType.Emit;
        emitter.emissionRate = 1024;
        emitter.maxParticles = 256;
        emitter.life = 1500;
        emitter.lifeVar = 0;
        emitter.speed = 32;
        emitter.speedVar = 0;
        emitter.positionVarX = 1;
        emitter.positionVarY = 1;
        emitter.accelerationX = 0;
        emitter.accelerationY = 0;
        emitter.radialAcceleration = 0;
        emitter.radialAccelerationVar = 0;
        emitter.tangentalAcceleration = 0;
        emitter.tangentalAccelerationVar = 0;
        emitter.angle = 270;
        emitter.angleVar = 100;
        emitter.startSpin = 0;
        emitter.startSpinVar = 0;
        emitter.endSpin = null;
        emitter.endSpinVar = null;
        emitter.startColor = [48, 48, 48];
        emitter.startColorVar = null;//[0, 32, 32];
        emitter.startOpacity = 1;
        emitter.endColor = [0, 0, 0];
        emitter.endColorVar = null;
        emitter.endOpacity = null;
        emitter.startSize = 128;
        emitter.startSizeVar = 1;
        emitter.endSize = 124;
        emitter.endSizeVar = null;
        stage.addChild(emitter);
    }

    private function update():Void {
        stage.update();
        var window:Dynamic = Lib.window;
        var cx:Float = window.innerWidth * 0.5;
        var cy:Float = window.innerHeight * 0.5;
        var r:Float = 100;
        var dx:Float = Math.sin(rad) * r * 2 + cx;
        var dy:Float = Math.cos(rad) * r + cy;
        if(emitter != null) {
            emitter.position = new Point(dx, dy);
        }
        rad+=0.0523598775;
    }

    private function handleResize(_):Void {
        var canvas:Dynamic = stage.canvas;
        var window:Dynamic = Lib.window;
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
        if(emitter != null) {
            emitter.position = new Point(canvas.width * 0.5, canvas.height * 0.5);
        }
    }
}

出力結果

こちら

我らがマスコット的存在、平井 祐樹 を素材にしております。