JavaScript 游戏中的控制机制

笔记本电脑、台式机、智能手机、平板电脑、电视机,甚至冰箱都有一个共同点 - 它们可能都可以运行浏览器,所以你可能可以在它们上面玩 HTML5 游戏。将游戏渲染到屏幕上是一回事,但你还需要以某种方式控制它,而且有很多不同的选项适合各种平台。从触摸、鼠标和键盘,到游戏手柄,甚至电视遥控器或... 香蕉 - 这些界面都包含在 MDN 上新发布的关于 控制机制 的一系列文章中。

captainrogers2-cover

为了展示它们在实际项目中的应用,这些控制机制在使用 Phaser 构建的 Captain Rogers: Battle at Andromeda demo 游戏中得到了实现,所以你可以看到游戏玩法是如何受到平台的影响的。你也可以看到,你不需要为不同的平台构建单独的版本 - Web 的跨平台特性可以帮助你根据游戏运行的设备调整控件,而不需要太多编码工作。

controls-purejsgame

有一个小型 纯 JavaScript 控制演示 在 GitHub 上开源,所以你可以确切地看到这些机制是如何实现的,并在你自己的游戏开发项目中尝试它。立即深入代码,或查看以下关键部分的亮点。

移动触摸

让我们从移动触摸支持开始,因为在 HTML5 游戏中,移动优先的方法非常流行

document.addEventListener("touchstart", touchHandler);
document.addEventListener("touchmove", touchHandler);
function touchHandler(e) {
    if(e.touches) {
        playerX = e.touches[0].pageX - canvas.offsetLeft - playerWidth / 2;
        playerY = e.touches[0].pageY - canvas.offsetTop - playerHeight / 2;
    }
}

这些少量的 JavaScript 代码是你需要在你的游戏中实现非常基本的触摸控制的全部内容,这样它就可以在移动设备上玩。前两行设置了我们感兴趣的触摸事件的事件监听器 - 当你触摸屏幕时,以及当你用手指在屏幕上滑动时。该函数检查是否执行了任何触摸,然后设置玩家的坐标,以便飞船可以在游戏画布的正确位置渲染。

这些只是基础,你可以(也应该)扩展可能性,例如实现多点触控或手势。这一切都取决于你拥有什么样的游戏,以及什么应该被控制(以及如何)。你也可以提供屏幕上的按钮来执行给定的操作,例如移动箭头和射击按钮。查看 移动触摸控制 文章了解更多详情。

桌面鼠标和键盘

既然我们说的是“移动箭头”,你可以在屏幕上为移动设备打印它们,但你也可以为桌面实现它们。光标键或 WASD 键是游戏中移动角色的常用方法。例如,下面的情况处理光标键

document.addEventListener("keydown", keyDownHandler);
function keyDownHandler(e) {
    if(e.keyCode == 39) {
        rightPressed = true;
    }
    else if(e.keyCode == 37) {
        leftPressed = true;
    }
    if(e.keyCode == 40) {
        downPressed = true;
    }
    else if(e.keyCode == 38) {
        upPressed = true;
    }
}

这一切都是关于不断检测并保存关于按下哪个键的信息,以便它可以在绘图循环中被处理

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);
}

玩家的 xy 位置变量被调整,然后在新的位置构建出一艘飞船的图像。

controls-howtoplay

从编码的角度来看,桌面鼠标和移动触摸非常相似:你需要做的就是获取触摸或点击发生的位置信息,并更新玩家的位置

document.addEventListener("mousemove", mouseMoveHandler);
function mouseMoveHandler(e) {
    playerX = e.pageX - canvas.offsetLeft - playerWidth / 2;
    playerY = e.pageY - canvas.offsetTop - playerHeight / 2;
}

mousemove 事件被检测到,玩家的位置被调整,以便在鼠标指针每次改变时将飞船放置在指针的中间。这就是让你的游戏在桌面上使用键盘和鼠标都可以玩所需要的一切 - 更多细节请查看 桌面鼠标和键盘控制 文章。

游戏手柄

我最喜欢的控制器 - 我使用 Gamepad API 在演示期间控制我所有的基于 HTML5 的幻灯片。我已经谈论过它很多次了,写了几篇文章,实现了一些游戏,并在 Gamepad API 内容套件 中包含了所有相关的信息。我们能够在电脑上体验到主机游戏体验,这真是太棒了,这一切都要感谢 Web 技术!使用游戏手柄玩 Captain Rogers 使体验更加丰富,而且感觉好多了。

controls-gamepadinfo

与触摸或键盘相比,涵盖 Gamepad API 支持稍微复杂一些,但仍然非常直观

window.addEventListener("gamepadconnected", gamepadHandler);
function gamepadHandler(e) {
    controller = e.gamepad;
}
function gamepadUpdateHandler() {
    buttonsPressed = [];
    if(controller.buttons) {
        for(var b=0; b<controller.buttons.length; b++) {
            if(controller.buttons[b].pressed) {
                buttonsPressed.push(b);
            }
        }
    }
}
function gamepadButtonPressedHandler(button) {
    var press = false;
    for(var i=0; i<buttonsPressed.length; i++) {
        if(buttonsPressed[i] == button) {
            press = true;
        }
    }
    return press;
}

当游戏手柄连接时,会触发一个事件,这样我们就可以在稍后使用的变量中获得对它的数据的引用。在每次更新时,都会创建一个新的按下按钮数组,这样当前状态始终是最新的。还有一个函数将循环遍历该数组,以查看我们感兴趣的特定按钮是否被按下。然后,这些信息可以在绘图循环中使用,与键盘检查类似

function draw() {
    // ...
    gamepadUpdateHandler();
    if(gamepadButtonPressedHandler(0)) {
        playerY -= 5;
    }
    else if(gamepadButtonPressedHandler(1)) {
        playerY += 5;
    }
    if(gamepadButtonPressedHandler(2)) {
        playerX -= 5;
    }
    else if(gamepadButtonPressedHandler(3)) {
        playerX += 5;
    }
    if(gamepadButtonPressedHandler(11)) {
        alert('BOOM!');
    }
    // ...
}

这样,我们可以通过按下相应的 DPad 按钮来控制玩家的飞船,甚至可以通过 A 按钮发射炸弹爆炸。你也可以检测轴,甚至构建你自己的小型库来处理游戏手柄输入 - 查看 桌面游戏手柄控制 文章,了解更多关于这方面的细节。

非常规控制

如果你愿意,你可以更进一步,在客厅里用遥控器玩游戏,在巨大的电视屏幕上玩,用手在笔记本电脑前面挥动,或者按下连接到电脑上的日常食物上的按钮。

controls-tvremote

例如,松下的电视遥控器非常容易实现控制,因为它重新使用了键盘事件,方向箭头与键盘光标键的代码完全相同 - 37383940,所以它可以开箱即用。如果你需要更多特定于遥控器的按钮,这里有一个 完整列表,以及更多详细的信息。

controls-leapmotion

你可以使用 Leap Motion 设备检测你的手部位置和其他参数来控制玩家的飞船,而不必触摸任何东西,而不是按下遥控器上的按钮。在预定义的循环中,我们可以获取手部详细信息...

Leap.loop({
    hand: function(hand) {
        horizontalDegree = Math.round(hand.roll() * toDegrees);
        verticalDegree = Math.round(hand.pitch() * toDegrees);
        grabStrength = hand.grabStrength;
    }
});

... 并使用它们来更新玩家的位置

function draw() {
    // ...
    if(horizontalDegree > degreeThreshold) {
        playerX -= 5;
    }
    else if(horizontalDegree < -degreeThreshold) {
        playerX += 5;
    }
    if(verticalDegree > degreeThreshold) {
        playerY += 5;
    }
    else if(verticalDegree < -degreeThreshold) {
        playerY -= 5;
    }
    if(grabStrength == 1) {
        alert('BOOM!');
    }
    // ...
}

你可以在 非常规控制 文章中找到其他有趣的控制机制的实现,例如多普勒效应、邻近 API,甚至 MaKey MaKey。

总结

如今,越来越多的设备,无论大小,都可以用来玩 HTML5 游戏。你的手表?语音激活的网页游戏?可能性是无限的。请记住:你的游戏支持的控制机制越多越好,因为它可以在各种设备上运行,在任何平台上都可以玩。利用浏览器提供的机遇。

关于 Andrzej Mazur

HTML5 游戏开发者,Enclave Games 独立游戏工作室创始人,js13kGames 比赛创办者,以及 Gamedev.js Weekly 时事通讯出版者。热衷于新兴的开放式 Web 技术的技术演讲者,对 WebXR 和 Web 货币化感到兴奋。

Andrzej Mazur 的更多文章...


2 条评论

  1. Michael M.

    令人恼火的是,许多开发者忘记为键盘输入事件调用 preventDefault()。当用户将浏览器搜索配置为在打字时立即启动(在 Firefox 中,首选项称为“当我开始打字时搜索文本”),打字一个字母将打开搜索并将焦点移动到那里,这将非常糟糕地中断游戏。调用 preventDefault() 按预期工作。因此,如果你是一名游戏开发者,即使按下某个键对你来说没有默认操作,也请调用 preventDefault()!(或者使用一个为你执行此操作的框架。)

    2016 年 10 月 28 日 00:28

    1. Andrzej Mazur

      PreventDefault 在纯 JS 演示的源代码和 MDN 中关于触摸事件的文章中都有,当然它也可以与键盘一起使用 - 我特意省略了它,只专注于控制本身,并使代码片段尽可能短。

      2016 年 10 月 28 日 01:00

本文评论已关闭。