案例研究 能自动调整大小的 HTML5 游戏
2010 年夏天,我们创建了 Sand Trap,这是一款我们参加的手机 HTML5 游戏竞赛。 但大多数手机要么只显示游戏的一部分,要么让游戏变得太小——使其完全无法玩。 所以我们自己决定让游戏流畅地调整以匹配任何分辨率。 经过一些重新编程和使用本文中概述的想法后,我们有了一款可以在任何现代浏览器上扩展的游戏,无论它是在台式机还是移动设备上运行。
这种方法对 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论