In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Unionチャットサンプル

http://fla.la/archives/364
Union Platform(5) チャットを作る
解説用コードです。 updated 2009.09.07 alpha4対応
@author Copyright (C) naoto koshikawa, All Rights Reserved.
Get Adobe Flash player
by naoto5959 07 Sep 2009
/**
 * Copyright naoto5959 ( http://wonderfl.net/user/naoto5959 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/uA8S
 */

package  
{
	import com.bit101.components.*;
	import flash.display.*;
	import flash.events.*;
	import flash.net.*;
	import flash.ui.Keyboard;
	import net.user1.logger.*;
	import net.user1.reactor.*;
	import org.libspark.betweenas3.*;
	import org.libspark.betweenas3.easing.*;
	import org.libspark.betweenas3.tweens.*;
	
	/**
	 * http://fla.la/archives/364
	 * Union Platform(5) チャットを作る
	 * 解説用コードです。 updated 2009.09.07 alpha4対応
	 * @author Copyright (C) naoto koshikawa, All Rights Reserved.
	 */
	public class TryUnion2 extends Sprite
	{
		//----------------------------------------------------------------------
		//  static properties
		//----------------------------------------------------------------------
		//------------------------------
		//  public static properties
		//------------------------------
		/**
		 * 接続先Union Server host
		 */
		public static const UNION_SERVER_HOST:String = "tryunion.com";
		
		/**
		 * 接続先Union Server port 
		 */
		public static const UNION_SERVER_PORT:Number = 9100;
		
		/**
		 * Room ID 
		 */
		public static const ROOM_CHAT:String = "com.asmple.union.chat";
		
		/**
		 * アバターURL
		 */
		public static const AVATAR_URL:String = "http://swf.wonderfl.net/swf/usercode/a/af/afe5/afe5412cf117b348681e9eb6e3595035cabd06e6.swf";
		
		/** 
		 * アバターの向いている方向(上) 
		 */
		public static const DIRECTION_UP:uint = 0;
		
		/**
		 * アバターの向いている方向(右)
		 */
		public static const DIRECTION_RIGHT:uint = 1;
		
		/**
		 * アバターの向いている方向(下)
		 */
		public static const DIRECTION_DOWN:uint = 2;
		
		/**
		 * アバターの向いている方向(左)
		 */
		public static const DIRECTION_LEFT:uint = 3;
		
		//----------------------------------------------------------------------
		//  properties
		//----------------------------------------------------------------------
		//------------------------------
		//  private properties 
		//------------------------------
		/**
		 * ユーザーインターフェース
		 */
		private var _ui:UnionChatUI;
		
		/**
		 * ClientグローバルAttribute の初期値を格納します。
		 */
		private var _clientData:Object = {};
		
		/**
		 * Reactor
		 */
		private var _reactor:Reactor;
		
		/**
		 * Room Manager
		 */
		private var _roomManager:RoomManager;
		
		/**
		 * ReactorのLogger
		 */
		private var _logger:Logger;
		
		/**
		 * 現在のRoom
		 */
		private var _room:Room;
		
		/**
		 * 自身のClient
		 */
		private var _self:IClient;
		
		/**
		 * avatarのIDs
		 */
		private var _avatars:Object = { };
		
		/**
		 * 現在テキスト入力中かを判別します。
		 */
		private var _isInputText:Boolean;
		
		/**
		 * join or observe
		 */
		private var _attempt:String = "";
		
		//----------------------------------------------------------------------
		//  methods
		//----------------------------------------------------------------------
		//------------------------------
		//  public methods
		//------------------------------
		/**
		 * 一番最初に実行されるメソッドです。
		 */
		public function TryUnion2() 
		{	
			// ユーザーインターフェースを作成します。
			addChild(_ui = new UnionChatUI());
			_ui.currentStatusLabel.text = "connecting...";
			_ui.playLoading();
			
			// Client Attributeの初期値を作成します。
			var initialX:Number = int(Math.random() * _ui.avatarField.width);
			var initialY:Number = int(Math.random() * _ui.avatarField.height);
			var initialDirection:Number = int(Math.random() * 4);
			_clientData = {
				nickname: "guest",
				color: Math.random() * 0x888888,
				avatar: [initialX, initialY, initialDirection, 0].join(",")
			};
			
			// UnionServerへ接続します。
			connect();
		}

		/**
		 * UnionServerへ接続します。
		 */
		private function connect():void
		{
			_reactor = new Reactor(null, false);
			_reactor.addEventListener(ReactorEvent.READY, _reactor_readyHandler);
			_reactor.addEventListener(ReactorEvent.CLOSE, _reactor_closeHandler);
			_reactor.connect(UNION_SERVER_HOST, UNION_SERVER_PORT);
		}
		
		/**
		 * UserEventを登録します。
		 */
		private function activate():void
		{
			_ui.stopLoading();
				
			// observeボタンの動作を登録します。
			_ui.observeButton.addEventListener(MouseEvent.CLICK,
				 _ui_observeButton_clickHandler);

			// joinボタンの動作を登録します。
			_ui.joinButton.addEventListener(MouseEvent.CLICK,
				 _ui_joinButton_clickHandler);
			
			// updateボタンの動作を登録します。
			_ui.updateButton.addEventListener(MouseEvent.CLICK,
				 _ui_updateButton_clickHandler);
				 
			// メッセージ入力時の動作を登録します。
			_ui.messageField.addEventListener(TextEvent.TEXT_INPUT,
				_ui_messageField_textInputHandler);
			_ui.messageField.addEventListener(KeyboardEvent.KEY_UP,
				_ui_messageField_keyUpHandler);
				
			// アバターフィールドクリック時の動作を登録します。
			_ui.avatarField.addEventListener(MouseEvent.CLICK,
				_ui_avatarField_clickHandler);
		}
		
		/**
		 * UserEventを解除します。
		 */
		private function deactivate():void
		{		
			// observeボタンの動作を解除します。
			_ui.observeButton.removeEventListener(MouseEvent.CLICK,
				 _ui_observeButton_clickHandler);

			// joinボタンの動作を解除します。
			_ui.joinButton.removeEventListener(MouseEvent.CLICK,
				 _ui_joinButton_clickHandler);
			
			// updateボタンの動作を解除します。
			_ui.updateButton.removeEventListener(MouseEvent.CLICK,
				 _ui_updateButton_clickHandler);
				 
			// メッセージ入力時の動作を解除します。
			_ui.messageField.removeEventListener(TextEvent.TEXT_INPUT,
				_ui_messageField_textInputHandler);
			_ui.messageField.removeEventListener(KeyboardEvent.KEY_UP,
				_ui_messageField_keyUpHandler);
				
			// アバターフィールドクリック時の解除を設定します。
			_ui.avatarField.removeEventListener(MouseEvent.CLICK,
				_ui_avatarField_clickHandler);
		}
		
		/**
		 * RoomEventのListener登録
		 */
		private function addRoomEventListeners():void
		{
			_room.addEventListener(RoomEvent.OBSERVE, _room_observeHandler);
			_room.addEventListener(RoomEvent.JOIN, _room_joinHandler);
			_room.addEventListener(RoomEvent.CLIENT_COUNT
				, _room_clientCountHandler);
			_room.addEventListener(RoomEvent.SYNCHRONIZE
				, _room_synchronizeHandler);
			_room.addEventListener(RoomEvent.ADD_CLIENT
				, _room_addClientHandler);
			_room.addEventListener(RoomEvent.REMOVE_CLIENT
				, _room_removeClientHandler);
			_room.addEventListener(RoomEvent.UPDATE_CLIENT_ATTRIBUTE
				, _room_updateClientAttributeHandler);
			_room.addMessageListener("chatMessage", chatMessageHandler);
		}
		
		/**
		 * RoomEventのListener解除
		 */
		private function removeRoomEventListeners():void
		{
			_room.removeEventListener(RoomEvent.OBSERVE, _room_observeHandler);
			_room.removeEventListener(RoomEvent.JOIN, _room_joinHandler);
			_room.removeEventListener(RoomEvent.CLIENT_COUNT
				, _room_clientCountHandler);
			_room.removeEventListener(RoomEvent.SYNCHRONIZE
				, _room_synchronizeHandler);
			_room.removeEventListener(RoomEvent.ADD_CLIENT
				, _room_addClientHandler);
			_room.removeEventListener(RoomEvent.REMOVE_CLIENT
				, _room_removeClientHandler);
			_room.removeEventListener(RoomEvent.UPDATE_CLIENT_ATTRIBUTE
				, _room_updateClientAttributeHandler);
			_room.removeMessageListener("chatMessage", chatMessageHandler);
		}
		
		/**
		 * _ui.avatarFieldにアバターを追加します。
		 * @param	client
		 */
		private function addAvatar(client:IClient):void
		{
			var loader:Loader = new Loader();
			loader.contentLoaderInfo.addEventListener(Event.INIT,
				function(event:Event):void {
					var avatar:* = loader.content;
					avatar.color = client.getAttribute("color");
					var values:Array = client.getAttribute("avatar").split(",");
					updateAvatar.apply(null, [avatar, false].concat(values));
					
					_avatars[client.getClientID()] = avatar;
					_ui.avatarField.addChild(avatar);
				}
			);
			
			loader.load(new URLRequest(AVATAR_URL));
		}
		
		/**
		 * _ui.avatarFieldからアバターを削除します。
		 * @param	client
		 */
		private function removeAvatar(client:IClient):void
		{
			var avatar:* = _avatars[client.getClientID()];
			if (!_ui.avatarField.contains(avatar)) return;
			_ui.avatarField.removeChild(avatar);
			delete _avatars[client.getClientID()];
		}
		
		/**
		 * アバターを状態更新します。
		 * @param	avatar
		 * @param	isTween
		 * @param	positionX
		 * @param	positionY
		 * @param	direction
		 * @param	distance
		 */
		private function updateAvatar(
				avatar:*,
				isTween:Boolean,
				positionX:Number, positionY:Number,
				direction:uint, distance:Number):void
		{
			avatar.play();
			switch (direction)
			{
				case DIRECTION_UP:
					avatar.back();
					break;
				case DIRECTION_RIGHT:
					avatar.right();
					break;
				case DIRECTION_DOWN:
					avatar.front();
					break;
				case DIRECTION_LEFT:
					avatar.left();
					break;
			}
			
			if (isTween)
			{
				var tween:IObjectTween = BetweenAS3.tween(
					avatar,
					{x: positionX, y: positionY },
					{x: avatar.x, y: avatar.y },
					distance * 0.005, Sine.easeOut
				);
				tween.play();
			}
			else
			{
				avatar.x = positionX;
				avatar.y = positionY;
			}
		}
		
		/**
		 * Message chatMessageを受け取った際に実行されるハンドラです。
		 * @param	fromClient
		 * @param	message
		 */
		private function chatMessageHandler(
				fromClient:IClient, message:String):void
		{
			var nickname:String = decodeURI(
				fromClient.getAttribute("nickname")
			);
			var color:uint = uint(fromClient.getAttribute("color"));
			message = decodeURI(message);
			_ui.appendMessage(
				"[chatMessage]" + nickname + "(" + fromClient.getClientID() + ")"
				+ "さん「" + message + "」",
				color
			);
		}
		
		//----------------------------------------------------------------------
		//  event handler
		//----------------------------------------------------------------------
		//------------------------------
		//  User Event系
		//------------------------------		
		/**
		 * _ui.observeButtonをクリックした際に実行されるハンドラ
		 * @param	event
		 */
		private function _ui_observeButton_clickHandler(event:MouseEvent):void
		{
			_ui.playLoading();
			removeRoomEventListeners();
			deactivate();
			_attempt = "observe";
			_reactor.disconnect();
			connect();
		}
		
		/**
		 * _ui.joinButtonをクリックした際に実行されるハンドラ
		 * @param	event
		 */
		private function _ui_joinButton_clickHandler(event:MouseEvent):void
		{
			_ui.playLoading();
			removeRoomEventListeners();
			deactivate();
			_attempt = "join";
			_reactor.disconnect();
			connect();
		}
		
		/**
		 * _ui.updateButtonをクリックした際に実行されるハンドラ
		 * @param	event
		 */
		private function _ui_updateButton_clickHandler(event:MouseEvent):void
		{
			var nickname:String = _ui.nicknameField.text;
			var color:uint = _ui.colorChooser.value;
			if (nickname.length == 0)
			{
				_ui.appendMessage("ニックネームは空に出来ません", 0xFF0000);
				return;
			}
			_self.setAttribute("nickname", encodeURI(nickname));
			_self.setAttribute("color", String(color));
		}
		
		/**
		 * _ui.messageFieldにテキストを入力中に実行されるハンドラ
		 * @param	event
		 */
		private function _ui_messageField_textInputHandler(event:TextEvent):void
		{
			_isInputText = true;
		}
		
		/**
		 * _ui.messageFieldにテキストを入力中、キーをアップした際に実行されるハンドラ
		 * @param	event
		 */
		private function _ui_messageField_keyUpHandler(event:KeyboardEvent):void
		{
			if (_ui.messageField.text.length == 0) return;
			if (!_isInputText && event.keyCode == Keyboard.ENTER)
			{
				var message:String = encodeURI(_ui.messageField.text);
				_room.sendMessage("chatMessage", true, null, message);
				_ui.messageField.text = "";
			}
			_isInputText = false;
		}
		
		/**
		 * _ui.avatarFieldをクリックした際に実行されるハンドラ
		 * @param	event
		 */
		private function _ui_avatarField_clickHandler(event:MouseEvent):void
		{
			// 入室していなければ何もしない。
			if (!_self.isInRoom(ROOM_CHAT)) return;
			
			var avatar:* = _avatars[_self.getClientID()];
			var direction:uint;
			var distanceX:Number = event.localX - avatar.x;
			var distanceY:Number = event.localY - avatar.y;
			var distance:Number = Math.sqrt(
				distanceX * distanceX + distanceY * distanceY
			);
			// 小数点を切り捨てる
			distance = int(distance);
			
			// アバターが向く方向を決定
			if (Math.abs(distanceX) <= Math.abs(distanceY))
			{
				if (distanceY < 0) direction = DIRECTION_UP;
				else direction = DIRECTION_DOWN;
			}
			else
			{
				if (distanceX < 0) direction = DIRECTION_LEFT;
				else direction = DIRECTION_RIGHT;
			}
			
			// Client Attributeを更新する。
			var values:Array = [event.localX-16, event.localY-16, direction, distance];
			_self.setAttribute("avatar", values.join(","));
		}
		
		//------------------------------
		//  Reactor系イベント
		//------------------------------
		/**
		 * ReactorとUnion Serverとの接続が完了した際に実行されるハンドラ
		 * @param	event
		 */
		private function _reactor_readyHandler(event:ReactorEvent):void
		{
			_ui.currentStatusLabel.text = "connect";
			_ui.appendMessage("ReadyEvent.READY");
			
			// 自身のClient参照を取得
			_self = _reactor.getClientManager().self();
			_self.setAttribute("nickname", _clientData.nickname);
			_self.setAttribute("color", _clientData.color);
			_self.setAttribute("avatar", _clientData.avatar);
			
			// 自身のnicknameを設定
			_ui.nicknameField.text = _clientData.nickname;
			
			// 自身のcolorを設定
			_ui.colorChooser.value = _clientData.color;
			
			// RoomManager参照を取得
			_roomManager = _reactor.getRoomManager();
			
			_roomManager.addEventListener(
				RoomManagerEvent.CREATE_ROOM_RESULTS,
				_roomManager_createRoomReslutsHandler);
			
			// Roomへの接続が0となっても残す設定
			var roomSetting:RoomSettings = new RoomSettings();
			roomSetting.dieOnEmpty = false;
			
			// 指定したRoom IDを作成する。
			_room = _roomManager.createRoom(ROOM_CHAT, roomSetting);
			addRoomEventListeners();
			
			// logger参照を取得
			_logger = _reactor.getLog();
			_logger.addEventListener(LogEvent.UPDATE, _logger_updateHandler);
		}
		
		/**
		 * ReactorからUnion Serverの接続が切断した際に実行されるハンドラ
		 * @param	event
		 */
		private function _reactor_closeHandler(event:ReactorEvent):void
		{
			_ui.currentStatusLabel.text = "connect closed.";
			_ui.appendMessage("ReadyEvent.CLOSE");
			_ui.currentClientsLabel.text = "occupants:unknown";
			for (var i:uint = 0; i < _ui.avatarField.numChildren; i++)
			{
				_ui.avatarField.removeChildAt(0);
			}
		}
		
		/**
		 * RoomManagerからRoomの作成結果が通知された際に実行されるハンドラ
		 * @param	event
		 */
		private function _roomManager_createRoomReslutsHandler(
				event:RoomManagerEvent):void
		{
			var status:String = event.getStatus();
			_ui.appendMessage("RoomManagerEvent.CREATE_ROOM_RESULTS:" + status);
			if (event.getStatus() == Status.SUCCESS
				|| event.getStatus() == Status.ROOM_EXISTS) 
			{
				if (_attempt == "observe") _room.observe();
				else if (_attempt == "join") _room.join();
				else activate();
			}
		}
		
		/**
		 * LoggerからLogの登録が通知された際に実行されるハンドラ
		 * @param	event
		 */
		private function _logger_updateHandler(event:LogEvent):void
		{
			var level:String = event.getLevel();
			if (level == Logger.DEBUG || level == Logger.INFO) return;
			_ui.appendMessage(level + ":" + event.getMessage(), 0xFF0000);
		}
		
		/**
		 * Roomへobserveした際に実行されるハンドラ
		 */
		private function _room_observeHandler(event:RoomEvent):void
		{
			_ui.currentStatusLabel.text = "observe";
			_ui.appendMessage("RoomEvent.OBSERVER");
			_ui.stopLoading();
			activate();
		}
			
		/**
		 * Roomへjoinした際に実行されるハンドラ
		 */
		private function _room_joinHandler(event:RoomEvent):void
		{
			_ui.currentStatusLabel.text = "join";
			_ui.appendMessage("RoomEvent.JOIN");
			_ui.stopLoading();
			activate();
		}
		
		/**
		 * Room内のClient数が更新された際に実行されるハンドラ
		 * @param	event
		 */
		private function _room_clientCountHandler(event:RoomEvent):void
		{
			_ui.appendMessage("RoomEvent.CLIENT_COUNT");
			_ui.currentClientsLabel.text = "occupants:" + event.getNumClients() + "人";
		}
		
		/**
		 * Room内の情報が同期された際に実行されるハンドラ
		 * @param	event
		 */
		private function _room_synchronizeHandler(event:RoomEvent):void
		{
			_ui.appendMessage("RoomEvent.SYNCHRONIZE");
			
			for each (var client:IClient in _room.getClients())
			{
				addAvatar(client);
			}
		}
		
		/**
		 * Room内にClientが追加された際に実行されるハンドラ
		 * @param	event
		 */
		private function _room_addClientHandler(event:RoomEvent):void
		{
			_ui.appendMessage("RoomEvent.ADD_CLIENT");
			addAvatar(event.getClient());
		}
		
		/**
		 * Room内からClientが削除された際に実行されるハンドラ
		 * @param	event
		 */
		private function _room_removeClientHandler(event:RoomEvent):void
		{
			_ui.appendMessage("RoomEvent.REMOVE_CLIENT");
			removeAvatar(event.getClient());
		}
		
		/**
		 * Room内のClient Attributeが更新された際に実行されるハンドラ
		 * @param	event
		 */
		private function _room_updateClientAttributeHandler(event:RoomEvent):void
		{
			_ui.appendMessage("RoomEvent.UPDATE_CLIENT_ATTRIBUTE");
			var attribute:Attribute = event.getChangedAttr();
			_ui.appendMessage(" id:" + event.getClientID() 
				+ ", name:" + attribute.name 
				+ ", oldValue:" + attribute.oldValue
				+ ", value:" + attribute.value
			);
			
			var avatar:* = _avatars[event.getClientID()];
			if (!avatar) return;
			switch (attribute.name)
			{
				case "color":
				{
					avatar.color = uint(attribute.value);
					break;
				}
				case "avatar":
				{
					var values:Array = attribute.value.split(",");
					updateAvatar.apply(null, [avatar, true].concat(values));
					break;
				}
			}
		}
	}	
}
//--------------------------------------------------------------------------
//  以降ヘルパークラス
//--------------------------------------------------------------------------
import com.bit101.components.*;
import flash.display.*;
import flash.text.*;
import flash.events.*;
import org.libspark.betweenas3.*;
import org.libspark.betweenas3.easing.*;
import org.libspark.betweenas3.tweens.*;
/**
 * Union Chat User Interface
 * @author Copyright (C) naoto koshikawa, All Rights Reserved.
 */
class UnionChatUI extends Sprite
{
	//----------------------------------------------------------------------
	//  static properties
	//----------------------------------------------------------------------
	//------------------------------
	//  public static properties
	//------------------------------
	/** ステージの横 */
	public static const STAGE_WIDTH:Number = 465;
	
	/** ステージの縦 */
	public static const STAGE_HEIGHT:Number = 465;
	
	//----------------------------------------------------------------------
	//  properties
	//----------------------------------------------------------------------		
	//------------------------------
	//  public properties
	//------------------------------
	private var _loadingCircle:Shape;
	/** ローディング中のサークル */
	public function get loadingCircle():Shape
	{
		return _loadingCircle;
	}
	
	private var _loadingTween:IObjectTween;
	/** ローディング中のサークルのトゥイーン */
	public function get loadingTween():IObjectTween
	{
		return _loadingTween;
	}
	
	private var _messageField:TextField;
	/** メッセージ入力フィールド */
	public function get messageField():TextField
	{
		return _messageField;
	}
	
	private var _colorChooser:ColorChooser;
	/** ユーザの色設定 */
	public function get colorChooser():ColorChooser
	{
		return _colorChooser;
	}
	
	private var _nicknameField:TextField;
	/** ユーザの名前 */
	public function get nicknameField():TextField
	{
		return _nicknameField;
	}
	
	private var _udpateButon:PushButton;
	/**
	 * ユーザ設定の変更ボタン
	 */
	public function get updateButton():PushButton
	{
		return _udpateButon;
	}
	
	private var _observeButton:PushButton;
	/**
	 * Roomへobserveするボタン
	 */
	public function get observeButton():PushButton
	{
		return _observeButton;
	}
	
	private var _joinButton:PushButton;
	/**
	 * Roomへjoinするボタン
	 */
	public function get joinButton():PushButton
	{
		return _joinButton;
	}
	
	private var _currentStatusLabel:Label;
	/**
	 * 現在の状態を表示
	 */
	public function get currentStatusLabel():Label
	{
		return _currentStatusLabel;
	}
	
	private var _currentClientsLabel:Label;
	/**
	 * 現在のクライアント数を表示
	 */
	public function get currentClientsLabel():Label
	{
		return _currentClientsLabel;
	}
	
	private var _avatarField:Sprite;
	/**
	 * アバターフィールド
	 */
	public function get avatarField():Sprite
	{
		return _avatarField;
	}
	
	private var _messageList:TextField;
	/**
	 * メッセージフィールド
	 */
	public function get messageList():TextField
	{
		return _messageList;
	}
	
	//----------------------------------------------------------------------
	//  methods
	//----------------------------------------------------------------------
	//------------------------------
	//  public methods
	//------------------------------
	/**
	 * constructor
	 */
	public function UnionChatUI() 
	{
		buildUI();
	}

	/**
	 * ローディングサークルを再生します。
	 */
	public function playLoading():void
	{
		addChild(_loadingCircle);
		_loadingCircle.visible = true;
		_loadingTween = BetweenAS3.tween(_loadingCircle,
			{ rotation:0 }, { rotation:360 }, 
			1.2, Sine.easeInOut
		);
		_loadingTween.stopOnComplete = false;
		_loadingTween.play();
	}
	
	/**
	 * ローディングサークルを停止します。
	 */
	public function stopLoading():void
	{
		_loadingCircle.visible = false;
		_loadingTween.stop();
	}
	
	/**
	 * メッセージリストに追加します。
	 */
	public function appendMessage(text:String, color:uint = 0x000000):void
	{
		_messageList.htmlText += '<font size="10" color="#' 
			+ color.toString(16) + '">' + text + "</font><br>";
		_messageList.scrollV = _messageList.maxScrollV;
	}
	
	//------------------------------
	//  private methods
	//------------------------------
	/**
	 * User Interfaceを作成します。
	 */
	private function buildUI():void
	{
		createLoadingCircle();
		createMessageField();
		createUserSetting();
		createRoomButton();
		createField();
		createMessageList();
	}
	
	/**
	 * ロード中を示す画像を表示します。
	 */
	private function createLoadingCircle():void
	{
		_loadingCircle = new Shape();
		
		var radian:Number;
		var radius:Number = 25;
		var posX:Number;
		var posY:Number;
		for (var i:uint = 0; i < 10; i++)
		{
			radian = (Math.PI * 2) * (i/10) - Math.PI;
			posX = Math.cos(radian) * radius;
			posY = Math.sin(radian) * radius;
			_loadingCircle.graphics.beginFill(0xFFFFFF, 1.0 - (i/10) + 0.1);
			_loadingCircle.graphics.drawCircle(posX, posY, 5);
		}
		_loadingCircle.x = STAGE_WIDTH / 2;
		_loadingCircle.y = STAGE_HEIGHT / 2;
		_loadingCircle.visible = false;
		addChild(_loadingCircle);
	}
	
	/**
	 * 共有するMessageを入力するフィールドを作成します。
	 */
	private function createMessageField():void
	{
		_messageField = createTextField(this, 0, STAGE_HEIGHT - 19)
		_messageField.type = TextFieldType.INPUT;
		_messageField.width = STAGE_WIDTH - 1;
		_messageField.height = 18;
	}
	
	/**
	 * ClientのAttributeを更新するUIを作成します。
	 */
	private function createUserSetting():void
	{
		_colorChooser = new ColorChooser(this, 0, STAGE_HEIGHT - 40, 0x000000);
		
		var nicknameLabel:Label = new Label(this,
			_colorChooser.width + 5, STAGE_HEIGHT - 40, "nickname:");
		nicknameLabel.setSize(45, 10);
		
		_nicknameField = createTextField(this,
			nicknameLabel.x + nicknameLabel.width + 5, STAGE_HEIGHT - 40, 10, "");
		_nicknameField.type = TextFieldType.INPUT;
		_nicknameField.width = 100;
		_nicknameField.height = 18;
		
		_udpateButon = new PushButton(this, 
			_nicknameField.x + _nicknameField.width + 5, 
			STAGE_HEIGHT - 40, "Update Attribute");
	}
	
	/**
	 * Roomボタンを作成します。
	 */
	private function createRoomButton():void
	{
		var margin:Number = 5;
		_observeButton = new PushButton(this, margin, margin, "observe");
		_observeButton.setSize(60, 20);
		_joinButton = new PushButton(this, 
			_observeButton.x + _observeButton.width + margin,
			margin,
			"join"
		);
		_joinButton.setSize(60, 20);

		var label:Label = new Label(this,
			_joinButton.x + _joinButton.width + margin,
			margin, "status:"
		);
		label.setSize(40, 10);
		
		_currentStatusLabel = new Label(this,
			label.x + label.width + margin,
			margin, ""
		);
		_currentStatusLabel.setSize(100, 20);
		
		_currentClientsLabel = new Label(this,
			_currentStatusLabel.x + _currentStatusLabel.width + margin,
			margin, "occupants:unknown"
		);
	}
	
	/**
	 * ユーザのアバターが活躍する(?)フィールドを作成します。
	 */
	private function createField():void
	{
		_avatarField = new Sprite();
		_avatarField.graphics.beginFill(0xEEEEEE);
		_avatarField.graphics.drawRoundRect(0, 0, 455, 300, 10, 10);
		_avatarField.x = 5;
		_avatarField.y = 30;
		_avatarField.mouseChildren = false;
		addChild(_avatarField);
	}
	
	/**
	 * メッセージを表示するフィールドを作成します。
	 */
	private function createMessageList():void
	{
		_messageList = createTextField(this, 5, 335);
		_messageList.width = 455;
		_messageList.height = 80;
		_messageList.wordWrap = true;
		_messageList.multiline = true;
	}
}	
/**
 * TextFieldの作成ヘルパーです。
 */
function createTextField(
		container:DisplayObjectContainer, positionX:Number, positionY:Number,
		size:Number = 10, text:String = "", borderColor:uint = 0x000000,
		backgroundColor:uint = 0xFFFFFF
		):TextField
{
	var textField:TextField = new TextField();
	textField.defaultTextFormat = new TextFormat("_等幅", size);
	textField.type = TextFieldType.DYNAMIC;
	textField.border = true;
	textField.borderColor = borderColor;
	textField.background = true;
	textField.backgroundColor = backgroundColor;
	textField.x = positionX;
	textField.y = positionY;
	textField.width = textField.height = 0;
	textField.text = text;
	container.addChild(textField);
	return textField;
}