[Box2D]いちおう時計
/**
* Copyright inippo ( http://wonderfl.net/user/inippo )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/e3jo
*/
/**
* Box2DClock
* Box2Dを使って時計もどき
*
* trick7さんのTeraClockをお借りしました。
* http://www.libspark.org/wiki/trick7/TeraClock
*
* */
package {
import Box2D.Collision.b2AABB;
import Box2D.Collision.Shapes.b2CircleDef;
import Box2D.Collision.Shapes.b2PolygonDef;
import Box2D.Common.Math.b2Vec2;
import Box2D.Dynamics.b2Body;
import Box2D.Dynamics.b2BodyDef;
import Box2D.Dynamics.b2DebugDraw;
import Box2D.Dynamics.b2World;
import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.text.*;
import flash.utils.*;
[SWF(width = 465, height = 465, frameRate = 60 , backgroundColor = "#F6f6f6")]
public class Box2DClock extends Sprite {
public var tf:TextField;
public var tfm:TextFormat;
public var world:b2World;
public var body:b2Body;
public var worldAABB:b2AABB;
public var floorBodyDef:b2BodyDef;
public var clock:TeraClock;
public const FONT:String = "Arial Black";
public const H_FONT_SIZE:int = 50;
public const M_FONT_SIZE:int = 30;
public const S_FONT_SIZE:int = 15;
public const H_FONT_COLOR:uint = 0xcc0000;
public const M_FONT_COLOR:uint = 0xcc0000;
public const S_FONT_COLOR:uint = 0xcc0000;
public const FLOOR_WIDTH:int = 300;
public const FLOOR_HEIGHT:int = 20;
public const FLOOR_ANGLE:int = 0;
public const FLOOR_COLOR:uint = 0x666666;
public const GRAVITY:int = 10;
public function Box2DClock() {
// Box2Dの初期設定
setb2d();
// 時計の設定
setClock();
// コピー元のテキストを作成
tf = new TextField();
tf.autoSize = TextFieldAutoSize.LEFT;
// タイマーで監視
var t:Timer = new Timer(33, 0);
t.addEventListener(TimerEvent.TIMER, update);
t.start();
// 初回表示
minutesListener(null);
hoursListener(null);
}
/**
* 秒の更新
*/
public function secondsListener(e:Event):void
{
var str:String = clock.seconds2.charAt(1);
var sp:Sprite = createTexture(S_FONT_SIZE,str,S_FONT_COLOR);
createB2Object(sp,60, clock.seconds)
}
/**
* 分の更新
*/
public function minutesListener(e:Event):void
{
var sp:Sprite = createTexture(M_FONT_SIZE,clock.minutes.toString(),M_FONT_COLOR);
createB2Object(sp, 60,clock.minutes);
}
/**
* 時の更新(毎分オブジェクト作成)
*/
public function hoursListener(e:Event):void
{
var sp:Sprite = createTexture(H_FONT_SIZE,clock.hours.toString(),M_FONT_COLOR);
createB2Object(sp,24,clock.hours)
}
/**
* オブジェクト作成
*/
public function createB2Object(texture:Sprite, length:int, time:int):void
{
var bodyDef:b2BodyDef = new b2BodyDef();
bodyDef.position.Set(((FLOOR_WIDTH / length) * time) / 100 + (stage.stageWidth - FLOOR_WIDTH) / 2 / 100, 0);
bodyDef.angle = Math.PI / 2 * Math.random();
bodyDef.userData = texture;
bodyDef.userData.width = texture.width;
bodyDef.userData.height = texture.height;
body = world.CreateBody(bodyDef);
var bodyShape:b2CircleDef = new b2CircleDef();
bodyShape.radius = texture.width / 2 / 100;
bodyShape.density = 0.5;
bodyShape.friction = 10;
bodyShape.restitution = 0.2;
body.CreateShape(bodyShape);
body.SetMassFromShapes();
}
/**
* 文字列作成
*/
public function createTexture(fontsize:uint,str:String,col:uint):Sprite
{
tf.text = str;
tfm = new TextFormat(FONT, fontsize, col);
tfm.kerning = true;
//if(str.length > 1) tfm.letterSpacing = -7;
tf.setTextFormat(tfm);
var bmd:BitmapData = new BitmapData(tf.width, tf.height,true, 0x00000000);
bmd.draw(tf);
var bmp:Bitmap = new Bitmap(bmd);
var sp:Sprite = new Sprite();
sp.y = -150;
sp.addChild(bmp);
addChild(sp);
bmp.smoothing = true;
bmp.x = -(bmp.width / 2);
bmp.y = -(bmp.height / 2);
return sp;
}
/**
* 時計の作成
*/
public function setClock():void
{
clock = new TeraClock();
clock.addEventListener(TeraClock.SECONDS_CHANGED, secondsListener);
clock.addEventListener(TeraClock.MINUTES_CHANGED, minutesListener);
clock.addEventListener(TeraClock.MINUTES_CHANGED, hoursListener);
}
/**
* Box2Dの初期設定
*/
public function setb2d():void
{
//外枠の定義
worldAABB = new b2AABB();
worldAABB.lowerBound.Set(-100, -100);
worldAABB.upperBound.Set(100, 100);
//重力の定義
var g:b2Vec2 = new b2Vec2(0, GRAVITY);
//エンジンのセットアップ
world = new b2World(worldAABB, g, true);
//床の定義
var sp:Sprite = new Sprite();
sp.graphics.beginFill(FLOOR_COLOR);
sp.graphics.drawRect(-FLOOR_WIDTH / 2, -FLOOR_HEIGHT / 2, FLOOR_WIDTH, FLOOR_HEIGHT);
sp.graphics.endFill();
floorBodyDef = new b2BodyDef();
floorBodyDef.position.Set(stage.stageWidth / 2 / 100, stage.stageHeight / 100 * 0.8);
floorBodyDef.angle = FLOOR_ANGLE; // 床の角度
floorBodyDef.userData = sp;
//床の形の定義
var floorShapeDef:b2PolygonDef = new b2PolygonDef();
floorShapeDef.SetAsBox(1.5, 0.1);
floorShapeDef.friction = 2;
floorShapeDef.density = 0;
//オブジェクトを作る
var floor:b2Body = world.CreateBody(floorBodyDef);
floor.CreateShape(floorShapeDef);
addChild(floor.GetUserData());
}
/**
* 描画の更新
*/
public function update(e:TimerEvent = null):void
{
//trace("update")
world.Step(1 / 24, 10);
for (var bb:b2Body = world.m_bodyList; bb; bb = bb.m_next){
if (bb.m_userData is Sprite){
bb.m_userData.x = bb.GetPosition().x*100;
bb.m_userData.y = bb.GetPosition().y*100;
bb.m_userData.rotation = bb.GetAngle() * (180 / Math.PI);
}
}
}
}
}
import flash.display.*;
import flash.events.Event;
import flash.events.EventDispatcher;
class TeraClock extends Sprite {
public static const HOURS_CHANGED:String = "hoursChanged";
public static const MINUTES_CHANGED:String = "minutesChanged";
public static const SECONDS_CHANGED:String = "secondsChanged";
private var _hours:int;
private var _minutes:int;
private var _seconds:int;
private var _preSeconds:int;
private var _gmt:int;
// コンストラクタ関数。引数でタイムゾーンを設定できる。デフォルトは+9:00(日本)
public function TeraClock(GMT:int = 9) {
_gmt = GMT%24;
this.enterFrameListener(null);
addEventListener(Event.ENTER_FRAME, enterFrameListener);
}
private function enterFrameListener(e:Event):void {
var date:Date = new Date();
if(_gmt>=0){
_hours = (date.getUTCHours() + _gmt) % 24;
}else {
_hours = (24+(date.getUTCHours() + _gmt)) % 24;
}
_minutes = date.getUTCMinutes();
_seconds = date.getUTCSeconds();
if (_seconds != _preSeconds) {
//trace(_hours + ":" + _minutes + ":" + _seconds);
dispatchEvent(new Event(SECONDS_CHANGED));
if (_seconds == 0) {
dispatchEvent(new Event(MINUTES_CHANGED));
if (_minutes == 0) {
dispatchEvent(new Event(HOURS_CHANGED));
}
}
}
_preSeconds = _seconds;
}
// 外部から値を取得するためのゲッター。セッターはとりあえずいらないや。
public function get hours():int { return _hours; }
public function get minutes():int { return _minutes; }
public function get seconds():int { return _seconds; }
public function get milliseconds():int { return (new Date()).getUTCMilliseconds(); }
// 上位1桁返す
public function get hoursUpper():int { return _hours / 10; }
public function get minutesUpper():int { return _minutes / 10; }
public function get secondsUpper():int { return _seconds / 10; }
// 下位1桁返す
public function get hoursLower():int { return _hours % 10; }
public function get minutesLower():int { return _minutes % 10; }
public function get secondsLower():int { return _seconds % 10; }
// 1桁の数の時を2桁にする。返り値は String 型になる。
public function get hours2():String { return niketa(_hours); }
public function get minutes2():String { return niketa(_minutes); }
public function get seconds2():String { return niketa(_seconds); }
// 1の位を切り捨てて2桁にする。返り値は String 型になる。
public function get milliseconds2():String { return niketa((new Date()).getUTCMilliseconds() / 10); }
// 3桁になるように接頭に0を付けくわえる。返り値は String 型になる。
public function get milliseconds3():String { return keta((new Date()).getUTCMilliseconds(), 3); }
// 2桁にして返す関数
private function niketa(num:int):String {
if (num < 10) {
return String("0"+num);
}else {
return String(num);
}
}
// 指定桁数にして返す関数
private function keta(num:int, keta:int):String {
var str:String = String(num);
while(str.length < keta) str = "0" + str;
return str;
}
//アナログ時計にした時の針の角度を返す。
public function get hoursDegree():Number {
return ((_hours % 12) * 30) + (_minutes / 2) + (_seconds/120);
}
public function get minutesDegree():Number {
return (_minutes * 6) + (_seconds / 10);
}
public function get secondsDegree():Number {
return _seconds * 6;
}
//現時刻からh時m分s秒だけずらした時間を取得する(戻り値のdateは元の時刻を0日としたときの差分)
public function getDifferenceTime(s:int, m:int, h:int):Object {
var time:Array = [_seconds, _minutes, _hours, 0];
var dt:Array = [s, m, h];
var cap:Array = [60, 60, 24];
for(var i:int = 0; i < 3; ++i) {
time[i] += dt[i];
if(time[i] < 0) {
time[i + 1] += Math.floor(time[i] / cap[i]);
time[i] = time[i] % cap[i] + cap[i];
continue;
}
if(time[i] >= cap[i]) {
time[i + 1] += Math.floor(time[i] / cap[i]);
time[i] = time[i] % cap[i];
continue;
}
}
return {seconds:time[0], minutes:time[1], hours:time[2], date:time[3]};
}
}