桌面鼠标和键盘控制
现在,我们已经有了移动控制,并且游戏可以在触控设备上玩,最好添加鼠标和键盘支持,以便游戏也可以在桌面上玩。这样,我们可以扩大支持平台的范围。我们将在下面讨论这一点。
在桌面上开发游戏时,也更容易测试与控制无关的功能,例如游戏玩法,因此您不必每次更改源代码时都将文件推送到移动设备。
注意:Captain Rogers: Battle at Andromeda 是使用 Phaser 构建的,并且控制管理基于 Phaser,但也可以用纯 JavaScript 完成。使用 Phaser 的好处是,它提供辅助变量和函数,可以更轻松、更快速地进行开发,但完全取决于您选择哪种方法。
纯 JavaScript 方法
让我们先考虑在游戏中实现纯 JavaScript 键盘/鼠标控制,看看它是如何工作的。首先,我们需要一个事件监听器来监听被按下的键
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
每当按下任何键时,我们都会执行 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
函数首先清除整个画布——我们在每一帧都从头开始绘制所有内容。然后检查被按下的键变量,并通过给定量(例如 5 像素)调整保存飞船位置的 playerX
和 playerY
变量(我们稍后在 leftPressed
和其他变量之后定义)。然后在屏幕上绘制玩家的飞船,并从 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,
);
该按钮将放置在屏幕左上角 10 像素处,使用 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()
方法,该方法将开始新游戏。
在不使用鼠标的情况下提供在桌面上玩游戏的选项很有用,因此您不必把手从键盘上移开。
控制游戏
我们可以通过使用 createCursorKeys()
函数在 create()
函数中启用基本光标键,来支持使用 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
按钮时触发。
总结
好了,我们已经处理了触控、键盘和鼠标控制。现在让我们继续了解如何使用 游戏手柄 API 设置游戏,使其可以使用游戏手柄控制。