JavaScript >> Javascript 文檔 >  >> JavaScript

Phaser 3 簡介:建築突破

簡介

遊戲開發是軟件開發的一個獨特分支,它既複雜又有益。在考慮創建遊戲時,我們通常會想到要在我們的計算機或控制台上安裝和玩的應用程序。 HTML5 規範引入了許多 API 來支持 Web 上的遊戲開發,使我們的遊戲能夠接觸到不同計算設備上的許多用戶。 Phaser 是一個流行的遊戲框架,它使我們能夠快速構建網絡遊戲。

掌握遊戲開發的最好方法是製作遊戲。我們將使用 Phaser 創建一個 Breakout 克隆,這是 1976 年經典且永恆的 Atari 遊戲版本的一個版本。

本教程包含一些非常基本的 HTML 和 CSS。您需要熟悉 JavaScript 函數和對象。它充分利用了 ES2015 的特性。

遊戲循環

所有遊戲都在一個循環中運行。設置好我們的遊戲世界後,我們進入執行以下任務的遊戲循環:

  1. 流程輸入
  2. 更新遊戲世界
  3. 呈現更改

讓我們看看遊戲循環在 Megaman 這樣的遊戲中是如何工作的。在篩選菜單開始關卡後,遊戲會決定在哪裡放置平台並加載要播放的音樂。該設置通常發生在加載屏幕期間。

遊戲開始時,您將在一個擁有平台、敵人和特定歌曲的世界中控制 Megaman。您可以使用操縱桿移動洛克人,並按下按鈕進行跳躍或射擊。遊戲循環正在處理輸入,更新 Megaman 的位置並在一秒鐘內多次渲染這些變化。

什麼是移相器?

Phaser 是一個 HTML5 遊戲框架。它使用許多 HTML5 API,如 Canvas、WebGL、Audio、Gamepad 等,並添加了一些有用的邏輯,如管理遊戲循環和為我們提供物理引擎。使用 Phaser,我們可以只使用 HTML、CSS 和 JavaScript 構建 2D 遊戲。

分線規則

在我們使用 Phaser 構建我們的 Breakout 克隆之前,讓我們首先定義遊戲的範圍:

  • 這款單人遊戲只有一個關卡,包含 30 個積木、一個槳和一個球
  • 目標是讓球摧毀每一塊磚,同時確保它不會離開遊戲屏幕的底部。
  • 玩家將控制一個可以左右移動的槳
  • 遊戲專為桌面網絡用戶打造,鍵盤將用於輸入

設置移相器

Phaser 是一個 JavaScript 庫,要開發和玩我們的遊戲,我們需要一些基本的 HTML 來加載 JS。創建一個名為 breakout 的目錄 在您的一個工作區中。在您的目錄中創建以下文件和文件夾:

  • 一個index.html 文件
  • 一個breakout.js 文件
  • 名為 assets 的文件夾
  • 在您的 assets 內 文件夾,創建一個 images 文件夾

遊戲資產是遊戲使用的美術、聲音、視頻和其他數據。對於這個簡單的 Breakout 克隆,沒有多少資產需要使用文件夾進行組織。但是,最好將資產與代碼分開,並按資產類型分開。

將以下代碼添加到您的 index.html 文件:

<!doctype html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
  <title>Breakout</title>
  <style>
    html,
    body {
      margin: 0 auto;
      padding: 0;
      width: 100%;
      height: 100%;
    }

    #game {
      margin: 10px auto;
      padding: 0;
      width: 800px;
      height: 640px;
    }
  </style>
</head>

<body>
  <noscript>You need to enable JavaScript to run this app.</noscript>
  <div id="game"></div>
  <script src="//cdn.jsdelivr.net/npm/[email protected]/dist/phaser.min.js"></script>
  <script src="breakout.js"></script>
</body>

</html>

此基本 HTML 代碼執行以下操作:

  • 從 html 和 body 標記中刪除瀏覽器邊距和填充。
  • 添加一個 game 將包含我們的 Breakout 克隆的 div 元素
  • 通過其 CDN 加載 Phaser v3.17
  • 加載我們的 breakout.js 該文件目前什麼都不做,但將包含我們的遊戲邏輯

為了使用 Phaser 有效地開發遊戲,我們需要這些文件由 Web 服務器提供服務。如果沒有網絡服務器,出於安全原因,我們的瀏覽器將不允許我們的遊戲腳本加載我們的資產。

幸運的是,無需設置 Apache 或 Nginx 即可獲得運行的 Web 服務器。如果您像我一樣使用 VisualStudio 代碼,那麼您可以安裝 Live Server 擴展。大多數 IDE 和文本編輯器都有一個具有類似功能的插件。如果您安裝了 Python 版本 3,您可以通過終端進入您的工作區並輸入 python3 -m http.server .還有其他提供簡單 Web 服務器的 CLI 工具,請選擇能夠讓您以最快的時間開發遊戲的工具。

最後,下載我們為此遊戲創建的圖像資源。將 PNG 文件複製並粘貼到 images 文件夾中。

開發提示 - 當您開發遊戲時,您可能希望 JavaScript 控制台可見,這樣您就可以看到彈出的任何錯誤。如果您使用的是 Chrome 或 Firefox,請右鍵單擊頁面並選擇“檢查元素”。應該會從瀏覽器窗口的底部或側面彈出一個框。選擇“控制台”選項卡以查看來自我們的 JavaScript 代碼的更新錯誤或日誌。

創建我們的遊戲世界

設置好 HTML 和 CSS 後,讓我們編輯 breakout.js 文件來設置我們的遊戲世界。

啟動移相器

首先,我們需要配置 Phaser 並創建我們的 Game 實例。 Game 實例是 Phaser 遊戲的中央控制器,它為我們完成所有設置並啟動遊戲循環。

添加以下內容來配置和創建我們的 Game 實例:

// This object contains all the Phaser configurations to load our game
const config = {
  type: Phaser.AUTO,
  parent: 'game',
  width: 800,
  heigth: 640,
  scale: {
    mode: Phaser.Scale.RESIZE,
    autoCenter: Phaser.Scale.CENTER_BOTH
  },
  scene: {
    preload,
    create,
    update,
  },
  physics: {
    default: 'arcade',
    arcade: {
      gravity: false
    },
  }
};

// Create the game instance
const game = new Phaser.Game(config);

type 屬性告訴 Phaser 使用什麼渲染器。 Phaser 可以使用 HTML5 的 WebGL 或 Canvas 元素渲染我們的遊戲。通過將類型設置為 Phaser.AUTO ,我們告訴 Phaser 首先嘗試使用 WebGL 進行渲染,如果失敗,則使用 Canvas 進行渲染。

parent 屬性表示我們的遊戲將在其中播放的 HTML 元素的 ID。我們使用 width 以像素為單位定義遊戲尺寸 和 height . scale object 為我們做了兩件事:

  • mode 告訴 Phaser 如何使用我們父元素的空間,在這種情況下,我們確保遊戲適合父 div 的大小
  • autoCenter 如果我們願意,告訴 Phaser 如何將我們的遊戲置於父 div 中。在這種情況下,我們在父 div 中垂直和水平地居中我們的遊戲。當遊戲不佔用父 div 的整個空間時,此屬性更有用,此處顯示為常見問題。

在 Phaser 中,我們的遊戲邏輯在 Scenes 中定義。把場景想像成我們遊戲中的各種狀態:標題畫面是一個場景,遊戲的每一關都是自己的場景,過場動畫就是自己的場景。 Phaser 提供了一個 Scene 對象,但它也可以與包含 preload 的常規 JavaScript 對像一起使用 , createupdate 函數定義。

最後一個配置告訴 Phaser 使用哪個物理引擎。 Phaser 可以使用 3 種不同的物理引擎:Arcade、Impact 和 Matter。 Arcade 是最容易上手的遊戲,足以滿足我們的遊戲需求。

Breakout 不需要重力來工作,因此我們禁用了該屬性。如果我們正在構建一個平台遊戲,我們可能會啟用重力,這樣當我們的玩家跳躍時,他們會自然地落回地面。

為了確保我們的遊戲設置正常,我們需要添加 preload , createupdate 函數,創建我們的遊戲實例後添加以下空白函數:

function preload() { }

function create() { }

function update() { }

隨著您的網絡服務器運行,導航到您的遊戲正在運行的頁面。你應該會看到一個像這樣的空白屏幕:

加載資產

該遊戲中的資產由 5 張圖像組成。在您可能創建的其他遊戲中,您的資產可能是巨大的。高清圖像、音頻和視頻文件可能會佔用數兆字節的空間。資產越大,負載所需的時間就越長。因此,Phaser 有一個 preload 我們可以在開始運行遊戲之前加載所有資產的功能。玩遊戲從來都不是一個好的用戶體驗,它突然變慢了,因為它正在嘗試加載新資產。

更改 preload 函數如下,這樣我們就可以在遊戲循環開始之前加載我們的圖像:

function preload() {
  this.load.image('ball', 'assets/images/ball_32_32.png');
  this.load.image('paddle', 'assets/images/paddle_128_32.png');
  this.load.image('brick1', 'assets/images/brick1_64_32.png');
  this.load.image('brick2', 'assets/images/brick2_64_32.png');
  this.load.image('brick3', 'assets/images/brick3_64_32.png');
}

第一個參數是我們稍後將用來引用圖像的鍵,第二個參數是圖像的位置。

加載圖像後,我們想在屏幕上放置精靈。在 breakout.js 的頂部 ,添加這些將包含我們的精靈數據的變量:

let player, ball, violetBricks, yellowBricks, redBricks;

一旦它們被全局定義,我們所有的函數都可以使用它們。

添加精靈

精靈是遊戲場景中的任何 2D 圖像。在 Phaser 中,精靈封裝了圖像及其位置、速度、物理屬性和其他屬性。讓我們從創建我們的玩家精靈開始。在 create 函數添加如下:

player = this.physics.add.sprite(
  400, // x position
  600, // y position
  'paddle', // key of image for the sprite
);

您現在應該能夠在屏幕上看到一個槳:

sprite 的第一個參數 方法是放置精靈的 X 坐標。第二個參數是Y坐標,最後一個參數是preload中添加的圖片資源的key 功能。

了解 Phaser 和大多數 2D 遊戲框架如何使用坐標非常重要。我們在學校學習的圖形通常將原點,即點 (0, 0) 放在中心。在 Phaser 中,原點位於屏幕的左上角。隨著 x 的增加,我們基本上向右移動。隨著 y 的增加,我們正在向下移動。我們的遊戲寬度為 800 像素,高度為 640 像素,所以我們的遊戲坐標如下所示:

讓我們將球添加到球員上方。將以下代碼添加到 create 功能:

ball = this.physics.add.sprite(
  400, // x position
  565, // y position
  'ball' // key of image for the sprite
);

因為球在上方 我們的玩家,Y坐標的值是lower 比玩家的 Y 坐標。

添加精靈組

雖然 Phaser 可以很容易地添加精靈,但如果每個精靈都必須單獨定義,它很快就會變得乏味。 Breakout中的磚塊幾乎相同。位置不同,但它們的屬性(如顏色以及它們與球的交互方式)是相同的。我們可以使用創建精靈組來更好地管理它們,而不是創建 30 個磚精靈對象。

讓我們添加第一排紫磚。在你的 create 函數添加如下:

// Add violet bricks
violetBricks = this.physics.add.group({
  key: 'brick1',
  repeat: 9,
  setXY: {
    x: 80,
    y: 140,
    stepX: 70
  }
});

而不是 this.physics.add.sprite 我們使用 this.physics.add.group 並傳遞一個 JavaScript 對象。 key 屬性引用了 sprite 組中的所有 sprite 將使用的圖像鍵。 repeat 屬性告訴 Phaser 還要創建多少次精靈。每個精靈組創建一個精靈。使用 repeat 設置為 9,Phaser 將在該精靈組中創建 10 個精靈。 setXY 對象具有三個有趣的屬性:

  • x 是第一個精靈的 X 坐標
  • y 是第二個精靈的 Y 坐標
  • stepX 是 x 軸上重複精靈之間的像素長度。

有一個 stepY 屬性也是如此,但我們不需要在這個遊戲中使用它。讓我們為磚塊添加另外兩個剩餘的精靈組:

// Add yellow bricks
yellowBricks = this.physics.add.group({
  key: 'brick2',
  repeat: 9,
  setXY: {
    x: 80,
    y: 90,
    stepX: 70
  }
});

// Add red bricks
redBricks = this.physics.add.group({
  key: 'brick3',
  repeat: 9,
  setXY: {
    x: 80,
    y: 40,
    stepX: 70
  }
});

我們的遊戲已經開始了,你的屏幕應該是這樣的:

輸贏

保持終點在望是一種很好的遊戲開發(和編程)實踐。在 Breakout 中,如果我們的球落到屏幕底部,我們可能會輸掉一場比賽。在 Phaser 中,如果球在屏幕下方,則球的 Y 坐標大於遊戲世界的高度。讓我們創建一個檢查這個的函數,添加 breakout.js 的底部 添加以下內容:

function isGameOver(world) {
  return ball.body.y > world.bounds.height;
}

我們的函數從場景的物理屬性中獲取世界對象,該屬性將在 update 中可用 功能。它檢查球精靈的 Y 坐標是否大於遊戲世界邊界的高度。

為了贏得比賽,我們需要擺脫所有的磚塊。 Phaser 中的精靈都有一個 active 屬性。我們可以使用該屬性來確定我們是否贏了。精靈組可以計算其中包含的活動精靈的數量。如果每個積木精靈組中都沒有活躍的積木,即有 0 個活躍的積木精靈,則玩家贏得了遊戲。在 breakout.js 的底部 添加如下函數:

function isWon() {
  return violetBricks.countActive() + yellowBricks.countActive() + redBricks.countActive() == 0;
}

我們接受每個精靈組作為參數,在其中添加活動精靈的數量並檢查它是否等於 0。

現在我們已經定義了我們的輸贏條件,我們希望 Phaser 在遊戲循環開始時檢查它們。一旦玩家獲勝或失敗,遊戲就應該停止。更改 update 作用如下:

function update() {
  // Check if the ball left the scene i.e. game over
  if (isGameOver(this.physics.world)) {
    // TODO: Show "Game over" message to the player
  } else if (isWon()) {
    // TODO: Show "You won!" message to the player
  } else {
    // TODO: Logic for regular game time
  }
}

該代碼更新沒有視覺上的變化。

注意 - 當我們使用 this 在我們的 preload , createupdate 函數,我們指的是之前創建的遊戲實例運行的場景。

使用鍵盤輸入移動播放器

玩家的移動取決於鍵盤輸入。為了能夠跟踪鍵盤輸入,讓我們添加一個名為 cursors 的全局變量 在 breakout.js 的頂部 :

let player, ball, violetBricks, yellowBricks, redBricks, cursors;

在我們的 create 底部 函數,添加如下:

cursors = this.input.keyboard.createCursorKeys();

Phaser 中的光標鍵跟踪 6 個鍵盤鍵的使用情況:上、右、下、左、Shift 和空格。

現在我們需要對 cursors 的狀態做出反應 對象來更新我們的玩家的位置。在 else 我們的 update 子句 函數添加如下:

// Put this in so that the player stays still if no key is being pressed
player.body.setVelocityX(0);

if (cursors.left.isDown) {
  player.body.setVelocityX(-350);
} else if (cursors.right.isDown) {
  player.body.setVelocityX(350);
}

現在我們可以從左到右移動我們的播放器了!

免費電子書:Git Essentials

查看我們的 Git 學習實踐指南,其中包含最佳實踐、行業認可的標準以及隨附的備忘單。停止谷歌搜索 Git 命令並真正學習 它!

您會注意到玩家精靈能夠離開遊戲屏幕,理想情況下它不應該。我們稍後會在處理碰撞時解決這個問題。

等待開始

在我們添加邏輯來移動球之前,如果遊戲在移動之前等待用戶輸入會有所幫助。加載遊戲並立即強制玩家,這不是很好的體驗,玩家沒有公平的反應時間!

讓我們在玩家按下空格鍵後將球向上移動。如果用戶將球拍向左或向右移動,球也會隨之移動,因此它始終位於球拍的中心。

首先,我們需要自己的變量來跟踪遊戲是否開始。在 breakout.js 的頂部 ,在我們的遊戲變量聲明後添加以下內容:

let gameStarted = false;

顧名思義,該變量跟踪我們的遊戲是否已經開始。現在,在 else 我們的更新函數的子句添加以下內容:

if (!gameStarted) {
  ball.setX(player.x);

  if (cursors.space.isDown) {
    gameStarted = true;
    ball.setVelocityY(-200);
  }
}

如果遊戲還沒有開始,將X坐標或我們的球設置到玩家的中心。遊戲對象的坐標基於它們的中心,所以 xy 精靈的屬性與精靈的中心相關。

請注意,雖然可以獲取像 x 這樣的屬性值 通過直接引用它,在設置屬性時,我們總是嘗試使用適當的 setter 函數。 setter 函數可以包含驗證輸入、更新另一個屬性或觸發事件的邏輯。它使我們的代碼更具可預測性。

和之前移動播放器一樣,我們檢查是否按下了空格鍵。如果它被按下,我們切換 gameStarted 標記為 true 因此球將不再跟隨玩家的水平位置,並將球的 Y Velocity 設置為 -200。負 y 速度將物體向上發送。對於正速度,較大的值會更快地向下移動對象。對於負速度,較小的值會使物體向上移動得更快。

現在,當我們移動玩家時,球會跟隨,如果我們按下空格鍵,球會向上射擊:

你會從我們遊戲目前的表現中觀察到一些事情:

  1. 球在磚塊後面渲染
  2. 玩家可以離開屏幕邊界
  3. 球可以離開屏幕的邊界

球是在磚塊後面渲染的,因為它是在我們的創建函數中在磚塊精靈組之前添加到遊戲中的。在 Phaser 中,通常使用 HTML5 畫布元素,最近添加的圖像被繪製在之前的圖像之上。

最後兩個問題可以通過添加一些世界碰撞來解決。

處理碰撞

世界碰撞

我們所有的精靈交互都在 create 中定義 功能。使用 Phaser 啟用與世界場景的碰撞非常簡單,將以下內容添加到 create 的末尾 功能:

player.setCollideWorldBounds(true);
ball.setCollideWorldBounds(true);

它應該給我們這樣的輸出:

雖然球員的動作很好,但球似乎卡在了頂部。為了解決這個問題,我們需要設置 bounce 球精靈的屬性。 bounce 屬性會告訴 Phaser 在與物體碰撞後要保持多少速度。將此添加到您的 create 末尾 功能:

ball.setBounce(1, 1);

這告訴移相器,球應保持其所有 X 和 Y 速度。如果我們用空格鍵釋放球,球應該會在遊戲世界中上下彈跳。我們需要從遊戲世界的底部禁用碰撞檢測。如果我們不這樣做,我們將永遠不知道遊戲何時結束。通過在 create 末尾添加此行來禁用與遊戲世界底部的碰撞 功能:

this.physics.world.checkCollision.down = false;

我們現在應該有一個這樣的遊戲:

磚碰撞

現在我們的移動精靈正確地與我們的遊戲世界發生碰撞,讓我們來處理球和磚塊之間的碰撞,然後是球和玩家之間的碰撞。

在我們的create函數中以下面幾行代碼結束:

this.physics.add.collider(ball, violetBricks, hitBrick, null, this);
this.physics.add.collider(ball, yellowBricks, hitBrick, null, this);
this.physics.add.collider(ball, redBricks, hitBrick, null, this);

collider 方法告訴 Phaser 的物理系統執行 hitBrick ball 時的功能 與各種磚精靈組發生碰撞。

每按一次空格鍵,球就會向上射。沒有 X 速度,所以球會直接回到槳。那將是一場無聊的比賽。因此,當我們第一次碰到磚塊時,我們將設置 X 速度。在 breakout.js 的底部 定義 hitBrick 下面:

function hitBrick(ball, brick) {
  brick.disableBody(true, true);

  if (ball.body.velocity.x == 0) {
    randNum = Math.random();
    if (randNum >= 0.5) {
      ball.body.setVelocityX(150);
    } else {
      ball.body.setVelocityX(-150);
    }
  }
}

hitBrick 函數接受 collider 中使用的前兩個參數 方法,例如 ballvioletBricks . disableBody(true, true) 對磚塊的調用告訴 Phaser 使其處於非活動狀態並將其隱藏在屏幕上。如果小球的 X Velocity 為 0,那麼我們給小球一個速度取決於一個隨機數的值。

如果一個小球以緩慢的速度滾向你的腳,在碰撞時它會停下來。 Arcade Physics 引擎默認模擬碰撞對速度的影響。對於我們的遊戲,我們不希望球在擊中磚塊時失去速度。我們需要設置 immovable 屬性到我們的精靈組到 true .更新violetBricks的定義 , yellowBricksredBricks 如下:

// Add violet bricks
violetBricks = this.physics.add.group({
  key: 'brick1',
  repeat: 9,
  immovable: true,
  setXY: {
    x: 80,
    y: 140,
    stepX: 70
  }
});

// Add yellow bricks
yellowBricks = this.physics.add.group({
  key: 'brick2',
  repeat: 9,
  immovable: true,
  setXY: {
    x: 80,
    y: 90,
    stepX: 70
  }
});

// Add red bricks
redBricks = this.physics.add.group({
  key: 'brick3',
  repeat: 9,
  immovable: true,
  setXY: {
    x: 80,
    y: 40,
    stepX: 70
  }
});

我們的磚塊碰撞現在已經完成,我們的遊戲應該像這樣運行:

開發提示 - 在開發遊戲的物理特性時,您可能希望啟用調試模式以查看精靈的邊界框以及它們如何相互碰撞。在你的遊戲中 config 對象,在 arcade 內 我們定義 gravity 的屬性 ,您可以通過將此添加到對象來啟用調試:

debug: true

玩家碰撞

管理球和球員之間的碰撞是類似的努力。首先,讓我們確保播放器是不動的。在 create 的末尾 函數添加如下:

player.setImmovable(true);

然後我們在球和玩家之間添加一個碰撞器:

this.physics.add.collider(ball, player, hitPlayer, null, this);

當球擊中球員時,我們希望發生兩件事:

  • 球應該移動得快一點,逐漸增加遊戲的難度
  • 球的水平方向取決於它擊中球員的哪一側 - 如果球擊中球員的左側,那麼它應該向左,如果它擊中球員的右側,那麼它應該向右。

breakout.js 的底部 添加 hitPlayer 功能:

function hitPlayer(ball, player) {
  // Increase the velocity of the ball after it bounces
  ball.setVelocityY(ball.body.velocity.y - 5);

  let newXVelocity = Math.abs(ball.body.velocity.x) + 5;
  // If the ball is to the left of the player, ensure the X Velocity is negative
  if (ball.x < player.x) {
    ball.setVelocityX(-newXVelocity);
  } else {
    ball.setVelocityX(newXVelocity);
  }
}

注意 - 一個精靈可以與另一個精靈發生碰撞,一個精靈可以與一個精靈組發生碰撞,而精靈組可以相互碰撞。 Phaser 足夠聰明,可以使用我們在上下文中適當定義的碰撞函數。

現在我們的遊戲有玩家和磚塊碰撞:

添加文本

雖然我們的遊戲功能齊全,但玩此遊戲的人不知道如何開始或知道遊戲何時結束。在 gameStarted 之後添加 3 個新聞全局變量來存儲我們的文本數據 breakout.js 頂部的聲明 :

let openingText, gameOverText, playerWonText;

開頭文字

讓我們在遊戲加載時添加一些文本來告訴玩家按空格鍵。在 create 函數添加如下代碼:

openingText = this.add.text(
  this.physics.world.bounds.width / 2,
  this.physics.world.bounds.height / 2,
  'Press SPACE to Start',
  {
    fontFamily: 'Monaco, Courier, monospace',
    fontSize: '50px',
    fill: '#fff'
  },
);

openingText.setOrigin(0.5);

text 的前兩個參數 方法是文本框的 X 和 Y 坐標。我們使用遊戲場景的寬度和高度來確定它的放置位置 - 中心。第三個參數是要顯示的文本。第四個參數是一個包含字體相關數據的JS對象。

與精靈不同,文本對象的 X 和 Y 坐標指的是對象的最左上角,而不是它們的中心。這就是我們使用 setOrigin 的原因 使坐標系統像精靈一樣工作的方法,在這種情況下,它更容易定位在中心。

當我們在玩的時候,我們不想再看到開頭的文字了。在 update 函數,將檢查空格鍵是否被按下的 if 語句更改為:

if (cursors.space.isDown) {
  gameStarted = true;
  ball.setVelocityY(-200);
  openingText.setVisible(false);
}

文本對像不是精靈,我們不能禁用它們的身體。當我們不需要看到它們時,我們可以讓它們不可見。我們的遊戲現在是這樣開始的:

遊戲結束和遊戲獲勝文本

和之前一樣,我們需要在 create 中添加文本對象 功能,並使其不可見,以便在遊戲開始時不會看到:

// Create game over text
gameOverText = this.add.text(
  this.physics.world.bounds.width / 2,
  this.physics.world.bounds.height / 2,
  'Game Over',
  {
    fontFamily: 'Monaco, Courier, monospace',
    fontSize: '50px',
    fill: '#fff'
  },
);

gameOverText.setOrigin(0.5);

// Make it invisible until the player loses
gameOverText.setVisible(false);

// Create the game won text
playerWonText = this.add.text(
  this.physics.world.bounds.width / 2,
  this.physics.world.bounds.height / 2,
  'You won!',
  {
    fontFamily: 'Monaco, Courier, monospace',
    fontSize: '50px',
    fill: '#fff'
  },
);

playerWonText.setOrigin(0.5);

// Make it invisible until the player wins
playerWonText.setVisible(false);

現在它們已定義,我們必須在 update 中更改它們的可見性 功能:

// Check if the ball left the scene i.e. game over
if (isGameOver(this.physics.world)) {
  gameOverText.setVisible(true);
  ball.disableBody(true, true);
} else if (isWon()) {
  playerWonText.setVisible(true);
  ball.disableBody(true, true);
} else {
  ...

我們禁用了球體,因此不再需要它時它會停止更新和顯示。

如果我們輸掉比賽,我們會看到:

如果我們贏了比賽,我們會看到:

我們的 Breakout 克隆完成了!

結論

Phaser 是一個 HTML5 遊戲開發框架,可以讓我們在 Web 上快速構建視頻遊戲。除了抽象 HTML5 API 之外,它還為我們提供了有用的實用程序,例如物理引擎並管理遊戲循環——所有遊戲的執行生命週期。

我們通過以下方式構建了一個 Breakout 克隆:

  • 加載我們的資產,在本例中是我們的圖片
  • 為我們的球員和球創建精靈,為我們的積木創建精靈組
  • 監聽鍵盤事件以便我們移動播放器
  • 使用物理引擎處理精靈對象與遊戲世界之間的碰撞
  • 顯示文字以指導玩家,並告知他們輸贏

類似的開發方法可用於在 Phaser 中創建其他遊戲。

提高遊戲開發技能的最佳方法是不斷開發遊戲。如果您想了解更多關於 Phaser 遊戲開發的知識,請查看官網的入門教程。

您可以在此處查看遊戲的註釋源代碼。


Tutorial JavaScript 教程
  1. 這個請求響應格式是什麼?

  2. 有沒有辦法動態加載本地JS文件?

  3. 比較 rust 與 nodejs 腳本運行時

  4. 週五前端:生日版

  5. React 與普通 JS

  6. 用 Arduino 和...Angular 創建智能鎖?!

  7. 我用 JavaScript 構建了一個交互式 3D 照片顯示

  1. 如何將 Javascript 對象鍵設置為另一個對象的值

  2. ReactJS/CSS:如何根據其他元素高度設置 div 高度?

  3. Chrome DevTools:使用代碼段提高生產力

  4. Hugo Pipeline 系列 - 編輯和部署

  5. Strapi CMS 媒體 VS MongoDB

  6. 如何反應滑塊

  7. 節點安全版本 v0.5.0

  1. 基於 Quasar 和 Firebase 構建的簡單生產力應用程序

  2. Node.js 畫布圖像重疊問題/畫布正在上一個圖像之上創建圖像

  3. 使用 PHP 進行服務器端反應

  4. 我的 Electron 應用程序 - 組織我的書籤