Studi Kasus - Mengubah Ukuran Game HTML5 Secara Otomatis

Derek Detweiler
Derek Detweiler

Pengantar

Pada musim panas tahun 2010, kami membuat Sand Trap, game yang kami masukkan dalam kompetisi di game HTML5 untuk ponsel. Namun, sebagian besar ponsel hanya menampilkan sebagian game atau membuat game terlalu kecil sehingga benar-benar tidak dapat dimainkan. Jadi kami memutuskan untuk membuat game menyesuaikan dengan lancar agar sesuai dengan resolusi apa pun. Setelah sedikit memprogram ulang dan menggunakan ide yang diuraikan dalam artikel ini, kami memiliki game yang diskalakan dengan semua browser modern, baik itu berjalan di desktop atau perangkat seluler.

Screenshot layar penuh thwack
screenshot jendela browser yang lebih kecil

Pendekatan ini sangat cocok untuk Sand Trap, jadi kami menggunakan metode yang sama pada game terbaru kami, Thwack!. Game secara otomatis menyesuaikan resolusi layar agar sesuai dengan jendela layar penuh dan berukuran kustom, seperti yang ditunjukkan pada screenshot di bawah.

Penerapan ini diperlukan dengan memanfaatkan CSS dan JavaScript. Menggunakan CSS untuk mengisi seluruh layar adalah hal yang mudah, tetapi CSS tidak memungkinkan Anda mempertahankan rasio lebar tinggi yang sama untuk mencegah perluasan kanvas dan area game. Di situlah JavaScript berperan. Anda dapat menskalakan ulang elemen dokumen dengan JavaScript dan memicu perubahan ukuran pada peristiwa jendela.

Mempersiapkan Halaman

Langkah pertama adalah menentukan area di halaman tempat game akan berlangsung. Jika Anda menyertakannya sebagai blok div, Anda dapat menempatkan tag lain atau elemen kanvas di dalamnya. Jika disiapkan dengan benar, elemen turunan ini akan mewarisi penskalaan blok div induk.

Jika Anda memiliki dua bagian area game, yaitu area bermain dan area pencatatan skor, tampilannya mungkin terlihat seperti ini:

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

Setelah memiliki struktur dokumen dasar, Anda dapat memberikan beberapa properti CSS untuk elemen ini agar dapat diubah ukurannya. Banyak properti CSS untuk “gameArea” dimanipulasi langsung oleh JavaScript, tetapi agar dapat berfungsi, siapkan beberapa properti CSS lainnya yang dimulai dengan blok div gameArea induk:

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

Cara ini menempatkan sudut kiri atas kanvas di tengah layar. Fungsi ubah ukuran otomatis JavaScript yang dijelaskan di bagian berikutnya memanipulasi properti CSS tambahan untuk mengubah ukuran area game dan memusatkannya di jendela.

Karena area game secara otomatis diubah ukurannya sesuai dengan dimensi jendela, Anda tidak ingin dimensinya dalam piksel untuk elemen turunan blok div gameArea; sebagai gantinya, Anda menginginkannya dalam persentase. Nilai piksel tidak memungkinkan elemen dalam diskalakan dengan div induk karena elemen tersebut berubah. Namun, akan sangat membantu untuk memulai dengan piksel dan kemudian mengubahnya menjadi persentase setelah Anda memiliki tata letak yang Anda sukai.

Untuk contoh ini, mulailah dengan area permainan yang memiliki tinggi 300 piksel dan lebar 400 piksel. Kanvas mencakup seluruh area game, dan panel statistik semi-transparan berada di sepanjang bagian bawah dengan tinggi 24 piksel, seperti yang ditunjukkan pada Gambar 1.

Dimensi elemen turunan gameArea dalam piksel
Gambar 1: Dimensi elemen turunan gameArea dalam piksel

Menerjemahkan nilai-nilai ini ke persentase membuat lebar kanvas menjadi 100% dan tinggi 100% (dari gameArea, bukan jendela). Membagi 24 dengan 300 memberikan ketinggian panel statistik pada 8%, dan, karena itu akan menutupi bagian bawah area permainan, lebarnya juga akan menjadi 100%, seperti yang terlihat pada Gambar 2.

Dimensi elemen turunan gameArea dalam persentase
Gambar 2: Dimensi elemen turunan gameArea dalam persentase

Setelah menentukan dimensi area game dan elemen turunannya, Anda dapat menyatukan properti CSS untuk dua elemen di dalamnya sebagai berikut:

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

Mengubah Ukuran Game

Sekarang Anda siap membuat fungsi untuk menangani jendela yang diubah ukurannya. Pertama, ambil referensi ke elemen dokumen gameArea induk.

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

Karena Anda tidak mengkhawatirkan lebar atau tinggi yang tepat, informasi berikutnya yang perlu Anda setel adalah rasio lebar atau tinggi. Menggunakan referensi Anda sebelumnya tentang area permainan dengan lebar 400 piksel dan tinggi 300 piksel, Anda tahu bahwa Anda ingin mengatur rasio aspek pada lebar 4 unit dan tinggi 3 unit.

var widthToHeight = 4 / 3;

Karena fungsi ini dipanggil setiap kali jendela diubah ukurannya, Anda juga perlu mengambil dimensi baru jendela agar dapat menyesuaikan dimensi game agar sesuai. Temukan ini dengan menggunakan properti innerWidth dan innerHeight jendela.

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

Sama seperti menentukan rasio lebar ke tinggi yang Anda inginkan, kini Anda dapat menentukan rasio lebar terhadap tinggi jendela saat ini:

var newWidthToHeight = newWidth / newHeight;

Tindakan ini memungkinkan Anda memutuskan apakah akan membuat game mengisi layar secara vertikal atau horizontal, seperti yang ditunjukkan di Gambar 3.

Menyesuaikan elemen gameArea ke jendela dengan tetap mempertahankan rasio aspek
Gambar 3: Menyesuaikan elemen gameArea ke jendela dengan tetap mempertahankan rasio aspek

Jika bentuk area permainan yang diinginkan lebih lebar dari bentuk jendela (dan tingginya lebih pendek), Anda harus mengisi jendela secara horizontal dan menyisakan margin di sepanjang bagian atas dan bawah. Demikian pula, jika bentuk area game yang diinginkan lebih tinggi dari bentuk jendela (dan lebarnya lebih sempit), Anda harus mengisi jendela secara vertikal dan menyisakan margin di sepanjang kiri dan kanan.

Untuk melakukannya, uji rasio lebar ke tinggi yang diinginkan dengan rasio lebar terhadap tinggi jendela saat ini dan buat penyesuaian yang sesuai sebagai berikut:

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

Setelah menyesuaikan lebar dan tinggi area game, Anda perlu memusatkan semuanya dengan menempatkan margin negatif di bagian atas yang merupakan setengah dari tinggi dan di sebelah kiri yang berukuran setengah dari lebar tersebut. Ingat bahwa CSS sudah menempatkan pojok kiri atas div gameArea tepat di tengah jendela, sehingga area game dipusatkan di jendela:

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

Anda juga perlu menyesuaikan ukuran font secara otomatis. Jika Anda memiliki semua elemen turunan menggunakan em, Anda cukup menyetel properti CSS fontSize dari blok div gameArea ke nilai yang ditentukan oleh ukurannya.

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

Terakhir, Anda ingin membuat dimensi gambar kanvas sesuai dengan lebar dan tingginya yang baru. Perhatikan bahwa kode game lainnya harus menjaga dimensi game engine terpisah dari dimensi gambar kanvas untuk mengakomodasi resolusi kanvas dinamis.

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

Jadi fungsi ubah ukuran yang selesai mungkin terlihat seperti ini:

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

Sekarang, Anda ingin penyesuaian ini dibuat secara otomatis setiap kali jendela diubah ukurannya atau, untuk perangkat seluler, orientasi layar diubah. Tangani peristiwa ini dengan meminta mereka memanggil fungsi resizeGame() seperti:

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

Jika ukuran jendela terlalu tinggi atau orientasi layar vertikal, Anda membuat lebar jendela 100%, dan jika ukuran jendela diubah terlalu lebar atau orientasi layar horizontal, berarti Anda membuat tinggi 100% jendela. Dimensi yang tersisa diubah ukurannya sesuai dengan rasio aspek lebar ke tinggi yang telah ditentukan.

Ringkasan

Gopherwood Studios telah menggunakan versi struktur ini untuk semua game HTML5 kami dan terbukti sangat berguna untuk mengakomodasi berbagai resolusi layar dan berbagai perangkat seluler. Selain itu, dengan bantuan browser layar penuh, permainan web kami memberikan pengalaman mendalam yang lebih mirip dengan game desktop tradisional daripada game berbasis browser lainnya. Kami berharap semakin banyak inovasi dalam game web seiring perkembangan teknologi HTML5 dan web.