実装の機会は非常に稀ですが、複数Flash間のやりとりを可能にするLocalConnectionを使った相互通信を実装してみます。

おさらい

まずLocalConnectionについての簡単なおさらいです。

LocalConnectionを使用すると、複数のFlash間で動作のやりとりができます。LocalConnectionには受信側と送信側があり、先に受信側が接続設定しておいたコネクション名を送信側が指定することで、受信側の関数を実行させることができます。以下に例を示します。

まずこれが受信側のスクリプトです。「Connection123」というコネクション名で接続を待機しています。

var _connectReciever:LocalConnection = new LocalConnection();
_connectReciever.client = this;
_connectReciever.connect('Connection123');

function doSomething():void
{
	trace('recieved!');
}

そしてこちらは送信側のスクリプトです。受信側が待機しているコネクション名と、実行してほしい関数の名前をsendします。(一応StatusEventをハンドリングするようにしておきましょう)

var _connectSender:LocalConnection = new LocalConnection();
_connectSender.addEventListener(StatusEvent.STATUS, statusHandler);
function statusHandler(e:StatusEvent):void
{
}
_connectSender.send('Connection123','doSomething');

 これでOKです。受信側のswfを再生している状態で送信側swfを新たに開くとdoSomething関数が実行されます。

相互通信できるようにする

さて、上記の実装ではひとつ問題があり、通信が送信側から受信側への一方通行になってしまっています。もしも送信側の方が先にロード完了してしまった場合、受信側がまだ準備できていないという事態が起こりかねません。どちらが先にロードを完了しても大丈夫なように相互通信を実装してみましょう。

どうするかというと、送信側にも同じように待機用のLocalConnectionを立てておけばOKです。以下のように実装します。(相互通信なので受信側・送信側ではなくA・Bとします)

まずA側です。A側は「ConnectionA」を受信用のコネクション名として待機しつつ、「ConnectionBのimReady関数」実行をリクエストします。

var _connectReciever:LocalConnection = new LocalConnection();
_connectReciever.client = this;
_connectReciever.connect('ConnectionA');

var _connectSender:LocalConnection = new LocalConnection();
_connectSender.addEventListener(StatusEvent.STATUS, statusHandler);
function statusHandler(e:StatusEvent):void
{
}
_connectSender.send('ConnectionB','imReady');

function imReady():void
{
	trace('A recieved the message from B.');
	this._connectSender.send('ConnectionB','connectOK');
	fusion();
}

function connectOK():void
{
	trace('connection ok');
	fusion();
}

function fusion():void
{
	//双方準備OK!
}

次にB側です。こちらは逆に「ConnectionB」を受信用コネクション名として待機。「ConnectionAのimReady関数」をリクエストしています。

var _connectReciever:LocalConnection = new LocalConnection();
_connectReciever.client = this;
_connectReciever.connect('ConnectionB');

var _connectSender:LocalConnection = new LocalConnection();
_connectSender.addEventListener(StatusEvent.STATUS, statusHandler);
function statusHandler(e:StatusEvent):void
{
}
_connectSender.send('ConnectionA','imReady');

function imReady():void
{
	trace('B recieved the message from A.');
	this._connectSender.send('ConnectionA','connectOK');
	fusion();
}

function connectOK():void
{
	trace('connection ok');
	fusion();
}

function fusion():void
{
	//双方準備OK!
}

 まぁ要はどっちも同じコードで、コネクション名のAとBを入れ替えているだけです。さて、実際に動作させるとどうなるでしょうか。

もしA側が先にロードされ、Bが後からロードされた場合、A側からリクエストされた「ConnectionBのimReady」はB側の準備が出来ていないため無視されます。B側がロード完了し「ConnectionAのimReady」がリクエストされ、A側のimReady関数が実行されます。その関数内では「ConnectionBのconnectOK関数」がリクエストされ、B側はA側が既に準備OKであることを知ることができます。最後に両側でほぼ同時にfusion関数が実行されるというわけです。

Picture.png

これなら、もしベジータが後からやって来ても無事にフュージョンすることができますね!

HTML5飯