Membuat Permainan Pong di HTML5 dengan EaselJS
Indonesian (Bahasa Indonesia) translation by ⚡ Rova Rindrata (you can also view the original English article)
Dalam tutorial ini, kita akan membuat tiruan permainan klasik, Pong, di HTML5, menggunakan perpustakaan EaselJS. Permainan ini akan memiliki banyak layar, efek suara, dan lawan AI (yang sangat sederhana).
Langkah 1: Ikhtisar Singkat
Dengan menggunakan grafis pra-dibuat, kita akan mengkode permainan Pong yang menghibur di HTML5 menggunakan perpustakaan EaselJS, yang menyediakan antarmuka mirip Flash untuk kanvas HTML5. Untuk pengantar EaselJS, lihat artikel Activetuts+ ini.
Pemain akan bisa mengendalikan dayung menggunakan mouse dan bermain melawan lawan yang dikendalikan komputer untuk mendapatkan poin.
Langkah 2: Antarmuka
Antarmuka sederhana dengan gaya neo-futuristik akan digunakan; ini melibatkan banyak bentuk, tombol, bitmap dan banyak lagi.
Grafis yang dibutuhkan untuk tutorial ini dapat ditemukan di unduhan terlampir.
Langkah 3: Mendapatkan EaselJS
Perpustakaan EaselJS akan digunakan untuk membangun permainan kita, pastikan Anda membaca tutorial Getting Started jika Anda baru mengenal perpustakaan ini.
Anda bisa mengunduh versi terbaru dari EaselJS dari situs resminya. Namun, ini mungkin tidak sesuai dengan kode di sini, jadi saya sarankan untuk menggunakan versi perpustakaan yang disertakan dengan unduhan sumber.
Langkah 4: Struktur HTML
Mari kita siapkan dokumen HTML kita. Kita akan mulai dengan dasar-dasarnya, hanya garis besar barebones:
<!DOCTYPE html> <html> <head> <title>Pong</title> </head> <body> </body> </html>
Langkah 5: Menyembunyikan Sorotan Mobile
Kita juga harus menambahkan sedikit CSS juga, untuk menghapus sorotan default yang diterapkan saat Anda menyentuh elemen di browser mobile. Tanpa ini, pengalaman mobile akan menurun drastis.
<!DOCTYPE html> <html> <head> <title>Pong</title> <style>*{-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}</style> </head> <body> </body> </html>
Langkah 6: Perpustakaan Javascript
Kode berikut menambahkan perpustakaan javascript yang diperlukan agar aplikasi kita dapat bekerja.
<!DOCTYPE html> <html> <head> <title>Pong</title> <style>*{-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}</style> <script src="easel.js"></script> <script src="Tween.js"></script> <script src="sound.js"></script> <script src="Main.js"></script> </head> <body> </body> </html>/
Beserta EaselJS, kita juga akan menggunakan TweenJS (untuk menangani transisi layar dan perulangan permainan) dan SoundJS (untuk efek suara).
Main.js
adalah file yang akan kita gunakan untuk menyimpan kode JS kita sendiri.
Langkah 7: Memanggil Fungsi Utama
Pada baris berikutnya kita memanggil fungsi Main()
kita. Ini adalah fungsi yang akan memulai aplikasi kita; itu akan dibuat nanti di tutorial, di dalam Main.js
.
<!DOCTYPE html> <html> <head> <title>Pong</title> <style>*{-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}</style> <script src="easel.js"></script> <script src="Tween.js"></script> <script src="sound.js"></script> <script src="Main.js"></script> </head> <body onload="Main();"> </body> </html>
Langkah 8: Tag Canvas
Kanvas HTML5 dibuat di baris ini; kita menetapkan sebuah ID sehingga kita bisa mereferensikannya nanti dan juga mengatur lebar dan tingginya.
<!DOCTYPE html> <html> <head> <title>Pong</title> <style>*{-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}</style> <script src="easel.js"></script> <script src="Tween.js"></script> <script src="sound.js"></script> <script src="Main.js"></script> </head> <body onload="Main();"> <canvas id="Pong" width="480" height="320"></canvas> </body> </html>
Langkah 9: Membuat Main.js
Mari kita mulai pembuatan permainan kita!
Buka editor JavaScript pilihan Anda (editor teks akan bekerja, namun Anda tidak akan memiliki penyorotan sintaks) dan bersiap untuk menulis kode. Ingatlah untuk menyimpan file sebagai Main.js
di folder proyek Anda.
Langkah 10: Mendefinisikan Kanvas
Kita akan mulai dengan mendefinisikan semua variabel grafis dan logika.
Variabel berikutnya mewakili elemen canvas HTML dan tahap yang akan dikaitkan dengannya. Variabel stage akan berperilaku serupa dengan stage AS3.
/* Define Canvas */ var canvas; var stage;
Langkah 11: Latar Belakang
Variabel ini menyimpan judul gambar latar belakang.
/* Background */ var bgImg = new Image(); var bg;
Langkah 12: Tampilan Judul
Ini adalah Tampilan Judul, layar interaktif pertama yang muncul dalam permainan kita. Variabel-variabel ini menyimpan komponennya.
/* Title View */ var mainImg = new Image(); var main; var startBImg = new Image(); var startB; var creditsBImg = new Image(); var creditsB; var TitleView = new Container();
Langkah 13: Kredit
Tampilan ini akan menunjukkan kredit, tahun dan hak cipta permainan, variabel-variabel ini akan digunakan untuk menyimpannya.
/* Credits */ var creditsViewImg = new Image(); var credits;
Langkah 14: Tampilan Permainan
Variabel berikutnya menyimpan grafis individu yang muncul di Game View:
/* Game View */ var playerImg = new Image(); var player; var ballImg = new Image(); var ball; var cpuImg = new Image(); var cpu; var winImg = new Image(); var win; var loseImg = new Image(); var lose;
Langkah 15: Skor
Nilai skor akan ditangani oleh variabel-variabel berikutnya:
/* Score */ var playerScore; var cpuScore;
Langkah 16: Variabel-variabel
Ini adalah variabel yang akan kita gunakan, baca komentar di kode untuk memahami tujuan mereka:
var xSpeed = 5; //Horizontal speed of the ball var ySpeed = 5; //Vertical speed of the ball var gfxLoaded = 0; //used as a preloader, counts the already loaded items var tkr = new Object; //used as an event listener to the Ticker
Langkah 17: Membuat Efek Suara
Kita akan menggunakan efek suara untuk meningkatkan rasa permainan. Suara dalam contoh ini dibuat dengan menggunakan alat as3sfxr yang sangat bagus dan dikonversi ke MP3 menggunakan Audacity.
Suara yang dibutuhkan semuanya bisa ditemukan di unduhan sumber. Jika Anda ingin membuat sendiri, Anda memerlukan empat:
-
hit.mp3
: dimainkan saat bola menyentuh dayung -
playerScore.mp3
: dimainkan saat pemain mencetak skor -
enemyScore.mp3
: dimainkan saat musuh mencetak skor -
wall.mp3
: dimainkan saat bola menyentuh batas atas atau bawah
Langkah 18: Fungsi Main
Fungsi Main()
akan menjadi yang pertama dijalankan saat halaman web dimuat, karena dirujuk ke atribut onload
dari dokumen HTML (lihat Langkah 7).
Ini akan memanggil fungsi yang diperlukan untuk memulai permainan.
function Main() { //code... }
Langkah 19: Tautan Kanvas
Kode ini mendapatkan ID kanvas HTML dan menghubungkannya ke kelas Stage EaselJS. Ini akan membuat variabel stage berperilaku seperti kelas stage di AS3. Tambahkan ini ke Main()
.
/* Link Canvas */ canvas = document.getElementById('Pong'); stage = new Stage(canvas);
Langkah 20: Mengaktifkan Event Mouse
Event mouse dinonaktifkan secara default di EaselJS untuk meningkatkan kinerja. Karena kita membutuhkannya dalam permainan, kita tambahkan baris berikut. Tambahkan ini ke Main()
.
stage.mouseEventsEnabled = true;
Langkah 21: Memuat Suara
Kita akan menggunakan SoundJS untuk menambahkan suara pada permainan kita; tulis kode berikut untuk mengimpor suara yang akan kita gunakan. Tambahkan ini ke Main()
.
/* Sound */ SoundJS.addBatch([ {name:'hit', src:'hit.mp3', instances:1}, {name:'playerScore', src:'playerScore.mp3', instances:1}, {name:'enemyScore', src:'enemyScore.mp3', instances:1}, {name:'wall', src:'wall.mp3', instances:1}]);
Langkah 22: Memuat Grafis
Kode ini digunakan untuk pemuatan awal grafis, dengan bantuan fungsi yang akan kita tulis nanti. Ini menetapkan objek Image yang kita buat sebelumnya untuk menunjuk ke file PNG sumber yang relevan di folder dokumen kita.
Sebuah nama diberikan untuk masing-masing, jadi kita bisa mendeteksi gambar mana yang dimuat nanti, dan terakhir fungsi yang menangani gambar yang dimuat dipanggil.
Tambahkan ini ke Main()
.
/* Load GFX */ bgImg.src = 'bg.png'; bgImg.name = 'bg'; bgImg.onload = loadGfx; mainImg.src = 'main.png'; mainImg.name = 'main'; mainImg.onload = loadGfx; startBImg.src = 'startB.png'; startBImg.name = 'startB'; startBImg.onload = loadGfx; creditsBImg.src = 'creditsB.png'; creditsBImg.name = 'creditsB'; creditsBImg.onload = loadGfx; creditsViewImg.src = 'credits.png'; creditsViewImg.name = 'credits'; creditsViewImg.onload = loadGfx; playerImg.src = 'paddle.png'; playerImg.name = 'player'; playerImg.onload = loadGfx; ballImg.src = 'ball.png'; ballImg.name = 'ball'; ballImg.onload = loadGfx; cpuImg.src = 'paddle.png'; cpuImg.name = 'cpu'; cpuImg.onload = loadGfx; winImg.src = 'win.png'; winImg.name = 'win'; winImg.onload = loadGfx; loseImg.src = 'lose.png'; loseImg.name = 'lose'; loseImg.onload = loadGfx;
Langkah 23: Menetapkan Ticker
Kelas Ticker menyediakan penyiaran tick atau heartbeat terpusat pada interval yang ditentukan. Ini bisa digunakan untuk memicu perulangan permainan.
Kode berikut menetapkan frame rate menjadi 30 dan mendefinisikan stage sebagai listener untuk ticks.
Kelas TweenJS akan melakukan listen kepada tick ini untuk melakukan animasi. Tambahkan ini ke Main()
.
/* Ticker */ Ticker.setFPS(30); Ticker.addListener(stage);
Langkah 24: Fungsi Preload
Setiap kali grafik dimuat fungsi ini akan berjalan. Ini akan menugaskan setiap gambar ke objek bitmap dan memeriksa apakah semua elemen dimuat sebelum melanjutkan.
function loadGfx(e) { if(e.target.name = 'bg'){bg = new Bitmap(bgImg);} if(e.target.name = 'main'){main = new Bitmap(mainImg);} if(e.target.name = 'startB'){startB = new Bitmap(startBImg);} if(e.target.name = 'creditsB'){creditsB = new Bitmap(creditsBImg);} if(e.target.name = 'credits'){credits = new Bitmap(creditsViewImg);} if(e.target.name = 'player'){player = new Bitmap(playerImg);} if(e.target.name = 'ball'){ball = new Bitmap(ballImg);} if(e.target.name = 'cpu'){cpu = new Bitmap(cpuImg);} if(e.target.name = 'win'){win = new Bitmap(winImg);} if(e.target.name = 'lose'){lose = new Bitmap(loseImg);} gfxLoaded++; if(gfxLoaded == 10) // remember to change this if you add more images { addTitleView(); } }
Langkah 25: Menambahkan Judul Tampilan
Saat semua grafis dimuat, Title View ditambahkan ke atas panggung dengan fungsi berikut:
function addTitleView() { startB.x = 240 - 31.5; startB.y = 160; startB.name = 'startB'; creditsB.x = 241 - 42; creditsB.y = 200; TitleView.addChild(main, startB, creditsB); stage.addChild(bg, TitleView); stage.update();
Langkah 26: Listener Tombol Mulai
Fungsi ini menambahkan listener yang diperlukan ke tombol TitleView (ini adalah bagian dari addTitleView()
):
startB.onPress = addGameView; creditsB.onPress = showCredits; }
Langkah 27: Menampilkan Credits
Layar Credits ditampilkan saat pengguna mengklik tombol credits; listener mouse ditambahkan ke gambar penuh untuk menghapusnya.
function showCredits() { // Show Credits credits.x = 480; stage.addChild(credits); stage.update(); Tween.get(credits).to({x:0}, 300); credits.onPress = hideCredits; }
Langkah 28: Menyembunyikan Kredit
Saat layar Credits diklik maka akan di-tween kembali dan dihapus dari atas stage.
// Hide Credits function hideCredits(e) { Tween.get(credits).to({x:480}, 300).call(rmvCredits); } // Remove Credits function rmvCredits() { stage.removeChild(credits); }
Mari kita berhenti di sini untuk menguji apa yang telah kita lakukan sejauh ini. Klik di sini untuk demo milestone.
Ingatlah bahwa beberapa baris telah dikomentari karena beberapa fungsi belum dibuat.
Ingat bahwa milestone disertakan dalam file sumber, jadi jika karena alasan tertentu file Anda tidak meniru yang ini, bandingkan sumber Anda dengan milik saya untuk melihat apa yang bisa menyebabkannya.
Langkah 29: Menampilkan Tampilan Permainan
Baris berikut menghapus TitleView dari atas stage dan menambahkan item GameView ke atas stage. Listener mouse ditambahkan ke latar belakang, untuk memulai permainan saat diklik.
function addGameView() { // Destroy Menu & Credits screen stage.removeChild(TitleView); TitleView = null; credits = null; // Add Game View player.x = 2; player.y = 160 - 37.5; cpu.x = 480 - 25; cpu.y = 160 - 37.5; ball.x = 240 - 15; ball.y = 160 - 15; // Score playerScore = new Text('0', 'bold 20px Arial', '#A3FF24'); playerScore.maxWidth = 1000; //fix for Chrome 17 playerScore.x = 211; playerScore.y = 20; cpuScore = new Text('0', 'bold 20px Arial', '#A3FF24'); cpuScore.maxWidth = 1000; //fix for Chrome 17 cpuScore.x = 262; cpuScore.y = 20; stage.addChild(playerScore, cpuScore, player, cpu, ball); stage.update(); // Start Listener bg.onPress = startGame; }
Langkah 30: Gerakan Pemain
Pemain akan bergerak seiring dengan posisi vertikal mouse:
function movePaddle(e) { // Mouse Movement player.y = e.stageY; }
Langkah 31: Memulai Permainan
Kode ini berjalan saat pemain mengklik latar belakang permainan, ia menambahkan listener mouse yang memicu fungsinya pada langkah sebelumnya, dan menambahkan Ticker untuk mengendalikan perulangan permainan.
Perhatikan cara ticker dibuat: ini setara dengan event Timer di AS3.
function startGame(e) { bg.onPress = null; stage.onMouseMove = movePaddle; Ticker.addListener(tkr, false); tkr.tick = update; }
Langkah 32: Reset
Bila ada yang mencetak gol (oleh pemain atau komputer), dayung dan bola akan kembali ke posisi semula dan permainan akan dihentikan sementara:
function reset() { ball.x = 240 - 15; ball.y = 160 - 15; player.y = 160 - 37.5; cpu.y = 160 - 37.5; stage.onMouseMove = null; //stop listening to the mouse Ticker.removeListener(tkr); //pause the game bg.onPress = startGame; }
Langkah 33: Pergerakan Bola
Jika permainan tidak dijeda, bola akan dipindahkan setiap frame dengan menggunakan variabel yang telah kita buat sebelumnya.
function update() { // Ball Movement ball.x = ball.x + xSpeed; ball.y = ball.y + ySpeed;
Langkah 34: Pergerakan CPU
Kode ini mengendalikan gerakan komputer; dayung dipindahkan dengan cara yang akan mengikuti bola sambil tetap memiliki beberapa batas kesalahan.
if(cpu.y < ball.y) { cpu.y = cpu.y + 2.5; } else if(cpu.y > ball.y) { cpu.y = cpu.y - 2.5; }
Langkah 35: Tabrakan Tembok
Di sini kita periksa apakah bola berada di batas atas atau bawah kanvas; jika demikian, kecepatan vertikal dibalik dan suara diputar.
if((ball.y) < 0) { ySpeed = -ySpeed; SoundJS.play('wall');};//Up if((ball.y + (30)) > 320) { ySpeed = -ySpeed; SoundJS.play('wall');};//down
Langkah 36: Skor
Sekarang sisi kiri dan kanan. Kode ini juga memodifikasi skor, memanggil fungsi reset dan memainkan suara yang berbeda tergantung pada sisi yang disentuh bola.
/* CPU Score */ if((ball.x) < 0) { xSpeed = -xSpeed; cpuScore.text = parseInt(cpuScore.text + 1); reset(); SoundJS.play('enemyScore'); } /* Player Score */ if((ball.x + (30)) > 480) { xSpeed = -xSpeed; playerScore.text = parseInt(playerScore.text + 1); reset(); SoundJS.play('playerScore'); }
Langkah 37: Tabrakan Bola-Dayung
Kode berikut memeriksa apakah bola bertabrakan dengan dayung, dengan membandingkan posisi dayung dengan koordinat bola. Jika kotak pembatas keduanya berpotongan, ada tabrakan, jadi kita membalikkan kecepatan x bola dan memainkan suara.
/* Cpu collision */ if(ball.x + 30 > cpu.x && ball.x + 30 < cpu.x + 22 && ball.y >= cpu.y && ball.y < cpu.y + 75) { xSpeed *= -1; SoundJS.play('hit'); } /* Player collision */ if(ball.x <= player.x + 22 && ball.x > player.x && ball.y >= player.y && ball.y < player.y + 75) { xSpeed *= -1; SoundJS.play('hit'); }
Langkah 38: Periksa Win/Game Over
Anda dapat memodifikasi kondisi akhir pada baris berikutnya - ini diatur menjadi 10 poin secara default.
/* Check for Win */ if(playerScore.text == '10') { alert('win'); } /* Check for Game Over */ if(cpuScore.text == '10') { alert('lose'); }
Langkah 39: Peringatan
Fungsi ini akan menghentikan permainan dan menunjukkan peringatan, isinya yang bergantung pada hasil permainan.
function alert(e) { Ticker.removeListener(tkr); stage.onMouseMove = null; bg.onPress = null if(e == 'win') { win.x = 140; win.y = -90; stage.addChild(win); Tween.get(win).to({y: 115}, 300); } else { lose.x = 140; lose.y = -90; stage.addChild(lose); Tween.get(lose).to({y: 115}, 300); } }
Langkah 40: Pengujian
Simpan pekerjaan Anda (jika belum) dan buka file HTML di browser untuk melihat permainan Anda bekerja!
Kesimpulan
Cobalah memodifikasi variabel-variabel permainan untuk membuat versi permainan Anda sendiri!
Saya harap Anda menyukai tutorial ini, terima kasih telah membaca!