Skip to content

🛠️ Mini Proyek: Game 2D dengan Flame

⭐⭐⭐⭐ · 1–2 hari

Apa yang akan kamu bangun

Penadah Bintang — game arcade satu layar. Pemain menggerakkan keranjang di dasar layar untuk menangkap bintang yang jatuh dari langit malam, sambil menghindari meteor. Setiap bintang menambah skor, setiap meteor mengurangi nyawa. Semakin lama kamu bertahan, semakin cepat benda berjatuhan.

Genrenya sengaja berbeda dari Asteroids di Bab 50. Di sana kamu mengendalikan pesawat yang berputar dan menembak ke segala arah; di sini gerakannya hanya satu sumbu, tetapi tekanan datang dari waktu. Perbedaan itu memindahkan titik beratnya: alih-alih menghabiskan energi pada trigonometri sudut tembak, kamu menghabiskannya pada kurva kesulitan, pengaturan spawn, dan rasa game yang enak — yang justru bagian paling sering dilewati orang.

Struktur objeknya sederhana, dan itu memberi ruang untuk mengerjakan hal-hal yang membuat game terasa hidup. Bintang dan meteor sama-sama komponen yang jatuh (Bab 43), jadi wajar kalau keduanya mewarisi satu induk. Kecepatan spawn yang meningkat seiring waktu adalah kasus buku teks untuk Bab 47 — termasuk jebakannya, karena kesulitan yang naik tanpa clamp akan membuat game mustahil dalam waktu satu menit. Langit berlapis yang bergerak pada kecepatan berbeda adalah Bab 48. Dan percikan saat menangkap bintang, ledakan kecil saat tertabrak meteor, adalah tempat Bab 49 memberi hasil paling terasa per baris kode.

Satu hal yang tidak boleh kamu lewati: kekebalan sesaat setelah tertabrak. Tanpa itu, satu meteor bisa menghabiskan seluruh nyawa dalam sepersekian detik, karena onCollision dipanggil setiap frame (Bab 46).

Prasyarat

Selesaikan dulu:

Requirement fungsional

  • Keranjang dikendalikan dengan joystick di layar, dan tidak bisa keluar dari tepi layar.
  • Bintang dan meteor muncul dari atas pada posisi horizontal acak, lalu jatuh dengan kecepatan yang bervariasi.
  • Menangkap bintang menambah skor; skor terlihat di layar sepanjang permainan.
  • Tertabrak meteor mengurangi satu nyawa, memicu kekebalan sesaat dengan tanda visual yang jelas (misalnya keranjang berkedip).
  • Kesulitan meningkat seiring waktu: jeda antar spawn memendek dan kecepatan jatuh bertambah — sampai batas tertentu, lalu berhenti naik.
  • Latar belakang berupa parallax minimal tiga lapisan yang bergerak pada kecepatan berbeda.
  • Efek partikel saat menangkap bintang (percikan) dan saat tertabrak meteor (ledakan). Keduanya harus terlihat berbeda.
  • Efek suara untuk menangkap, tertabrak, dan kehabisan nyawa, plus musik latar yang berulang.
  • Ada layar pengaturan suara: musik dan efek bisa dimatikan terpisah, dan pilihannya bertahan setelah aplikasi ditutup.
  • Nyawa habis memunculkan layar game over dengan skor akhir, skor tertinggi, dan tombol main lagi yang benar-benar mengembalikan permainan ke keadaan awal.
  • Musik berhenti ketika aplikasi masuk ke latar belakang, dan lanjut lagi saat kembali.

Requirement teknis

  • Game memakai mixin HasCollisionDetection, dan setiap objek yang bertabrakan punya CollisionCallbacks beserta hitbox.
  • Kerusakan dan penambahan skor terjadi di onCollisionStart, bukan onCollision — kalau tidak, satu sentuhan bernilai enam puluh kali per detik.
  • Untuk setiap pasangan tabrakan, hanya satu sisi yang bertanggung jawab atas efeknya, supaya tidak berlipat.
  • Benda yang sudah melewati bawah layar dihapus dari pohon komponen, bukan dibiarkan menumpuk di luar pandangan.
  • Waktu dikelola lewat dtTimer, TimerComponent, atau penghitung manual. Jangan pakai Timer dari dart:async untuk logika game, karena ia tidak ikut berhenti saat pauseEngine().
  • Kejadian sekali pakai (game over, naik level) diberi penanda "sudah terjadi", supaya tidak terpicu berulang setiap frame.
  • Kenaikan kesulitan diberi clamp pada batas atas dan bawah.
  • Semua efek suara dimuat di awal lewat loadAll() di onLoad(), dan seluruh pemutaran melewati satu fungsi yang memeriksa pengaturan.
  • TextComponent skor hanya diperbarui saat teksnya berubah, bukan setiap frame.
  • Vector2 yang dibagikan antar komponen di-clone(), supaya dua objek tidak diam-diam bergerak bersamaan.

Checklist penerimaan

  • Bermain sampai game over lalu menekan main lagi: skor, nyawa, kecepatan, dan seluruh benda di layar kembali ke keadaan awal — tidak ada sisa dari ronde sebelumnya.
  • Bermain selama tiga menit penuh tanpa penurunan frame rate yang terasa. Nyalakan penghitung frame untuk memastikan.
  • Menabrak meteor sekali mengurangi tepat satu nyawa.
  • Mematikan efek suara di pengaturan benar-benar membuat semuanya diam, termasuk suara yang jarang muncul.
  • Menekan tombol home lalu kembali: musik berhenti dan lanjut dengan benar, dan permainan tidak melompat karena dt yang menumpuk.

Tantangan ekstra (opsional)

  • Tambahkan item bonus dengan efek sementara: keranjang melebar, waktu melambat, atau bintang bernilai ganda. Tangani kasus "sudah aktif" supaya bonus beruntun memperpanjang durasi, bukan menumpuk timer.
  • Tambahkan kemampuan menembak ke atas untuk menghancurkan meteor, memakai pola peluru dari Bab 44 — lengkap dengan jeda tembak dan batas umur peluru.
  • Tambahkan guncangan kamera saat tertabrak. Ini efek dengan dampak tertinggi per baris kode di seluruh Bagian VI.
  • Simpan sepuluh skor tertinggi beserta tanggalnya, dan tampilkan sebagai papan peringkat lokal.

Terjebak?

Dua kegagalan paling umum di Bagian VI tidak menghasilkan pesan error sama sekali: tabrakan yang tidak pernah terdeteksi (biasanya satu dari dua mixin yang lupa dipasang), dan Timer yang diam karena tidak pernah di-update(dt) dari update() induknya. Sebelum menebak, nyalakan penggambaran hitbox seperti di Bab 46 — melihat kotaknya menjawab sebagian besar pertanyaan dalam hitungan detik. Kalau masih macet di satu bagian spesifik, itu wajar: proyek ini memang dirancang untuk memaksamu mengingat kembali konsep yang sudah dibahas, bukan menghafalnya.

Rangkuman pembelajaran pribadi, disusun ulang dari beberapa kursus Flutter.