按鈕

這是 Gamedev Phaser 教程 的 16 個步驟中的第 15 步。與其立即開始遊戲,不如透過新增一個玩家可以按下的“開始”按鈕來將這個決定權交給玩家。讓我們來研究一下如何實現這一點。

新屬性

我們需要一個屬性來儲存一個布林值,表示遊戲當前是否正在進行,以及另一個屬性來表示我們的按鈕。在其他屬性定義下方新增這些行

js
class ExampleScene extends Phaser.Scene {
  // ... previous property definitions ...
  playing = false;
  startButton;
  // ... rest of the class ...
}

載入按鈕精靈圖

我們可以像載入小球的搖擺動畫一樣載入按鈕精靈圖。在 preload() 方法的末尾新增以下內容

js
this.load.spritesheet("button", "img/button.png", {
  frameWidth: 120,
  frameHeight: 40,
});

單個按鈕幀的寬度為 120 畫素,高度為 40 畫素。

您還需要 獲取按鈕精靈圖,並將其儲存在您的 /img 目錄中。

將按鈕新增到遊戲中

透過使用 add.sprite 方法將新按鈕新增到遊戲中。在 create() 方法的末尾新增以下行

js
this.startButton = this.add.sprite(
  this.scale.width * 0.5,
  this.scale.height * 0.5,
  "button",
  0,
);

除了我們傳遞給其他 add.sprite 呼叫的引數(例如新增小球和擋板時)之外,這次我們還傳遞了幀編號,在本例中為 0。這意味著精靈圖的第一幀將用於按鈕的初始外觀。

為了讓按鈕響應各種輸入,例如滑鼠點選,我們需要在前面的 add.sprite 呼叫後立即新增以下行

js
this.startButton.setInteractive();
this.startButton.on(
  "pointerover",
  () => {
    this.startButton.setFrame(1);
  },
  this,
);
this.startButton.on(
  "pointerdown",
  () => {
    this.startButton.setFrame(2);
  },
  this,
);
this.startButton.on(
  "pointerout",
  () => {
    this.startButton.setFrame(0);
  },
  this,
);
this.startButton.on(
  "pointerup",
  () => {
    this.startGame();
  },
  this,
);

首先,我們在按鈕上呼叫 setInteractive 以使其響應指標事件。然後,我們將四個事件監聽器新增到按鈕中

  • pointerover — 當指標懸停在按鈕上時,我們將按鈕的幀更改為 1,即精靈圖的第二幀。
  • pointerdown — 當按鈕被按下時,我們將按鈕的幀更改為 2,即精靈圖的第三幀。
  • pointerout — 當指標移出按鈕時,我們將按鈕的幀改回 0,即精靈圖的第一幀。
  • pointerup — 當按鈕被釋放時,我們呼叫 startGame 方法來開始遊戲。

現在,我們需要定義上面程式碼中引用的 startGame() 方法

js
class ExampleScene extends Phaser.Scene {
  // ...
  startGame() {
    this.startButton.destroy();
    this.ball.body.setVelocity(150, -150);
    this.playing = true;
  }
}

當按下按鈕時,我們移除按鈕,設定小球的初始速度,並將 playing 屬性設定為 true

最後,在本節中,回到您的 create 方法,找到 this.ball.body.setVelocity(150, -150); 行,並將其刪除。您只希望在按下按鈕時小球才移動,而不是之前!

遊戲開始前保持擋板靜止

它按預期工作,但我們仍然可以在遊戲開始前移動擋板,這看起來有點奇怪。為了阻止這種情況,我們可以利用 playing 屬性,使擋板僅在遊戲開始後才能移動。為此,請按如下方式調整 update() 方法

js
class ExampleScene extends Phaser.Scene {
  // ...
  update() {
    // ...
    if (this.playing) {
      this.paddle.x = this.input.x || this.scale.width * 0.5;
    }
    // ...
  }
  // ...
}

這樣,在所有內容載入和準備好之後,但在實際遊戲開始之前,擋板是不可移動的。

Compare your code

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

後續步驟

在本系列文章中,我們做的最後一件事是透過為小球從擋板反彈的方式新增一些 隨機化 來使遊戲玩法更加有趣。