Pada episode ini kita menyelami fondasi game 2D: sprite, tileset, tilemap, dan parallax background. Lalu physics bodies, collision, deteksi area, animasi dengan AnimationPlayer dan Tween, sampai Camera2D dan UI overlay agar kamera selalu mengikuti aksi pemain.

Di episode 5 kalian sudah akrab dengan GDScript: variabel, fungsi, sinyal, dan lifecycle callback seperti _ready(){gdscript} dan _process(delta). Sekarang saatnya memakai semua itu untuk membangun dunia 2D yang hidup. Episode 6 ini adalah titik di mana kalian berhenti "menulis script" dan mulai "membuat game". Semua elemen yang dibahas di sini — sprite, tilemap, physics, animasi, dan kamera — adalah bahan baku yang akan kalian rakit terus-menerus di setiap project 2D.
Roadmap episode ini: kita mulai dari sprite dan cara menampilkan visual, lalu merakit dunia dari tileset dan tilemap, menambahkan kedalaman dengan parallax, menghidupkan fisika lewat physics bodies dan collision, mendeteksi kejadian dengan Area2D, menggerakkan animasi dengan AnimationPlayer dan Tween, dan menutupnya dengan Camera2D plus overlay UI.
Node paling dasar untuk menampilkan gambar 2D adalah Sprite2D. Kalian bisa menyeretnya ke scene, lalu mengisi properti texture dari file gambar yang diimpor Godot. Untuk mengatur posisi, cukup ubah properti position di inspector — atau lewat script:
extends Sprite2D
func _ready() -> void:
texture = preload("res://assets/player.png")
scale = Vector2(2, 2)
rotation_degrees = 15Perhatikan preload("res://..."){gdscript} — ini memuat resource saat compile time, jadi gambarnya sudah tersedia begitu scene berjalan. Untuk asset yang besar atau dimuat sesuai kebutuhan, gunakan load(){gdscript} yang dievaluasi saat runtime. Kunci penting: Godot menyimpan posisi di tengah node (centered), bukan pojok kiri-atas, jadi saat kalian memindahkan sprite, titik pivot-nya ada di tengah.
Menaruh satu sprite saja mudah. Tapi bagaimana kalau level terdiri dari ratusan ubin tanah, rumput, dan batu? Inilah kerja TileSet dan TileMapLayer. TileSet adalah resource yang mendefinisikan "ubin-ubin" yang tersedia, lengkap dengan collision shape per ubin. TileMapLayer adalah node yang menempatkan ubin-ubin tersebut di grid.
Workflow dasarnya: import satu sheet gambar berisi semua ubin, buat TileSet baru, atur tile_size (misal 16x16), pilih ubin mana saja yang valid, lalu tarik TileMapLayer ke scene dan paint ubinnya langsung di editor. Setelah itu collision per ubin diatur lewat properti physics layer pada tile. Ini cara paling efisien untuk membangun level — bukan satu sprite per ubin, tapi satu panggilan draw per tilemap.
extends TileMapLayer
func _ready() -> void:
var cell := local_to_map(Vector2(32, 32))
var source := get_cell_source_id(cell)
print("cell: %s, source id: %s" % [cell, source])Fungsi local_to_map{gdscript} mengubah koordinat dunia menjadi koordinat cell grid, sedangkan get_cell_source_id{gdscript} memberi tahu ubin mana yang menempati cell tersebut — sangat berguna untuk sistem interaksi seperti memecah batu atau membuka pintu.
Latar belakang yang diam terasa datar dan membosankan. Solusinya adalah parallax: beberapa lapisan bergerak dengan kecepatan berbeda sehingga menimbulkan kesan kedalaman. Di Godot, cukup pakai dua node: ParallaxBackground sebagai root, dan satu atau lebih ParallaxLayer sebagai lapisan.
Setiap ParallaxLayer punya properti motion_scale. Nilai (1, 1) berarti bergerak sama cepat dengan kamera; nilai (0.2, 0.2) bergerak sangat lambat sehingga terlihat jauh di belakang. Sebagai contoh, lapisan langit dengan motion_scale = (0, 0) akan diam total, sementara lapisan gunung dengan (0.3, 0.3) seolah tertinggal di belakang pemain.
extends ParallaxLayer
@export var parallax_speed: Vector2 = Vector2(0.3, 0.3)
func _ready() -> void:
motion_scale = parallax_speedSatu aturan praktis: ParallaxBackground harus menjadi child langsung dari root scene, dan kamera harus di bawahnya agar gerakan sinkron. Kombinasi beberapa ParallaxLayer dengan Sprite2D di dalamnya adalah pola standar untuk hampir semua platformer 2D.
Sekarang kita masuk bagian paling krusial: fisika. Godot menyediakan beberapa body yang masing-masing punya peran:
CharacterBody2D — dikendalikan langsung oleh code (biasanya pemain), memakai move_and_slide(){gdscript}.RigidBody2D — dikendalikan mesin fisika, kena gravitasi dan dorongan.StaticBody2D — diam di tempat, untuk lantai dan dinding.Semua body membutuhkan CollisionShape2D (atau CollisionPolygon2D) sebagai bentuk fisiknya. Contoh dasar pemain yang bisa digerakkan dan tidak menembus lantai:
extends CharacterBody2D
@export var speed := 250.0
func _physics_process(delta: float) -> void:
var direction := Input.get_axis("move_left", "move_right")
velocity.x = direction * speed
move_and_slide()move_and_slide(){gdscript} melakukan semua kerja berat: memindahkan body sesuai velocity, mendeteksi tabrakan, dan meluncur di sepanjang permukaan. Inilah cara paling umum membuat karakter berjalan di lantai tanpa menembusnya — selama lantainya StaticBody2D dengan collision shape yang rapi.
Kadang kalian tidak butuh benturan fisik, hanya butuh tahu "apakah sesuatu masuk ke zona ini?". Jawabannya adalah Area2D. Node ini mendeteksi body lain yang tumpang tindih dengannya, tanpa menolaknya seperti dinding. Area2D dipakai untuk: trigger level, pickup item, zona damage, dan checkpoint.
Area2D mengeluarkan sinyal body_entered dan body_exited yang bisa kalian sambungkan:
extends Area2D
signal coin_collected
func _on_body_entered(body: Node2D) -> void:
if body.is_in_group("player"):
coin_collected.emit()
queue_free()Perhatikan pola di atas: Area2D memeriksa apakah yang masuk adalah player lewat is_in_group("player"), lalu mengirim sinyal coin_collected dan menghapus dirinya sendiri dengan queue_free(){gdscript}. Sinergi sinyal (episode 5) + Area2D inilah yang membangun sebagian besar logika interaksi di game 2D. Bedakan perannya: CharacterBody2D dan StaticBody2D untuk benturan fisik yang memengaruhi pergerakan, sedangkan Area2D untuk deteksi tanpa benturan — player memakai body, zona danger memakai area.
AnimationPlayer merekam keyframe properti dari waktu ke waktu — misalnya rangkaian frame berjalan dari sebuah sprite sheet, atau pintu yang membuka. Animasi ini dibuat di editor lewat panel Animation, lalu diputar dari script:
extends AnimationPlayer
func _ready() -> void:
play("run")
func _physics_process(delta: float) -> void:
var direction := Input.get_axis("move_left", "move_right")
if direction != 0.0:
play("run")
else:
play("idle")Tween berbeda: ia menganimasikan properti secara programatik dari nilai A ke nilai B. Cocok untuk efek yang sifatnya sekali jalan — melompat, fade out, pop-up UI, atau perpindahan kamera.
extends Node2D
func _ready() -> void:
var tween := create_tween()
tween.tween_property(self, "position", Vector2(200, 0), 1.0)Perbedaan kunci: AnimationPlayer untuk animasi berulang yang disiapkan di editor dan bisa di-preview, Tween untuk animasi ad-hoc dari dalam kode yang dinamis terhadap kondisi gameplay. Kalian akan memakai keduanya sepanjang karier Godot.
Semua dunia itu tidak berguna kalau tidak terlihat. Camera2D adalah mata kalian. Saat enabled = true, layar mengikuti node ini — taruh sebagai child dari player dan kamera otomatis membuntuti pergerakan. Beberapa properti yang wajib kalian tahu:
position_smoothing_enabled — kamera bergerak halus, tidak patah-patah.limit_left/right/top/bottom — batasi agar kamera tidak keluar dari level.zoom — perbesar atau perkecil tampilan.extends Camera2D
func _ready() -> void:
enabled = true
position_smoothing_enabled = true
position_smoothing_speed = 8.0
limit_left = 0
limit_right = 1024Terakhir, UI overlay: elemen antarmuka seperti skor dan nyawa sebaiknya tidak ikut bergeser dengan dunia. Solusinya CanvasLayer — layer terpisah yang posisinya tidak terpengaruh transformasi dunia. Di dalamnya kalian taruh Label untuk skor, TextureProgressBar untuk nyawa, dan seterusnya. Overlay inilah yang akan kita bedah lebih dalam di episode 8 tentang UI & HUD.
Episode 6 ini membekali kalian dengan seluruh fondasi visual dan fisika game 2D: menampilkan sprite, membangun level modular dengan TileSet dan TileMapLayer, menciptakan kedalaman lewat parallax, menghidupkan gameplay dengan physics bodies dan Area2D, menganimasikan dengan AnimationPlayer dan Tween, hingga menuntun pemain dengan Camera2D dan overlay UI.
Inti yang harus dibawa pulang:
TileSet + TileMapLayer, bukan ribuan sprite terpisah; pilih body sesuai peran: CharacterBody2D untuk pemain, StaticBody2D untuk lantai, Area2D untuk deteksi.move_and_slide(){gdscript} menangani logika benturan karakter dengan lantai; AnimationPlayer untuk animasi editor berulang dan Tween untuk animasi programatik.Camera2D menjadi child player dan CanvasLayer untuk UI yang tidak ikut bergeser.Di episode 7 kalian akan berpindah dimensi: 3D Game Fundamentals. Kita akan belajar Node3D, mesh dan material, pencahayaan, physics body 3D, camera, environment, sampai cara mengimpor model 3D dan menganimasikannya. Sampai jumpa di dimensi baru!