forked from: 【AS100本ノック】7回目:ローディング(バー)
AS100本ノック
* 7回目のお題は「ローディング(バー)」
* あなたなりの「ローディング(バー)」を表現してください。
*
* 100個のボールがボトルに注がれるローダーです。
/**
* Copyright mex_takagi ( http://wonderfl.net/user/mex_takagi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/yAmP
*/
// forked from mex's 【AS100本ノック】7回目:ローディング(バー)
/*
* AS100本ノック
* 7回目のお題は「ローディング(バー)」
* あなたなりの「ローディング(バー)」を表現してください。
*
* 100個のボールがボトルに注がれるローダーです。
*/
package
{
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.ProgressEvent;
import flash.events.TimerEvent;
import flash.filters.BlurFilter;
import flash.net.URLRequest;
import flash.utils.Timer;
import flash.filters.BevelFilter;
import Box2D.Dynamics.*;
import Box2D.Collision.*;
import Box2D.Collision.Shapes.*;
import Box2D.Dynamics.Joints.*;
import Box2D.Dynamics.Contacts.*;
import Box2D.Common.*;
import Box2D.Common.Math.*;
[SWF(backgroundColor = "0xCCCCCC", width = "465", height = "465", frameRate = 60)]
public class Main extends Sprite
{
public var stageW:uint;
public var stageH:uint;
private var m_sprite:Sprite;
private var m_world:b2World;
private var m_physScale:Number = 30.0;
private var m_iterations:int = 10;
private var m_timeStep:Number = 1.0 / 60.0;
private var _radius:uint;
private var _timer:Timer;
private var _per:uint;
private var _oldPer:uint;
private var _grad:Gradation;
private var _bottle:Sprite;
private var _loader:Loader;
/**
* constructor
*/
public function Main():void
{
stageW = 465;
stageH = 465;
m_sprite = new Sprite();
addChild(m_sprite);
var worldAABB:b2AABB = new b2AABB();
worldAABB.lowerBound.Set(-1000.0, -1000.0);
worldAABB.upperBound.Set(1000.0, 1000.0);
var gravity:b2Vec2 = new b2Vec2(0.0, 10.0);
var doSleep:Boolean = true;
m_world = new b2World(worldAABB, gravity, doSleep);
_grad = new Gradation(0xde4849, 0xf6f63b, 0x63c24a, 0x5471ef, 0xdf01c8);
_radius = 9;
_per = 0;
_oldPer = 0;
createBottle();
var date:Date = new Date();
//一応ダミーの画像がキャッシュに残っても良いようにタイムスタンプ
var stamp:String = addZero(date.getMonth() + 1, 2) +
addZero(date.getDate(), 2) +
addZero(date.getHours(), 2) +
addZero(date.getMinutes(), 2) +
String(date.getMilliseconds());
_loader = new Loader();
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
_loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);
_loader.load(new URLRequest("http://image.dev-mex.com/dummy.jpg?" + stamp));
_timer = new Timer(100);
_timer.addEventListener(TimerEvent.TIMER, timerHandler);
_timer.start();
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
/**
* ロード中
* _perをアップデート。
* @param event ProgressEvent
*/
private function onProgress(event:ProgressEvent):void
{
_per = Math.floor(event.bytesLoaded / event.bytesTotal * 100);
}
/**
* ロード終了
* @param event Event
*/
private function onComplete(event:Event):void
{
_loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onComplete);
_loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, onProgress);
}
/**
* 一定間隔で_perの変化を読み取って、変化量だけボールを生成。
* @param event TimerEvent
*/
private function timerHandler(event:TimerEvent):void
{
var color:uint;
if (_oldPer != _per)
{
for (var i:uint = _oldPer; i < _per;i++ )
{
color = _grad.getColor(i / 100);
createCircle(color, i);
addChild(_bottle);
}
_oldPer = _per;
}
else if (_oldPer == 100 && _per == 100)
{
_timer.stop();
_timer.removeEventListener(TimerEvent.TIMER, timerHandler);
color = _grad.getColor(100);
createCircle(color, 100);
}
}
/**
* ボールを生成
*/
private function createCircle(color:uint, id:uint):void
{
var circleDef:b2CircleDef = new b2CircleDef();
var circleBodyDef:b2BodyDef = new b2BodyDef();
var circle:Sprite = new Circle(id, _radius, color);
circle.y = -100;
circleDef.radius = _radius / m_physScale;
circleDef.density = 25;
circleDef.friction = 0.1;
circleDef.restitution = 0.2;
circleBodyDef = new b2BodyDef();
circleBodyDef.userData = circle;
circleBodyDef.position.Set(465 / 2 / m_physScale, (-_radius - id * 10) / m_physScale);
var circleBody:b2Body = m_world.CreateBody(circleBodyDef);
circleBody.CreateShape(circleDef);
circleBody.SetMassFromShapes();
addChild(circleBodyDef.userData);
}
/**
* ボトルを生成
*/
private function createBottle():void
{
var bottleObject:b2PolygonDef = new b2PolygonDef();
bottleObject.density = 0.0;
var bottleDef:b2BodyDef = new b2BodyDef();
var bottleBody:b2Body;
_bottle = bottleGraphic();
bottleDef.userData = _bottle;
bottleObject.friction = 0.3;
bottleObject.restitution = 0.9;
bottleDef.position.Set(218 / m_physScale, 95 / m_physScale);
bottleObject.SetAsBox(1 / m_physScale, 65 / m_physScale);
bottleBody = m_world.CreateBody(bottleDef);
bottleBody.CreateShape(bottleObject);
bottleBody.SetMassFromShapes();
bottleDef.position.Set(201 / m_physScale, 180 / m_physScale);
bottleDef.angle = Math.PI/180 * 42;
bottleObject.SetAsBox(1 / m_physScale, 25 / m_physScale);
bottleBody = m_world.CreateBody(bottleDef);
bottleBody.CreateShape(bottleObject);
bottleBody.SetMassFromShapes();
bottleDef.position.Set(185 / m_physScale, 318 / m_physScale);
bottleDef.angle = 0;
bottleObject.SetAsBox(2 / m_physScale, 118 / m_physScale);
bottleBody = m_world.CreateBody(bottleDef);
bottleBody.CreateShape(bottleObject);
bottleBody.SetMassFromShapes();
bottleDef.position.Set(256 / m_physScale, 95 / m_physScale);
bottleDef.angle = 0;
bottleObject.SetAsBox(1 / m_physScale, 65 / m_physScale);
bottleBody = m_world.CreateBody(bottleDef);
bottleBody.CreateShape(bottleObject);
bottleBody.SetMassFromShapes();
bottleDef.position.Set(274 / m_physScale, 180 / m_physScale);
bottleDef.angle = -Math.PI/180 * 42;
bottleObject.SetAsBox(1 / m_physScale, 25 / m_physScale);
bottleBody = m_world.CreateBody(bottleDef);
bottleBody.CreateShape(bottleObject);
bottleBody.SetMassFromShapes();
bottleDef.position.Set(291 / m_physScale, 318 / m_physScale);
bottleDef.angle = 0;
bottleObject.SetAsBox(2 / m_physScale, 118 / m_physScale);
bottleBody = m_world.CreateBody(bottleDef);
bottleBody.CreateShape(bottleObject);
bottleBody.SetMassFromShapes();
bottleDef.position.Set((465 / 2 + 5) / m_physScale, 439 / m_physScale);
bottleDef.angle = -Math.PI/180 * 1;
bottleObject.SetAsBox(55 / m_physScale, 1 / m_physScale);
bottleBody = m_world.CreateBody(bottleDef);
bottleBody.CreateShape(bottleObject);
bottleBody.SetMassFromShapes();
addChild(_bottle);
}
/**
* ボトルのグラフィック生成
*/
private function bottleGraphic():Sprite
{
var bevel:BevelFilter = new BevelFilter(5, 22, 0xFFF7E8, 1, 0x000000, 0.27, 11, 14, 1, 3, "inner", true);
var container:Sprite = new Sprite();
var sprite:Sprite = new Sprite();
sprite.graphics.beginFill(0xFFFFFF);
sprite.graphics.moveTo(35, 5);
sprite.graphics.curveTo(35, 0, 40, 0);
sprite.graphics.lineTo(70, 0);
sprite.graphics.curveTo(75, 0, 75, 5);
sprite.graphics.lineTo(75, 0);
sprite.graphics.lineTo(75, 130);
sprite.graphics.curveTo(110, 150, 110, 180);
sprite.graphics.lineTo(110, 400);
sprite.graphics.curveTo(110, 410, 105, 410);
sprite.graphics.lineTo(5, 410);
sprite.graphics.curveTo(0, 410, 0, 400);
sprite.graphics.lineTo(0, 180);
sprite.graphics.curveTo(0, 150, 35, 130);
sprite.graphics.lineTo(35, 0);
sprite.filters = [bevel];
sprite.x = -36;
sprite.y = -65;
container.addChild(sprite);
return container;
}
/**
* enterFrameHandler
* @param event Event
*/
private function enterFrameHandler(event:Event):void
{
m_world.Step(m_timeStep, m_iterations);
m_sprite.graphics.clear();
for (var bb:b2Body = m_world.m_bodyList; bb; bb = bb.m_next)
{
if (bb.m_userData is Sprite)
{
bb.m_userData.x = bb.GetPosition().x * 30;
bb.m_userData.y = bb.GetPosition().y * 30;
bb.m_userData.rotation = bb.GetAngle() * 180 / Math.PI;
}
}
}
/**
* 数字に、指定した桁数だけ0を足すメソッド。タイムスタンプ用。
*
* @param num 0を足したい数字です。
* @param digit 桁数です。
* @return 計算結果の文字列です。
*/
public function addZero( num:uint, digit:uint):String
{
var str:String = num.toString();
var len:uint = str.length;
var zeroNum:int = digit - len;
if (zeroNum > 0)
{
var temp:String = "";
for (var i:uint = 0; i < zeroNum;i++ )
{
temp += "0";
}
str = temp + str;
}
return str;
}
}
}
/**
* ボールのグラフィック
*/
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.geom.Matrix;
class Circle extends Sprite
{
/**
* constructor
* @param r uint
* @param color uint
*/
public function Circle(id:uint, r:uint, color:uint)
{
graphics.beginFill(color);
graphics.drawCircle(0, 0, r);
graphics.endFill();
/*数字入れたければコメントアウト解除
var field:TextField = new TextField();
var format:TextFormat = new TextFormat();
format.color = 0xAAAAAA;
format.size = 9;
format.bold = true;
field.defaultTextFormat = format;
field.selectable = false;
field.antiAliasType = "advanced";
field.autoSize = "left";
field.text = String(id);
var bmd:BitmapData = new BitmapData(field.width, field.height, true, 0x00ffffff);
bmd.draw(field);
var bitmap:Bitmap = new Bitmap(bmd);
bitmap.x = -field.width / 2;
bitmap.y = -field.height / 2;
addChild(bitmap);
*/
}
}
/**
* ↓Gradationクラスを拝借
* http://wonderfl.net/code/7ed2d650b9d513edf9a499fb704c19ecb7aa4694
*/
import frocessing.color.ColorLerp;
import org.libspark.betweenas3.core.easing.IEasing;
import org.libspark.betweenas3.easing.Linear;
class Gradation
{
private var _colors:Array;
private var _easing:IEasing;
public function Gradation(...args)
{
_colors = args.concat();
_easing = Linear.linear;
}
public function setEasing(easing:IEasing):void
{
_easing = easing;
}
public function getColor(position:Number):uint
{
position = (position < 0 ? 0 : position > 1 ? 1 : position) * (_colors.length - 1);
var idx:int = position;
var alpha:Number = _easing.calculate(position - idx, 0, 1, 1);
if (alpha == 0) {
return _colors[idx];
} else {
return ColorLerp.lerp(_colors[idx], _colors[idx + 1], alpha);
}
}
}