Membekali diri dengan matematika di balik setiap game: vektor untuk posisi & arah, matriks untuk transform, sistem koordinat, dan collision detection, lalu mengimplementasikan physics sederhana untuk Rimba Runner tanpa bergantung penuh pada engine

Setiap perintah gerak yang kalian tulis di episode 3-6 — move_and_slide(), rb.velocity, AddMovementInput — bekerja di atas satu bahasa universal: matematika vektor dan fisika. Game developer yang paham matematika ini tidak akan kebingungan saat engine tidak melakukan apa yang diinginkan, karena ia bisa menghitung sendiri.
Episode ini bukan pelajaran matematika abstrak — kita hubungkan setiap konsep langsung ke kode game. Vektor untuk posisi dan arah, matriks untuk transform, sistem koordinat, lalu collision detection dan implementasi physics sederhana untuk Rimba Runner. Target akhirnya: kalian bisa menjelaskan apa yang engine lakukan saat karakter bergerak.
Vektor adalah nilai yang punya arah dan besar (magnitude). Dalam game 2D, vektor posisi (x, y) memberitahu di mana objek berada; vektor kecepatan memberitahu ke mana dan seberapa cepat ia bergerak. Operasi dasar yang dipakai setiap saat:
posisi_baru = posisi + velocity * dt — memindahkan objek (kita sudah pakai ini di episode 2).a.x * b.x + a.y * b.y — hasilnya angka; dipakai untuk mengukur "seberapa searah" dua vektor. Contoh: mendeteksi apakah musuh di depan pemain (dot product arah menghadap vs arah ke musuh lebih besar dari 0).Panjang vektor (magnitude) dihitung dengan rumus Pythagoras:
|v| = sqrt(v.x^2 + v.y^2)Contoh pemakaian nyata: menembakkan peluru ke arah target. Ambil vektor dari pemain ke target, normalisasi, kalikan dengan kecepatan peluru:
func shoot_to(target: Vector2) -> void:
var dir := (target - global_position).normalized()
bullet.velocity = dir * bullet_speedMatriks adalah cara kompak menyimpan dan menggabungkan transformasi: translate (pindah), rotate (putar), dan scale (skala). Engine menyimpan setiap Transform (posisi, rotasi, skala) sebagai matriks, dan menerapkannya ke setiap titik pada model.
Konsep penting yang harus dipahami:
Transform — kecuali saat debugging transform yang aneh, pemahaman urutan ini menyelamatkan.AddMovementInput(GetActorForwardVector(), ...) di episode 5 memakai ini: bergerak ke arah hadap karakter, bukan arah absolut dunia.Kalian tidak perlu mengalikan matriks manual — engine menyediakannya. Yang wajib adalah memahami apa yang terjadi, agar bisa mendiagnosis: "kenapa sprite anak ikut miring saat parent berotasi?" Jawabannya: transformasi child dihitung relatif ke transform parent.
Setiap engine punya konvensi sumbu:
| Engine | Arah Y ke atas? | Sumbu kedalaman |
|---|---|---|
| Unity 2D | Ya (Y ke atas) | Z untuk sorting |
| Godot 2D | Ya (Y ke bawah) | Z untuk sorting |
| Unreal 3D | Ya (Z ke atas) | Konvensi left-handed |
Perbedaan paling sering membuat bingung: di Godot 2D, Y positif mengarah ke bawah (seperti layar); di Unity 2D, Y positif ke atas. Saat pindah engine, cek dulu arah sumbu — bug "karakter melompat ke bawah" biasanya dari sini.
Collision detection menjawab: "apakah dua objek saling tumpang tindih?" Engine memakai collider (bentuk, bukan gambar) untuk efisiensi. Dua pendekatan dasar:
AABB (Axis-Aligned Bounding Box) — kotak sejajar sumbu. Cek tumpang tindih per sumbu:
func overlaps_aabb(a_min: Vector2, a_max: Vector2, b_min: Vector2, b_max: Vector2) -> bool:
return (a_min.x < b_max.x and a_max.x > b_min.x and
a_min.y < b_max.y and a_max.y > b_min.y)AABB sangat cepat, itulah mengapa collider berbentuk kotak jadi standar. Circle collision hampir semudah itu: tumpang tindih jika jarak pusat lebih kecil dari jumlah jari-jari.
Triggers vs solid — engine membedakan dua perilaku: collider solid (menghalangi gerakan, misal lantai) dan trigger (hanya melaporkan tumpang tindih tanpa menghalangi, misal zona buah). Di episode 3-4 kita memakai keduanya: BoxCollider2D solid untuk ground, Area2D sebagai trigger untuk buah.
Engine menangani physics lengkap (Rigidbody, gravitasi, tabrakan) — tapi memahami inti integrasi gerak membuat kalian bisa menerapkan physics kustom kapan pun dibutuhkan. Fisika dasar untuk objek dengan gravitasi:
const GRAVITY := 980.0
var position := Vector2.ZERO
var velocity := Vector2.ZERO
func step(delta: float) -> void:
velocity.y += GRAVITY * delta # gravitasi mempercepat
position += velocity * delta # kecepatan menggerakkan posisiMetode ini dikenal sebagai integration step — setiap frame, kecepatan diperbarui dari percepatan, posisi dari kecepatan. Engine menggunakan algoritma lebih canggih (semi-implicit Euler) dengan langkah tetap (fixed timestep) agar deterministik, persis alasan kita membedah fixed update di episode 2.
Tip
Untuk pendalaman visual yang luar biasa, buka Red Blob Games (redblobgames.com) — terutama artikel tentang collision detection, pathfinding, dan matematika game. Ini salah satu referensi terbaik yang ada untuk matematika game, dan akan kita rujuk lagi di episode 10 dan 24.
Matematika bukan PR sekolah — ia adalah bahasa sehari-hari game developer.
Inti yang harus dibawa pulang:
Di episode 8 selanjutnya kita akan menyentuh lapisan yang langsung dirasakan pemain: UI & UX game — HUD, menu, UI toolkit, dan prinsip UX game, lengkap dengan membangun antarmuka Rimba Runner. Sampai jumpa di episode 8!