enchant.jsで重要なスプライトとシーンを使うには:enchant.jsでHTML5+JavaScriptゲーム開発入門(3)(4/4 ページ)
大人気のHTML5+JavaScriptベースのゲームエンジン「enchant.js」を使ってゲームアプリを作る方法を解説していく。今回は、スプライトの3つの基本操作、スプライトシート、シーンの扱い方を解説。最後に「もぐらたたきゲーム」を作ってみよう
シーンの遷移―― 3種類の切り替え方法
次に、赤字部分のシーンの切り替え方法について解説します。enchant.jsはシーンを切り替える際に使うメソッドが3つ用意されています。これによってシーンを切り替えるだけではなく、シーンの上に別のシーンをかぶせてポーズ画面にしたり、メッセージウィンドウにしたりと柔軟な対応を可能にしています。
【1】replaceScene(シーンを取り換える)
ゲーム.replaceScene(新しいシーン)
現在のゲームで表示しているシーンを新しいシーンと取り換えることができます。取り換える直前の古いシーンは失われてしまいます。失いたくないときは後述のpushSceneとpopSceneを使いましょう。タイトル画面からゲーム中画面に進むときなど、特に戻る必要がないときに使います。
【2】pushScene(一番上にシーンを重ねる)
ゲーム.pushScene(新しいシーン)
現在のゲームで表示しているシーンの上に、新しいシーンをかぶせます。かぶせる直前の古いシーンはかぶせた瞬間に待機状態になります。かぶせたシーンを剥がしたいときは後述のpopSceneを使います。
なお、pushSceneは何回も使えますが、重ね過ぎると処理が重くなっていくので注意しましょう。
【3】popScene(一番上のシーンを外す)
ゲーム.popScene();
最後にpushSceneで押し込んだシーンを取り出し、前のシーンを表示させます。再び表示された前のシーンのイベントは再開されます。他の書き方と違い、括弧の中にシーン名を指定する必要はありません。
また、全てのシーンをpopScene()してしまうと表示するシーンが1つもなくなってしまうので注意してください。
現在の知識を使って「もぐらたたきゲーム」を作ってみよう
今回の最後に、これまでの知識を使ったゲームの紹介をします。
さて、前回から今回まで、enchant.jsにおけるゲーム作りの基礎の部分をやってきました。この辺りで1つ、ゲームらしいゲームを作ってみましょう。動くもぐらたたきゲーム、「くまたたき」です。制限時間内になるべく多くのくまを叩き、叩いた数を競うゲームです。
下のプログラムをmain.jsに書き写してみてください。
enchant(); window.onload = function() { var game_ = new Game(320, 320); // 表示領域の大きさを設定 game_.fps = 24; // ゲームの進行スピードを設定 game_.preload('./img/chara1.png', './img/start.png', './img/gameover.png'); // ゲームに使う素材を、あらかじめ読み込む game_.onload = function() { // ゲームの準備が整ったらメインの処理を実行します /** * タイトルシーン * * タイトルシーンを作り、返す関数です。 */ var createStartScene = function() { var scene = new Scene(); // 新しいシーンを作る scene.backgroundColor = '#fcc800'; // シーンの背景色を設定 // スタート画像設定 var startImage = new Sprite(236, 48); // スプライトを作る startImage.image = game_.assets['./img/start.png']; // スタート画像を設定 startImage.x = 42; // 横位置調整 startImage.y = 136; // 縦位置調整 scene.addChild(startImage); // シーンに追加 // タイトルラベル設定 var title = new Label('くまたたき'); // ラベルを作る title.textAlign = 'center'; // 文字を中央寄せ title.color = '#ffffff'; // 文字を白色に title.x = 0; // 横位置調整 title.y = 96; // 縦位置調整 title.font = '28px sans-serif'; // 28pxのゴシック体にする scene.addChild(title); // シーンに追加 // サブタイトルラベル設定 var subTitle = new Label('- くまをたくさん叩こう -'); // ラベルを作る subTitle.textAlign = 'center'; // 文字中央寄せ title.x = 0; // 横位置調整 subTitle.y = 196; // 縦位置調整 subTitle.font = '14px sans-serif'; // 14pxのゴシック体にする scene.addChild(subTitle); // シーンに追加 // スタート画像にタッチイベントを設定 startImage.addEventListener(Event.TOUCH_START, function(e) { game_.replaceScene(createGameScene()); // 現在表示しているシーンをゲームシーンに置き換える }); // タイトルシーンを返します。 return scene; }; /** * ゲームシーン * * ゲームシーンを作り、返す関数です。 */ var createGameScene = function() { var scene = new Scene(); // 新しいシーンを作る scene.backgroundColor = '#fcc8f0'; var time = 240; // 残り時間を初期化 var score = 0; // 得点を初期化 // 得点欄を作成 var label = new Label('スコア: ' +score+ '体叩いた!'); // スコア: ○体叩いた!と表示するラベルを作る label.font = '14px sans-serif'; // 14pxのゴシック体にする scene.addChild(label); // シーンに追加 // 残り時間欄を作成 var timeLimit = new Label('残り時間:' + time); // 残り時間: ○○と表示するラベルを作る timeLimit.font = '14px sans-serif'; // 14pxのゴシック体にする timeLimit.x = 0; // 横位置調整 timeLimit.y = 20; // 縦位置調整 scene.addChild(timeLimit); // シーンに追加 // 背景テキストを作成 var backgroundText = new Label('くまを叩け!'); backgroundText.color = '#ffffff'; // 文字を白色に backgroundText.font = '60px sans-serif'; // 60pxのゴシック体にする backgroundText.textAlign = 'center'; // 中央揃えにする backgroundText.x = 0; // 横位置調整 backgroundText.y = 130; // 縦位置調整 scene.addChild(backgroundText); // シーンに追加 // くまを作成 var kuma = new Sprite(32, 32); // スプライトを作る kuma.image = game_.assets['./img/chara1.png']; // くま画像を設定 kuma.x = Math.random() * 288; // くまの横位置を0〜288pxの間でランダムに設定 kuma.y = Math.random() * 288; // くまの縦位置を0〜288pxの間でランダムに設定 scene.addChild(kuma); // シーンに追加 var kumaSpeed = Math.random() * 8 - 4; // くまのスピードを-4〜+4の間でランダムに設定 // くまの移動方向が左ならスプライトを反転させる if (kumaSpeed > 0) { kuma.scaleX = 1; // 横方向の大きさを1に(通常) } else { kuma.scaleX = -1; // 横方向の大きさをマイナス1に(反転) } // シーンに毎フレームイベントを設定 scene.addEventListener(Event.ENTER_FRAME, function() { time --; // 残り時間を1ずつ減らす timeLimit.text = '残り時間:' + time; // 残り時間の表示を更新 // 時間切れ if (time <= 0) { game_.replaceScene(createGameoverScene(score)); // 現在表示しているシーンをゲームオーバーシーンに置き換える } kuma.x += kumaSpeed; // くまを横方向に移動 // くまが画面端に来た時の対処 if (kuma.x > 320) { // もしも右端に到達したら kuma.x = -32; // 左端にワープさせる } else if (kuma.x < -32) { // もしも左端に到達したら kuma.x = 320; // 右端にワープさせる } // くまのスプライトシートのフレームを動かし、走っているような効果を与える kuma.frame ++; // くまのフレームを動かす if (kuma.frame > 2) { // くまのフレームが3以上になったら kuma.frame = 0; // 0に戻す } }); // くまにタッチイベントを設定する kuma.addEventListener(Event.TOUCH_START, function(e) { score ++; // くまを叩いたらスコアに1を加える label.text = 'スコア: ' + score + '体叩いた!'; // スコアの文言を更新 kuma.x = Math.random() * 288; // くまの横位置を0〜288pxの間にランダムで再設定(ワープ) kuma.y = Math.random() * 288; // くまの縦位置を0〜288pxの間にランダムで再設定(ワープ) kumaSpeed = Math.random() * 8 - 4; // くまのスピードを-4〜+4の間でランダムに再設定 // くまの移動方向が左ならスプライトを反転させる if (kumaSpeed > 0) { kuma.scaleX = 1; // 横方向の大きさを1に(通常) } else { kuma.scaleX = -1; // 横方向の大きさをマイナス1に(反転) } }); // ゲームシーンを返す return scene; }; /** * ゲームオーバーシーン * * ゲームオーバーシーンを作り、返す関数です。 * createGameoverScore(※引数) ※引数にスコアを入れると画面にスコアが表示されます * ※は任意の名前でOKで、カンマ区切りで複数設定できます。 * 例) var createGameoverScore = function (resultScore, test1, test2) { */ var createGameoverScene = function(resultScore) { var scene = new Scene(); // 新しいシーンを作る scene.backgroundColor = '#303030'; // シーンの背景色を設定 // ゲームオーバー画像設定 var gameoverImage = new Sprite(189, 97); // スプライトを作る gameoverImage.image = game_.assets['./img/gameover.png']; // ゲームオーバー画像を設定 gameoverImage.x = 65; // 横位置調整 gameoverImage.y = 112; // 縦位置調整 scene.addChild(gameoverImage); // シーンに追加 // スコアラベル設定 var label = new Label(resultScore + '体叩いた'); // ラベルを作る スコアを代入 label.textAlign = 'center'; // 文字を中央寄せ label.color = '#fff'; // 文字を白色に label.x = 0; // 横位置調整 label.y = 60; // 縦位置調整 label.font = '40px sans-serif'; // 40pxのゴシック体にする scene.addChild(label); // シーンに追加 // リトライラベル(ボタン)設定 var retryLabel = new Label('もう一度遊ぶ'); // ラベルを作る retryLabel.color = '#fff'; // 文字を白色に retryLabel.x = 0; // 横位置調整 retryLabel.y = 300; // 縦位置調整 retryLabel.font = '20px sans-serif'; // 20pxのゴシック体にする scene.addChild(retryLabel); // シーンに追加 // リトライラベルにタッチイベントを設定 retryLabel.addEventListener(Event.TOUCH_START, function(e) { game_.replaceScene(createStartScene()); // 現在表示しているシーンをタイトルシーンに置き換える }); return scene; }; game_.replaceScene(createStartScene()); // ゲームの_rootSceneをスタートシーンに置き換える } game_.start(); // ゲームをスタートさせます };
なお、素材として、enchant.jsに同梱されている2つの画像も追加しておきます。enchant.jsのフォルダから「start.png」と「gameover.png」というファイルを探し出し、「img」ディレクトリ内に追加してください(赤字の部分です)。
ディレクトリ構造
フォルダ(任意の場所)
└index.html……ゲームを表示するためのhtmlファイル(前回を参照)
└「js」フォルダ
└main.js……ゲームプログラム本体
└「lib」フォルダ
└enchant.js……ダウンロードしたenchant.js本体
└「img」フォルダ
└chara1.png……enchant.jsと一緒に同梱されている、くまがたくさん並んだ画像
└start.png……同じく同梱されている、大きなSTARTの文字の画像
└gameover.png……同じく同梱されている、大きなGAMEOVERの文字の画像
プログラムが長いと難しそうに感じるかもしれませんが、3つあるシーンのうち、色で分けられた1つ1つのシーンに注目してみれば、それほど難しいことはしていないことが分かると思います。
各シーンで主に行われていることをまとめると、以下のようになります。
- 表示する要素(画像やラベルなど)を用意
- 表示する要素(画像やラベルなど)をシーンに追加
- イベントをシーンもしくはシーンの中の要素にイベントを追加(※ゲームシーンのみ、くま画像の移動やスコアのカウントなどのゲーム性に関わる処理を追加)
- 何かのイベント内で次のシーンへ移るように設定
次回からは、もっとリッチな表現について
いかがだったでしょうか。うまく動かないときは前回お教えした、Webブラウザのデベロッパツールからのコンソールでエラーの起きてる個所を探してみてください。
もしうまくいったなら、画像を差し替えたり、ポーズ画面を入れたり、1度に表示するくまの数を増やしたりと、自分だけのオリジナルなゲームにしていくのも楽しいと思います。
またもや駆け足になってしまいましたが、今回でゲームを作る分には必要十分な知識を得られたと思いますので、次回からは、もっとリッチな表現について解説していきたいと思います。
著者プロフィール
大関隆介
2006年に株式会社アローズ・システムズに入社し飲食店検索サイトの要件定義〜運用までを行いPHPやperlなどを利用したサーバサイドの開発からJavaScript(Ajax、jQuery)を使ったクライアントサイドの開発も行う。モバイルに特化した業務がしたいと考えるようになり、2010年10月に株式会社ゆめみに入社し、現在はシステムエンジニアとしてスマートフォンサイトやスマホアプリの提案・設計・開発に従事。最近では、大規模なアプリの開発・運用チームの中心メンバーとして活躍。
佐藤浩昭
2011年に株式会社ゆめみに入社。学生時代はPC向けのFlashコンテンツを制作していた。入社後はフィーチャーフォン向けのPHP+Flash Lite 1.1のWebアプリの制作やenchant.jsを用いたサントリーのゲーム開発に従事し、現在は大手メーカーのAndroidアプリのメイン開発に携わる。Webコンテンツからネイティブアプリまで幅広い知識を持つ
Copyright © ITmedia, Inc. All Rights Reserved.