enchant.jsで重要なスプライトとシーンを使うにはenchant.jsでHTML5+JavaScriptゲーム開発入門(3)(4/4 ページ)

» 2013年04月01日 18時00分 公開
[佐藤浩昭, 大関隆介,ゆめみ]
前のページへ 1|2|3|4       

シーンの遷移―― 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(); // ゲームをスタートさせます
};
ゲームプログラム main.js

 なお、素材として、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つのシーンに注目してみれば、それほど難しいことはしていないことが分かると思います。

 各シーンで主に行われていることをまとめると、以下のようになります。

  1. 表示する要素(画像やラベルなど)を用意
  2. 表示する要素(画像やラベルなど)をシーンに追加
  3. イベントをシーンもしくはシーンの中の要素にイベントを追加(※ゲームシーンのみ、くま画像の移動やスコアのカウントなどのゲーム性に関わる処理を追加)
  4. 何かのイベント内で次のシーンへ移るように設定

次回からは、もっとリッチな表現について

 いかがだったでしょうか。うまく動かないときは前回お教えした、Webブラウザのデベロッパツールからのコンソールでエラーの起きてる個所を探してみてください。

 もしうまくいったなら、画像を差し替えたり、ポーズ画面を入れたり、1度に表示するくまの数を増やしたりと、自分だけのオリジナルなゲームにしていくのも楽しいと思います。

 またもや駆け足になってしまいましたが、今回でゲームを作る分には必要十分な知識を得られたと思いますので、次回からは、もっとリッチな表現について解説していきたいと思います。

著者プロフィール


大関隆介

2006年に株式会社アローズ・システムズに入社し飲食店検索サイトの要件定義〜運用までを行いPHPやperlなどを利用したサーバサイドの開発からJavaScript(Ajax、jQuery)を使ったクライアントサイドの開発も行う。モバイルに特化した業務がしたいと考えるようになり、2010年10月に株式会社ゆめみに入社し、現在はシステムエンジニアとしてスマートフォンサイトやスマホアプリの提案・設計・開発に従事。最近では、大規模なアプリの開発・運用チームの中心メンバーとして活躍。


佐藤浩昭

2011年に株式会社ゆめみに入社。学生時代はPC向けのFlashコンテンツを制作していた。入社後はフィーチャーフォン向けのPHP+Flash Lite 1.1のWebアプリの制作やenchant.jsを用いたサントリーのゲーム開発に従事し、現在は大手メーカーのAndroidアプリのメイン開発に携わる。Webコンテンツからネイティブアプリまで幅広い知識を持つ


前のページへ 1|2|3|4       

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。