phina.js tips - Fire Effect Particle
phina.js で パーティクルを使った炎エフェクトを作ったので簡単にそのデモとコードを紹介したいと思います.
phina.js を使えば 100 行程度でこういったエフェクトを簡単に作ることができます.ちょっと応用すればゲームとかで爆発エフェクトとして使えるかと思います.
また, 下の方にアレンジ例も乗っけているのでよかったら参考にしてください.
Runstant demo
デモです. 中央に炎エフェクトを表示してます. タッチすると発火点が移動するのでマウスでごにょごにょやるとキレイですよ.
Code
実装コード全体になります. パーティクル実装部分だけでいくと 50~60 行程度ですね.
/*
* runstant
*/
phina.globalize();
var PARTICLE_MAX_NUM = 256; // 最大パーティクル数
var PARTICLE_COLOR_START = 0; // color angle の開始値
var PARTICLE_COLOR_END = 30; // color angle の終了値
var PARTICLE_VELOCITY_RANGE_X = 8; // 速度の初期値の範囲 x
var PARTICLE_VELOCITY_RANGE_Y = 6; // 速度の初期値の範囲 y
var PARTICLE_ACCELERATION_Y = -0.5; // 加速度 y
var PARTICLE_SCALE = 1; // 初期スケール
var PARTICLE_SCALE_DOWN_SPEED = 0.025;// スケールダウンのスピード
phina.define('Particle', {
superClass: 'CircleShape',
init: function(x, y) {
this.superInit({
stroke: false,
radius: 64,
});
this.blendMode = 'lighter';
var grad = this.canvas.context.createRadialGradient(0, 0, 0, 0, 0, this.radius);
grad.addColorStop(0, 'hsla({0}, 75%, 50%, 1.0)'.format(Math.randint(PARTICLE_COLOR_START, PARTICLE_COLOR_END)));
grad.addColorStop(1, 'hsla({0}, 75%, 50%, 0.0)'.format(Math.randint(PARTICLE_COLOR_START, PARTICLE_COLOR_END)));
this.fill = grad;
this.beginPosition = Vector2();
this.velocity = Vector2();
this.reset(x, y);
},
reset: function(x, y) {
this.beginPosition.set(x, y);
this.position.set(this.beginPosition.x, this.beginPosition.y);
this.velocity.set(
Math.randint(-PARTICLE_VELOCITY_RANGE_X, PARTICLE_VELOCITY_RANGE_X),
Math.randint(-PARTICLE_VELOCITY_RANGE_Y, PARTICLE_VELOCITY_RANGE_Y)
);
this.scaleX = this.scaleY = Math.randfloat(PARTICLE_SCALE*0.8, PARTICLE_SCALE*1.2);
},
update: function() {
this.position.add(this.velocity);
this.velocity.x += (this.beginPosition.x-this.x)/(this.radius/2);
this.velocity.y += PARTICLE_ACCELERATION_Y;
this.scaleX -= PARTICLE_SCALE_DOWN_SPEED;
this.scaleY -= PARTICLE_SCALE_DOWN_SPEED;
if (this.scaleX < 0) {
this.flare('disappear');
}
}
});
phina.define('MainScene', {
superClass: 'CanvasScene',
init: function(options) {
this.superInit(options);
this.targetPosition = Vector2(this.gridX.center(), this.gridY.center(4));
},
update: function(app) {
var p = app.pointer;
if (p.getPointing()) {
this.targetPosition.x = p.x;
this.targetPosition.y = p.y;
}
if (this.children.length < PARTICLE_MAX_NUM) {
var p = Particle(this.targetPosition.x, this.targetPosition.y).addChildTo(this);
p.ondisappear = function() {
p.reset(this.targetPosition.x, this.targetPosition.y);
}.bind(this);
}
},
});
phina.main(function() {
var app = GameApp({
startLabel: 'main',
backgroundColor: '#222',
});
app.enableStats();
app.run();
});
Arrange
アレンジしよう♪
色を変更してみよう
var PARTICLE_COLOR_START = 0; // color angle の開始値
var PARTICLE_COLOR_END = 30; // color angle の終了値
↓
var PARTICLE_COLOR_START = 0; // color angle の開始値
var PARTICLE_COLOR_END = 360; // color angle の終了値
パーティクルを大きくしてみよう
var PARTICLE_SCALE = 1; // 初期スケール
↓
var PARTICLE_SCALE = 2; // 初期スケール
線香花火
var PARTICLE_SCALE = 1; // 初期スケール
var PARTICLE_SCALE_DOWN_SPEED = 0.025;// スケールダウンのスピード
↓
var PARTICLE_SCALE = 0.25; // 初期スケール
var PARTICLE_SCALE_DOWN_SPEED = 0.05;// スケールダウンのスピード
加速度を変えてみよう
竜巻のような軌跡を描くようになります.
var PARTICLE_VELOCITY_RANGE_X = 8; // 速度の初期値の範囲 x
var PARTICLE_VELOCITY_RANGE_Y = 6; // 速度の初期値の範囲 y
var PARTICLE_ACCELERATION_Y = -0.5; // 加速度 y
↓
var PARTICLE_VELOCITY_RANGE_X = 24; // 速度の初期値の範囲 x
var PARTICLE_VELOCITY_RANGE_Y = 10; // 速度の初期値の範囲 y
var PARTICLE_ACCELERATION_Y = -1; // 加速度 y
Rainbow Particle
phina.js contributor でもある @simiraaaa san がアレンジしてくれました. 時間経過とともにパーティクルの色がレインボーに変化していきます. それとマウスの位置に応じてパーティクルの進む方向も変わるみたいです.
valueOf
を使った演算子ハックが素晴らしい♪
ボクと彼女とアクアリウム 泡ブクブク
phina.js attributor で GLBoost の開発者でもある @emadurandal san のアレンジ作品です.
泡っぽさを出すため、Sinで横位置をプルプルさせてるのがポイント
とのことで良い感じにアクア感が出てますね♪
上記の例の他にもアレンジあれば気軽にメッセージください.
クレジット付きで掲載します!