Skip to content

socket.enchant.jsに重大なバグ発見!と、もっとわかりやすいサンプル

さてさて、先日リアルタイム通信に対応したenchant.jsだが、β版以前にsocket.enchant.js自体に重大なバグがあることが解った。

開発責任者の伏見君が電話で捕まらないので私、shi3zが緊急デバッグとサンプル配布を行うことにする。

なお、現在(12月3日22時25分) githubで配布されているsocket.enchant.jsはバグっているので、この記事で配っているソースに含まれているsocket.enchant.jsを使っていただきたい。本当に監督不行き届きで申し訳ない。

※ (12/3 23:30) githubにバグ修正版をアップロードしました。ご迷惑をおかけして申し訳ありませんでした。ダウンロードはこちらから

まあ伏見君もそうなんだけど、今回のリアルタイム通信対応を担当した安田君(東北大学)の解説も天才肌のプログラマにありがちな「説明すっ飛ばし」でけっこう理解するのが難しかった。

そこでサンプルも新たに書き直したのでenchant.jsでソケット通信ができん!!!とお嘆きの方はぜひ読んでいただきたい。

まずはサンプルだけど、そもそもリアルタイム通信を確認するには、二つ以上のブラウザで別々のTwitterIDで9leapにログインする必要がある。

socket.enchant.jsはTwitterIDでユーザを判別しているため、同じブラウザで同じページを二つ開いても通信はされないのだ。

これは最低限の準備なので各自やっていただきたい。

 

次に、開発をする前にgameIDというものを取得する必要がある。

これは9leapに投稿されたURLと関係があるので、とにもかくにも非公開でなにかをアップロードしてgameIDを取得する必要がある。

この状態でまずダミーのファイルかなんかをアップロードして、gameIDを取得する。

今回、僕は987というgameIDを取得した。

http://9leap.net/games/987 というURLを叩くと僕のサンプルプログラムに行くようになっている。

 

さて、では実際のコードを見てみよう

enchant();
window.onload = function(){
    game = new Game(320, 320);
    game.fps = 20;


	//ソケットを作る
	//↓一度9leapにアップロードしてgameIDを取得して埋め込む
    game.socket = new Socket(987); 
    game.socket.lobby.join();

	//接続して対戦相手がやってきたときに呼び出されるイベント
    game.socket.gameRoom.addEventListener('ready', function (data) {
        
		// 接続した相手の名前とアイコンをラベルに表示する
        label.text="Connect with "+game.socket.gameRoom.member[0]+" <img width=24 src='http://9leap.net/api/icon/screen_name/"+game.socket.gameRoom.member[0]+"'>";
        label.x = 50;
        label.y = 280;
		
    });



    game.onload = function(){

		//お絵かきする場所を初期化
	    scr = new Sprite(320,320);
        surface = new Surface(320,320);
        scr.image=surface;
		game.rootScene.backgroundColor="black";
		game.rootScene.addChild(scr);
 		ctx = surface.context;

		//接続情報等を表示するラベル
		label = new Label("Connecting...");
		label.x = 140;
		label.y=140;
		label.color="white";
		game.rootScene.addChild(label);

		//タッチし始め
		scr.addEventListener('touchstart',function(e){
			this.ax = e.x;
			this.ay = e.y;
			this.penDown = true;
		});

		//タッチ終了
		scr.addEventListener('touchend',function(e){
			this.penDown = false;
		});

		//タッチ移動中
		scr.addEventListener('touchmove',function(e){

			if(!this.penDown)return;
			var x = this.ax;
			var y = this.ay;
			var dx = (e.x -x)/20;
			var dy = (e.y -y)/20;

			//サーバへ線分の情報を送信
			game.socket.gameRoom.push('put',
				{x:x, y:y, dx:dx,dy:dy});

			this.ax = e.x;
			this.ay = e.y;

			//実際に線分を描画
			line(x,y,dx,dy,'green');
		});

		//サーバから送られて来た線分の描画		
		game.socket.gameRoom.addEventListener('put', function (data){
			line(data.x,data.y,data.dx,data.dy,'red');
		});
    }
    game.start();
}

function line(x,y,dx,dy,color){
	for(var i=0;i<20;i++){
		ctx.beginPath();
		ctx.arc(x,y, 3, 0, Math.PI*2, false);
		ctx.fillStyle =color; 
		ctx.fill();
		x+=dx;y+=dy;
	}
}

大事なところはできるだけコメントとして書いたつもりだ。
このコードはここからソースコードまるごとダウンロードできる。

また、今回のsocket.enchant.jsはPusherというnode.jsのプロキシーサービスを利用している。

なので、index.htmlでもpusherのAPIを読み込む必要がある。
ここは最初気づかなくて僕もハマった。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta equiv="expires" content="0">
    <meta name="viewport" content="width=device-width, user-scalable=no"> 
    <meta name="apple-mobile-web-app-capable" content="yes">
        <script src="http://js.pusherapp.com/1.9/pusher.min.js" type="text/javascript"></script>
    <script type="text/javascript" src="enchant.js"></script>
    <script type="text/javascript" src="socket.enchant.js"></script>
    <script type="text/javascript" src="main.js"></script>
    <style type="text/css">
        body {
            margin: 0;
        }
    </style>
    </head>
  <body>
  </body>
</html>

さて、このプログラムでは、自分(ローカル)で書いた線を緑、相手(リモート)から送られて来た線を赤で描画している。

ただし、実際に実行してみるとわかるが、かなりのタイムラグがある。
また、開発するときにあんまり連続して呼ぶと、Pusherの呼び出し制限にひっかかるようだ。

このへんはイマイチいけてないのでいずれ解決する方法を見つけたい。

最初のサンプルはリバーシだったので、理解するのがすごく複雑になってしまったと思うが、今回のは単に線分の情報を受け取って描画するだけなので理解するのが少しはマシではないかと思う。

もし「もっと簡単なサンプルが必要」ということであれば、さらに簡単なサンプルも用意したい。

とりあえずこれで「なぜだ!?なぜ動かんのだ!」という状況の改善になればと思っている。

リアルタイム通信ゲームを作る時は実はもっと気をつけなければならないことがあるのだが、それはほぼテクニックの領域なのでまた項を改めて説明したい。

要するにこのタイムラグをどう解決するか、それが腕の見せ所なわけだ。

とりあえず試していただきたい

文・shi3z

Facebook comments:

Post a Comment

Your email is never published nor shared. Required fields are marked *
*
*