Programing > Phaser > チュートリアル2
前回のチュートリアルは、Phaserによる基本的なゲームの作り方を翻訳したものだった。
今回、これを独自に改良して、もう少しゲームぽくしてみる。
あのチュートリアルでは不足していた情報が、いくつか補完できていると思う。
まあ、ソースコードを見てもらえば分かる部分もあると思うけど、いちおう簡単に解説してみます。
ここでは、順番にソースコードを組み立てていくのではなく、完成版の全体像を見てもらって、特徴的なところをピンポイントで取り上げています。
レスポンシブにする方法など、詳細は末尾を参照。
Copyright 2014 Yutaka Kachi released under MIT license.
間違いなどあるかも知れません。
もしも見つけたら、Twitter @y_catchへ連絡いただけると助かります。
前回のチュートリアルは、単一のindex.htmファイルに100行くらいのJavascriptコードを埋め込んでいた。これは、単純だしサクサク作れるんだけど、一方で、もう少し機能の多いゲームを作りたい場合とか見通しが悪いし、グローバル変数を使いすぎている。
そこで、Phaserに同梱されている、Project Templateの「Basic 」を使う。
これは、Phaserのresources/Project Templates にあるPhaserゲームの骨組みで、複数のファイルで構成されている。
詳しい使い方は、コメントとして記載されている。
まだ骨組みだけなので。ファイルを開いてもなにも表示されない。
完成版のゲームのファイル構成は、こんな感じ。
JavaScriptは、複数のファイルに分かれていて、jsフォルダに置いてある。
最終的には、単一のjsファイルに統合しちゃえばいいんだけれど、開発中の見通しをよくするため分割しておく。
BasicGame │ │ index.html │ ├─ audio(効果音) │ idou_ochiru_normal.mp3 │ jump08.mp3 │ ├─ images(グラフィック) │ button.png │ dude.png │ platform320.png │ preloadr_bar.png │ sky-dark.png │ star.png │ timesup.png │ title.png │ └─ js(コード) Boot.js Game.js MainMenu.js phaser.min.js Preloader.js
このindex.htmlを開くと、ゲームが起動する。
まず、<head>部で必要なJavascriptを読み込む。
<head> <meta charset="UTF-8" /> <title>Jumping Dude</title> <script src="js/phaser.min.js"></script> <script src="js/Boot.js"></script> <script src="js/Preloader.js"></script> <script src="js/MainMenu.js"></script> <script src="js/Game.js"></script> </head>
で、ゲーム自体を表示するコンテナを用意する。
<div id="gameContainer"></div>
<script>部のJavascriptでは、window.onloadで呼び出して、ゲームのステータスを登録する。それからBootステータスを起動する。
<script type="text/javascript"> window.onload = function() { // Create your Phaser game and inject it into the gameContainer div. // We did it in a window.onload event, but you can do it anywhere (requireJS load, anonymous function, jQuery dom ready, - whatever floats your boat) var game = new Phaser.Game(640, 480, Phaser.AUTO, 'gameContainer'); // Add the States your game has. // You don't have to do this in the html, it could be done in your Boot state too, but for simplicity I'll keep it here. game.state.add('Boot', BasicGame.Boot); game.state.add('Preloader', BasicGame.Preloader); game.state.add('MainMenu', BasicGame.MainMenu); game.state.add('Game', BasicGame.Game); // Now start the Boot state. game.state.start('Boot'); }; </script>
枠組みとしては、BasicGame.Bootを定義して、prototypeで機能を追加していく。
ここでは、init、preload、createに関数を割り当てている。
ゲームプログラムが起動したら、まずinitで必要最小限の設定をして、preloadでリソース(読み込み中を示すバー)を読み込む。
読み込んだら、createでPreloadステータスに移動する。
preload関数で、グラフィックとサウンドファイルを読み込んで、createでMainMenuステータスに遷移する。
読み込み中(プログレスバー)は、こんな感じで表示する。
// These are the assets we loaded in Boot.js // A nice sparkly background and a loading progress bar // 背景色 this.stage.backgroundColor = 'navy'; //作業中バーの位置 this.preloadBar = this.add.sprite((BasicGame.GAME_WIDTH-311)/2, (BasicGame.GAME_HEIGHT-27)/2, 'preloaderBar'); // This sets the preloadBar sprite as a loader sprite. // What that does is automatically crop the sprite from 0 to full-width // as the files below are loaded in. // 作業開始 this.load.setPreloadSprite(this.preloadBar);
で作業が完了して、次のステータスに遷移するときは、createのところで作業中バーを停止する
this.preloadBar.cropEnabled = false;
読み込み中は、作業中のバーを表示する。 画像やスプライトと同じように、こんなふうにして読みこむ。
this.load.audio('getSound', ['audio/jump08.mp3']); this.load.audio('jumpSound', ['audio/idou_ochiru_normal.mp3']);
スタート画面とスタートボタンを表示するだけ。
スタートボタンは、こんな感じ。ボタンは、スプライトになっている。これを画面中央に配置。
ボタンがクリックされると、startGame関数が呼び出される。
this.add.button(BasicGame.GAME_WIDTH/2-43, BasicGame.GAME_HEIGHT-100,'start-button', this.startGame, this, 1, 0, 2);
startGame関数は、次のGameステータスに遷移する。
ゲーム自体は、前のチュートリアルと同じく、走ってジャンプして星を集める。
いちおう、効果音を付けてみた。ジャンプしたときと星を取ったときに効果音がなる。
まず、createのところで、このステータスで使う効果音を登録する
this.getSound = this.add.audio('getSound'); this.jumpSound = this.add.audio('jumpSound');
それから、実際のアクションに合わせて、効果音を再生する
this.jumpSound.play(); //ジャンプ
this.getSound.play(); //星ゲット
時間制限制のゲームにしてみた。
そのために、まずcreateのところで、タイマーとタイマー表示を初期化する
this._timeCounter = 0; //タイマー this._leftTime = 30; //残り時間 this._leftTimeText = this.add.text(300, 16, 'Time: 0', { fontSize: '28px', fill: '#FFF' }); //時間表示
で、updateのところで、タイマーを更新する
// update timer every frame this._timeCounter += this.time.elapsed; // if spawn timer reach one second (1000 miliseconds) if(this._timeCounter > 1000) { // reset it this._timeCounter = 0; this._leftTime --; this._leftTimeText.text = 'Time: ' + this._leftTime; }
残り時間が、ゼロになったら、ゲームオーバーでquitGameを呼び出す。
if(this._leftTime <= 0) { this.quitGame(); }
quitGameは、こんな感じ。まず、効果音を止めて、Time'sUp(時間切れ)を表示する
quitGame: function (pointer) { // Here you should destroy anything you no longer need. // Stop music, delete sprites, purge caches, free resources, all that good stuff. // Then let's go back to the main menu. this.getSound.stop(); this._timesup_title = this.add.sprite((this.world.width - 400) / 2, (this.world.height - 100) / 2, 'timesup');
それから、ゲーム全体を一時停止して、クリックしたらメインメニューへ戻るようにする。
this.game.paused = true; var pausedText = this.add.text(160, 360, "Tap anywhere to Menu.", { fontSize: '28px', fill: '#FFF' }); this.input.onDown.add(function(){ pausedText.destroy(); this.game.paused = false; this.state.start('MainMenu'); }, this); },
basicテンプレートではなく、こっちのテンプレートを使うと、わりと簡単にレスポンシブにできた。
PCやタブレットなどデバイスの画面サイズに合わせて、ゲーム画面のサイズを調整してくれる。
スマホで縦持ちのときは、横持ちにするようガイダンスも自動的に出る。
ただし、ゲームはまだタッチだけでは操作できないんだけどな。
これもまた別のゲーム+チュートリアル。