Beautifl - Flash Gallery

Thumbnail : Box2D Clock
Box2D Clock
hatiya123 2010-03-31 MIT License

再生するにはFlash Playerが必要です。デスクトップのブラウザでご覧ください。

package  {
	import Box2D.Collision.b2AABB;
	import Box2D.Collision.Shapes.b2CircleDef;
	import Box2D.Collision.Shapes.b2PolygonDef;
	import Box2D.Collision.Shapes.b2Shape;
	import Box2D.Collision.Shapes.b2CircleShape;

	import Box2D.Common.Math.b2Vec2;
	import Box2D.Dynamics.b2Body;
	import Box2D.Dynamics.b2BodyDef;
	import Box2D.Dynamics.b2DebugDraw;
	import Box2D.Dynamics.b2World;
	import Box2D.Dynamics.Contacts.b2ContactEdge;
	
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	
	public class Box2D_Clock extends Sprite {
		// 物理エンジン内の1mを表すためのピクセル数
		private static const DRAW_SCALE:Number = 100;
		private var world:b2World;
		private static const DEBUG_DRAW:Boolean = false;
		private static const TIME_RADIUS:uint = 4;		//円の半径
		private static const TIME_RADIUS_SEP:uint = 2;	//円同士の間隔
		private var clock:EventClock;
		private var contactListener:ContactListener;
		public function Box2D_Clock() {
			initWorld();
			
			//_buildStaticBox(0, -50, 500, 50);//up
            _buildStaticBox(0, 300, 500, 50);//bottom
			_buildStaticBox(-50, 0, 50, 300);//right
			_buildStaticBox(500, 0, 50, 300);//left
		
			clock = new EventClock();
			clock.addEventListener(EventClock.SECONDS_CHANGED, secondsListener);
			
			////////////////////////////////////////
			// 描画設定
			if (DEBUG_DRAW) {
				var debugDraw:b2DebugDraw = new b2DebugDraw();
				debugDraw.m_sprite = this;
				debugDraw.m_drawScale = DRAW_SCALE; // 1mを100ピクセルにする
				debugDraw.m_fillAlpha = 0.5; // 不透明度
				debugDraw.m_lineThickness = 1; // 線の太さ
				debugDraw.m_drawFlags = b2DebugDraw.e_shapeBit;
				world.SetDebugDraw(debugDraw);
			}
			
			// イベントハンドラを登録する
			addEventListener(Event.ENTER_FRAME, enterFrameHandler);
		}
		
		private function minutesListener(e:Event):void {
			//分
			buildNumCercle(
				clock.minutes2,
				200,
				-50,
				10
			);
		}

		
		private function secondsListener(e:Event):void {
			//trace(clock.seconds + "秒です。現在:" +clock.hours2 + ":" + clock.minutes2 + ":" + clock.seconds2 + " です。" );

			//時
			buildNumCercle(
				clock.hours2,
				120,
				-50,
				10
			);
			
			//分
			buildNumCercle(
				clock.minutes2,
				220,
				-50,
				10
			);
			
			//秒
			buildNumCercle(
				clock.seconds2,
				320,
				-50,
				10
			);
		}
		
		private function buildNumCercle(numStr:String, baseX:Number, baseY:Number, numSep:Number):void {
			for (var i:int = 0; i < 2; i++) {
				var colorCount:uint = 0;
				var numTime:String = numStr.charAt(i);
				var ledW:int = Led.ledArray[numTime][0].length;
				var ledH:int = Led.ledArray[numTime].length;
				for(var yy:int=0; yy<ledH; yy++){
					for(var xx:int=0; xx<ledW; xx++){
						if (Led.ledArray[numTime][yy][xx] == 1) {
							_buildDynamicCircle(
								TIME_RADIUS ,
								//baseX + numSep * i + TIME_RADIUS * 2 * xx + TIME_RADIUS_SEP * xx,
								baseX + (TIME_RADIUS * 2 + TIME_RADIUS_SEP) * xx + i * (Led.ledArray[0][0].length * (TIME_RADIUS*2 + TIME_RADIUS_SEP) + numSep),
								baseY + TIME_RADIUS * 2 * yy + TIME_RADIUS_SEP * yy,
								colorCount ? 0 : 1,
								String("s_" + yy + "_" + xx)
							);
							colorCount = 1;
						}
					}
				}
			}
		}
		
		private function initWorld():void
		{
			// 物理計算エリア
			var worldAABB:b2AABB = new b2AABB();
			worldAABB.lowerBound.Set(-100, -100);
			worldAABB.upperBound.Set(100, 100);
			
			// 重力を下方向に10m/s^2とする
			var gravity:b2Vec2 = new b2Vec2(0, 10);
			
			// 外枠と重力を指定して、物理エンジン全体をセットアップする
			world = new b2World(worldAABB, gravity, true);
			
            ///////////////////////////////////////////////////
            // 接触リスナーのインスタンスを登録
            contactListener = new ContactListener();
            world.SetContactListener(contactListener);

		}
		
		//内部的にbox2d用にうまく設定する。いつもどおり左上を基準に指定する
        private function _buildStaticBox(x:Number, y:Number, width:Number, height:Number):void {
			//位置決め。中心座標を指定。単位はメートル
            var bodyDef:b2BodyDef = new b2BodyDef();
            bodyDef.position.Set((x + width/2) / DRAW_SCALE, (y + height/2) / DRAW_SCALE);
            
			//形を決める。指定するのはその半分の値。中心からの大きさと考えればすっきりする?
            var boxDef:b2PolygonDef = new b2PolygonDef();
            boxDef.SetAsBox(width / DRAW_SCALE / 2, height / DRAW_SCALE / 2);
            //boxDef.friction = 0.5; //摩擦
            //boxDef.density = 0;	   //密度
            
			//物体として作る
            var body:b2Body = world.CreateBody(bodyDef);
            body.CreateShape(boxDef);
            //body.SetMassFromShapes();
			
        }
		
		//内部的にbox2d用にうまく設定する。いつもどおり左上を基準に指定する
        private function _buildStaticOrientBox(x:Number, y:Number, width:Number, height:Number):void {
			//位置決め。中心座標を指定。単位はメートル
            var bodyDef:b2BodyDef = new b2BodyDef();
            bodyDef.position.Set((x + width/2) / DRAW_SCALE, (y + height/2) / DRAW_SCALE);
            
			//形を決める。指定するのはその半分の値。中心からの大きさと考えればすっきりする?
            var boxDef:b2PolygonDef = new b2PolygonDef();
            //boxDef.SetAsBox(width / DRAW_SCALE / 2, height / DRAW_SCALE / 2);
            boxDef.SetAsOrientedBox(width / DRAW_SCALE / 2, height / DRAW_SCALE / 2, new b2Vec2(0, 0), 0.1)
			
			//物体として作る
            var body:b2Body = world.CreateBody(bodyDef);
            body.CreateShape(boxDef);
        }
		
		private function _buildDynamicCircle(radius:Number, centerX:Number, centerY:Number, colorIndex:uint, name:String):void {
			radius /= DRAW_SCALE;
			// 円の場所を設定する
			var bodyDef:b2BodyDef = new b2BodyDef();
			bodyDef.position.Set(centerX / DRAW_SCALE, centerY / DRAW_SCALE);
			
			// 円の大きさなどを設定する
			var shapeDef:b2CircleDef = new b2CircleDef();
			shapeDef.radius = radius;
			shapeDef.density = 1;     // 密度 [kg/m^2]
			shapeDef.restitution = 0.3;  // 反発係数、通常は0~1
			
			// 円を動く物体として作る
			var body:b2Body = world.CreateBody(bodyDef);
			body.CreateShape(shapeDef);

			// 円の画像を作る
			var floorImage:Sprite;
			if(colorIndex == 0){
				floorImage = new PCircle();
				addChild(floorImage);
			}else{
				floorImage = new PCircle2();
				addChild(floorImage);
				name += "red";
			}
			
			// 画像のサイズを合わせる
			floorImage.width = floorImage.height = radius * 2 * DRAW_SCALE;

			// b2BodyのユーザデータとしてSpriteを作る
			var sp:Recorder = new Recorder(stage, name);
			body.SetUserData(sp);
			body.GetUserData().addChild(floorImage);
			
			body.SetMassFromShapes();
			addChild(body.GetUserData());
		}
		
		private function enterFrameHandler(event:Event):void {
			// Flashはデフォルトで秒間24フレームなので、
			// 物理シミュレーションを1/24秒進める
			//ステップを先に進めてから下記を実行しないと実態と計算上のオブジェクトがずれる
			world.Step(1 / 24, 10);
			for (var bb:b2Body = world.GetBodyList(); bb; bb = bb.m_next){
				if (bb.GetUserData() is Sprite) {
					var r:Recorder = bb.GetUserData();
					if (bb.GetUserData().name == 'delete') {
						//画像の削除
						//var imageData:Sprite = bb.GetUserData().getChildAt(0);
						//bb.GetUserData().removeChild(imageData);
						//imageData = null;
						//Recorderの削除
						removeChild(bb.GetUserData());
						world.DestroyBody(bb);
					}else {
						r.x = bb.GetPosition().x * DRAW_SCALE;
						r.y = bb.GetPosition().y * DRAW_SCALE;
						r.rotation = bb.GetAngle() * (180 / Math.PI);
						//trace(r.contactCount + "(" + r.name + ")");
						
						//trace(shapeName1);
						//shapeBody1.m_userData.contactCount++;
						//var shapeBody2:b2Body = contactListener.GetShape2().m_body;
						//shapeBody2.m_userData.contactCount++;
						//trace(shapeBody1.m_userData.contactCount);
						
						//if (contactListener.GetShape1()) {
							//var shape1:b2Shape = contactListener.GetShape1();
							//trace(shape1.m_body.m_userData.name);
						//}
			
						//for (var ce:b2ContactEdge = bb.m_contactList; ce != null; ce = ce.next) {  
							//var obj1:b2Body = ce.contact.GetShape1().m_body;
							//var obj2:b2Body = ce.contact.GetShape2().m_body;
							//trace(obj1.m_userData.name);
							//obj1.m_userData.contactCount++;
							//obj2.m_userData.contactCount++;
							//trace(obj1.m_userData.name + "(" + obj1.m_userData.contactCount + ")");
						//}

					}
					
					//if (bb.GetUserData().contactCount == 6 && bb.GetUserData().name == "s_0_1red") {
						//trace(bb.GetAngle());
						//bb.GetAngle() = 13;
						//trace(bb.m_angularVelocity)
						//bb.GetUserData().addChild(new Grass());
					//}
					if (bb.GetUserData().contactCount > 15 && bb.GetUserData().name != 'red'){
						bb.GetUserData().name = 'delete';
						bb.SetMassFromShapes();
					}
				}
			}
		}
	}
}

import flash.display.Sprite;
import flash.display.Stage;
import flash.events.MouseEvent;
class Recorder extends Sprite {
	public var contactCount:Number = 0;
	
	public function Recorder(stage:Stage, name:String) {
		this.name = name;
	}
}

class PCircle extends Sprite {
	public function PCircle() {
		graphics.beginFill(0xAEEE00);
		graphics.drawCircle( -25, -25, 50);
		graphics.endFill();
	}
}

class PCircle2 extends Sprite {
	public function PCircle2() {
		graphics.beginFill(0xFF348B);
		graphics.drawCircle( -25, -25, 50);
		graphics.endFill();
	}
}

class Led extends Sprite {
	public static var ledArray:Array = [
		[
			[1, 1, 1],
			[1, 0, 1],
			[1, 0, 1],
			[1, 0, 1],
			[1, 1, 1],
		],
		[
			[0, 1, 0],
			[0, 1, 0],
			[0, 1, 0],
			[0, 1, 0],
			[0, 1, 0]
		],
		[
			[1, 1, 1],
			[0, 0, 1],
			[1, 1, 1],
			[1, 0, 0],
			[1, 1, 1]
		],
		[
			[1, 1, 1],
			[0, 0, 1],
			[1, 1, 1],
			[0, 0, 1],
			[1, 1, 1]
		],
		[
			[0, 0, 1],
			[0, 1, 1],
			[1, 0, 1],
			[1, 1, 1],
			[0, 0, 1]
		],
		[
			[1, 1, 1],
			[1, 0, 0],
			[1, 1, 1],
			[0, 0, 1],
			[1, 1, 1]
		],
		[
			[1, 1, 1],
			[1, 0, 0],
			[1, 1, 1],
			[1, 0, 1],
			[1, 1, 1]
		],
		[
			[1, 1, 1],
			[1, 0, 1],
			[1, 0, 1],
			[0, 0, 1],
			[0, 0, 1]
		],
		[
			[1, 1, 1],
			[1, 0, 1],
			[1, 1, 1],
			[1, 0, 1],
			[1, 1, 1]
		],
		[
			[1, 1, 1],
			[1, 0, 1],
			[1, 1, 1],
			[0, 0, 1],
			[0, 0, 1]
		]
	];
}


import Box2D.Collision.Shapes.b2CircleShape;
import Box2D.Dynamics.*;
import Box2D.Collision.*;
import Box2D.Dynamics.Contacts.*;
import Box2D.Collision.Shapes.b2Shape;

/**
 * ...
 * @author 
 */
class ContactListener extends b2ContactListener
{
	
	public function ContactListener() 
	{
	}
	
	// 物体が衝突したときに呼び出される
	public override function Add(point:b2ContactPoint) : void
	{
		m_flag = 0;
		if(point.shape1 is b2CircleShape)
			point.shape1.m_body.m_userData.contactCount++;
		if(point.shape2 is b2CircleShape)
			point.shape2.m_body.m_userData.contactCount++;
	}
	
	// 物体が衝突してから離れるまで繰り返し呼び出される
	public override function Persist(point:b2ContactPoint) : void
	{
		m_flag = 1;
	}
	
	// 物体が離れたときに呼び出されるメソッド
	public override function Remove(point:b2ContactPoint) : void
	{
		m_flag = 2;
	}
	
	// 接触点が解決されたとき
	public override function Result(point:b2ContactResult) : void
	{
	}
	
	public function GetFlag() : int
	{
		return m_flag;
	}
	
	//======================
	// Member data
	//======================
	private var m_flag:int = -1;
	
 }
 
import flash.display.*;
import flash.events.*;
class EventClock 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;
	public function EventClock(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) {
			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(); }
	
	public function get hours2():String { return niketa(_hours); }
	public function get minutes2():String { return niketa(_minutes); }
	public function get seconds2():String { return niketa(_seconds); }

	private function niketa(num:int):String {
		if (num < 10) {
			return String("0"+num);
		}else {
			return String(num);
		}
	}
}