桌面滑鼠和鍵盤控制元件
現在,當我們的移動端控制元件已就位,並且遊戲可以在觸控式螢幕裝置上玩時,最好新增滑鼠和鍵盤支援,以便遊戲也可以在桌面上玩。這樣我們就可以擴大支援的平臺列表。我們將在下面進行介紹。
此外,如果您在桌面上開發獨立於控制元件的遊戲玩法等功能,那麼進行測試會更容易,這樣您就不必在每次更改原始碼時都將檔案推送到移動裝置上。
注意: Captain Rogers: Battle at Andromeda 是使用 Phaser 構建的,控制元件管理也是基於 Phaser 的,但也可以用純 JavaScript 完成。使用 Phaser 的好處是它提供了輔助變數和函式,使開發更輕鬆、更快,但選擇哪種方法完全取決於您。
純 JavaScript 方法
讓我們先來考慮在遊戲中實現純 JavaScript 鍵盤/滑鼠控制元件,看看它是如何工作的。首先,我們需要一個事件監聽器來監聽按下的按鍵。
document.addEventListener("keydown", keyDownHandler);
document.addEventListener("keyup", keyUpHandler);
每當按下任何按鍵時,我們就會執行 keyDownHandler 函式,當按鍵釋放時,我們就會執行 keyUpHandler 函式,這樣我們就知道何時按鍵不再按下。為此,我們將儲存有關我們感興趣的按鍵是否被按下的資訊。
let rightPressed = false;
let leftPressed = false;
let upPressed = false;
let downPressed = false;
然後,我們將監聽 keydown 和 keyup 事件,並在兩個處理函式中進行相應操作。在其中,我們可以從事件物件的 code 屬性中獲取被按下按鍵的程式碼,檢視是哪個按鍵,然後設定相應的變數。程式碼都是可讀的字串名稱,但您可以 查詢它們 以確保;"ArrowLeft" 是左箭頭。
function keyDownHandler(event) {
if (event.code === "ArrowRight") {
rightPressed = true;
} else if (event.code === "ArrowLeft") {
leftPressed = true;
}
if (event.code === "ArrowDown") {
downPressed = true;
} else if (event.code === "ArrowUp") {
upPressed = true;
}
}
keyUpHandler 的寫法幾乎與上面的 keyDownHandler 完全相同,但不同的是,我們將按下變數設定為 true,而這裡我們將它們設定為 false。如果按下左箭頭(⬅︎;"ArrowLeft"),我們可以將 leftPressed 變數設定為 true,並在 draw 函式中執行分配給它的操作——將飛船向左移動。
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (rightPressed) {
playerX += 5;
} else if (leftPressed) {
playerX -= 5;
}
if (downPressed) {
playerY += 5;
} else if (upPressed) {
playerY -= 5;
}
ctx.drawImage(img, playerX, playerY);
requestAnimationFrame(draw);
}
draw 函式首先清除整個 Canvas——我們每一幀都從頭開始繪製所有內容。然後檢查按鍵變數,並調整 playerX 和 playerY 變數(我們在 leftPressed 和其他變數之後立即定義了它們)來儲存飛船的位置,調整量為給定值,例如 5 畫素。然後,玩家的飛船繪製在螢幕上,並在 requestAnimationFrame 中呼叫下一個繪製。

您可以線上檢視此示例的執行情況:end3r.github.io/JavaScript-Game-Controls,完整的原始碼可以在 github.com/end3r/JavaScript-Game-Controls 找到。
Phaser 方法
正如我之前提到的,您可以自己編寫所有內容,但也可以利用 Phaser 等框架中的內建函式。這些將使您的生活更輕鬆,開發速度更快。所有邊緣情況——瀏覽器實現之間的差異等——都由框架處理,因此您可以專注於您想要做的實際任務。
滑鼠
遊戲中的滑鼠互動主要集中在點選按鈕。在 Phaser 中,您建立的按鈕可以接受任何型別的輸入,無論是移動裝置上的觸控還是桌面上的點選。這樣,如果您已經按照《移動端觸控控制元件》一文中的說明實現了按鈕,那麼它在桌面上也可以開箱即用。
const buttonEnclave = this.add.button(
10,
10,
"logo-enclave",
this.clickEnclave,
this,
);
按鈕將放置在螢幕左上角十畫素處,使用 logo-enclave 圖片,並在點選時執行 clickEnclave() 函式。我們可以直接為按鈕分配操作。
this.buttonShoot = this.add.button(
this.world.width * 0.5,
0,
"button-alpha",
null,
this,
);
this.buttonShoot.onInputDown.add(this.shootingPressed, this);
this.buttonShoot.onInputUp.add(this.shootingReleased, this);
用於射擊的按鈕在移動和桌面方法下都能完美執行。
如果您想在螢幕上使用滑鼠游標位置,可以使用 this.game.input.mousePointer。假設您想在滑鼠點選螢幕右側時射擊子彈,可以這樣做:
if (this.game.input.mousePointer.isDown) {
if (this.game.input.mousePointer.x > this.world.width * 0.5) {
// shoot
}
}
如果您想區分按下的滑鼠按鈕,有三個預設選項可供選擇:
this.game.input.mousePointer.leftButton.isDown;
this.game.input.mousePointer.middleButton.isDown;
this.game.input.mousePointer.rightButton.isDown;
請記住,為了實現平臺無關的輸入,如果您想保留對移動端觸控互動的支援,最好使用 activePointer 而不是 mousePointer。
鍵盤
整個遊戲都可以僅用鍵盤控制,而無需其他任何裝置。內建的 this.game.input.keyboard 物件管理鍵盤輸入,並具有 一些有用的方法,如 addKey() 和 isDown()。還有一個 Phaser.KeyCode 物件,其中包含所有可用的鍵盤按鍵。

在遊戲的主選單中,我們可以新增一種額外的開始遊戲方式。可以點選“開始”按鈕來實現這一點,但我們也可以使用 Enter 鍵來實現相同的功能。
const keyEnter = this.game.input.keyboard.addKey(Phaser.KeyCode.ENTER);
keyEnter.onDown.add(this.clickStart, this);
您可以使用 addKey() 來新增 Phaser.KeyCode 物件提供的任何按鍵。每當按下 Enter 鍵時,就會執行 onDown() 函式。它將呼叫 clickStart() 方法,該方法會啟動一個新遊戲。
提供一個選項讓玩家在桌面上不使用滑鼠玩遊戲非常有用,這樣他們就不必將手從鍵盤上移開。
控制遊戲
透過在 create() 函式中使用 createCursorKeys() 函式,我們可以透過啟用基本的方向鍵來支援使用 Phaser 構建的遊戲中的鍵盤輸入。
this.cursors = this.input.keyboard.createCursorKeys();
這會為我們建立四個方向箭頭鍵。
this.cursors.left;
this.cursors.right;
this.cursors.up;
this.cursors.down;
您也可以自己定義按鍵,並提供一個替代的 W A S D 控制元件機制。例如:
this.keyLeft = this.input.keyboard.addKey(Phaser.KeyCode.A);
this.keyRight = this.input.keyboard.addKey(Phaser.KeyCode.D);
this.keyUp = this.input.keyboard.addKey(Phaser.KeyCode.W);
this.keyDown = this.input.keyboard.addKey(Phaser.KeyCode.S);
為了同時支援方向鍵和 W A S D 鍵,我們需要這樣做:
if (this.cursors.left.isDown || this.keyLeft.isDown) {
// move left
} else if (this.cursors.right.isDown || this.keyRight.isDown) {
// move right
}
if (this.cursors.up.isDown || this.keyUp.isDown) {
// move up
} else if (this.cursors.down.isDown || this.keyDown.isDown) {
// move down
}
在 update() 函式中,我們現在可以使用兩種移動按鍵選項之一來向任何方向移動玩家的飛船。
我們還可以提供射擊控制元件的替代方案。對於方向鍵,自然的射擊按鈕會在鍵盤的另一側,這樣玩家就可以使用另一隻手——例如 X 鍵。對於 W A S D 鍵,可以是空格鍵。
this.keyFire1 = this.input.keyboard.addKey(Phaser.KeyCode.X);
this.keyFire2 = this.input.keyboard.addKey(Phaser.KeyCode.SPACEBAR);
在 update() 函式中,我們可以輕鬆地檢查每一幀是否按下了這兩個按鍵中的任何一個。
if (this.keyFire1.isDown || this.keyFire2.isDown) {
// fire the weapon
}
如果按下,那麼就該射擊一些子彈了!
我們甚至可以定義一個秘密的作弊按鈕。
this.keyCheat = this.input.keyboard.addKey(Phaser.KeyCode.C);
然後在 update() 函式中,每當按下 C 鍵時,我們就會這樣做:
if (this.keyCheat.isDown) {
this.player.health = this.player.maxHealth;
}
我們可以將玩家的生命值設定為最大。請記住:這是秘密,所以不要告訴任何人!
如何玩
我們已經實現了控制元件,現在我們應該告知玩家他們的遊戲控制選項。否則他們不會知道!在顯示“如何玩”螢幕,其中展示了遊戲中控制飛船的各種方法時,我們不必向所有人展示所有內容,而是可以檢測遊戲是在桌面還是移動裝置上啟動,然後僅顯示適合該裝置的控制元件。
if (this.game.device.desktop) {
moveText = "Arrow keys or WASD to move";
shootText = "X or Space to shoot";
} else {
moveText = "Tap and hold to move";
shootText = "Tap to shoot";
}
如果遊戲在桌面上執行,將顯示方向鍵和 W A S D 鍵的訊息。否則,將顯示移動端觸控控制元件的訊息。

要跳過“如何玩”螢幕,我們可以監聽任何按鍵按下並繼續。
this.input.keyboard.onDownCallback = function () {
if (this.stateStatus === "intro") {
this.hideIntro();
}
};
這會隱藏介紹並開始實際遊戲,而無需我們為這個目的設定新的按鍵控制元件。
暫停和遊戲結束螢幕
為了使遊戲完全可以用鍵盤玩,應該可以從暫停和遊戲結束螢幕返回主選單、繼續遊戲或重新開始遊戲。這可以透過捕獲按鍵程式碼並執行操作來完成,方法與之前完全相同。例如,透過指定 Phaser.KeyCode.Backspace 或 Phaser.KeyCode.Delete,您可以將一個操作繫結到按下 Delete/Backspace 鍵時觸發。
總結
好的,我們已經處理了觸控、鍵盤和滑鼠控制元件。現在讓我們繼續研究如何使用 Gamepad API 設定遊戲以透過控制檯遊戲手柄進行控制。