簡介
2010 年夏季,我們打造了 Sand Trap 這款手機遊戲,並參與智慧型手機 HTML5 遊戲競賽。但大多數手機都只展示部分遊戲,就是尺寸過小,因此完全無法玩遊戲。因此,我們自行挑選出合適的遊戲尺寸,讓遊戲能夠流暢地配合各種解析度調整。我們稍微重新設計了遊戲程式,並運用本文所述的構想後,成功打造出一款適用於各種新型瀏覽器的遊戲,無論是在電腦或行動裝置上執行都沒問題。
這個做法非常適合 Sand Trap,因此我們最新的遊戲《Twack!》也採用相同的做法。遊戲會自動調整螢幕解析度,以符合全螢幕和自訂大小的視窗,如以下螢幕截圖所示。
導入這段程式碼必須同時善用 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 所示。
將這些值轉譯為百分比後,畫布寬度會變為 100%,高度為 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;
}
現在,您希望在每次重新調整視窗大小時,或 (行動裝置) 的螢幕方向改變時,自動做出這些調整。讓這些事件呼叫 sizeGame() 函式以處理這些事件,如下所示:
window.addEventListener('resize', resizeGame, false);
window.addEventListener('orientationchange', resizeGame, false);
如果調整視窗大小過高或螢幕方向為直向,則表示視窗寬度已增加 100%,如果視窗縮小了寬度,或是螢幕方向為橫向,高度就會佔視窗的 100%。剩餘的尺寸將根據預先定義的寬高長寬比進行調整。
摘要
Gopherwood Studios 在所有 HTML5 遊戲中都採用這種架構,而且在支援多種螢幕解析度和各種行動裝置時非常實用。此外,由於我們支援全螢幕瀏覽器,因此網頁遊戲的沉浸式體驗比傳統桌面遊戲來得有別,而非許多瀏覽器遊戲。隨著 HTML5 和網頁技術持續發展,我們期許能創造更多網路遊戲的創新成果。