アプリケーション・ゲーム・インターフェイス実装ガイド
この記事は、インテル® デベロッパー・ゾーンに掲載されている「App Game Interface Implementation Guide」(http://software.intel.com/en-us/html5/articles/app-game-interface-implementation-guide) の日本語参考訳です。
インテル® XDK のアプリケーション・ゲーム・インターフェイス (AGI) テクノロジーにより、ハイブリッド HTML5 アプリケーションはネイティブ・デバイス・レベルのテクノロジーを利用して<canvas>タグを高速化できます。この記事では、HTML5 の<canvas>タグをすでに使用している開発者に、このタグと AGI を使ってグラフィカルなアプリケーションを高速化する方法を紹介します。また、これらのテクノロジーにより、Android* および iOS* 向けに充実したグラフィカル・アプリケーションを開発する最も一般的な手法も示します。
インテル® XDK にサンプル・アプリケーションを読み込む
この記事の終わりにある「コードのダウンロード」リンクからサンプル・アプリケーションをダウンロードできます。このサンプルは、iOS* および Android* デバイス向けに AGI で<canvas>タグを高速化します。次のステップに従って、サンプル・アプリケーションをインテル® XDK に読み込みます。
- インテル® XDK を起動します。
- [Projects] タブで [Start a New Project] を選択し、新しい HTML5 アプリケーションを作成します。
- サンプル・アプリケーションを保存したフォルダーからプロジェクトをインポートします。
- [Emulate] タブに切り替えてアプリケーションのシミュレーションを開始します。
ターゲットデバイスでサンプル・アプリケーションを実行する
実際のデバイスとインテル® XDK エミュレーションで、AGI による<canvas>タグの高速化のパフォーマンスを確認するには、アプリケーションをビルドしてバイナリーを生成する必要があります。iOS* の場合は「Ad Hoc」ビルドを、Android* の場合は通常のビルドを行います。インテル® XDK の [Build] タブをクリックし、 [iOS Ad Hoc] ビルドまたは [Android] ビルドを選択して画面の指示に従います。アプリケーションのビルドが完了したら、テストを行うためデバイスにロードします。ビルド手順の詳細は、次の資料を参照してください。
http://www.html5dev-software.intel.com/documentation/index.php?DOC=TUTORIAL_BUILD_BINARY_IOS (iOS* Ad Hoc ビルド) (英語)
http://www.html5dev-software.intel.com/documentation/index.php?DOC=TUTORIAL_BUILD_BINARY_ANDROID (Android* ビルド) (英語)
ビルドが完了し、デバイスにアプリケーションをインストールしたら、デバイスでアプリケーションを表示してテストすることができます。
これまでの背景
AGI テクノロジーは、HTML5 ツールとサービスを提供する appMobi* (http://www.appmobi.com (英語)) 社により開発され、当初は「directCanvas」と呼ばれていました。そのため、AGI の JavaScript* オブジェクトの多くは、今でも AppMobi という名前を使用しています。以前のアプリケーションの機能を保持するため、あえてオブジェクト名は変更されませんでした。
AGI アーキテクチャー
AGI を使用するには、最初にその構造を理解する必要があります。AGI の高速化された canvas コマンドは、HTML フレームではなく、独自の「ビュー」にロードされます。「ビュー」では、コマンドが低レベルで解釈され、高速に実行されます。しかし、この「ビュー」はドキュメント・オブジェクト・モデル (DOM) にアクセスできないため、標準の Web 「ビュー」と高速化された「ビュー」間のやり取りはブリッジコマンドによって行われます。
高速化された「ビュー」のコードは、実際には HTML5 Web ビューの下に描画されます。つまり、AGI を利用するアプリケーションでは、HTML ファイルに含まれるすべてのグラフィカル要素が、AGI によって高速化されたグラフィックスにレンダリングされます。
ベストプラクティス
ここからは、AGI を使って iOS* または Android* 向けに充実したグラフィカル・アプリケーションを開発する「最も一般的な手法」を説明します。必要に応じて、サンプル・アプリケーションのコードを例に示します。
1 つの HTML ファイルを使用する
新しい HTML ページがロードされて描画されるたびに画面が更新されます。1 つの HTML ファイルを使用することで、これを回避できます。index.html は最初にロードされる HTML ファイルなので、このファイルを使用すると良いでしょう。
intel.xdk JavaScript* ブリッジ・ライブラリー
AGI の JavaScript* オブジェクトにアクセスするには、アプリケーションの index.html ファイルに intel.xdk JavaScript* ブリッジ・ライブラリーをインクルードする必要があります。このライブラリーは、インテル® XDK からアクセスする場合も、アプリケーションからアクセスする場合も、アプリケーションによって処理されます。intel.xdk JavaScript* ブリッジ・ライブラリーの詳細は、こちらのドキュメント (英語) を参照してください。
CSS スタイルに関する考慮事項
CSS の背景画像や背景色は、AGI レイヤーのグラフィックスを覆ってしまうため、使用できません。CSS の background-color 属性は、必ず「transparent」に設定してください。また、Android* の選択ハイライト、iOS の選択、WP8* のクリック・フィードバックはすべて、CSS では無効にすべきです。
AGI ビューを作成する
AGI ビューレイヤーは、AppMobi.canvas.load() コマンドを呼び出して JavaScript* ライブラリーをロードするときに作成されます。この JavaScript* ライブラリーには、AGI によって高速化されたキャンバスへの描画に必要なすべての<canvas>タグの呼び出しが含まれていなければいけません。AGI によって高速化されたキャンバスレイヤーは、常に全画面になります。複数の AppMobi.canvas.load() コマンドを呼び出して複数の AGI レイヤーを作成できますが、レイヤーが増えるにつれてモバイルデバイスのリソースへの負担が増え、パフォーマンスが低下する可能性があります。
すべてのキャンバスコードを AGI ビューに追加する
<canvas>タグに関連するすべての JavaScript* コードは、AppMobi.canvas.load() コマンドを用いて AGI ビューにロードすべきです。
サンプル・アプリケーションでは、index.html 内に AGI ビューを作成し、そのビューに index.js ファイルをロードしています。
// AGI ビューレイヤーをロードする AppMobi.canvas.load("index.js");
index.js を AGI ビューにロードした後、AppMobi.context.include() コマンドを使って、ビューにほかの JavaScript* ライブラリーのホストをインクルードします。
// context.include メソッドにより外部 JavaScript* ライブラリーを AGI ビューレイヤーにロードする AppMobi.context.include( 'agiDebug.js' ); AppMobi.context.include( 'eventListeners.js' ); AppMobi.context.include( 'screenSizing.js' ); AppMobi.context.include( 'starBackground.js' ); AppMobi.context.include( 'rocketSprite.js' ); AppMobi.context.include( 'spaceRockSprites.js' ); AppMobi.context.include( 'sounds.js' ); AppMobi.context.include( 'animationLoop.js' );
canvas コマンドを AGI コンテキストに渡す
HTML5 の<canvas>タグに対する通常の呼び出しとは異なり、AGI の canvas 呼び出しは、AppMobi.canvas.getContext(‘2d’) への参照で present() メソッドが呼び出されるまで実行されません。このメソッドにより、AGI の canvas ビューは、すべての canvas 操作を画面にレンダリングします。このメソッドが呼び出されなければ、AGI は何も描画しません。
サンプル・アプリケーションでは、ゲームループの最後で速度 (FPS) を計算する直前に present() メソッドを呼び出しています。これは、animationLoop.js ファイルの animate() 関数にあります。
// キャンバス・コンテキスト変数 var ctx; if (ctx == null) { var ctx = AppMobi.canvas.getContext("2d"); } … // アニメーション・ループ関数 function animate() { // 画面をクリアする ctx.fillRect(0,0,w,h); // 別の方法として、ctx.clearRect(0, 0, w, h); を使用して画面をクリアすることもできる // ここでは、不透明度により星野を不鮮明にし、速度があるように見せるため fillRect を使用する // 背景を描画する drawStarBackground(); // 隕石を描画する drawRockSprites(); // 宇宙船を描画する drawRocketSprite(); // AGI に新しいフレームの供給を指示する ctx.present(); // FPS を計算し、次のアニメーション・フレームをキューに追加する throttle(); }
AGI レイヤーと HTML5 レイヤー間のやり取り
2 つのビューが重なり合っているため、2 つのビュー間でやり取りする必要性が出てきます。例えば、ユーザーが HTML5 WebView にタッチするとトリガーされるイベントは、下位の AGI ビューレイヤーで実行しているグラフィック要素に指示する必要があります。
HTML5 WebView では、AppMobi.canvas.execute() メソッドを用いて AGI ビューで実行する JavaScript* コードを呼び出せます。サンプル・アプリケーションの index.html ファイルに、この良い例があります。
// この WebView 関数はボタン・タッチ・イベントを処理し、 // 情報を AGI ビューレイヤーに渡して動作が行われるようにする function laser_fire() { // AGI ビューレイヤーに動作を指示する AppMobi.canvas.execute("handle_fire_laser();"); // 同じイベントが連続して発生しないように、インベントハンドラーに false を返す return false; }
通常、逆方向のやり取りも必要になります。AGI のビューレイヤーで実行している JavaScript* コードは、AppMobi.webview.execute() コマンドにより HTML5 WebView をコールバックできます。サンプル・アプリケーションではこの呼び出しを使って、agiDebug.js ライブラリーの WebView にデバッグ情報を記述しています。
// デバイスでは通常の console.log メソッドを利用できないため、 // この関数によりアプリケーションの AGI ビュー関連領域のデバッグを支援する var maxDebugLevel = 0; function dbg(txt,debugLevel) { if (debugLevel <= maxDebugLevel) { AppMobi.webview.execute("document.getElementById('debugMessage').innerText = '" + txt + "';"); try { console.log(txt); } catch(e) {} } }
Android* 向けにマルチタッチ・イベントを有効にする
Google* Android* プラットフォーム向けの AGI により、開発者は一度に画面の複数の場所をタッチするマルチタッチを処理することができます。この AGI は、プレーヤーが同時に複数のボタンを操作できるユーザー・インターフェイスを開発できるように設計されています。しかし、同じ HTML 要素でマルチタッチが使われるジェスチャーに、この AGI を使用することはできません。Apple* iOS* プラットフォームはすでにマルチタッチをサポートしているため、Apple* iOS* プラットフォーム向けの AGI ではこの機能は不要です。
サンプル・アプリケーションでは、index.html ファイル内の次の行でマルチタッチを有効にしています。
// Android* デバイスで AGI のマルチタッチを有効にする try { AppMobi.multitouch.enable(); } catch(e) {}
AppMobi.multitouch.enable メソッドは、Android* プラットフォームでマルチタッチに対応するため、さまざまな HTML 要素の複数のタッチイベントのリスニングを開始します。
AGI のサウンド機能を使用する
AGI のマルチサウンド拡張により、HTML5 のサウンド関連の多くの欠点を補うことができます。HTML5 は、レイテンシーの低い複数の非同期サウンドを再生するようには設計されていません。しかし、それこそがゲームやほかのアプリケーションで求められていることです。AGI のマルチサウンド・テクノロジーは、同時に再生されているサウンドに関係なく、ゲームの各エンティティーが必要に応じてサウンドを再生できるようにします。唯一の制限は、メモリーとストレージの典型的な問題だけです。
AGI で利用可能なオーディオ API は 2 セットあります。1 つ目は、通常の HTML5 の
// HTML5 WebView と同様に、仮想 Audio タグを作成してサウンドをロードできる engineSound = new Audio(); // AGI の Audio タグ engineSound.src = "sounds/engines.wav"; engineSound.load();
2 つ目の API セットは、AppMobi.context オブジェクトを介して利用できます。この API セットは使いやすく、パフォーマンスが向上するように設計されています。次の URL にこの節で触れた API のドキュメントが掲載されています。
http://www.html5dev-software.intel.com/documentation/gamingAPI/directCanvas/AppMobi/ context/index.html (英語)
1 つのバックグラウンド・サウンド (繰り返し再生も可) を制御するメソッドには、startBackgroundSound、toggleBackgroundSound、stopBackgroundSound の 3 つがあります。
ほかのサウンドは、loadSound または loadPolySound で事前にロードし、playSound で再生できます。loadPolySound は、特定のサウンドの複数のコピーをロードし、それらをオーバーラップさせて生成することができます。つまり、loadPolySound(‘sound.mp3’, 3) で 3 秒のサウンドをロードし、playSound(‘sound.mp3’) を 1 秒間隔で 3 回呼び出すと、サウンドの 3 つのコピーが同時に再生されます。polyCount 値を超える playSound の呼び出しや loadPolySound でロードされていないサウンドの再生は無視されるか、サウンドが検索されます (特定のサウンドに対する playSound の頻繁な呼び出しによって生じるパフォーマンス問題を回避するさまざまな要因に依存します)。
その場合は、unloadSound で個々のサウンドをアンロードするか、unloadAllSounds で現在ロードされているすべてのサウンドをアンロードできます。サンプル・アプリケーションの sounds.js ライブラリーに、マルチサウンドのロードの例があります。
// AGI によって高速化されたキャンバスを使用するアプリケーションで、 // (自身とオーバーラップする場合も含めて) 繰り返しサウンドを再生するには、 // このメソッドでサウンドをロードし、後で playSound メソッドで再生する AppMobi.context.loadPolySound("sounds/laser.wav",5);
すべてのアセットはローカルに配置する
インターネット上にあるアセットは、ネイティブ実行アプリケーションでは利用できない可能性があります。イメージやビデオなどのファイルは、相対パス名で参照すべきです。また、これらのファイルは index.html と同じディレクトリーまたはそのサブディレクトリーに配置します。iOS および Android* オペレーティング・システムでは、大文字と小文字が区別されます。ファイル参照には正しいパスと名前を指定してください。
AGI の制限事項
AGI には、HTML5 開発者が知っておくべき制限事項がいくつかあります。まず、AGI は DOM にアクセスできません。console.log や alert() などの通常は問題なく動作する呼び出しが、AGI を利用するアプリケーションでは警告なしにクラッシュすることがあります。つまり、インテル® XDK の AGI シミュレーターでは動作しても、実際のデバイスでは動作しない場合があります。
サンプル・アプリケーションに含まれるようなデバッグヘルパー関数を作成し、開発時に使用することを検討してください。
// デバイスでは通常の console.log メソッドは利用できないため、この関数を使って // アプリケーションの AGI ビュー関連のコードのデバッグを簡単にする var maxDebugLevel = 0; function dbg(txt,debugLevel) { if (debugLevel <= maxDebugLevel) { AppMobi.webview.execute("document.getElementById('debugMessage').innerText = '" + txt + "';"); try { console.log(txt); } catch(e) {} } }
AGI は、HTML5 の<canvas>タグを完全に実装するものではありません。開発を容易にするため、いくつかのコマンドには対応していますが、対応していないコマンドもあります。現時点でのコマンドの相対表は、次のオンライン・ドキュメントを参照してください。
http://www.html5dev-software.intel.com/documentation/resources/pregenPages/ AGIFeaturesMatrix.html (英語)
できるだけ早期に、そして頻繁にデバイスでテストを行うことで、AGI で高速化されたキャンバスにより応答性に優れた魅力的なアプリケーションを開発できるでしょう。