パーティクル
オブジェクトプールパターンを用いた単純なパーティクルシステム(のつもり)
♥0 |
Line 181 |
Modified 2010-09-12 11:39:17 |
MIT License
archived:2017-03-20 00:56:04
ActionScript3 source code
/**
* Copyright Nicolas ( http://wonderfl.net/user/Nicolas )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/ykFp
*/
package {
import flash.events.Event;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.Sprite;
import net.hires.debug.Stats;
[SWF(frameRate="60")]
public class FlashTest extends Sprite
{
private const WIDTH:int = 465;
private const HEIGHT:int = 465;
private var bmp:Bitmap;
private var bmd:BitmapData;
private var updater:Updater;
private var renderer:Renderer;
private var poolSize:int = 200;
private var pool:ParticlePool;
private var count:int = 0;
public function FlashTest()
{
bmd = new BitmapData(WIDTH, HEIGHT, false, 0x000000);
bmp = addChild(new Bitmap(bmd)) as Bitmap;
ParticlePool.setPoolSize(poolSize);
pool = ParticlePool.getInstance();
updater = new Updater(WIDTH, HEIGHT);
renderer = new Renderer(bmd);
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
addChild(new Stats());
}
private function enterFrameHandler(e:Event):void
{
if(count % 2 == 0)
{
var p:Particle = pool.acquire();
p.x = Math.random() * 465;
p.y = Math.random() * 465;
p.vx = Math.random() * 10 - 5;
p.vy = Math.random() * 10 - 5;
if(p.vx > -1 && p.vx < 1 && p.vy > -1 && p.vy < 1)
{
p.vx = Math.random() * 10 + 3;
p.vy = Math.random() * 10 + 3;
}
p.ax = Math.random() * 1 - 0.5;
p.ay = Math.random() * 1 - 0.5;
}
updater.update();
renderer.render();
count++;
}
}
}
import flash.geom.ColorTransform;
import flash.geom.Rectangle;
import flash.display.BitmapData;
class Renderer
{
private var targetBmd:BitmapData
private var rect:Rectangle;
private var colorTransform:ColorTransform;
private var pool:ParticlePool;
public function Renderer(bmd:BitmapData)
{
targetBmd = bmd;
rect = targetBmd.rect;
colorTransform = new ColorTransform(0.9, 0.9, 0.9);
pool = ParticlePool.getInstance();
}
public function render():void
{
targetBmd.lock();
targetBmd.colorTransform(targetBmd.rect, colorTransform);
var len:int = pool.livingParticles.length;
var p:Particle;
for (var i:int = 0; i < len; i++)
{
p = pool.livingParticles[i];
targetBmd.setPixel(p.x, p.y, 0xFFFFFF);
}
targetBmd.unlock();
}
}
class Updater
{
private var bmdWidth:int;
private var bmdHeight:int;
private var pool:ParticlePool;
public function Updater(width:int, height:int)
{
bmdWidth = width;
bmdHeight = height;
pool = ParticlePool.getInstance();
}
public function update():void
{
var len:int = pool.livingParticles.length;
var p:Particle;
for (var i:int = 0; i < len; i++)
{
p = pool.livingParticles[i];
p.vx += p.ax;
p.vy += p.ay;
p.x += p.vx;
p.y += p.vy;
if(p.x < 0 || p.x > bmdWidth || p.y < 0 || p.y > bmdHeight)
{
pool.release(p);
}
}
}
}
class Particle
{
public var x:int;
public var y:int;
public var vx:int;
public var vy:int;
public var ax:int;
public var ay:int;
public function Particle()
{
}
}
class NullParticle extends Particle
{
private static var _instance:NullParticle;
public function NullParticle(s:SingletonEnforcer)
{
if (!s) throw new Error("Singleton Error");
}
public static function getInstance():NullParticle
{
if (!_instance) return new NullParticle(new SingletonEnforcer());
else return _instance;
}
}
class ParticlePool
{
private static var _instance:ParticlePool;
private static var _poolSize:int;
private var _livingParticles:Vector.<Particle>;
private var _deadParticles:Vector.<Particle>;
public function ParticlePool(s:SingletonEnforcer)
{
if (!s) throw new Error("Singleton Error");
_deadParticles = new Vector.<Particle>();
for (var i:int = 0; i < _poolSize; i++)
{
_deadParticles[i] = new Particle();
}
_livingParticles = new Vector.<Particle>();
}
public static function setPoolSize(n:int):void
{
if (!_instance) _poolSize = n;
else throw new Error("setPoolSize() must be used before creating ParticlePool instance");
}
public static function getInstance():ParticlePool
{
if (!_instance) _instance = new ParticlePool(new SingletonEnforcer());
return _instance;
}
public function acquire():Particle
{
var p:Particle;
if (_deadParticles.length > 0) {
p = _deadParticles.pop();
_livingParticles.push(p);
}
else p = NullParticle.getInstance();
return p;
}
public function release(p:Particle):void
{
var index:int = _livingParticles.indexOf(p);
_livingParticles.splice(index, 1);
_deadParticles.push(p);
}
public function get livingParticles():Vector.<Particle> { return _livingParticles; }
}
class SingletonEnforcer {}