phi

I'm a Game Programmer and Frontend Engineer passionate about programming education. Math / C / C++ / C# / JavaScript / HTML5 / CSS3 / Python

phiaryjust a creator

phina.js tips - Fire Effect Particle

9 years ago

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

アレンジしよう♪

色を変更してみよう

fire effect rainbow

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 の終了値  

パーティクルを大きくしてみよう

fire effect scale up

var PARTICLE_SCALE            = 1;    // 初期スケール  
↓
var PARTICLE_SCALE            = 2;    // 初期スケール  

runstant

線香花火

fire effect sparkler

var PARTICLE_SCALE            = 1;    // 初期スケール  
var PARTICLE_SCALE_DOWN_SPEED = 0.025;// スケールダウンのスピード  
↓
var PARTICLE_SCALE            = 0.25;    // 初期スケール  
var PARTICLE_SCALE_DOWN_SPEED = 0.05;// スケールダウンのスピード  

runstant

加速度を変えてみよう

fire effect

竜巻のような軌跡を描くようになります.

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  

runstant

Rainbow Particle

Rainbow Particle

phina.js contributor でもある @simiraaaa san がアレンジしてくれました. 時間経過とともにパーティクルの色がレインボーに変化していきます. それとマウスの位置に応じてパーティクルの進む方向も変わるみたいです.

valueOf を使った演算子ハックが素晴らしい♪

runstant

ボクと彼女とアクアリウム 泡ブクブク

aqua

phina.js attributor で GLBoost の開発者でもある @emadurandal san のアレンジ作品です.

泡っぽさを出すため、Sinで横位置をプルプルさせてるのがポイント

とのことで良い感じにアクア感が出てますね♪

runstant

上記の例の他にもアレンジあれば気軽にメッセージください.
クレジット付きで掲載します!