소개
2010년 여름, 휴대전화용 HTML5 게임 대회에 참가하기 위해 Sand Trap이라는 게임을 만들었습니다. 하지만 대부분의 휴대전화는 게임의 일부만 표시하거나 게임이 너무 작아서 플레이할 수 없었습니다. 따라서 모든 해상도에 맞게 게임이 원활하게 조정되도록 했습니다. 약간의 재프로그래밍과 이 도움말에 설명된 아이디어를 사용한 결과, 데스크톱에서 실행되든 휴대기기에서 실행되든 모든 최신 브라우저에서 확장되는 게임을 만들었습니다.


이 접근 방식은 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픽셀로 시작합니다. 캔버스는 전체 게임 영역을 덮고 있으며, 반투명 통계 패널은 그림 1과 같이 하단을 따라 24픽셀 높이로 표시됩니다.

이러한 값을 비율로 변환하면 캔버스의 너비와 높이가 100%가 됩니다 (창이 아닌 gameArea의 너비와 높이). 24를 300으로 나누면 통계 패널의 높이가 8%가 되며, 경기 영역의 하단을 가리키므로 너비도 100%가 됩니다(그림 2 참고).

이제 게임 영역과 하위 요소의 크기를 결정했으므로 다음과 같이 두 내부 요소의 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과 같이 게임이 화면을 세로로 채울지 아니면 가로로 채울지 결정할 수 있습니다.

원하는 게임 영역 모양이 창 모양보다 넓고 높이가 더 짧은 경우 창을 가로로 채우고 상단과 하단에 여백을 두어야 합니다. 마찬가지로 원하는 게임 영역 도형이 창의 도형보다 높고 너비가 더 좁은 경우 창을 세로로 채우고 왼쪽과 오른쪽에 여백을 두어야 합니다.
이렇게 하려면 현재 창의 너비-높이 비율을 사용하여 원하는 너비-높이 비율을 테스트하고 다음과 같이 적절하게 조정합니다.
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;
따라서 완성된 크기 조절 함수는 다음과 같이 표시될 수 있습니다.
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와 웹 기술이 계속 발전함에 따라 웹 게임에서 더 많은 혁신이 이루어지기를 기대합니다.