はじめに
Phaserは、 PIXI.jsライブラリに基づいたモバイルおよびデスクトップHTML5ゲームを開発するためのエンジンです。 CanvasおよびWebGLでのレンダリング、アニメーションスプライト、パーティクル、オーディオ、さまざまな入力方法、オブジェクト物理学をサポートしています。 ソースは、表示と無料の変更の両方で利用できます。 Flixelフレームワークを使用してプログラマーのコミュニティに積極的に参加したことで知られるRichard Daveyによって作成されました。 リチャードは彼がフリクセルに触発されたことを隠していないので、フェイザーのいくつかのことは経験豊富なフラッシャーに馴染みがあるでしょう。 新しいエンジンの最初のバージョンは、今年の9月13日にリリースされました。現在、ライブラリが積極的に開発されているだけでなく、ドキュメントも作成されています。 私の謙虚な意見では、これは修正すべきです。
ライブラリとローカルWebサーバーをインストールする
それでは始めましょう。 アプリケーションを実行およびテストするには、ローカルWebサーバーをインストールする必要があります。 ライブラリキットのサンプルはすべてPHPを使用しているため、サーバーにも適切なものが必要です。 MacOSにはMAMPを使用しましたが、Windowsには国内のDenwerまたはその他のアナログが適しています。
Webサーバーのインストール後、GitHubから最新バージョンのPhaserをダウンロードする必要があります: https : //github.com/photonstorm/phaser 現時点(2013年10月13日)では、devブランチをダウンロードすることをお勧めします。このバージョンには、主なものと比較して、より多くのドキュメントなど、非常に便利な変更が多数含まれているためです。 GitHubを使用していない場合は、アーカイブへの直接リンクhttps://github.com/photonstorm/phaser/archive/dev.zipを利用できます 。
すべてが正しくセットアップされていることを確認するには、小さなHello Phaserサンプルアプリケーションを実行します。 WebサイトのWebサーバーのディレクトリにhellophaserフォルダーを作成し、 Docs / Hello Phaserフォルダーから3つのファイルをコピーします。

お気に入りのブラウザを起動し、コピーしたファイルでURLを開きます(私の場合は、 http:// localhost:8888 / hellophaser / )。 すべてうまくいけば、下のスクリーンショットのように、かわいい回転ロゴが表示されます。

ゲーム開発
必要なファイルを準備する
これで、最初のゲームの開発を開始できます。 Webサーバー上にそのための phaser -pongフォルダーを作成し、そこにフレームワークソースを含むbuildフォルダーからphaser.jsファイルをコピーします。 また、その中に、ゲームに関連するすべてのリソースとindex.htmlファイルを保存するアセットフォルダーを作成します(実際、ここにゲームがあります)。
ボール、ラケット、および背景の画像をアセットフォルダーにコピーします。 次のファイルを取ることができます(背景として、私はPhaserの例から星空を取りました)、またはあなた自身の何かを描くことができます。 主なことは、正しい名前と適切なサイズの必要な画像をゲームに確実にロードすることです。 また、レンダリングの問題が発生する可能性があるため、大きすぎる画像を選択しないでください。 したがって、猫の写真を使用する前に、たとえば480x640(ゲームの解像度)に縮小すると、すべてがうまくいきます。



その結果、 phaser-pongフォルダーの内容は次のようになります。

そして、 assetsフォルダーには3つの画像があります。

ゲームのメインオブジェクトの作成、リソースの読み込み
最後に、すべての準備手順が完了し、実際の開発が開始されます。 index.htmlを開き、次のコードをそこに貼り付けます。
<script src="phaser.js"></script> <script type="text/javascript"> var game = new Phaser.Game(480, 640, Phaser.AUTO, '', { preload: preload, create: create, update: update }); function preload() { game.load.image('bet', 'assets/bet.png'); game.load.image('ball', 'assets/ball.png'); game.load.image('background', 'assets/starfield.jpg'); } function create() { game.add.tileSprite(0, 0, 480, 640, 'background'); } function update () { } </script>
ブラウザで新しいゲームのアドレスを開き( http:// localhost:8888 / phaser-pong / )、背景がペイントされたウィンドウが表示されます

書かれたコードはどうなりますか? 最初にライブラリをインポートします。 次に、
Game
タイプのオブジェクトを作成し、アプリケーションの解像度、この場合は幅480、高さ640ピクセルを設定します。
Phaser.AUTO
は、レンダリングのタイプが自動的に選択されることを意味します。 オプションでCanvasまたはWebGLを設定できます。 4番目のパラメーターは、ゲームの親DOMオブジェクトを設定しますが、指定しません。
5番目のパラメーターは、ゲームの主な機能をリストします。
preload()
はリソースをロードするためのコードが含まれ、
create()
-ゲームの初期化、および
update()
-アプリケーションの更新時に実行されるコマンド。 デスクトップコンピューターでは、1秒あたり約60回
update()
が呼び出されます。 この関数には、メインのゲームロジックが含まれます。
create()
関数では、ゲームの背景に静的なスプライトを追加します。 スプライトは、最初の4つの
tileSprite
パラメーターで指定されたスペースを埋めます。
ゲームオブジェクト
次に、最も興味深いものに移ります-ゲームをロジックで満たします。
game
変数を宣言した後、
preload()
関数の前に、プレーヤーとコンピューターのラケット、ボール
preload()
してオブジェクト
preload()
宣言し、その速度も示します。
var playerBet; var computerBet; var ball; var computerBetSpeed = 190; var ballSpeed = 300;
ラケットを作成するには、
createBet(x, y)
関数を作成します。
function createBet(x, y) { var bet = game.add.sprite(x, y, 'bet'); bet.anchor.setTo(0.5, 0.5); bet.body.collideWorldBounds = true; bet.body.bounce.setTo(1, 1); bet.body.immovable = true; return bet; }
このメソッドは、指定された座標でスプライトを作成し、ゲームに追加します。
anchor
フィールドは、スプライトの原点を担当し、ラケットイメージの中心に設定します。
body
は物理学を扱うための要素が含まれています。 ここでは、ラケットの動きを競技スペースの外側に制限し、「バウンス」の強さを設定し、オブジェクトと衝突したときにラケットが横に飛ばないことを示します。
背景を作成した直後に、 create()でこの関数に2つの呼び出しを追加します 。 ラケットは背景画像の後にゲームに追加されるので、画面に表示されます。
playerBet = createBet(game.world.centerX, 600); computerBet = createBet(game.world.centerX, 20);
同様に、create
createBet()
関数を呼び出した直後に次のコードを追加して、ボールを
create()
し
create()
。
ball = game.add.sprite(game.world.centerX, game.world.centerY, 'ball'); ball.anchor.setTo(0.5, 0.5); ball.body.collideWorldBounds = true; ball.body.bounce.setTo(1, 1);
その結果、ゲームでは、静止している間に2つのラケットとボールが表示されます。

ロジック
写真はきれいになりましたが、少し復活させる価値があると思います。
ボールの状態を制御する変数と、ボールを実行する関数を追加します。
var ballReleased = false; function releaseBall() { if (!ballReleased) { ball.body.velocity.x = ballSpeed; ball.body.velocity.y = -ballSpeed; ballReleased = true; } }
この関数は、ボールがまだ動いていないことを確認し、この場合、 速度フィールドを使用して速度を設定します。
create()に次の行を記述することにより、マウスボタンをクリックして関数呼び出しをハングさせます。
game.input.onDown.add(releaseBall, this);
マウスでクリックするとボールが開始され、ゲームの境界から跳ね返ります。
update()
関数を編集して、動きとラケットを追加します。
function update () { // playerBet.x = game.input.x; var playerBetHalfWidth = playerBet.width / 2; if (playerBet.x < playerBetHalfWidth) { playerBet.x = playerBetHalfWidth; } else if (playerBet.x > game.width - playerBetHalfWidth) { playerBet.x = game.width - playerBetHalfWidth; } // if(computerBet.x - ball.x < -15) { computerBet.body.velocity.x = computerBetSpeed; } else if(computerBet.x - ball.x > 15) { computerBet.body.velocity.x = -computerBetSpeed; } else { computerBet.body.velocity.x = 0; } }
プレーヤーのラケットはマウスポインターに従い、コンピューターラケットはボールに従います。 プレーヤーのラケットには、競技場から飛び出そうとしないように、
x
座標の最大値と最小値にも制限を追加しました。
ゲームの本質は、ラケットでボールを打つことなので、ラケットとボールの衝突をチェックする必要があります。 幸いなことに、Phaserには既に対応する機能があるため、使用するだけです。
update()
最後に次の3行を追加します。
// game.physics.collide(ball, playerBet, ballHitsBet, null, this); game.physics.collide(ball, computerBet, ballHitsBet, null, this);
collide
メソッドは、2つのオブジェクト(最初の2つのパラメーター)の衝突をチェックし、3番目に指定された関数を呼び出して、衝突するスプライトでアクションを実行します。 この関数は次のようになります。
function ballHitsBet (_ball, _bet) { var diff = 0; if (_ball.x < _bet.x) { // diff = _bet.x - _ball.x; _ball.body.velocity.x = (-10 * diff); } else if (_ball.x > _bet.x) { // diff = _ball.x -_bet.x; _ball.body.velocity.x = (10 * diff); } else { // , _ball.body.velocity.x = 2 + Math.random() * 8; } }
衝突では、ラケットのどの部分が打たれるかによって、ボールの動きの方向が変わります。
逃した目標のチェックを追加するだけです。 誰かがそれを逃した場合、フィールドの中央の元の位置にボールを置きます。
function checkGoal() { if (ball.y < 15) { setBall(); } else if (ball.y > 625) { setBall(); } } function setBall() { if (ballReleased) { ball.x = game.world.centerX; ball.y = game.world.centerY; ball.body.velocity.x = 0; ball.body.velocity.y = 0; ballReleased = false; } }
checkGoal()
は常に呼び出されるので、それを
update()
最後にコピーします。
//, - checkGoal();
それだけです! ブラウザを開き、ゲームの素晴らしい最新のゲームプレイを楽しみ、人生と新たに習得したプログラミングスキルを楽しみます。
おわりに
当然のことながら、ゲームには少なくとも勝者を採点して決定するものがはるかに不足しています。 しかし、ここに示したものはPhaserでの開発の紹介に十分であるように思えます。 このエンジンは、他の多くのクールな機能をサポートしています。これは、Habrに少し関連する、より複雑で直接興味深い新しいゲームの例として紹介します。
調整してください。
開発中に、 breakout.phpの例のコードを積極的に使用しました。 この例に加えて、Fazerフォルダーには他のゲームもあるため、新しいフレームワークを使用したい人は、まずexamplesフォルダーの内容を確認することをお勧めします。
便利なリンク:
1. Phaserの英語による紹介
2. エンジンフォーラム
3. リチャード・デイビーによるTwitter
更新:友人のアドバイスに基づいて、 hell0w0rdがgithubに例を投げて、ゲームを試すことができるようにページを作成しました。
https://github.com/nononononono/phaser-pong
http://nononononono.github.io/phaser-pong/
10/20/2013からの更新: fessnecroは、ボールとラケットおよび新しいレベルの衝突でパーティクルを追加しました。 これらの変更はメインブランドにあります。 この記事で説明されている元のバージョンは、 gh-pagesブランチにあります。
また、念のため、完全なソースコードはindex.htmlです。
<script src="phaser.js"></script> <script type="text/javascript"> var game = new Phaser.Game(480, 640, Phaser.AUTO, '', { preload: preload, create: create, update: update }); var playerBet; var computerBet; var ball; var computerBetSpeed = 190; var ballSpeed = 300; var ballReleased = false; function preload() { game.load.image('bet', 'assets/bet.png'); game.load.image('ball', 'assets/ball.png'); game.load.image('background', 'assets/starfield.jpg'); } function create() { game.add.tileSprite(0, 0, 480, 640, 'background'); playerBet = createBet(game.world.centerX, 600); computerBet = createBet(game.world.centerX, 20); ball = game.add.sprite(game.world.centerX, game.world.centerY, 'ball'); ball.anchor.setTo(0.5, 0.5); ball.body.collideWorldBounds = true; ball.body.bounce.setTo(1, 1); game.input.onDown.add(releaseBall, this); } function createBet(x, y) { var bet = game.add.sprite(x, y, 'bet'); bet.anchor.setTo(0.5, 0.5); bet.body.collideWorldBounds = true; bet.body.bounce.setTo(1, 1); bet.body.immovable = true; return bet; } function update () { // playerBet.x = game.input.x; var playerBetHalfWidth = playerBet.width / 2; if (playerBet.x < playerBetHalfWidth) { playerBet.x = playerBetHalfWidth; } else if (playerBet.x > game.width - playerBetHalfWidth) { playerBet.x = game.width - playerBetHalfWidth; } // if(computerBet.x - ball.x < -15) { computerBet.body.velocity.x = computerBetSpeed; } else if(computerBet.x - ball.x > 15) { computerBet.body.velocity.x = -computerBetSpeed; } else { computerBet.body.velocity.x = 0; } // game.physics.collide(ball, playerBet, ballHitsBet, null, this); game.physics.collide(ball, computerBet, ballHitsBet, null, this); //, - checkGoal(); } function ballHitsBet (_ball, _bet) { var diff = 0; if (_ball.x < _bet.x) { // diff = _bet.x - _ball.x; _ball.body.velocity.x = (-10 * diff); } else if (_ball.x > _bet.x) { // diff = _ball.x -_bet.x; _ball.body.velocity.x = (10 * diff); } else { // , _ball.body.velocity.x = 2 + Math.random() * 8; } } function checkGoal() { if (ball.y < 15) { setBall(); } else if (ball.y > 625) { setBall(); } } function setBall() { if (ballReleased) { ball.x = game.world.centerX; ball.y = game.world.centerY; ball.body.velocity.x = 0; ball.body.velocity.y = 0; ballReleased = false; } } function releaseBall() { if (!ballReleased) { ball.body.velocity.x = ballSpeed; ball.body.velocity.y = -ballSpeed; ballReleased = true; } } </script>