額外生命

這是 Gamedev Phaser 教程 的 16 個步驟中的第 13 步。在本文中,我們將實現一個生命系統,這樣玩家就可以一直玩下去,直到失去三條生命,而不僅僅是一條,這使得遊戲更有趣、更持久。

新屬性

在您的程式碼中,在現有屬性下方新增以下新屬性

js
class ExampleScene extends Phaser.Scene {
  // ... previous property definitions ...
  lives = 3;
  livesText;
  lifeLostText;
  // ... rest of the class ...
}

這些屬性將分別儲存生命的 數量、顯示剩餘生命數量的文字標籤,以及當玩家失去一條生命時螢幕上顯示的文字標籤。

定義新的文字標籤

定義文字看起來和我們在 分數 課程中學到的很相似。在 create() 方法中,在現有的 scoreText 定義下方新增以下幾行

js
this.livesText = this.add.text(
  this.scale.width - 5,
  5,
  `Lives: ${this.lives}`,
  { font: "18px Arial", fill: "#0095dd" },
);
this.livesText.setOrigin(1, 0);
this.lifeLostText = this.add.text(
  this.scale.width * 0.5,
  this.scale.height * 0.5,
  "Life lost, click to continue",
  { font: "18px Arial", fill: "#0095dd" },
);
this.lifeLostText.setOrigin(0.5, 0.5);
this.lifeLostText.visible = false;

this.livesTextthis.lifeLostText 物件看起來與 this.scoreText 非常相似——它們定義了螢幕上的位置、要顯示的實際文字以及字型樣式。前者在其右上角錨定以正確對齊螢幕,後者居中,都使用了 setOrigin

lifeLostText 只會在失去生命時顯示,因此其可見性最初設定為 false

讓我們的文字樣式 DRY

您可能已經注意到,我們對所有三個文字:scoreTextlivesTextlifeLostText 使用了相同的樣式。如果我們想更改字型大小或顏色,將不得不在多個地方進行更改。為了將來更易於維護,我們可以建立一個單獨的變數來儲存我們的樣式,我們稱之為 textStyle,並將其放在文字定義之前

js
const textStyle = { font: "18px Arial", fill: "#0095dd" };

現在我們可以在設定文字標籤樣式時使用此變數——更新您的程式碼,將多個文字樣式例項替換為該變數

js
this.scoreText = this.add.text(5, 5, "Points: 0", textStyle);

this.livesText = this.add.text(
  this.scale.width - 5,
  5,
  `Lives: ${this.lives}`,
  textStyle,
);
this.livesText.setOrigin(1, 0);
this.lifeLostText = this.add.text(
  this.scale.width * 0.5,
  this.scale.height * 0.5,
  "Life lost, click to continue",
  textStyle,
);
this.lifeLostText.setOrigin(0.5, 0.5);
this.lifeLostText.visible = false;

這樣,在一個變數中更改字型將把更改應用於所有使用它的地方。

生命處理程式碼

為了在我們的遊戲中實現生命系統,讓我們先改變當球超出邊界時的行為。而不是立即重新開始

js
if (ballIsOutOfBounds) {
  // Game over logic
  location.reload();
}

我們將呼叫一個名為 ballLeaveScreen() 的新方法;刪除之前的行(如上所示),並用以下行替換

js
if (ballIsOutOfBounds) {
  this.ballLeaveScreen();
}

我們希望每次球離開畫布時都減少生命數量。將 ballLeaveScreen() 方法定義新增到 ExampleScene 類的末尾

js
class ExampleScene extends Phaser.Scene {
  // ...
  ballLeaveScreen() {
    this.lives--;
    if (this.lives > 0) {
      this.livesText.setText(`Lives: ${this.lives}`);
      this.lifeLostText.visible = true;
      this.ball.body.reset(this.scale.width * 0.5, this.scale.height - 25);
      this.input.once(
        "pointerdown",
        () => {
          this.lifeLostText.visible = false;
          this.ball.body.setVelocity(150, -150);
        },
        this,
      );
    } else {
      // Game over logic
      location.reload();
    }
  }
}

而不是在失去生命時立即彈出提示,我們首先從當前數量中減去一條生命,並檢查它是否為非零值。如果是,則玩家仍有一些生命,並且可以繼續玩——他們將看到生命丟失訊息,球和擋板的位置將在螢幕上重置,在下一個輸入(單擊或觸控)時,訊息將隱藏,球將再次開始移動。

當可用生命數量達到零時,遊戲結束,將顯示遊戲結束提示訊息。

事件

您可能已經注意到上述程式碼塊中的 once 方法呼叫,並想知道它是什麼。once() 方法是一個 Phaser 事件偵聽器,它偵聽指定事件(在本例中為 pointer down 事件)的下一次發生,然後在觸發後自行移除。這意味著回撥中的程式碼在呼叫 once 後只會執行一次,這正是我們想要的——我們只想在玩家單擊或觸控式螢幕幕後隱藏生命丟失訊息並重新開始球的移動。

Compare your code

這是您到目前為止應該看到的效果,即時執行。要檢視其原始碼,請單擊“播放”按鈕。

後續步驟

生命系統讓遊戲更加寬容——如果您失去一條生命,您還有兩條生命可以繼續玩。現在,讓我們透過新增 動畫和緩動效果 來擴充套件遊戲的外觀和感覺。