Accessibility

Director TechNote

ビヘイビアのインスタンスとメッセージ(3)

(複数のスプライト間でメッセージをやりとりする)

ビヘイビアスクリプティングの中級者の方向けに、複数のスプライトのビヘイビア間でメッセージをやりとりする方法について解説します。

1 スプライト間のメッセージ受け渡しとビヘイビアインスタンスの生成

トグルボタンや再生/ポーズの切替ボタンなど、複数のスプライトを連係させて動作させたいときがあります。このとき、ひとつのスクリプトに一連の動作をすべて書き込んで制御する方法もあります。けれど、バージョン6から導入されたビヘイビアのスクリプティングでは、ビヘイビア間のメッセージのやりとりで処理し、個々のビヘイビアをパーツ化することができます。それにより、ビヘイビアの再利用がしやすくなり、デバッグの手間も省けます(ビヘイビアのメッセージの受け渡しの意味についてはtechnote ID: dr016876「ビヘイビアのインスタンスとメッセージ(1)」をご参照ください )。

スプライトにメッセージを送るのは、まず'sendSprite'コマンドです。ただ、この場合スプライト番号を特定しなくてはなりません。複数のスプライトを制御したい場合、どのスプライトにメッセージを送るか、そのたびごとに確認するのでは柔軟性に欠けます。最初に、連係が必要なスプライトのビヘイビアインスタンスを互いに自分のビヘイビアのプロパティとして取得しておくと、あとはそのプロパティに対してメッセージを送ることができます(インスタンスとプロパティ、メッセージの関係については、前出technote ID: dr016876参照)。

初期化処理は、通常'on beginSprite'ハンドラで行います。そのとき、'sendAllSprites'コマンドでインスタンスを受け渡すためのメッセージを送り、自分のインスタンス(me)をパラメータとして渡せばよさそうに思えます。ただ、このとき問題があります。以下のビヘイビアを1から4チャネルのスプライトに設定して、メッセージウィンドウの結果を確認してみましょう。


-- [テスト用ビヘイビア]

property spriteNum

property plSpriteList


on beginSprite me
  plSpriteList = []
  put #beginSprite, spriteNum
  sendAllSprites(#xCollectList, spriteNum)
end


on xCollectList me, nSpriteNum
  plSpriteList.append(nSpriteNum)
  put [spriteNum, plSpriteList]
end


[メッセージウィンドウでの実行結果例]
-- #beginSprite 1
-- [1, [1]]
-- #beginSprite 2
-- [1, [1, 2]]
-- [2, [2]]
-- #beginSprite 3
-- [1, [1, 2, 3]]
-- [2, [2, 3]]
-- [3, [3]]
-- #beginSprite 4
-- [1, [1, 2, 3, 4]]
-- [2, [2, 3, 4]]
-- [3, [3, 4]]
-- [4, [4]]

スプライト4つにビヘイビアを設定しましたので、'beginSprite'のメッセージは都合4回発生します。そのとき、メッセージウィンドウに#beginSprite [スプライト番号]が出力されます。つぎに、'on beginSprite'ハンドラで'sendAllSprites'を実行していますので、送られたメッセージを受けて、各スプライトのxCollectListハンドラが実行され、[スプライト番号、plSpriteListの内容」が出力されます。そう見てみると、スプライト1'sendAllSprites'で送ったメッセージ#xCollectListは、スプライト1 しか受取っていないことがわかります。スプライト4が'beginSprite'メッセージを受取ったところで、ようやく4つのスプライトすべてが#xCollectListメッセージを受取っています。

これは、ビヘイビアのインスタンスがスプライトの若い番号(1)から順に生成され、そのとき'beginSprite'メッセージが発生するからです。したがって、スプライト1のインスタンスが生成された時点では、他のスプライトのインスタンスはまだ存在しません。ですから、他のスプライトのインスタンスはメッセージを受取ることができないのです。そのため、4つのスプライトからの'xCollectList'メッセージを受取ることができたのは、スプライト1のビヘイビアインスタンスだけなのです。それは、スプライト1のビヘイビアのプロパティplSpriteListのみが、4つのスプライトの番号をリスト中に取得していることからもわかります。

この方法で、必要なビヘイビアインスタンスをプロパティとして取得しようとすると、工夫が必要です。ひとつの方法は、一番番号の大きなスプライトに全体をコントロールするビヘイビアを設定するやり方です。この方法を利用した場合には、上記の「テスト用ビヘイビア」とは逆に、必要なすべてのスプライトに対して自分に各インスタンスの参照を渡すようにメッセージを送ることになります。そのうえで、その全体をコントロールするビヘイビアのインスタンスをグローバル変数に設定すれば、他のインスタンスからもアクセスできます。


2 複数のスプライトのビヘイビア間でインスタンスを持ち合う

少しトリッキーですが、もっと簡単で汎用性のある方法があります。それをご紹介しましょう。まず以下のビヘイビアを先程と同様に、スプライト1から4に設定してみてください。(スクリプトの内容については後の解説をご参照下さい。)


-- [テスト用ビヘイビア2]

property spriteNum
property plSpriteList


on beginSprite me
  sendAllSprites(#xCollectList, [])
end

on xCollectList me, lListPointer
  plSpriteList = lListPointer
  lListPointer.append(spriteNum)
end


on xPutMyList me
  put [spriteNum, plSpriteList]
end


今回はメッセージウィンドウでの確認には、'sendAllSprites(#xPutMyList)'を実行する必要があります。メッセージウィンドウでの実行結果は以下のようになります。

[メッセージウィンドウでの実行結果例]
sendAllSprites(#xPutMyList)
-- [1, [1, 2, 3, 4]]
-- [2, [1, 2, 3, 4]]
-- [3, [1, 2, 3, 4]]
-- [4, [1, 2, 3, 4]]

4つのスプライトすべてが、プロパティplSpriteListに全スプライトの番号を取得できています。この秘密は'sendAllSprites'で、パラメータとしてリストを渡していることにあります。リストを変数(plSpriteList)に割り当てたとき、実際にはリストそのものではなく、リストへの参照が渡されます。これは、メッセージウィンドウでつぎのようなテストをすれば、簡単に確認できます。

[メッセージウィンドウでのテスト例]
lMyList = [1, 2, 3, 4]
put lMyList
-- [1, 2, 3, 4]
lYourList = lMyList
put lYourList
-- [1, 2, 3, 4]
lYourList.deleteAt(4)
put lYourList
-- [1, 2, 3]
put lMyList
-- [1, 2, 3]

lYourListにlMyListを割り当てたとき、lYourListにはlMyListと同内容の新規のリストが作成されたわけではありません。lMyListに割り当てられたリストへの参照が代入されたのです。したがって、lYourListとlMyListは、同じリストを参照しています。そのため一方のリストの内容を変更すれば、他方も同じように変わることになるのです。

上記「テスト用ビヘイビア2」の説明に戻りましょう。'sendAllSprites'で、メッセージ#xCollectListとともにパラメータとしてリスト([])を渡しています。メッセージを受けた'on xCollectList'ハンドラは、その第1ステートメントで、渡されたパラメータのリストをプロパティplSpriteListに割り当てています。ここで渡されたのはリストへの参照です。ですから、メッセージを受けたスプライトすべてが同じリストを参照し、その同じリストに対して自分のスプライト番号を加えたのです。したがって、メッセージを受けたすべてのスプライトのビヘイビアインスタンスは、プロパティplSpriteListに同じリストを共有したことになるのです。(デバッガを利用するとさらに詳しくスクリプトの流れを確認できますのでお試しください。)

ID: dr0267
Product: Director
Versions: 7 and above
OS: ---
Browser: N/A
Server: N/A
Database: N/A
Former ID: N/A