みんなでふよふよ
互いに互いを回避
これが現代社会の縮図
/**
* Copyright uwi ( http://wonderfl.net/user/uwi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/oAnj
*/
// forked from uwi's ふよふよ
// 互いに互いを回避
// これが現代社会の縮図
package {
import com.flashdynamix.utils.SWFProfiler;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.Graphics;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.filters.BitmapFilter;
import flash.filters.GradientBevelFilter;
import flash.filters.BlurFilter;
import flash.utils.Timer;
import flash.utils.getTimer;
import flash.geom.Point;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.display.BlendMode;
[SWF(width=465, height=465, backgroundColor=0x000000, frameRate=60)]
public class Hirari extends Sprite {
private var _bullets : Array;
private var _ct : int;
private var _myx : Point;
private var _myv : Point;
private var _nhit : int;
private const R_BULLET : Number = 10.0;
private var _tf : TextField;
private var _space : BitmapData;
private var _bgspace : BitmapData;
private var _shapeself : Shape;
private var _bmdbullet : BitmapData;
private var _avs : Array; // <Avoider>
private const P0 : Point = new Point(0, 0);
private const WEAKBLUR : BitmapFilter = new BlurFilter(2.0, 2.0);
public function Hirari() {
Wonderfl.capture_delay(5);
SWFProfiler.init(this);
// 宇宙
_space = new BitmapData(465, 465, false, 0x000000);
var bmpspace : Bitmap = new Bitmap(_space);
addChild(bmpspace);
var shs : Shape = new Shape();
var mat : Matrix = new Matrix();
mat.createGradientBox(465, 465, 0, 0, 0);
shs.graphics.beginGradientFill(
"linear",
[0x333377, 0x000000],
[1, 1],
[0, 255],
mat
);
shs.graphics.drawRect(0, 0, 465, 465);
shs.graphics.endFill();
_bgspace = new BitmapData(465, 465, false, 0x000000);
_bgspace.draw(shs);
_shapeself = new Shape();
// 弾描画
var bevel : BitmapFilter = new GradientBevelFilter(4.0, 45, [0xffffff, 0x0000ff], [1.0, 1.0], [70, 255], 4.0, 4.0, 1, 2, "inner");
var sh : Shape = new Shape();
var g : Graphics = sh.graphics;
g.lineStyle(1.0, 0x999999);
g.beginFill(0xeeeeee);
g.drawCircle(R_BULLET, R_BULLET, R_BULLET);
g.endFill();
_bmdbullet = new BitmapData(R_BULLET * 2, R_BULLET * 2, true, 0x00000000);
_bmdbullet.draw(sh);
_bmdbullet.applyFilter(_bmdbullet, _bmdbullet.rect, P0, bevel);
_bmdbullet.applyFilter(_bmdbullet, _bmdbullet.rect, P0, WEAKBLUR);
_myx = new Point(465 / 2, 465 / 2);
_myv = new Point(0, 0);
_bullets = [];
_ct = 0;
_nhit = 0;
addEventListener(Event.ENTER_FRAME, onEnterFrame);
_avs = [];
for(var i : int = 0;i < 12;i++){
addBullet();
_avs.push(new Avoider(_bullets, 465, 0, 465, 0, R_BULLET, 0.4, 0.4, 0.2, 0.2, _bullets[i]));
}
// デバッグ用
_tf = new TextField();
_tf.autoSize = "left";
// _tf.text = "" + _bmd.width + "\t" + _bmd.height;
_tf.textColor = 0xffffff;
_tf.borderColor = 0xffffff;
_tf.border = true;
addChild(_tf);
}
private function onEnterFrame(e : Event) : void
{
draw();
judge();
_ct++;
var i : int = 0;
for each(var b : Bullet in _bullets){
var a : Array = _avs[i].algo(b.x.x, b.x.y, b.v.x, b.v.y, 1);
b.v.x += a[0];
b.v.y += a[1];
b.x.x += b.v.x;
b.x.y += b.v.y;
i++;
}
_tf.text =
"time : " + _ct;
/* +
"\nhit : " + _nhit +
"\nbullets : " + _bullets.length +
"\nval : " + _av._val;
*/
// "\n" + a;
}
// 弾削除
private function removeBullet(i : int) : void
{
if(i < _bullets.length - 1){
_bullets[i] = _bullets.pop();
}else{
_bullets.pop();
}
}
// 当たり判定
private function judge() : void
{
for(var i : int = _bullets.length - 1;i >= 0;i--){
var b : Bullet = _bullets[i];
if(b.x.x < 0 || b.x.x > 465.0 || b.x.y < 0 || b.x.y > 465.0){
var x : Point = new Point(Math.random() * 465, Math.random() * 465);
var v : Point = new Point(Math.random() * 0.2 - 0.1, Math.random() * 0.2 - 0.1);
b.x = x;
b.v = v;
}
}
}
// 描画
private function draw() : void
{
_space.lock();
// _space.fillRect(_space.rect, 0x000000);
_space.copyPixels(_bgspace, _bgspace.rect, P0);
/*
var g : Graphics = _shapeself.graphics;
g.clear();
// self
g.lineStyle(1.0, 0x333399);
g.beginFill(0x3333ff);
g.drawCircle(_myx.x, _myx.y, 5);
g.endFill();
_space.draw(_shapeself, null, null, BlendMode.ADD);
*/
// bullets
for each(var b : Bullet in _bullets){
_space.copyPixels(_bmdbullet, _bmdbullet.rect,
new Point(b.x.x - R_BULLET, b.x.y - R_BULLET));
}
_space.unlock();
}
// 弾追加
private function addBullet() : void
{
var x : Point = new Point(Math.random() * 465, Math.random() * 465);
// var v : Point = new Point(Math.random() * 5 + 2, Math.random() * 4 - 2);
var v : Point = new Point(Math.random() * 0.2 - 0.1, Math.random() * 0.2 - 0.1);
var b : Bullet = new Bullet();
b.x = x;
b.v = v;
b.r = R_BULLET;
_bullets.push(b);
}
}
}
import flash.geom.Point;
class Bullet
{
public var x : Point;
public var v : Point;
public var r : Number;
}
class Avoider
{
private var _bullets : Array;
private var MAXXX : Number;
private var MINXX : Number;
private var MAXXY : Number;
private var MINXY : Number;
private var MYR : Number;
private var LIMAX : Number;
private var LIMAY : Number;
private var STEPAX : Number;
private var STEPAY : Number;
public var _val : Number;
private var _self : Bullet;
public function Avoider(
bullets : Array,
maxxx : Number, minxx : Number,
maxxy : Number, minxy : Number,
myr : Number,
limax : Number, limay : Number,
stepax : Number, stepay : Number,
self : Bullet
) : void
{
_bullets = bullets;
MAXXX = maxxx; MINXX = minxx;
MAXXY = maxxy; MINXY = minxy;
MYR = myr;
LIMAX = limax; LIMAY = limay;
STEPAX = stepax; STEPAY = stepay;
_self = self;
}
// もっとも長い時間生き残れる加速度の組を返す
public function algo(xx : Number, xy : Number, vx : Number, vy : Number, depth : int) : Array
{
var ret : Array = [0.0, 0.0];
var maxval : Number = 0;
for(var ax : Number = -LIMAX;ax <= LIMAX;ax += STEPAX){
for(var ay : Number = -LIMAY;ay <= LIMAY;ay += STEPAY){
// 最低速度を設ける
if((vx + ax) * (vx + ax) + (vy + ay) * (vy + ay) < 0.3)continue;
var val : Number = algoCore(xx, xy, vx, vy, ax, ay, 0, depth);
if(maxval < val){
maxval = val;
ret[0] = ax;
ret[1] = ay;
}
}
}
_val = maxval;
return ret;
}
private function algoCore(xx : Number, xy : Number, vx : Number, vy : Number, ax : Number, ay : Number, dt : int, depth : int) : Number
{
var mint : Number = 50;
// wall
var t : Number;
t = solveQPositive(ax, vx, xx - (MAXXX - MYR)); if(!isNaN(t) && t < mint)mint = t;
t = solveQPositive(ax, vx, xx - (MINXX + MYR)); if(!isNaN(t) && t < mint)mint = t;
t = solveQPositive(ay, vy, xy - (MAXXY - MYR)); if(!isNaN(t) && t < mint)mint = t;
t = solveQPositive(ay, vy, xy - (MINXY + MYR)); if(!isNaN(t) && t < mint)mint = t;
// bullet
for each(var b : Bullet in _bullets){
if(b == _self)continue;
var mybr2 : Number = (MYR + b.r) * (MYR + b.r);
var rxx : Number = xx - (b.x.x + b.v.x * dt);
var rxy : Number = xy - (b.x.y + b.v.y * dt);
var rvx : Number = vx - b.v.x;
var rvy : Number = vy - b.v.y;
for(t = 0;t < mint;t++){
if(rxx * rxx + rxy * rxy <= mybr2)break;
rvx += ax;
rvy += ay;
rxx += rvx;
rxy += rvy;
}
mint = t;
}
if(mint >= 1 && depth >= 1){
// recursion
var maxval : Number = 0;
var tt : int = mint - 1;
var newxx : Number = (ax * (tt + 1) / 2 + vx) * tt + xx;
var newxy : Number = (ay * (tt + 1) / 2 + vy) * tt + xy;
var newvx : Number = ax * tt + vx;
var newvy : Number = ay * tt + vy;
for(var newax : Number = -LIMAX;newax <= LIMAX;newax += STEPAX){
for(var neway : Number = -LIMAY;neway <= LIMAY;neway += STEPAY){
var val : Number = algoCore(newxx, newxy, newvx, newvy, newax, neway, dt + tt, depth - 1);
if(maxval < val){
maxval = val;
}
}
}
mint += maxval;
}
return mint;
}
// 0以上の最小解を求める
private static function solveQPositive(a : Number, b : Number, c : Number) : Number
{
if(a > -0.0001 && a < 0.0001){
return -c / b;
}else{
var D : Number = b * b - 4 * a * c;
if(D < 0)return Number.NaN;
var sqd : Number = Math.sqrt(D);
var a1 : Number = (-b - sqd) / (2 * a);
var a2 : Number = (-b + sqd) / (2 * a);
if(a < 0){
var d : Number = a1; a1 = a2; a2 = d;
}
if(a1 >= 0)return a1;
if(a2 >= 0)return a2;
return Number.NaN;
}
}
}