案例研究 能自动调整大小的 HTML5 游戏

发布于 2022-09-18 13:23:06 字数 5660 浏览 171 评论 0

2010 年夏天,我们创建了 Sand Trap,这是一款我们参加的手机 HTML5 游戏竞赛。 但大多数手机要么只显示游戏的一部分,要么让游戏变得太小——使其完全无法玩。 所以我们自己决定让游戏流畅地调整以匹配任何分辨率。 经过一些重新编程和使用本文中概述的想法后,我们有了一款可以在任何现代浏览器上扩展的游戏,无论它是在台式机还是移动设备上运行。

thwack 全屏截图

浏览器窗口中 thwack 的屏幕截图变小了

这种方法对 Sand Trap 很有效,所以我们在最新的游戏 Thwack!! 中使用了相同的方法。 游戏会自动调整屏幕分辨率以适应全屏和自定义大小的窗口,如下面的屏幕截图所示。

实现这一点需要同时利用 CSS 和 JavaScript。 使用 CSS 填充整个屏幕是微不足道的,但 CSS 不允许您保持相同的宽高比以防止画布和游戏区域的拉伸。 这就是 JavaScript 的用武之地。您可以使用 JavaScript 重新缩放文档元素并触发窗口事件的大小调整。

准备页面

第一步是在页面上指定进行游戏的区域。 如果您将其包含为 div 块,则可以在其中放置其他标签或画布元素。 通过正确设置,这些子元素将继承父 div 块的缩放。

如果你的游戏区有两个部分,一个游戏区和一个记分区,它可能看起来像这样:

<div id=”gameArea”>
  <canvas id=”gameCanvas”></canvas>
  <div id=”statsPanel”></div>
</div>

一旦你有了一个基本的文档结构,你就可以给这些元素一些 CSS 属性来为调整大小做准备。 “gameArea”的许多 CSS 属性是由 JavaScript 直接操作的,但为了让它们工作,从父 gameArea div 块开始设置一些其他 CSS 属性:

#gameArea {
  position: absolute;
  left:     50%;
  top:      50%;
}

这会将画布的左上角置于屏幕中央。 下一节中描述的 JavaScript 自动调整大小功能会操纵额外的 CSS 属性来调整游戏区域的大小并将其置于窗口的中心。

由于游戏区域会根据窗口的尺寸自动调整大小,因此您不希望 gameArea div 块的子元素的尺寸以像素为单位; 相反,你想要它的百分比。 像素值不允许内部元素随着父 div 的变化而缩放。 但是,从像素开始,然后在您拥有自己喜欢的布局后将其转换为百分比可能会有所帮助。

对于此示例,从 300 像素高和 400 像素宽的游戏区域开始。 画布覆盖了整个游戏区域,底部有一个半透明的统计面板,高 24 像素,如图 1 所示。

Figure 1: Dimensions of gameArea child elements in pixels

图 1:gameArea 子元素的尺寸(以像素为单位)

将这些值转换为百分比会使画布的宽度为 100%,高度为 100%(游戏区域的,而不是窗口的)。 将 24 除以 300 使统计面板的高度为 8%,并且由于它将覆盖游戏区域的底部,因此它的宽度也将是 100%,如图 2 所示。

图 2:gameArea 子元素的尺寸百分比

现在您已经确定了游戏区域及其子元素的尺寸,您可以将两个内部元素的 CSS 属性放在一起,如下所示:

#gameCanvas {
  width: 100%;
  height: 100%;
}
#statsPanel {
  position: absolute;
  width: 100%;
  height: 8%;
  bottom: 0;
  opacity: 0.8;
}

调整游戏大小

现在您已准备好创建一个函数来处理正在调整大小的窗口。 首先,获取对父 gameArea 文档元素的引用。

var gameArea = document.getElementById('gameArea');

由于您不关心确切的宽度或高度,因此您需要设置的下一条信息是宽度与高度的比率。 使用之前对 400 像素宽和 300 像素高的游戏区域的参考,您知道要将纵横比设置为 4 单位宽和 3 单位高。

var widthToHeight = 4 / 3;

由于每当调整窗口大小时都会调用此函数,因此您还希望获取窗口的新尺寸,以便能够调整游戏的尺寸以匹配。 通过使用窗口的 innerWidth 和 innerHeight 属性找到它。

var newWidth = window.innerWidth;
var newHeight = window.innerHeight;

正如您确定了所需的宽高比一样,现在您可以确定窗口的当前宽高比:

var newWidthToHeight = newWidth / newHeight;

这使您可以决定是让游戏垂直还是水平填充屏幕,如图 3 所示。

图 3:在保持纵横比的同时将 gameArea 元素安装到窗口中

如果所需的游戏区域形状比窗口的形状宽(并且高度更短),则需要水平填充窗口并沿顶部和底部留出边距。 同样,如果所需的游戏区域形状高于窗口的形状(并且宽度更窄),则需要垂直填充窗口并沿左右留出边距。

为此,请使用当前窗口的宽高比测试所需的宽高比,并进行如下适当调整:

if (newWidthToHeight > widthToHeight) {
  // window width is too wide relative to desired game width
  newWidth = newHeight * widthToHeight;
  gameArea.style.height = newHeight + 'px';
  gameArea.style.width = newWidth + 'px';
} else { // window height is too high relative to desired game height
  newHeight = newWidth / widthToHeight;
  gameArea.style.width = newWidth + 'px';
  gameArea.style.height = newHeight + 'px';
}

现在您已经调整了游戏区域的宽度和高度,您需要通过在顶部(高度的一半)和左侧(宽度的一半)放置负边距来使事物居中。 请记住,CSS 已经将 gameArea div 的左上角放置在窗口的正中心,因此这会将游戏区域置于窗口的中心:

gameArea.style.marginTop = (-newHeight / 2) + 'px';
gameArea.style.marginLeft = (-newWidth / 2) + 'px';

您还想自动调整字体大小。 如果所有子元素都使用 em,则可以简单地将 gameArea div 块的 fontSize CSS 属性设置为由其大小确定的值。

gameArea.style.fontSize = (newWidth / 400) + 'em';

最后,您要使画布的绘图尺寸与其新的宽度和高度相匹配。 请注意,游戏代码的其余部分必须将游戏引擎尺寸与画布绘图尺寸分开,以适应动态画布分辨率。

var gameCanvas = document.getElementById('gameCanvas');
gameCanvas.width = newWidth;
gameCanvas.height = newHeight;

所以完成的 resize 函数可能看起来像这样:

function resizeGame() {
    var gameArea = document.getElementById('gameArea');
    var widthToHeight = 4 / 3;
    var newWidth = window.innerWidth;
    var newHeight = window.innerHeight;
    var newWidthToHeight = newWidth / newHeight;
    
    if (newWidthToHeight > widthToHeight) {
        newWidth = newHeight * widthToHeight;
        gameArea.style.height = newHeight + 'px';
        gameArea.style.width = newWidth + 'px';
    } else {
        newHeight = newWidth / widthToHeight;
        gameArea.style.width = newWidth + 'px';
        gameArea.style.height = newHeight + 'px';
    }
    
    gameArea.style.marginTop = (-newHeight / 2) + 'px';
    gameArea.style.marginLeft = (-newWidth / 2) + 'px';
    
    var gameCanvas = document.getElementById('gameCanvas');
    gameCanvas.width = newWidth;
    gameCanvas.height = newHeight;
}

现在,您希望在调整窗口大小时自动进行这些调整,或者在移动设备的情况下,更改屏幕方向。 通过让它们调用您的 resizeGame() 函数来处理这些事件,如下所示:

window.addEventListener('resize', resizeGame, false);
window.addEventListener('orientationchange', resizeGame, false);

如果窗口调整得太高或屏幕的方向是垂直的,则将宽度设置为窗口的 100%,如果窗口的大小调整得太宽或屏幕的方向为水平,则将高度设置为窗口的 100%。 剩余的尺寸根据预定的宽高比确定尺寸。

概括

Gopherwood Studios 在我们所有的 HTML5 游戏中都使用了这种结构的版本,事实证明它对于适应多种屏幕分辨率和各种移动设备非常有用。 此外,借助全屏浏览器,与许多基于浏览器的游戏相比,这为我们的网页游戏提供了更类似于传统桌面游戏的沉浸式体验。 随着 HTML5 和网络技术的不断发展,我们期待更多的网络游戏创新。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

柠檬

暂无简介

0 文章
0 评论
734 人气
更多

推荐作者

亽野灬性zι浪

文章 0 评论 0

少年亿悲伤

文章 0 评论 0

南七夏

文章 0 评论 0

qq_EJoXxu

文章 0 评论 0

17780639550

文章 0 评论 0

萌逼全场

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文