パーティクルクラスを作ってみた
勉強用に自作で作ってみたので公開してみる。4月なので桜の花びらをパーティクルで散らしてみた。使い方はドキュメントクラスに下記のように記述する。
Main.as
ACTIONSCRIPT:
package
{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.MouseEvent;
import info.five.filters.Particle;
public class Main extends Sprite
{
private var p:Particle;
//------------------------------
// コンストラクタ
//------------------------------
public function Main():void
{
this.stage.addEventListener(MouseEvent.CLICK, onClick);
//-----[パーティクル]
p = new Particle("flower", this);
p.gravity = -0.2;
p.wind = -0.5;
}
private function onClick(e:MouseEvent):void
{
p.click();
}
}
}
{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.MouseEvent;
import info.five.filters.Particle;
public class Main extends Sprite
{
private var p:Particle;
//------------------------------
// コンストラクタ
//------------------------------
public function Main():void
{
this.stage.addEventListener(MouseEvent.CLICK, onClick);
//-----[パーティクル]
p = new Particle("flower", this);
p.gravity = -0.2;
p.wind = -0.5;
}
private function onClick(e:MouseEvent):void
{
p.click();
}
}
}
まずはパーティクルインスタンスを作る。第1引数はパーティクルの元となるムービークリップのリンケージ名。第2引数はパーティクルを配置する場所。この場合はステージに配置するのでthisとする。インスタンスを作った後は各パラメータを指定する。gravityはマイナス値でパーティクルが上昇。windはマイナス値で左向きにパーティクルが流れる(0だと円状に広がる)。
p.gravity = -0.2;
p.wind = -0.5;
このサンプルではステージにクリックイベントを登録しているので、リスナー関数の中でp.click()を呼び出すことでクリックタイプのパーティクルを発動することができる。これをp.start()にするとパーティクルが生成され続ける。p.stop()で止める事ができる。
パーティクルクラスはこちら
Particle.as
ACTIONSCRIPT:
package info.five.filters
{
import flash.display.DisplayObjectContainer;
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.utils.Timer;
import flash.utils.getDefinitionByName;
import flash.geom.Point;
public class Particle
{
private var container:DisplayObjectContainer;
private var linkage:String;
private var timer:Timer;
private var xVel:Number;
private var yVel:Number;
private var _vol:Number = 5;
private var _drag:Number = 0.99;
private var _shrink:Number = 0.95;
private var _gravity:Number = 0.8;
private var _fade:Number = 0.02;
private var _wind:Number = 0;
//------------------------------
// コンストラクタ
//------------------------------
public function Particle(s:String, targetContainer:DisplayObjectContainer)
{
linkage = s;
container = targetContainer;
}
//------------------------------
// パーティクルの生成
//------------------------------
private function makeParticle(e:Event):void
{
for (var i:uint = 0; i <_vol; i++)
{
var mc:MovieClip = new(getDefinitionByName(linkage));
container.addChild(mc);
var mouseX:int = container.stage.mouseX;
var mouseY:int = container.stage.mouseY;
var mousePt:Point = new Point(mouseX, mouseY);
var pt:Point = getNearPoint(mousePt);
mc.x = pt.x;
mc.y = pt.y;
mc.xVel = getRandRange( -5, 5);
mc.yVel = getRandRange( -5, 5);
mc.rot = getRandRange( -20, 20);
mc.addEventListener(Event.ENTER_FRAME, onRender);
}
}
//------------------------------
// 指定範囲からランダム値の取得
//------------------------------
private function getRandRange(min:Number, max:Number):Number
{
var randomNum:Number = (Math.random() * (max - min )) + min;
return randomNum;
}
//------------------------------
// 近似ポイント座標の取得
//------------------------------
private function getNearPoint(pt1:Point):Point
{
var len:uint = Math.round(Math.random() * 10);
var angle:uint = Math.round(Math.random() * 2 * Math.PI);
var pt2:Point = Point.polar(len, angle);
pt2.offset(pt1.x, pt1.y);
return pt2;
}
//------------------------------
// スタート
//------------------------------
public function start():void
{
container.stage.addEventListener(Event.ENTER_FRAME, makeParticle);
}
//------------------------------
// ストップ
//------------------------------
public function stop():void
{
container.stage.removeEventListener(Event.ENTER_FRAME, makeParticle);
}
//------------------------------
// クリック
//------------------------------
public function click():void
{
container.stage.addEventListener(Event.ENTER_FRAME, makeParticle);
timer = new Timer(300, 1);
timer.addEventListener(TimerEvent.TIMER, onDelay);
timer.start();
}
private function onDelay(e:TimerEvent):void
{
container.stage.removeEventListener(Event.ENTER_FRAME, makeParticle);
timer.removeEventListener(TimerEvent.TIMER_COMPLETE, onDelay);
}
//------------------------------
// レンダー
//------------------------------
private function onRender(e:Event):void
{
var mc:MovieClip = e.target as MovieClip;
if (mc.alpha> 0)
{
mc.x += mc.xVel + _wind * 10;
mc.y += mc.yVel;
mc.xVel *= _drag;
mc.yVel *= _drag;
mc.scaleX *= _shrink;
mc.scaleY *= _shrink;
mc.yVel += _gravity;
mc.alpha -= _fade;
mc.rotation += mc.rot;
}
else
{
mc.removeEventListener(Event.ENTER_FRAME, onRender);
mc.removeChildAt(0);
container.removeChild(mc);
mc = null;
}
}
//------------------------------
// getter setter
//------------------------------
public function get vol():Number { return _vol; }
public function set vol(value:Number):void {
_vol = value;
}
public function get drag():Number { return _drag; }
public function set drag(value:Number):void {
_drag = value;
}
public function get shrink():Number { return _shrink; }
public function set shrink(value:Number):void {
_shrink = value;
}
public function get gravity():Number { return _gravity; }
public function set gravity(value:Number):void {
_gravity = value;
}
public function get fade():Number { return _fade; }
public function set fade(value:Number):void {
_fade = value;
}
public function get wind():Number { return _wind; }
public function set wind(value:Number):void {
_wind = value;
}
}
}
{
import flash.display.DisplayObjectContainer;
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.utils.Timer;
import flash.utils.getDefinitionByName;
import flash.geom.Point;
public class Particle
{
private var container:DisplayObjectContainer;
private var linkage:String;
private var timer:Timer;
private var xVel:Number;
private var yVel:Number;
private var _vol:Number = 5;
private var _drag:Number = 0.99;
private var _shrink:Number = 0.95;
private var _gravity:Number = 0.8;
private var _fade:Number = 0.02;
private var _wind:Number = 0;
//------------------------------
// コンストラクタ
//------------------------------
public function Particle(s:String, targetContainer:DisplayObjectContainer)
{
linkage = s;
container = targetContainer;
}
//------------------------------
// パーティクルの生成
//------------------------------
private function makeParticle(e:Event):void
{
for (var i:uint = 0; i <_vol; i++)
{
var mc:MovieClip = new(getDefinitionByName(linkage));
container.addChild(mc);
var mouseX:int = container.stage.mouseX;
var mouseY:int = container.stage.mouseY;
var mousePt:Point = new Point(mouseX, mouseY);
var pt:Point = getNearPoint(mousePt);
mc.x = pt.x;
mc.y = pt.y;
mc.xVel = getRandRange( -5, 5);
mc.yVel = getRandRange( -5, 5);
mc.rot = getRandRange( -20, 20);
mc.addEventListener(Event.ENTER_FRAME, onRender);
}
}
//------------------------------
// 指定範囲からランダム値の取得
//------------------------------
private function getRandRange(min:Number, max:Number):Number
{
var randomNum:Number = (Math.random() * (max - min )) + min;
return randomNum;
}
//------------------------------
// 近似ポイント座標の取得
//------------------------------
private function getNearPoint(pt1:Point):Point
{
var len:uint = Math.round(Math.random() * 10);
var angle:uint = Math.round(Math.random() * 2 * Math.PI);
var pt2:Point = Point.polar(len, angle);
pt2.offset(pt1.x, pt1.y);
return pt2;
}
//------------------------------
// スタート
//------------------------------
public function start():void
{
container.stage.addEventListener(Event.ENTER_FRAME, makeParticle);
}
//------------------------------
// ストップ
//------------------------------
public function stop():void
{
container.stage.removeEventListener(Event.ENTER_FRAME, makeParticle);
}
//------------------------------
// クリック
//------------------------------
public function click():void
{
container.stage.addEventListener(Event.ENTER_FRAME, makeParticle);
timer = new Timer(300, 1);
timer.addEventListener(TimerEvent.TIMER, onDelay);
timer.start();
}
private function onDelay(e:TimerEvent):void
{
container.stage.removeEventListener(Event.ENTER_FRAME, makeParticle);
timer.removeEventListener(TimerEvent.TIMER_COMPLETE, onDelay);
}
//------------------------------
// レンダー
//------------------------------
private function onRender(e:Event):void
{
var mc:MovieClip = e.target as MovieClip;
if (mc.alpha> 0)
{
mc.x += mc.xVel + _wind * 10;
mc.y += mc.yVel;
mc.xVel *= _drag;
mc.yVel *= _drag;
mc.scaleX *= _shrink;
mc.scaleY *= _shrink;
mc.yVel += _gravity;
mc.alpha -= _fade;
mc.rotation += mc.rot;
}
else
{
mc.removeEventListener(Event.ENTER_FRAME, onRender);
mc.removeChildAt(0);
container.removeChild(mc);
mc = null;
}
}
//------------------------------
// getter setter
//------------------------------
public function get vol():Number { return _vol; }
public function set vol(value:Number):void {
_vol = value;
}
public function get drag():Number { return _drag; }
public function set drag(value:Number):void {
_drag = value;
}
public function get shrink():Number { return _shrink; }
public function set shrink(value:Number):void {
_shrink = value;
}
public function get gravity():Number { return _gravity; }
public function set gravity(value:Number):void {
_gravity = value;
}
public function get fade():Number { return _fade; }
public function set fade(value:Number):void {
_fade = value;
}
public function get wind():Number { return _wind; }
public function set wind(value:Number):void {
_wind = value;
}
}
}
不具合があれば、指摘していただけると嬉しいです。
I’m starting AS3 and i would like to thank you for the tips on targetContainer’
That’s strange that the stage can’t be call from every where…
>Adrien
I’m studying AS3 too.I think it is difficult until becoming accustomed.
In the another way, after the MovieClip is done in addChild, the reference to the stage can be acquired from MovieClip’s property.
interesting point…
So let’s do that in all AS3 project’
var stageContainer:MovieClip = new MovieClip();
addChild(stageContainer);
var _stage:Stage = stageContainer.stage;
trace(_stage.stageWidth , _stage.stageHeight);
Thank you for your help work Simo*
>Adrien
You’re welcome. It was good to have your help!
こんにちは。
このパーティクル、おもしろいなと思って試していて発見です。
レンダーの if (mc.alpha> 0)
→>は >
パーティクルの生成の for (var i:uint = 0; i <_vol; i++)
→<は <
ですよね。
あら、同じになってしまった…
該当箇所見ていただければ、どういうことか分かりますので
見てみて下さい!
はじめまして。コメントありがとうございます!
んーと、仰っている意味がよく分かりませんで申し訳ないです。不等号の向きが逆ではないかという事でしょうか?お手数ですが詳しく教えていただけますか?
説明不足ですみません><
本当は不等号が表示されるところに、実体参照が表示されてしまってたのです。今見たら直ってました!
僕のブラウザの問題だったら穴に潜りたい…
なるほど、そういう事だったんですね。実体参照はwordPress側で変換してくれるはずなので、もしかしたらブラウザで表示するときに何かの拍子に参照されずそのままレンダリングされていたのかもしれません・・・。
また表示がおかしくなってたら、連絡してもらえるとありがたいです。今後ともよろしくお願いしますね!
そんなことがあるんですねー。
僕も偉そうですがこの件で実体参照って言葉覚えましたw
日々勉強ですね
もちろんですとも。こちらこそよろしくおねがいしますー!
[作ったよ][Flash][AS3]スターパーティクルクラス作ったよ
5ive.blogのsimoさんがAS3で面白いパーティクルを作っておられて、 俺個人的にはこうしたい!ってとこがあったので改造してみたよ。 イメージ capsule の新曲 JUMPER のPVのキラキラ星 やったこ…
勝手に僕好みに改造してしまいました、すいません><
http://d.hatena.ne.jp/dasign/20081128
見ましたよー。パラメータとか色々細かく調整していくと気持ち良い動きになりますよね。がんがん弄ってもらって発展させて下さい!今後の展開も楽しみにしていますので。w