forked from: forked from: パーティクルの応用で弾幕3 - 超最適化 - 凝視注意
コードのリファクタリング & 最適化
* Nicolasが最適化してくれました。
* http://wonderfl.net/code/63f88f2189846bdc7275a01d5d228b1607344e51
* BitmapData#draw() を BitmapData#coloyPixces() に変えるだけ!
* めっちゃ早いよ!これ!
* by coppieee
さらに最適化!
* http://wonderfl.net/code/9dcd5e428a43c4b20f69f86873f2831fa9ec32f3
* に触発されて、私も最適化してみた。Linked listは使いたくなかったので別の方法で。
* これでもか!ってぐらいがんばった。
*
* Particleのプール用意して、
* 削除のところ工夫して、
* 回転の計算のアルゴリズム変更して、
* とかもろもろ。
*
* 弾の大きさを変更したのはオマケ。(オマケなんだけど、小さければ小さいほど速くなるよ。)
* きっとこれ以上の最適化は無理だと思うよ!
*
*
* _canvas.copyPixels()のところを別の描画のアルゴリズムで置き換えたら、あるいはもっと速く・・・。
* by coppieee
*
* ぐおおん、1fps程度しか速くならねぇ。あとのアイデアとしては
* 弾のステップ計算をBitmapDataかPixel Bender使って並列演算ぐらいかな
* 取得のほうが時間かかるのかな
凝視注意
/**
* Copyright uwi ( http://wonderfl.net/user/uwi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/9E8e
*/
// forked from NOB_Q's forked from: パーティクルの応用で弾幕3 - 超最適化 - 凝視注意
// forked from coppieee's パーティクルの応用で弾幕3 - 超最適化
// forked from coppieee's forked from: パーティクルの応用で弾幕2 - 早くなったよ~
// forked from coppieeee's パーティクルの応用で弾幕2 - 早くなったよ~
// forked from coppieeee's 弾幕 - パーティクルの応用で弾幕
/*
* コードのリファクタリング & 最適化
* Nicolasが最適化してくれました。
* http://wonderfl.net/code/63f88f2189846bdc7275a01d5d228b1607344e51
* BitmapData#draw() を BitmapData#coloyPixces() に変えるだけ!
* めっちゃ早いよ!これ!
* by coppieee
*/
/*
* さらに最適化!
* http://wonderfl.net/code/9dcd5e428a43c4b20f69f86873f2831fa9ec32f3
* に触発されて、私も最適化してみた。Linked listは使いたくなかったので別の方法で。
* これでもか!ってぐらいがんばった。
*
* Particleのプール用意して、
* 削除のところ工夫して、
* 回転の計算のアルゴリズム変更して、
* とかもろもろ。
*
* 弾の大きさを変更したのはオマケ。(オマケなんだけど、小さければ小さいほど速くなるよ。)
* きっとこれ以上の最適化は無理だと思うよ!
*
*
* _canvas.copyPixels()のところを別の描画のアルゴリズムで置き換えたら、あるいはもっと速く・・・。
* by coppieee
*
* ぐおおん、1fps程度しか速くならねぇ。あとのアイデアとしては
* 弾のステップ計算をBitmapDataかPixel Bender使って並列演算ぐらいかな
* 取得のほうが時間かかるのかな
*/
/**
* 凝視注意
*/
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import net.hires.debug.Stats;
[SWF(width="512",height="512", frameRate="60" )]
public class PShooting extends Sprite
{
//1fpsあたりの弾の生成数
public static const BULLET_COUNT:int = 200;
public static const WIDTH:Number = 512;
public static const HEIGHT:Number = 512;
//弾のビットマップキャッシュ
private const COLOR_NUM:int = 24;
private var _bulletImg:Vector.<BitmapData> = new Vector.<BitmapData>(COLOR_NUM);
private var _bigColor:Vector.<int> = new Vector.<int>(COLOR_NUM);
private var _smallColor:Vector.<int> = new Vector.<int>(COLOR_NUM);
//キャンバス
private var _canvas:BitmapData;
//パーティクルリスト(Vector#unshift()がバグってて使えないので、しょうがないからArray使う。)
private var _particles:/*Particle*/Array;
//敵。というか弾の再生位置。
private var _enemy:Particle;
//パーティクルプール(いらなくなったパーティクルを溜めとくとこ)
private var _particlesPool:Vector.<Particle>;
private var _colorIndexCount:int = 0;
public function PShooting()
{
Wonderfl.capture_delay( 7 );
//キャンバスの生成
_canvas = new BitmapData(WIDTH, HEIGHT,false,0x000000);
var cb:Bitmap = new Bitmap(_canvas);
addChild(cb);
_particles = [];
_enemy = new Particle();
_particlesPool = new Vector.<Particle>();
var seq:int = 0;
_bigColor[seq] = 0xFF0000; _smallColor[seq] = 0x550000; seq++;
_bigColor[seq] = 0xFF0040; _smallColor[seq] = 0x550015; seq++;
_bigColor[seq] = 0xFF007F; _smallColor[seq] = 0x55002B; seq++;
_bigColor[seq] = 0xFF00C0; _smallColor[seq] = 0x550040; seq++;
_bigColor[seq] = 0xFF00FF; _smallColor[seq] = 0x550055; seq++;
_bigColor[seq] = 0xC000FF; _smallColor[seq] = 0x400055; seq++;
_bigColor[seq] = 0x7F00FF; _smallColor[seq] = 0x2B0055; seq++;
_bigColor[seq] = 0x4000FF; _smallColor[seq] = 0x150055; seq++;
_bigColor[seq] = 0x0000FF; _smallColor[seq] = 0x000055; seq++;
_bigColor[seq] = 0x0040FF; _smallColor[seq] = 0x001555; seq++;
_bigColor[seq] = 0x007FFF; _smallColor[seq] = 0x002B55; seq++;
_bigColor[seq] = 0x00C0FF; _smallColor[seq] = 0x004055; seq++;
_bigColor[seq] = 0x00FFFF; _smallColor[seq] = 0x005555; seq++;
_bigColor[seq] = 0x00FFC0; _smallColor[seq] = 0x005540; seq++;
_bigColor[seq] = 0x00FF7F; _smallColor[seq] = 0x00552B; seq++;
_bigColor[seq] = 0x00FF40; _smallColor[seq] = 0x005515; seq++;
_bigColor[seq] = 0x00FF00; _smallColor[seq] = 0x005500; seq++;
_bigColor[seq] = 0x40FF00; _smallColor[seq] = 0x155500; seq++;
_bigColor[seq] = 0x7FFF00; _smallColor[seq] = 0x2B5500; seq++;
_bigColor[seq] = 0xC0FF00; _smallColor[seq] = 0x405500; seq++;
_bigColor[seq] = 0xFFFF00; _smallColor[seq] = 0x555500; seq++;
_bigColor[seq] = 0xFFC000; _smallColor[seq] = 0x554000; seq++;
_bigColor[seq] = 0xFF7F00; _smallColor[seq] = 0x552B00; seq++;
_bigColor[seq] = 0xFF4000; _smallColor[seq] = 0x551500; seq++;
//弾のBitmapの生成
var shape:Shape;
var g:Graphics;
for (var i:int = 0; i < COLOR_NUM; i++) {
//Shapeに円を書く。
shape = new Shape();
g = shape.graphics;
g.beginFill(_bigColor[i], 0.5);
g.drawCircle(8, 8, 8);
g.beginFill(_smallColor[i]);
g.drawCircle(8, 8, 4);
g.endFill();
//BitmapDataにdraw()
_bulletImg[i] = new BitmapData(shape.width, shape.height, true, 0xFFFFFF);
_bulletImg[i].draw(shape);
}
//Statsの生成
addChild(new Stats());
addEventListener(Event.ENTER_FRAME, onEnterFrame);
//particlsの個数表示用のTextField生成
var tf:TextField = new TextField();
tf.y = 100;
tf.textColor = 0xFFFFFF;
tf.background = true;
tf.backgroundColor = 0x000000;
tf.autoSize = TextFieldAutoSize.LEFT;
tf.multiline = true;
addChild(tf);
addEventListener(Event.ENTER_FRAME, function(e:Event):void {
tf.text = "bullets:" + _particles.length +"\n pool:"+_particlesPool.length ;
});
}
private var _radian:Number = 0;
private var _ct:ColorTransform = new ColorTransform (0.9, 0.9, 0.95);
private var _phi:Number = Math.PI / 180 * 80;
private var _cosPhi:Number = Math.cos(_phi) * 0.02; //0.02はオマケ
private var _sinPhi:Number = Math.sin(_phi) * 0.02;
private var _cosplus:Number = Math.cos(Math.PI * 2 / BULLET_COUNT);
private var _sinplus:Number = Math.sin(Math.PI * 2 / BULLET_COUNT);
private function onEnterFrame(e:Event):void
{
//弾の生成場所をマウスのところへ移動
_enemy.vx = (stage.mouseX - _enemy.x) * 0.05;
_enemy.vy = (stage.mouseY - _enemy.y) * 0.05;
_enemy.x += _enemy.vx;
_enemy.y += _enemy.vy;
//回転
_radian += (Math.PI / 180) *62.1;
var bRadian:Number = _radian;
var c:Number = Math.cos(bRadian);
var s:Number = Math.sin(bRadian);
//弾の生成
for (var i:int = 0; i <BULLET_COUNT; i++ )
{
var vx:Number = c * 10;
var vy:Number = s * 10;
var newP:Particle;
if (_particlesPool.length != 0)
{
newP = _particlesPool.pop();
}else{
newP = new Particle();
}
newP.x = _enemy.x;
newP.y = _enemy.y;
newP.vx = vx;
newP.vy = vy;
newP.ci = _colorIndexCount % COLOR_NUM;
_particles.unshift(newP);
var nc:Number = c * _cosplus - s * _sinplus;
var ns:Number = s * _cosplus + c * _sinplus;
c = nc;
s = ns;
}
_colorIndexCount++;
//必要な計算はforループの前にしておく。
var bulletRect:Rectangle = _bulletImg[0].rect;
var bulletPoint:Point = new Point();
var bWidth_2:int = _bulletImg[0].width / 2;
var bHeight_2:int = _bulletImg[0].height / 2;
var xMin:int = - bWidth_2 / 2;
var yMin:int = - bHeight_2 / 2;
var xMax:int = bWidth_2 + WIDTH;
var yMax:int = bHeight_2 + HEIGHT;
_canvas.lock();
_canvas.colorTransform(_canvas.rect, _ct);
//下の方が軽いけど、見た目が悪くなる。
//_canvas.fillRect(_canvas.rect, 0x000000);
//弾の移動
for (var j:int = _particles.length - 1; j != -1 ;j--)
{
var p:Particle = _particles[j];
//ベクトルうめぇww
p.ax = p.vx * _cosPhi - p.vy * _sinPhi;
p.ay = p.vy * _cosPhi + p.vx * _sinPhi;
p.x += (p.vx += p.ax);
p.y += (p.vy += p.ay);
// p.vx += p.ax;
// p.vy += p.ay;
//画面外に出たら削除
if (p.x < xMin || p.x > xMax || p.y < yMin || p.y > yMax)
{
_particlesPool.push(p);
if(j == _particles.length - 1){
_particles.pop();
}else{
_particles[j] = _particles.pop();
}
// _particles.splice(j, 1);
continue;
}
bulletPoint.x = p.x - bWidth_2;
bulletPoint.y = p.y - bHeight_2;
_canvas.copyPixels(_bulletImg[p.ci], bulletRect, bulletPoint);
}
_canvas.unlock();
}
}
}
class Particle
{
public var x:Number = 0;
public var y:Number = 0;
public var vx:Number = 0;
public var vy:Number = 0;
public var ax:Number = 0;
public var ay:Number = 0;
public var ci:int = 0;
}