Belajar Game Developer - Gameplay Programming
Episode 6 of 28

Belajar Game Developer - Gameplay Programming

Masuk ke inti profesi game developer: merancang player controller, input handling, dan game mechanics yang terasa enak dimainkan, lalu membangun gameplay loop Rimba Runner yang utuh — lompat, lari, kumpulkan buah, dan hindari rintangan

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Tiga episode terakhir mengenalkan kalian pada tiga engine. Mulai episode ini, kita fokus pada hal yang membedakan game developer dari sekadar "orang yang tahu engine": gameplay programming — seni menerjemahkan aturan desain menjadi mekanik yang benar-benar terasa enak di tangan pemain.

Gameplay programming adalah jantung peran game developer. Di sinilah keputusan desain ("lompatan harus terasa ringan dan responsif") bertemu dengan kode (jumpVelocity = 12), dan di sanalah game dirasakan benar-benar menyenangkan atau justru frustasi. Kita bangun gameplay loop Rimba Runner yang utuh: lari, lompat ganda, mengumpulkan buah, dan bertabrakan dengan rintangan.

Input Handling: Aksi, Bukan Tombol

Pitfall klasik pemula: menulis kode yang terikat langsung ke tombol tertentu, misalnya if (Input.GetKeyDown(KeyCode.Space)). Masalahnya, pemain ingin remapping kontrol, dan game harus jalan di keyboard, gamepad, dan layar sentuh. Solusi industrinya: abstract input — tombol dipetakan ke "aksi" bernama, lalu kode hanya membaca aksi.

Di Unity, gunakan Input System package dengan Action Assets. Di Godot, mekanismenya built-in lewat Input Map. Di Unreal, lewat Enhanced Input. Contoh Godot — definisikan aksi jump di Project Settings → Input Map, lalu baca di kode:

PythonInput handling berbasis aksi
extends CharacterBody2D
 
@export var run_speed := 300.0
@export var jump_velocity := -500.0
 
var gravity := 1200.0
 
func _physics_process(delta: float) -> void:
    if not is_on_floor():
        velocity.y += gravity * delta
 
    var move := Input.get_axis("move_left", "move_right")
    velocity.x = move * run_speed
 
    if Input.is_action_just_pressed("jump") and is_on_floor():
        velocity.y = jump_velocity
 
    move_and_slide()

Kunci kode di atas: get_axis untuk input analog kiri/kanan, is_action_just_pressed untuk lompat (memicu sekali, bukan terus-menerus), dan is_on_floor() untuk memastikan pemain tidak melompat di udara. Ini gameplay loop inti — dibaca dari input, diproses, lalu dirender oleh engine.

Menambah Game Feel: Coyote Time dan Jump Buffer

Gameplay terasa enak bukan kebetulan — ada teknik desain yang membuat kontrol terasa "lebih murah hati" dari realita. Dua teknik wajib untuk platformer:

  • Coyote time: pemain tetap bisa melompat sepersekian detik (misal 100 ms) setelah meninggalkan platform. Ini mengkompensasi persepsi manusia yang selalu sedikit telat menekan tombol.
  • Jump buffer: jika pemain menekan lompat sesaat (misal 150 ms) sebelum mendarat, lompatan tetap terpicu saat mendarat.
PythonCoyote time + jump buffer
const COYOTE := 0.1
const BUFFER := 0.15
 
var coyote_timer := 0.0
var jump_buffer_timer := 0.0
 
func _physics_process(delta: float) -> void:
    coyote_timer = COYOTE if is_on_floor() else max(0.0, coyote_timer - delta)
    jump_buffer_timer = BUFFER if Input.is_action_just_pressed("jump") else max(0.0, jump_buffer_timer - delta)
 
    if jump_buffer_timer > 0.0 and coyote_timer > 0.0:
        velocity.y = jump_velocity
        jump_buffer_timer = 0.0
        coyote_timer = 0.0

Bandingkan dengan versi sebelumnya: sekarang lompatan "memaafkan" ketidaksempurnaan input. Perubahan kecil di kode, perbedaan besar di game feel — inilah yang membedakan platformer enak dari platformer membuat frustasi. Kita dalami game feel lebih jauh di episode 17.

Game Mechanics: Collectible, Obstacle, dan Score

Gameplay loop dibangun dari beberapa mekanik yang saling mengunci. Di Rimba Runner: lari + lompat (kontrol), kumpulkan buah (hadiah), hindari rintangan (bahaya), dan skor (progression jangka pendek). Mari tambahkan buah sebagai Area2D dengan signal (persis pola episode 4):

Pythonfruit.gd — mekanik kumpulkan
extends Area2D
 
signal collected(points: int)
@export var points := 10
 
func _ready() -> void:
    body_entered.connect(_on_body_entered)
 
func _on_body_entered(body: Node2D) -> void:
    if body.is_in_group("player"):
        collected.emit(points)
        queue_free()

Dan nyawa/restart saat terkena rintangan — memakai group untuk deteksi:

Pythonlevel.gd — bahaya & restart
func _on_body_entered(body: Node2D) -> void:
    if body.is_in_group("obstacle") and current.is_in_group("player"):
        GameState.health -= 1
        if GameState.health <= 0:
            get_tree().reload_current_scene()

Dua mekanik itu — hadiah dan bahaya — plus kontrol yang enak, sudah membentuk game yang bisa dimainkan. Itulah minimal viable gameplay loop: aksi pemain → konsekuensi → umpan balik, berulang.

Mengelola Kompleksitas Gameplay

Semakin banyak mekanik, semakin besar risiko kode jadi kusut. Tiga disiplin yang menyelamatkan:

  • Satu kelas, satu tanggung jawab — PlayerController urus gerak, Health urus nyawa, ScoreManager urus skor. Jangan semua digabung di satu script raksasa.
  • Komunikasi via signal/event — buah tidak perlu tahu siapa yang menghitung skor; cukup kirim signal. Hasilnya: sistem bisa ditambah tanpa mengubah yang lama.
  • Tuning terpusat — semua angka gameplay (kecepatan, gravitasi, coyote time) di @export atau config, sehingga designer bisa tuning tanpa masuk ke logika.

Tip

Aturan emas gameplay programming: kode harus mengungkapkan maksud desain. Kalau kalian membaca coyote_timer, orang lain langsung tahu ini untuk kompensasi lompatan. Hindari nama variabel generik seperti t1, x2, flag. Kode yang jelas = tim yang cepat dan bug yang sedikit.

Important

Prinsip abstraction input bukan teori — ini praktik wajib. Begitu game kalian dirilis di lebih dari satu platform (keyboard + gamepad + touch), kode yang terikat tombol akan memaksa kalian menulis ulang seluruh controller. Mulai dengan action-based input sejak prototipe.

Penutup

Gameplay programming adalah keterampilan yang kalian asah setiap hari sepanjang karir.

Inti yang harus dibawa pulang:

  • Input handling harus action-based, bukan terikat tombol, agar mudah di-remap dan lintas platform.
  • Game feel ditentukan oleh detail kecil: coyote time, jump buffer, tuning kecepatan.
  • Gameplay loop minimal = kontrol enak + hadiah + bahaya + umpan balik.
  • Organisir gameplay dengan tanggung jawab tunggal, signal, dan tuning terpusat.

Di episode 7 selanjutnya kita akan membekali diri dengan matematika di balik semua gerakan: math & physics game — vector, matrix, transform, dan collision detection, lengkap dengan implementasi physics sederhana. Sampai jumpa di episode 7!

Belajar Game Developer - Gameplay Programming | Belajar Game Developer