2002/03/18
サンプル1(簡単な作例)
- Flashによるマルチユーザーコンテンツ
このチュートリアルでは、実際にActionScriptを使った作例を通してマルチユーザコンテンツを説明します。マルチユーザといっても難しく考える必要はありません。ユーザ1人1人が皆に、自分のことを教えてあげればよいのです。重要なことは、「皆に教えること」「皆から教えてもらうこと」なのです。それだけできれば、マルチユーザコンテンツができあがるのです。それを潤滑に行うためにplashサーバープログラムがあります。では、実際にfacesサーバープログラムを使用したマルチユーザコンテンツの作例を見てみましょう。
説明の中で、flash特有のもの、faces特有のもの、それぞれのcontents特有のものがあります。文中では、(fla)、(fcs)、(con)と表記します。
(また、ActionScriptで定義されているものをメソッド、プロパティと呼び、今回functionを使用しこちらで作成しているものを関数、変数と呼びます。)
サンプルコンテンツ
サンプルファイル
- 「みんなで協力して隠れた画像を見よう」(peepTheDeep)
flaファイル内で機能ごとに4シーン作成しています。- バージョンチェック
- ローディング
- ロビー
- メインコンテンツ
- バージョンチェック
- バージョンチェック
最初のシーンは、バージョンチェックです。
flashでマルチユーザコンテンツを作成する場合、XML言語を扱います。XML未対応のバーション4以下のflashプレイヤーでは、マルチユーザコンテンツは見れないわけです。そこで、一番最初に_currentframeプロパティ(fla)(flash4対応)や、getVersion()メソッド(fla)(flash5対応)などを使ってバージョンチェックを行います。
クライアント側がflash5プレイヤーであれば、無事ローディングへと進みます。1: version = getVersion(); 2: version = version.split(" "); 3: userAgent = version[0]; 4: version = version[1].split(); 5: majorVer = version[0]; 6: minorVer = version[2]; 7: if (majorVer>=5) { 8: this.gotoAndPlay(_currentframe+2); 9: }
- ローディング
次に、ローディングです。ネットワークを通して他ユーザとやり取りするXMLsocketオブジェクトを認識させるための準備をします。
新しくXMLsocket(fla)を生成し、サーバーに接続します。
Connect()メソッド(fla)により、指定したサーバーへ指定したポート番号を使って接続します。1: function loadEnd () { 2: mySocket = new XMLSocket(); 3: mySocket.onConnect = checkConnect; 4: mySocket.connect(serverAddr, serverPort); 5: mySocket.onClose = checkClose; 6: }onXML()メソッド(fla)により、XMLsocketオブジェクトからデータを受信した時に呼び出されるコールバックです。ここでは、次のロビーで定義するgetData関数(fcs)を指定しておきます。1: function checkConnect (check) { 2: if (check) { 3: trace ("trueconnection"); 4: mySocket.onXML = getData; 5: queryNumber(appNam,roomNum); 6: } else { 7: trace ("falseconnection"); 8: } 9: }やり取りするXMLの定義を行います。
postXML()関数(fcs)は、文字列を受け取り、XMLとして読み込み、mySocket(fcs)へ送信します。各sendData用関数(fcs)内で使用します。1: function sendStr () { 2: theXML = new XML(); 3: theXML.parseXML(str); 4: mySocket.send(theXML); 5: }queryNumber()関数(fcs)は、アプリケーション名と、ルームナンバーを送信します。1: function queryNumber (app,room) { 2: trace ("connect : "+app+" room : "+room); 3: str = "<QN app=\""+app+"\" r=\""+room+"\" />\n"; 4: sendStr(str); 5: }queryServer()関数(fcs)は、ノードを送信します。サーバーが保持するデータの内、指定したノードのデータだけリクエストします。1: function queryServer (node) { 2: str = "<"+node+"/>\n"; 3: sendStr(str); 4: }
- ロビー
簡単なロビーを設けています。今回は、画面をクリックすることで不特定多数のユーザーがコンテンツに参加できるようにしています。ユーザに参加意思を聞き、参加であれば、アプリケーション名、ルーム番号と、ユーザ番号を発行します。
接続するサーバーアドレス、ポート暗号を指定します。アプリケーション名、ルーム番号を指定します。ここでは、アプリケーション名をtutorial、ルーム番号を0とし、ルーム番号0をロビーとしています。コンテンツによっては、ここで部屋毎にユーザーを分類するような機能を設けます。
1: serverAddr = "localhost"; 2: serverPort = "8080"; 3: appNam = "peepTheDeep"; 4: roomNum = "0";
(2)で実装したloadEnd()関数(fcs)を実行し、サーバー接続します。1: loadEnd(); 2: stop ();
Buttonを押すと、このコンテンツへ参加したことになります。その際に、自分の番号とルーム番号を送信します。ここでは、ユーザに関係なくルーム番号1に入室することにします。1: on (release) { 2: roomNum = "1"; 3: gotoAndPlay ("play"); 4: } - メイン
メインコンテンツです。ここで、コンテンツ独自の仕様を作成します。クリエイターの腕の見せ所だと思います。
このチュートリアルでは、画面上で画像を隠すマスク部分の整備をします。ユーザは入室した時、画面をランダムに配色(ユーザ毎に変わります。なぜなら配色のデータはXMLでやり取りしていないからです。)し、サイズ60の円を配列します。1: cC= new Color(_root.m.c); 2: cR = Math.random ()*100; 3: cG = Math.random ()*100; 4: cB = Math.random ()*100; 5: cA = 100; 6: cCT = {ra:cR, rb:'0', ga:cG, gb:'0', ba:cB, bb:'0', aa:cA, ab:'0'}; 7: cC.setTransform( cCT ); 8: cC= new Color(_root.mbg); 9: cCT = {ra:cR, rb:'0', ga:cG, gb:'0', ba:cB, bb:'0', aa:cA, ab:'0'}; 10: cC.setTransform( cCT ); 11: cSize = 60; 12: setProperty (_root.m.c, _width, cSize*1.02); 13: setProperty (_root.m.c, _height, cSize*1.02); 14: for (x=1; x<= 8; x++) { 15: for (y=1; y<=6; y++) { 16: dupName = "cX" + x + "Y" +y; 17: m.c.duplicateMovieClip(dupName, x*10+y); 18: setProperty ("_root.m.cX" + x + "Y" + y, _x, cSize/2 + (x - 1)*cSize); 19: setProperty ("_root.m.cX" + x + "Y" + y, _y, cSize/2 + (y - 1)*cSize); 20: } 21: }getMainData()関数(fcs)は、メインコンテンツ上で、他ユーザからのコールバックを firstChildプロパティ(fla)で識別し、それぞれの処理を行います。
firstChildプロパティ(fla)が"Hd"(con)の場合、指定の円を非表示するメソッドを実行します。
firstChildプロパティ(fla)が"Shw"(con)の場合、指定の円を表示するメソッドを実行します。
firstChildプロパティ(fla)が"N"(fcs)の場合、サーバーより割り当てられたユーザ番号を受け取り、selfname変数(fcs)に代入します。また、現在のサーバー上に保持されている情報をリクエストします。1: function getMainData (receiveXML) { 2: var e = receiveXML.firstChild; 3: if (e != null) { 4: trace (e); 5: if (e.nodeName == "H") { 6: // circleを非表示にする 7: t = e.attributes.n; 8: eval("m." + t).hideCircle(); 9: } else if (e.nodeName == "S") { 10: // circleを表示する。 11: t = e.attributes.n; 12: eval("m." + t).showCircle(); 13: } else if (e.nodeName == "N") { 14: // connect 15: selfname = e.attributes.n; 16: trace ("selfname : "+selfname); 17: queryServer("QR"); 18: } 19: } 20: }setXML()関数(fcs)は、指定したノードとユーザ番号を送信します。1: function setXML (node) { 2: str = "<"+node+" n=\""+selfname+"\" />\n"; 3: sendStr(str); 4: }setXMLc()関数(fcs)は、指定したノードと1つの指定した情報を送信します。1: function setXMLc (node, n) { 2: str = "<"+node+" n=\""+n+"\" />\n"; 3: sendStr(str); 4: }onXML()メソッド(fla)により、XMLSocketによりデータを受信した時に呼び出されるコールバックです。ここでは、2.で定義するgetMainData関数(fcs)を指定しなおします。再度アプリケーション名、ルーム番号を送信します。1: mySocket.onXML = getMainData; 2: queryNumber(appNam, roomNum);
各円内に自身の表示非表示を実行するためのメソッドです。
ここではalphaチャンネルを使ってやっていますが、単純にthis._visibleをtrue,false切り替えだけでも機能します。1: onClipEvent (load) { 2: function hideCircle () { 3: cC= new Color(this); 4: mC = cC.getTransform(); 5: cR = mC.ra; 6: cG = mC.ga; 7: cB = mC.ba; 8: cA = 0; 9: cCT = {ra:cR, rb:'0', ga:cG, gb:'0', ba:cB, bb:'0', aa:cA, ab:'0'}; 10: cC.setTransform( cCT ); 11: } 12: function showCircle () { 13: cC= new Color(this); 14: mC = cC.getTransform(); 15: cR = mC.ra; 16: cG = mC.ga; 17: cB = mC.ba; 18: cA = 100; 19: cCT = {ra:cR, rb:'0', ga:cG, gb:'0', ba:cB, bb:'0', aa:cA, ab:'0'}; 20: cC.setTransform( cCT ); 21: } 22: }各円内にあるボタンアクションです。ロールオーバーで、自身を非表示させるためのXMLを送信しています。ロールアウト、ドラッグアウトで表示させるためのXMLを送信しています。1: on (rollOver) { 2: _root.setXMLc("H", this._name); 3: 4: }on (rollOut, dragOut) { 5: _root.setXMLc("S", this._name); 6: }
- まとめ
簡単な説明ではありましたが、マルチユーザーコンテンツの仕組みがわかっていただけたかと思います。とはいっても、いろいろ面倒なことがあるのも事実です。ですが、一度流れを理解すれば、そんなに難しくないはずです。是非皆さん一度チャレンジしてみてください。おもしろいですから。
今回の作例は、シンプルなものにしてあるので、メイン部分で、個別認証の部分を省いています。もっとマルチユーザーコンテンツをおもしろくするには、ユーザー一人一人を認識し個別化することで更に違ったコミュニケーションが可能になります。
チュートリアル目次に戻る