HTML5 Canvas: Sprite Animation and Game Physics
HTML5 Canvas: Animasi Sprite dan Fisika Game
Setelah kita paham Game Loop, manajemen Input, serta teknik memutar Transformasi kanvas, ini saatnya menggunakan kode pamungkas untuk menggabungkan semuanya secara bersamaan. Mari kita bedah struktur fondasi dari Player Class / Kelas Jagoan berdasarkan cuplikan kodingan game berstandar produksi nyata (production code). Kita akan menghidupkan hukum Gravitasi agar karakter bisa melompat, sekaligus menggunakan sistem transisi Animasi Gambar Sprite bersambung!
1. Mempersiapkan Koleksi Aset Ekstensif
Lupakan menggambar kotak kaku. Game asli wajib memainkan gambar berderet (mirip film animasi tradisional frame-by-frame). Gambar-gambar tersebut kita muat dalam RAM lalu dan dikelompokkan ke array berdasarkan Status Aktif emosinya (seperti kumpulan frame Idle, frame saat mundur MoveBackward, saat melompat Jump).
// Fungsi pembantu perakit objek DOM <img /> murni
function loadImg(src) {
const img = new Image();
img.src = src;
return img;
}
// Menghimpun array besar gambar dengan ketepatan file numbering
function loadImagePlayer(country) {
const ImageState = { Idle: [], Jump: [], MoveForward: [] /* ... */ };
// Contoh: Menyedot 18 potong frame terpisah untuk Animasi Nafas/Diam (Idle)
for (let i = 0; i <= 17; i++) {
// Trik Cerdas: String(i).padStart(2, "0") otomatis menyulap angka 1 menjadi teks "01"
ImageState.Idle.push(loadImg(`./Sprites/Characters/${country}/Idle/Idle_0${String(i).padStart(2, "0")}.png`));
}
return ImageState;
}
2. Paradigma Kelas Pembungkus Organ Tubuh(Player Class)
Membungkus kode entitas dalam OOP Paradigma JavaScript class adalah tata cara teraman di jagad pembuatan game. Si Karakter (Objek) setidaknya harus mengingat perihal letak lokasi keberadaannya (x, y), variabel laju luncurannya (dx, dy), pemutar slide frame yang terputar (frame, state), serta massa hukum gravitasi beban tubuh (speed, gravity).
class Player {
constructor(country, position, ctx) {
this.ctx = ctx; // kanvas layar referensi
this.position = position; // Dari pihak "left" atau "right"?
this.image = loadImagePlayer(country);
// Dimensi dan Hukum Dunia
this.size = 150;
this.x = position === "left" ? 300 : 600; // Alokasi pijakan start base awal
this.y = 0;
this.dy = 0; // Delta Y: Kekuatan Tarik Turun/Keatas (Momentum Vertical)
this.gravity = 0.2; // Tambahan berat badan yang menarik konstan jatuh ke bawah
// Ingatan Mesin Status Animasi saat ini (State machine)
this.state = "Idle";
this.frame = 0; // Penentu gambar keberapa yg wajib digambar dari array nya
this.lastAnimate = Date.now(); // Stopwatch Delay laju putar Animasi (pacing kontroler)
}
}
3. Penerapan Ilmu Fisika: Gravitasi & Lemparan Bebas
Konsep simulasi gravitasi sungguh brilian dan tak terduga! Di dalam update(), variabel momentum tubuh vertikal this.dy terus menerus ditambah nilainya setiap Frame oleh variabel beban konstan this.gravity. Oleh karenanya badannya senantiasa terdorongan turun semakin jatuh!
Kecuali ia menabrak daratan (groundLevel). Sewaktu kakinya persis menyentuh tanah, perhitungan Gravitasi seketika ter-reset hangus menjadi nol (dy = 0). Tapii apabila ia membentur tombol Jump saat berpijak di dasar itu? Kita langsung jejalkan suntikan angka lemparan Ke atas bertolak keras (- Minus) pada dy (dy = -8), membuatnya sejenak melambung melawan gravitasi layaknya rudal roket terbang sesaat menyentuh angkasa!
update() {
this.prevState = this.state; // Recall ingatan di masa lalu memonitor pergantian aksi layar
const groundLevel = canvas.height - this.size - 90; // Kalkulasikan ketinggian batas tapak Lantai mutlak
// Cek apakah sol sepatu `Y` nya tembus ke garis Tanah bumi?
const onGround = this.y >= groundLevel;
if (onGround) {
this.y = groundLevel; // Paksa Posisi menempel sejajar di aspal (Anti-Glitch tembus lantai layar mati masuk neraka)
this.dy = 0; // Matikan Beban Daya Tumbuk Jatuhnya
// Trigger MELEDAKKAN Lompatan
if (this.keys["arrowup"]) {
this.dy = -8; // Tembakkan Rudal daya roket berakselerasi Ke-atas instan!
}
} else {
// Jika nyatanya masih Melayang Udara, izinkan rantai hukum grafitasi mencekiknya memeras kekuatannya untuk jatuh ke tanah terus menerus tiap sekian MS
this.dy += this.gravity;
}
// Akhirnya suntikan Total Akumulasi kalkulasi Vertikal (dy), mendarat dan mencemari Angka Titik Pijakan Lokasi Aslinya (y)
this.y += this.dy;
// STATE MACHINE : Mesin Pendiktean Pergolakan Penggantian Aksi
if (this.y < groundLevel) this.state = "Jump";
else if (this.keys["space"]) this.state = "Kick";
else if (this.keys["arrowright"]) this.state = "MoveForward";
else this.state = "Idle";
// Mekanisme Keamanan: Reset Auto-rewind penggulungan slide video kembali ke file img indeks '0' ketika pergantian antar Gerak Tiba (spti diam tau2 lompat)
if (this.prevState !== this.state) this.frame = 0;
}
4. Render Animasi Frame Beruntun & Pemantulan Cermin Otomatis Kaca Tim
Keahlian terakhir metode core tersembunyi Sang Jagoan berada di animate(). Skrip ini menggunakan logika cerdas pembatas Timer rentang pias Waktu (Date.now()). Laju delay perulangan antar gambar dimanipulasi dengan batas angka "lebih dari 50 Milikdetik" supaya framenya tertahan ganti secara rasional. Bila limit ini tidak di rem, maka 18 frame tendangan animasimu akan habis secepat panah dalam wujud "Seper Enam-Puluh" (1/60) detik di layar monitor! Manusia tidak akan menyadarinya.
Dan Terakhir, mari gunakan materi Transformasi Flip (Minus Scala 1) yang baru saja diajarkan untuk Player pihak sebelah Tim Kanan (position === "right"). Daripada kerepotan melukis manual karakter dengan gambar pose menghindar mengarah sebaliknya hadap kiri, kita cukup menyuruh Program melakukan Rotasi pencerminan dimensi koordinat ctx.scale(-1, 1) sesaat sebelum nge-print (drawImage) ke hadap Tim Sang Pemain Kiri Musuhnya.
animate() {
// Intip Array Koleksi Foto yang aktif saat Status Animainya di call ini
const KumpulanGambarAnimasiAktif = this.image[this.state];
const jamSkrg = Date.now();
// Gembok Stopwatch: Frame Tayang slide gambar selanjutnya HANYA tergeser apabila Waktu sudah terdiam berjaraknya melewati 50ms
if (jamSkrg - this.lastAnimate > 50) {
this.frame++; // Geser penunjuk slider ke Next Nomor gambar
// Gulung pemutar klise gambar jadi 0, persis sama saat Film animasinya habis tak tersisa
if (this.frame >= KumpulanGambarAnimasiAktif.length) this.frame = 0;
this.lastAnimate = jamSkrg;
}
// Trik Pembalikan Kaca Cermin Ekslusif Hanya untuk Pemain Posisi Markas "Kanan" Lapangan
if (this.position === "right") {
this.ctx.save();
// Pusat Geser pindah tembus menjarah ke sayap depan titik x Character supaya orientasi cermin tdk ngawur
this.ctx.translate(this.x + this.size, this.y);
this.ctx.scale(-1, 1); // Flip Putaran Bayangan Cermin Horizontal 180 Drajat Mutlak!
this.ctx.drawImage(
this.image[this.state][this.frame], // Pilih selambar spesifik file gambar index persis sesuai penempatannya.
0, 0, this.size, this.size
);
this.ctx.restore(); // Amankan ruang Kanvas kembali. Lepas bayangannya
} else {
// Menggambar Normal Biasa untuk kubu Pemain di sisi Kiri Lapangan yang emang fitrahnya aslinya tergambar menghadap arah kanan
this.ctx.drawImage(
this.image[this.state][this.frame],
this.x, this.y, this.size, this.size
);
}
}
Bila dinaluri sedalam mungkin, arsitektur pattern di dalam file OOP kelas ini adalah Masterpiece mutlak dalam pembentukan hampir di seluruh kodingan dari game model tarung pertarungan (Fight/Brawler), mapun Loncat-Loncatan Platform klasik Mario, Megaman yang ada belahan game manapun di muka dunia! Terus asah logika insting pengkodean keren hebat tersebut!