キューの利用
今回はキューで走塁状況を管理しているので、キャラクターの走塁はCSSで書いたkeyframesをclassで切り替えて制御しています。classを切り替えるタイミングをanimation-durationの値分キューに入れて待ち、切り替える方法です。
キューの処理は以下のようになっています。
// キューコンストラクタ
function Queue() {
// キューの管理
this.queue = [];
// 実行中監視フラグ
this.running = false;
}
Queue.prototype = {
// キューに登録
// funcは省略可
add: function() { // (func, wait) or (wait)
var _a = arguments;
// waitの指定がない場合は即時(10ms)実行
if ( typeof _a[0] !== "function" ) {
this.queue.push(_a[0] || 10);
} else {
this.queue.push([_a[0], _a[1] || 10]);
}
return this;
},
// 登録されたキューを全て削除
clear: function() {
this.running = false;
this.queue = [];
return this;
},
// 登録されたキューを先頭から実行する
flush: function() {
var _this = this,
_thisQueue;
// flushの実行は一度だけ
if ( this.running ) return false;
this.running = true;
// キューの先頭にある関数を実行し(ない場合は何もしない)
// waitミリセカンド後に次のキューへ移る
// 実行したら次のキューの処理へ
(function() {
var _thisWait;
// キューが残っていなければ処理を中断する
if ( _this.queue.length === 0 ) {
// there is no queue
_this.running = false;
return false;
}
_thisQueue = _this.queue[0];
// 先頭のキューを削除して詰める
_this.queue.splice(0, 1);
// 現在のキューに登録されている関数を実行
if ( typeof _thisQueue === "object" ) {
_thisQueue[0]();
_thisWait = _thisQueue[1];
} else {
_thisWait = _thisQueue;
}
// 関数とペアで登録されたwaitタイム後、次のキューへ
setTimeout(arguments.callee, _thisWait);
}());
return this;
}
}
キューは、コンストラクタ関数でキューオブジェクトを作成し、実行したい処理と待ちたい時間をadd()メソッドで追加して使います。関数であれば次に実行したい処理、数値であれば数値分待機した後に、次にaddした関数を実行します。
var queue = new Queue();
queue
.add(function() { /* something to do */ })
.add(500) // 500ms後に次の処理が実行される
.add(function() { /* something to do */ })
ランナーの制御
ランナーの追加と走塁は前のキューを利用したプレーヤーマネージャオブジェクトで制御しています。ランナーはそれぞれアニメーションを管理するためのキューを持ち、走塁はキューを利用しています。
// 攻撃側のプレーヤーマネージャ
function Player(id) {
this.player = mQ(d.createElement("div"));
this.queue = new MBBM.Queue(); // キューの初期化
field.append(
this.player
.attr("id", id)
.addKlass("chara runner")
);
// waitTimeはCSSで指定されたものを使う
this.waitTime = this.player.css()["-webkit-animation-duration"];
this.waitTime = parseFloat(this.waitTime) * 1000;
return this;
}
Player.prototype = {
// 省略
wait: function(time) { // animation-duration分waitするメソッド
this.queue.add(time || this.waitTime);
return this;
},
// 省略
toPoint: function(from, to, callback) { // 指定の塁まで走塁するメソッド
var _this = this,
_arr = ["home", "first", "second", "third", "home"];
if ( from === to - 1 ) { // 次の塁へ進むだけなら・・・
this.queue
.add(function() {
_this.player
.removeKlass("batter wait")
.removeKlass(_arr[from])
.addKlass(_arr[to]);
});
} else
if ( from === to - 2 ) { // 2塁先へ進む場合は・・・
this.queue
.add(function() {
_this.player
.removeKlass("batter wait")
.removeKlass(_arr[from])
.addKlass(_arr[to-1])
})
.add(_this.waitTime)
.add(function() {
_this.player
.removeKlass(_arr[to-1])
.addKlass(_arr[to])
});
} else
// 中略
if ( _arr[to] !== "home" ) {
this.queue
.add(_this.waitTime)
.add(function() {
_this.player.addKlass("wait");
});
} else {
this.queue
.add(_this.waitTime)
.add(function() {
_this.player.addKlass("batter");
});
}
}
}
走塁はPlayer.toPoint()メソッドで実行します。走塁の制御にはWebSocketからプッシュされるmessageイベントから取得したデータを利用します。
// WebSocketにイベントbind
qws.bind({ // qwsはWebSocket
// 省略
"message": function(e) {
var data = JSON.parse(e.data),
type = data.type;
switch ( type ) {
// 中略
// ランナー
case "game.moveRunner":
// 対象のランナーを送られてきた塁までアニメーションで移動する
MBBM.go(parseInt(data.uniformNo)-1, data.from, data.to);
break;
}
}
});
今後の展望
今回は、iPhone専用というかなり限定した環境向けのWebアプリを、HTML5/CSS3と関連する技術で作ってみましたが、実際にやってみてとても作りやすいと感じました。
もちろん、iPhoneのスペック、処理能力ではPCにかなわない点が多く、パフォーマンス最適化の苦労もあります。しかし、モバイル端末にはPCにはない魅力や長所もありますから、モバイルのよさを活かした使い方をすればよいだけです。Handy StadiumではiPhoneの加速度センサーを利用しましたが、ほかにもGeolocation APIによる位置情報を組み合わせたりしてもおもしろいでしょう。
また、マルチプラットフォーム対応への試みとして、Handy StadiumをChrome ウェブストアのアプリとしても公開しました。マルチプラットフォーム対応はWebアプリのメリットとしてよく挙げられますが、実際には単純に動くようにするだけでなく、PCではPCの特性を考慮してチューニングする必要があると分かりました。
現状ではWebSocketをサポートしているブラウザーがまだまだ少なく、AndroidブラウザーやInternet Explorer、Firefox、Operaなどでは残念ながらHandy Stadiumをプレイできません。WebSocketをサポートされていないブラウザーでも別の技術を使用して通信をしてくれるnode.jsのモジュールのSocket.IOを使用することによって、それらのブラウザーでも遊べるようにできそうです。
HandyStadiumは現在ベータ版の冠が付いていますが、今後も継続して新しい機能を実装していき、モバイルWebアプリの可能性を探っていきたいと考えています。
◆
連載は今回で終わりですが、Webアプリの可能性を感じてもらえましたか? これまでお読みいただき、ありがとうざいいました!
マインドフリーのシステムチームでは、ブログでも情報を発信しています。フロントエンドの技術ばかりではありませんが、ぜひ見に来てください。
- テクヤン - マインドフリー .NET カフェ
- http://d.hatena.ne.jp/mftech/
著者:ハン☆スタ制作委員会/マインドフリー株式会社
日々切磋琢磨する大阪のイノベーター集団マインドフリー。先端Techとフリーなマインドを武器に「Fun!」なものづくりを目指してます。今回も新しい技術や開発言語が大好き!なSuperフレッシュエンジニア“やんぎー”(Facebookアプリ「Profile Photo Mosaic」を開発)が「世界を驚かせる!?計画」のひとつとして、Webアプリ開発の極みに迫るため「ハン☆スタ」をつくってみました。Let's play baseball♪
フロントエンドエンジニア 5509のnori も技術協力しています。