forked from: [セルフフォーク]ひだまりスケッチの星 を飛び散るようにしてみた
some minor optimisation to cpu and mem
added a gravity-like behavior
ひだまりスケッチ ほしみっつ の星 を飛び散るようにしてみた
@author Hiiragi
セルフフォーク
作らなきゃいけないコンテンツを作る気が起きなかったので
なんとなく思いついて、違うことをしてみました。
OPのサビ前に、星がバシバシ飛び散るのを再現してみました。
ステージをクリックすると星が飛び散ります。
本当は、写真を読み込んで、それをクリックしたときに
ガーッと揺れ動くというか拡大するというか
そういうのをやりたかったんですが、上手くいかなかったので終了。
FlashCampで話が出た「cacheAsBitmap」と「オブジェクトプール」を
試してみた感じです。確かにSpriteをガシガシ作ってるけど、
ガベージコレクションがかからない感じ。
最初に720個の星と初期設定をしてるので、最初若干重いです。
// forked from Hiiragi's [セルフフォーク]ひだまりスケッチの星 を飛び散るようにしてみた
//
// some minor optimisation to cpu and mem
// added a gravity-like behavior
package
{
import flash.display.*;
import flash.events.*;
import flash.geom.Matrix;
import flash.net.FileReference;
import flash.utils.Timer;
import com.bit101.components.PushButton;
/**
* ひだまりスケッチ ほしみっつ の星 を飛び散るようにしてみた
* @author Hiiragi
*
* セルフフォーク
* 作らなきゃいけないコンテンツを作る気が起きなかったので
* なんとなく思いついて、違うことをしてみました。
*
* OPのサビ前に、星がバシバシ飛び散るのを再現してみました。
* ステージをクリックすると星が飛び散ります。
*
* 本当は、写真を読み込んで、それをクリックしたときに
* ガーッと揺れ動くというか拡大するというか
* そういうのをやりたかったんですが、上手くいかなかったので終了。
*
* FlashCampで話が出た「cacheAsBitmap」と「オブジェクトプール」を
* 試してみた感じです。確かにSpriteをガシガシ作ってるけど、
* ガベージコレクションがかからない感じ。
*
* 最初に720個の星と初期設定をしてるので、最初若干重いです。
*
*/
[SWF(width = 465, height = 465, frameRate = 60, backgroundColor = 0xFFAAAA)]
public class Main extends Sprite
{
private var _fr:FileReference;
private var _loadBtn:PushButton;
private var _loader:Loader;
private var _loadImageSp:Sprite;
private var _timer:Timer;
private var _backSp:Sprite;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
start();
// entry point
//_fr = new FileReference();
//_fr.addEventListener(Event.SELECT, fileSelectedHandler);
//
//_loadImageSp = new Sprite();
//
//_loader = new Loader();
//_loadBtn = new PushButton(this, 0, 0, "load Image", loadImage);
//_loadBtn.x = this.stage.stageWidth / 2 - _loadBtn.width / 2;
//_loadBtn.y = this.stage.stageHeight / 2 - _loadBtn.height / 2;
}
//public function loadImage(e:MouseEvent):void
//{
//_fr.browse();
//}
//
//private function fileSelectedHandler(e:Event):void
//{
//trace("test");
//_fr.addEventListener(ProgressEvent.PROGRESS,onProgress);
//_fr.addEventListener(Event.COMPLETE,onComplete);
// _fr.addEventListener(Event.OPEN, onOpen);
// _fr.addEventListener(IOErrorEvent.IO_ERROR, onIoError);
//_fr.load(); // 読み込み処理を開始
//}
//
//private function onProgress(e:ProgressEvent):void
//{
//trace("読み込んだバイト数:" + e.bytesLoaded + "、 全体のバイト数:" + e.bytesTotal);
//}
//
//private function onComplete(e:Event):void
//{
//_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imgLoadComplete);
//_loader.loadBytes(_fr.data);
//
// fr.type を参考にオブジェクト変換する等の処理を記述
// fr.removeEventListener(...)
//}
//
//private function imgLoadComplete(e:Event):void
//{
//trace("enemyImage Load Completed");
//
//var loadImage:Bitmap = new Bitmap(imageSizeCompressor(Bitmap(_loader.content).bitmapData, this.stage.stageWidth, this.stage.stageHeight));
//
//_loadImageSp.addChild(loadImage);
//
//_loadImageSp.x = this.stage.stageWidth / 2 - _loadImageSp.width / 2;
//_loadImageSp.y = this.stage.stageHeight / 2 - _loadImageSp.height / 2;
//
//this.addChild(_loadImageSp);
//
//start();
//}
//
///**
//* 指定のBitmapDataを、幅と高さの比率をそのままに、閾値に合わせて拡大縮小します。
//*
//* @param inputBitmapData 拡大・縮小したいBitmapData
//* @param maxWidth 幅の閾値
//* @param maxHeight 高さの閾値
//* @return 閾値に合わせて拡大・縮小したBitmapData
//*/
//private function imageSizeCompressor(inputBitmapData:BitmapData, maxWidth:int, maxHeight:int):BitmapData
//{
//var ratio:Number; //どれくらい拡大・縮小するか
//var fixWidth:int; //拡大・縮小したときの幅
//var fixHeight:int; //拡大・縮小したときの高さ
//
//var returnBitmapData:BitmapData;
//
//maxWidth * maxHeightの範囲内に最大限に収める
//横長の場合
//if (inputBitmapData.width / inputBitmapData.height >= maxWidth / maxHeight)
//{
//横長なので、横の大きさを閾値に合わせ、その比率分、高さを拡大縮小して、縦横の比率をそのままにサイズ変更する。
//ratio = maxWidth / inputBitmapData.width;
//fixWidth = maxWidth;
//fixHeight = inputBitmapData.height * ratio;
//}
//縦長の場合
//else if (inputBitmapData.width / inputBitmapData.height < maxWidth / maxHeight)
//{
//ratio = maxHeight / inputBitmapData.height;
//fixWidth = inputBitmapData.width * ratio;
//fixHeight = maxHeight;
//}
//
//returnBitmapData = new BitmapData(fixWidth, fixHeight, true, 0x0);
//returnBitmapData.draw(inputBitmapData, new Matrix(ratio, 0, 0, ratio));
//
//return returnBitmapData;
//}
private function start():void
{
//_timer = new Timer(33, 10);
//_timer.addEventListener(TimerEvent.TIMER, shakeDisplayObject);
//_timer.addEventListener(TimerEvent.TIMER_COMPLETE, shakeDisplayObjectComplete);
var mtx:Matrix = new Matrix();
mtx.createGradientBox(this.stage.stageWidth, this.stage.stageHeight, Math.PI / 2);
var g:Graphics = this.graphics;
g.beginGradientFill(GradientType.LINEAR, [0xFFEEEE, 0xFFFFFF], [1, 1], [0, 255], mtx);
g.drawRect(0, 0, this.stage.stageWidth, this.stage.stageHeight);
g.endFill();
var burst:HidamariStarBurst = new HidamariStarBurst(this.stage.stageWidth, this.stage.stageHeight);
this.addChild(burst);
this.stage.addEventListener(MouseEvent.MOUSE_DOWN, burst.burst);
//_loadImageSp.addEventListener(MouseEvent.CLICK, burst.burst);
//_loadImageSp.addEventListener(MouseEvent.CLICK, startShakeDisplayObject);
}
//private function startShakeDisplayObject(e:MouseEvent):void
//{
//if (_timer.running) _timer.stop();
//_timer.reset();
//_timer.start();
//}
//private function shakeDisplayObject(e:TimerEvent):void
//{
//_loadImageSp.x = Math.random() * 30 - 15;
//_loadImageSp.y = Math.random() * 30 - 15;
//}
//
//private function shakeDisplayObjectComplete(e:TimerEvent):void
//{
//_loadImageSp.x = _loadImageSp.y = 0;
//}
}
}
import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.Matrix;
import flash.geom.Point;
class HidamariStarBurst extends Sprite
{
private const STAR_MAX:uint = 90;
private const BURST_NUM:int = 15;
private var _sw:int;
private var _sh:int;
private var _starPool:Array;
private var _activeStars:Array;
private var _burstFlag:Boolean;
static public const secondStarBevelFilter:BevelFilter = new BevelFilter(2, -45, 0x996666, 1, 0, .3, 2, 2, 1, 2, BitmapFilterType.OUTER, false);
static public const centerStarBevelFilter:BevelFilter = new BevelFilter(2, -45, 0x996666, 1, 0, .5, 2, 2, 1, 2, BitmapFilterType.OUTER, false);
private var _clickPoint:Point;
public function HidamariStarBurst(stageWidth:int, stageHeight:int)
{
_sw = stageWidth;
_sh = stageHeight;
_starPool = [];
_activeStars = [];
var star:HidamariStarExtend;
var absX:Number;
var absY:Number;
for (var i:int = 0; i < STAR_MAX; i++)
{
star = new HidamariStarExtend(Math.random() * 30 + 20);
star.visible = false;
star.vx = Math.random() * 50 - 25;
star.vy = Math.random() * 50 - 25;
absX = Math.abs(star.vx);
absY = Math.abs(star.vy);
if (absX + absY < 10)
{ if (absX >= absY)
{
if (star.vx >= 0) star.vx += 25;
else star.vx -= 25;
}
else
{
if (star.vy >= 0) star.vy += 25;
else star.vy -= 25;
}
}
star.rotation = i;
star.cacheAsBitmap = true;
this.addChild(star);
_starPool[i] = star;
}
this.addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
}
public function velocityCompressor(velocity:Number):Number
{
if (velocity < 2 && velocity > -2)
{
if (velocity > 0) velocity += 2;
else velocity -= 2;
}
return velocity;
}
public function burst(e:MouseEvent):void
{
_burstFlag = true;
_clickPoint = new Point(e.stageX, e.stageY);
}
private function burstStarProcess():void
{
var star:HidamariStarExtend;
for (var i:int = 0; i < BURST_NUM; i++)
{
star = _starPool.shift();
star.visible = true;
star.x = _clickPoint.x;
star.y = _clickPoint.y;
star.vx = Math.random() * 50 - 25;
star.vy = Math.random() * 50 - 25;
_activeStars.push(star);
}
}
private function onEnterFrameHandler(e:Event):void
{
var len:int = _activeStars.length;
var star:HidamariStarExtend;
var deleteFlag:Boolean;
for (var i:int = len - 1; i >= 0; i--)
{
deleteFlag = false;
star = _activeStars[i];
star.x += star.vx;
star.y += star.vy;
star.vy += 1;
if (star.x < -star.width * .5)
{
deleteFlag = true;
}
else if (star.x > _sw + star.width * .5)
{
deleteFlag = true;
}
if (star.y < -star.height * .5)
{
deleteFlag = true;
}
else if (star.y > _sh + star.height * .5)
{
deleteFlag = true;
}
if (deleteFlag)
{
_activeStars.splice(i, 1);
_starPool.push(star);
star.visible = false;
}
}
if (_burstFlag)
{
burstStarProcess();
_burstFlag = false;
}
}
}
class HidamariStar extends Sprite
{
private var _cx:Number;
private var _cy:Number;
private var _radius:Number;
private var _insideRatio:Number;
private var _secondStar:Shape;
private var _centerStar:Shape;
private var _secondStarBevelFilter:BevelFilter;
private var _centerStarBevelFilter:BevelFilter;
public function HidamariStar(radius:Number,
cx:Number = 0,
cy:Number = 0,
insideRatio:Number = 0.5)
{
_radius = radius;
_cx = cx;
_cy = cy;
_insideRatio = insideRatio;
_secondStar = new Shape();
_centerStar = new Shape();
this.addChild(_secondStar);
this.addChild(_centerStar);
_secondStar.filters = [HidamariStarBurst.secondStarBevelFilter];
_centerStar.filters = [HidamariStarBurst.centerStarBevelFilter];
draw();
}
public function draw():void
{
var mtx:Matrix = new Matrix();
var g:Graphics = this.graphics;
g.clear();
g.beginFill(0xFFFFFF);
g.lineStyle(10, 0xFFFFFF);
drawStar(g, _radius);
g.endFill();
g = _secondStar.graphics;
g.clear();
mtx.createGradientBox(_radius * 2, _radius * 2, -Math.PI / 4, -_cx -_radius, -_cy - _radius);
g.beginGradientFill(GradientType.LINEAR, [0xf0ac96, 0x780100], [1, 1], [0, 255], mtx);
drawStar(g, _radius * .95);
g.endFill();
g = _centerStar.graphics;
g.clear();
mtx.createGradientBox(_radius * 2, _radius * 2, -Math.PI / 4, -_cx -_radius, -_cy - _radius);
g.beginGradientFill(GradientType.LINEAR, [0xfdf9fa, 0xfdae10], [1, 1], [0, 255], mtx);
drawStar(g, _radius * 0.8);
g.endFill();
}
private function drawStar(g:Graphics, radius:Number):void
{
g.moveTo(_cx, _cy - radius);
var diffRad:Number = Math.PI / 5;
var rad:Number = -Math.PI * .5;
var tempRadius:Number;
for (var i:int = 1; i <= 10; i++)
{
rad += diffRad;
tempRadius = (i % 2 == 1) ? tempRadius = radius * _insideRatio : tempRadius = radius;
g.lineTo(Math.cos(rad) * tempRadius + _cx, Math.sin(rad) * tempRadius + _cy);
}
}
public function get radius():Number { return _radius; }
public function set radius(value:Number):void
{
_radius = value;
draw();
}
public function get insideRatio():Number { return _insideRatio; }
public function set insideRatio(value:Number):void
{
_insideRatio = value;
draw();
}
}
class HidamariStarExtend extends HidamariStar
{
private var _vx:Number;
public function get vx():Number { return _vx; }
public function set vx(value:Number):void
{
_vx = value;
}
private var _vy:Number;
public function get vy():Number { return _vy; }
public function set vy(value:Number):void
{
_vy = value;
}
public function HidamariStarExtend(radius:Number,
cx:Number = 0,
cy:Number = 0,
insideRatio:Number = 0.5)
{
super(radius, cx, cy, insideRatio);
this.mouseEnabled = false;
}
}