home > 過去ログ(2004年以前) > サンプル1(簡単な作例)
2002/03/18

サンプル1(簡単な作例)


  • Flashによるマルチユーザーコンテンツ
    このチュートリアルでは、実際にActionScriptを使った作例を通してマルチユーザコンテンツを説明します。マルチユーザといっても難しく考える必要はありません。ユーザ1人1人が皆に、自分のことを教えてあげればよいのです。重要なことは、「皆に教えること」「皆から教えてもらうこと」なのです。それだけできれば、マルチユーザコンテンツができあがるのです。それを潤滑に行うためにplashサーバープログラムがあります。では、実際にfacesサーバープログラムを使用したマルチユーザコンテンツの作例を見てみましょう。
    説明の中で、flash特有のもの、faces特有のもの、それぞれのcontents特有のものがあります。文中では、(fla)、(fcs)、(con)と表記します。
    (また、ActionScriptで定義されているものをメソッド、プロパティと呼び、今回functionを使用しこちらで作成しているものを関数、変数と呼びます。)

    サンプルコンテンツ
    サンプルファイル

  • 「みんなで協力して隠れた画像を見よう」(peepTheDeep)
    flaファイル内で機能ごとに4シーン作成しています。
    1. バージョンチェック
    2. ローディング
    3. ロビー
    4. メインコンテンツ
  1. バージョンチェック
    最初のシーンは、バージョンチェックです。
    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:	}
    

  2. ローディング
    次に、ローディングです。ネットワークを通して他ユーザとやり取りする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: }
    

  3. ロビー
    簡単なロビーを設けています。今回は、画面をクリックすることで不特定多数のユーザーがコンテンツに参加できるようにしています。ユーザに参加意思を聞き、参加であれば、アプリケーション名、ルーム番号と、ユーザ番号を発行します。
    接続するサーバーアドレス、ポート暗号を指定します。アプリケーション名、ルーム番号を指定します。ここでは、アプリケーション名を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: }
    
  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: }
    

  • まとめ
    簡単な説明ではありましたが、マルチユーザーコンテンツの仕組みがわかっていただけたかと思います。とはいっても、いろいろ面倒なことがあるのも事実です。ですが、一度流れを理解すれば、そんなに難しくないはずです。是非皆さん一度チャレンジしてみてください。おもしろいですから。
    今回の作例は、シンプルなものにしてあるので、メイン部分で、個別認証の部分を省いています。もっとマルチユーザーコンテンツをおもしろくするには、ユーザー一人一人を認識し個別化することで更に違ったコミュニケーションが可能になります。

    チュートリアル目次に戻る