Skip to content

Tutorial 6 - Menu and In-Game Graphical User Interface

Selamat datang pada tutorial keenam kuliah Game Development. Pada tutorial kali ini, kamu akan mempelajari cara membuat menu screen, game over screen, dan in-game GUI.

Di akhir tutorial ini, diharapkan kamu paham cara menggunakan Container, Label, Button, serta unsur-unsur lain untuk menyusun menu dan antar muka dalam game.

Daftar Isi

Pengantar

Penting! Untuk tutorial kali ini, silakan menggunakan template proyek yang telah disediakan di GitHub ATAU melanjutkan dari pengerjaan proyek Tutorial 4. Jika melanjutkan proyek Tutorial 4, silakan mengerjakan di repositori Git pengerjaan tutorial tersebut dan membuat branch baru (misal: branch tutorial-6).

Tampilan Antar Muka

Saat kamu pertama kali memulai suatu game, apa yang pertama kali muncul? Splash screen dengan gambar logo perusahaan pembuat game tersebut?

Logo SEGA (Sumber: https://en.wikipedia.org/wiki/Sega#/media/File:SEGA_logo.svg)

Atau splash screen dengan ilustrasi tokoh dari game tersebut?

Sonic (Sumber: https://www.youtube.com/watch?v=CqOlpQ7sepE)

Pada umumnya, mayoritas game akan memiliki menu utama (main menu). Main menu adalah layar utama yang muncul pertama kali ketika mulai bermain game. Biasanya terdapat tombol atau instruksi untuk memulai permainan pada main menu.

Selain main menu, di dalam game juga terdapat tampilan antar muka yang menampilkan informasi terkait kondisi permainan sekarang secara visual. Tampilan antar muka tersebut dinamakan sebagai game GUI (Graphical User Interface). GUI digunakan untuk menampilkan banyak hal, seperti:

  • Jumlah sumber daya (misal: darah tokoh, uang virtual) yang dimiliki pemain.
  • Kondisi pemain relatif terhadap lawan-lawannya (misal: peringkat ketika balapan, posisi pemain pada dunia permainan).
  • Pilihan untuk masuk ke menu lain terkait permainan (biasanya pada game mobile yang dapat merespon aksi tap/sentuh layar, misal: tombol untuk membuka daftar tokoh yang bisa dikendalikan pemain).
  • Dan lain-lain.

Kemudian yang tidak kalah penting adalah tampilan saat pemain mencapai kondisi akhir permainan, seperti layar yang menampilkan kondisi menang atau kondisi kalah.

Pada Tutorial 4, kita sudah berhasil membuat game platformer 2D yang cukup dasar. Namun saat menjalankan proyek, scene yang dijalankan langsung level 1 dan tidak ada menu yang muncul terlebih dahulu.

Contoh Layar Menu Utama, Layar Kondisi Menang/Kalah, dan GUI

Berikut ini adalah beberapa contoh layar menu, layar kondisi akhir permainan, dan GUI pada beberapa game populer:

The Legend of Zelda NES Main Menu Undertale Game Over Screen Shovel Knight GUI

Tentu saja contoh-contoh di atas hanyalah representasi kecil dari sekian banyak contoh layar permainan. Apabila kamu ada contoh lain yang menarik, silakan cerita ketika sesi tutorial berlangsung. 😃

Pada tutorial ini kita akan melakukan hal berikut:

  • Membuat layar menu utama (main menu)
  • Membuat indikator nyawa (life counter)
  • Membuat layar kalah (game over screen)

Latihan: Membuat Menu Utama

Visualisasi

Untuk menghasilkan sebuah UI yang baik, sebaiknya kita membuat sebuah mockup terlebih dahulu. Apa saja yang ingin kita tampilkan di menu utama, dan posisi segala hal yang ingin kita tampilkan. Visualisasi boleh digambar di kertas, dan tidak harus bagus-bagus. Cukup untuk memberikan gambaran kasar apa yang ingin kita buat.

Berikut adalah contoh visualisasi main menu:

An example of visualization of a menu screen

Membuat Containers, Labels, dan Buttons

Salah satu cara untuk menyusun sebuah menu dengan rapi adalah menggunakan containers. Container pada konteks desain UI pada game merupakan elemen yang akan menampung komposisi elemen UI.

Jika kamu familiar dengan desain Web, anggaplah container serupa dengan tag <div> yang sering dipakai untuk membungkus elemen-elemen HTML pada sebuah halaman Web. Container di Godot akan membungkus elemen-elemen UI pada permainan yang dikembangkan.

Beberapa container yang terdapat di engine Godot antara lain:

  • MarginContainer untuk menyusun elemen dengan padding
  • HBoxContainer untuk menyusun elemen secara horizontal
  • VBoxContainer untuk menyusun elemen secara vertikal
  • CenterContainer untuk menyusun elemen secara centered

Sesuai dengan visualisasi yang telah dilakukan di atas, kita dapat menyusun main menu ini dengan susunan container sebagai berikut:

Kotak terbesar seukuran game window, dan terdapat padding di bagian ujung window. Oleh karena itu kita menggunakan parent MarginContainer. Kemudian layar dibagi dua kiri kanan, maka menggunakan HBoxContainer.

Di bagian kiri ada judul dan button, maka ada VBoxContainer. Button sendiri akan kita susun dengan VBoxContainer juga. Sedangkan sebelah kanan cukup kita berikan CenterContainer untuk gambar.

My Visualiation of Menu Screen Containers

Catatan: Kamu tidak harus mengikuti struktur dan layout persis sama seperti di atas. Bahkan diperbolehkan jika kamu tidak ingin menggunakan container sama sekali untuk menu utama. Namun container sangat membantu untuk visualisasi dan kerapihan.

Mulai dengan membuat scene baru. Karena root node UI yang kita inginkan adalah container paling luar, pilih root node type menjadi sebuah MarginContainer dan berikan nama scene MainMenu.tscn.

New Scene with MarginContainer as root

New Scene with MarginContainer as root

Pada tab Inspector, tekan menu Layout. Kemudian atur properti Anchors Preset, pilih opsi Full Rect. Ini dilakukan agar ukuran container menyesuai ukuran window.

Full Rect

Setelah itu masukan sebuah node VBoxContainer di dalam MarginContainer. Sesuai dengan visualisasi yang telah dilakukan di atas, kita menambahkan sebuah node VBoxContainer lagi di dalam VBoxContainer yang pertama.

Sekarang masukkan elemen teks ke dalam VBoxContainer. Untuk teks, gunakan node Label. Pada contoh ini, terdapat dua tombol yang diimplementasikan menggunakan node LinkButton.

Untuk menambahkan atau mengubah teks pada Label atau LinkButton cukup menulis di tab Inspector properti Text. Kamu dapat menambahkan judul game pada Label dan menambahkan "New Game" dan "Stage Select" pada kedua tombol LinkButton.

Jika sudah selesai, struktur scene dan workspace kamu akan terlihat seperti screenshot berikut:

First Scene Structure

Tetapi, pada saat ini tulisan judul dan tombol sangatlah membosankan, hanya default font dari Godot! Apakah tidak ada cara untuk mengubahnya??

Untungnya pada Godot 4.6 sudah mudah mengubah font dari suatu elemen teks. Kamu hanya perlu mengubah konfigurasi ThemeOverrides pada node Label dan juga LinkButton dan load file font yang kamu miliki. Kamu dapat load file dalam format TrueType Font (.ttf) atau OpenType Font (.otf). Pada contoh ini akan menggunakan font CC Wild Words Roman.ttf yang tersedia di folder assets template.

Configure Text Font

Sekarang, kita ingin menambahkan gambar agar MainMenu lebih menarik.

Tambahkan sebuah node HBoxContainer pada root node dan masukkan node VBoxContainer tadi ke dalamnya. Kemudian, tambahkan node CenterContainer pada HBoxContainer dan menambahkan node TextureRect pada node CenterContainer tersebut.

Cara menambahkan gambar pada TextureRect sama seperti menambahkan texture di Sprite, yaitu di tab Inspector pada properti Texture. Pada contoh ini akan menggunakan gambar spritesheet_alien.png pada folder assets/kenney_platformerpack/Spritesheets/.

Jika sudah selesai, struktur scene kamu akan terlihat seperti screenshot berikut:

New Structure with Image

Tetapi kenapa tulisannya berada di pojok atas, kenapa semua tulisannya saling tumpang tindih, dan kenapa tata letaknya masih berantakan??

Agar tulisan dan gambar berada di tengah layar, pada HBoxContainer, ubah Alignment menjadi Center. Kemudian lakukan hal yang sama pada VBoxContainer dan ubah ContainerSizing.Vertical menjadi Shrink Center.

Configure Alignment

Agar judul dan tombol tidak terlalu berhimpitan, ubah Separation pada ThemeOverrides di node VBoxContainer . Kamu juga bisa mengatur Separation pada HBoxContainer.

Configure Separation

Untuk mengubah ukuran gambar, pada node TextureRect kamu bisa melakukan: Mengubah Expand Mode menjadi Ignore Size, mengubah Stretch Mode menjadi Keep Aspect Centered, dan mengubah Custom Minimum Size sesuai keinginanmu.

Configure Size

Selamat! Layar menu utama kamu sudah terlihat cukup rapi!

Final Main Menu

Tapi masih belum clickable tentunya. Bagaimana caranya agar saat kita menekan tombol "New Game" dia akan melempar kita ke level 1?

Latihan: Clickable Menu

Kita ingin agar saat tombol "New Game" ditekan, game akan menjalankan scene level pertama. Pada Tutorial 4, kita sudah belajar menggunakan Signal. Sekarang kita akan menggunakannya lagi untuk menangani event handler ketika ada aksi menekan tombol, yaitu pressed().

Gunakan cuplikan script__ berikut sebagai _script yang ditempelkan pada LinkButton:

1
2
3
4
5
6
extends LinkButton

@export var scene_to_load: String

func _on_New_Game_pressed():
    get_tree().change_scene_to_file(str("res://scenes/" + scene_to_load + ".tscn"))

Kemudian pastikan LinkButton sedang dipilih dan lihat tab Inspector. Isi variabel scene_to_load pada tab Inspector dengan value "Level 1"

Load Level 1

Berhasil! Sekarang tombol "New Game" kamu akan langsung membawa pemain ke level 1.

Main Menu New Game Complete

"Mengapa saat saya tekan play (F5) yang jalan pertama bukan main menu?" Karena MainMenu.tscn belum diatur sebagai Main Scene. Main Scene dapat diubah di Project -> Project Settings -> Application -> Run -> Main Scene.

Change Main Scene

Latihan: Membuat GUI Life Counter

Sebelumnya kita sudah membuat kondisi dimana saat player jatuh, maka scene akan di-reload dengan player kembali ke tempat semula. Namun tidak ada penalti sama sekali untuk jatuh. Sekarang kita akan mencoba membuat kondisi dimana setiap kali player jatuh, player akan kehilangan satu nyawa. Saat sudah tidak ada nyawa lagi, maka permainan usai (game over).

Global Variables

Jika kamu pernah menyentuh bahasa pemrograman apapun, pasti sudah familiar dengan yang namanya global variable. Global Variable adalah sebuah variabel yang terlihat (visible) oleh seluruh program. Kita menggunakan global variable untuk mendefinisikan nyawa player. Nyawa player akan disimpan permanen (persist) walaupun scene baru dipanggil atau diulang-ulang. Variabel ini dapat dipanggil dari script manapun.

Pertama, buat script baru dengan nama Global.gd pada folder scripts. Kemudian, isi dengan script berikut:

1
2
3
extends Node

var lives = 3

Pada Project Settings, buka tab Globals, lalu tambahkan script Global.gd (tekan icon folder lalu cari berkas script-nya). Setelah ditambahkan, akan muncul di dalam daftar. Pastikan kolom Global Variable dalam kondisi aktif (enabled).

Add Global Variable

Sekarang kita punya variable nyawa yang dapat diakses kapan saja. Mari kita tampilkan menggunakan label.

Catatan: Bagi yang penasaran mengapa menggunakan global variable untuk contoh ini, alasannya karena tiap kali reload scene, player juga ikut reload. Maka lives disimpan dalam global variable agar tidak reset saat scene reload.

GUI Scene

Buat sebuah scene baru dan beri nama Life Counter.tscn dengan root node sebuah MarginContainer.

New Life Counter Scene

Buat sebuah child node Label, lalu berikan script.

1
2
3
4
extends Label

func _process(delta: float) -> void:
    self.text = "Lives : " + str(Global.lives)

Struktur akan terlihat seperti ini:

Life Counter Structure

Pada scene Level 1.tscn, tambahkan sebuah node CanvasLayer sebagai child node dari root node. CanvasLayer merupakan node yang membuat sebuah layer 2D tersendiri untuk seluruh child-nya. CanvasLayer berguna untuk membuat background untuk level, atau user interface seperti yang akan kita buat sekarang.

Tambahkan Life Counter.tscn yang tadi kita buat sebagai child node dari CanvasLayer. Struktur Level 1.tscn akan terlihat seperti screenshot berikut:

Level Updated with GUI

Coba jalankan Level 1.tscn kamu. Sekarang sudah muncul tampilan life counter di kiri atas yang mengikuti bentuk window yang ada.

Level 1 No Life Loss

Namun nyawa player belum berkurang ketika pemain mati. Waktunya melakukan sedikit scripting!

Ubah script di Area2D.gd dengan kode berikut:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
extends Area2D

@export var sceneName: String = "Level 1"

func _on_Area_Trigger_body_entered(body):
    var current_scene = get_tree().get_current_scene().get_name()
    if body.get_name() == "Player":
        if current_scene == sceneName:
            Global.lives -=1
        if (Global.lives == 0):
            pass
        else:
            get_tree().call_deferred("change_scene_to_file",(str("res://scenes/" + sceneName + ".tscn")))

What's happening above? Karena transisi dari level 1 ke 2 menggunakan fungsi yang sama, pertama kita periksa terlebih dahulu scene yang memanggil fungsi apakah sama dengan target scene (maka reload). Jika iya, nyawa berkurang satu. Baris pass di kondisi global.lives == 0 akan kita isi sebentar lagi. (you could probably already guess what goes there though).

Level 1 Life Loss

Sekarang nyawa player berkurang saat mati. Namun kita belum memasukkan kondisi dimana nyawa player 0, yaitu game over.

Latihan: Membuat Layar Game Over

Untuk membuat layar game over, langkah-langkahnya sama dengan membuat layar menu utama. Visualisasi layar game over di contoh tutorial ini berupa tulisan GAME OVER dengan warna latar merah. Jika ingin menambahkan warna latar, kita dapat menggunakan node ColorRect.

Buatlah sebuah scene baru dan beri nama Game Over.tscn, lalu atur sebuah ColorRect sebagai root node di scene tersebut.

New Game Over Scene

Mirip seperti MarginContainer sebelumnya, pilih menu Layout pada viewport dan pilih Full Rect agar kotak mengikuti ukuran window. Silakan ubah warna sesuka hati.

Setting Up Background Color and Full Rect

Tambahkan label bertuliskan "GAME OVER", atur font dan ukuran teks, kemudian atur posisinya. Selesailah Game Over screen kita!

Game Over Screen Finished

Sekarang bagaimana caranya agar saat nyawa pemain 0 akan menampilkan layar ini? Pada script Area2D.gd ubah baris pass menjadi:

1
get_tree().change_scene_to_file("res://scenes/Game Over.tscn")

Berhasil! Sekarang saat player nyawanya habis, layar game over akan muncul.

Game Over Desu

Selamat, tutorial ini sudah selesai!

Latihan Mandiri: Fitur Tambahan

Silakan baca referensi yang tersedia untuk membantu pengerjaan latihan mandiri. Di akhir tutorial, kamu diharapkan untuk mengerjakan minimal 2 (dua) dari beberapa contoh fitur tambahan berikut:

  • Tombol pada layar game over untuk kembali ke menu utama.
  • Fitur Select Stage (yang konon sudah ada button-nya di main menu namun tidak dihiraukan).
  • Layar dan efek transisi antar level, dari level 1 ke level 2.
  • Dan lain-lain (bebas), selama fitur tersebut melibatkan implementasi menu dan GUI di dalam game. Get creative!

Jangan lupa untuk menjelaskan proses pengerjaan tutorial ini di dalam berkas README.md. Jika kamu melanjutkan Tutorial 4, silakan tambahkan subbab (section) baru di berkas README.md yang berisi penjelasan proses pengerjaan Tutorial 6. Cantumkan juga referensi-referensi yang digunakan sebagai acuan ketika menjelaskan proses implementasi.

Skema Penilaian

Pada tutorial ini, ada empat kriteria nilai yang bisa diperoleh:

  • 4 (A) apabila kamu mengerjakan tutorial dan latihan melebihi dari ekspektasi tim pengajar. Nilai ini dapat dicapai apabila mengerjakan seluruh Latihan dan 2 (dua) fitur tambahan yang merupakan bagian dari Latihan Mandiri, ditambah dengan memoles (polishing) lebih lanjut permainannya.
  • 3 (B) apabila kamu hanya mengerjakan tutorial dan latihan sesuai dengan instruksi. Nilai ini dapat dicapai apabila mengerjakan seluruh Latihan dan 2 (dua) fitur tambahan yang merupakan bagian dari Latihan Mandiri.
  • 2 (C) apabila kamu hanya mengerjakan tutorial hingga tuntas. Nilai ini dapat dicapai apabila mengerjakan seluruh Latihan namun tidak mengerjakan Latihan Mandiri.
  • 1 (D) apabila kamu hanya sekedar memulai tutorial dan belum tuntas. Nilai ini dapat dicapai apabila belum tuntas mengerjakan Latihan.
  • 0 (E) apabila kamu tidak mengerjakan apapun atau tidak mengumpulkan.

Pengumpulan

Kumpulkan semua berkas pengerjaan tutorial dan latihan ke repositori Git. Kemudian, push riwayat commit-nya ke repositori Git pengerjaan Tutorial 6. Ingat kembali instruksi di awal Tutorial 6, kamu dapat memilih membuat repositori baru khusus untuk pengerjaan Tutorial 6 atau menggunakan repositori Tutorial 4 sebagai templat untuk mengerjakan Tutorial 6. Jika melanjutkan Tutorial 4, jangan lupa untuk mengambil aset yang dibutuhkan dari templat proyek Tutorial 6.

Apabila kamu mengerjakan latihan mandiri, pastikan scene dan node yang kamu buat dan ubah telah tercatat masuk ke dalam repositori Git. Kumpulkan tautan ke repositori Git hasil pengerjaan Tutorial 6 kamu di slot pengumpulan yang tersedia di SCELE.

Tenggat waktu pengumpulan adalah Jumat, 20 Maret 2026, pukul 21:00.

Referensi

  • Main Menu
  • GUI Design
  • Kenney Assets
  • Materi tutorial pengenalan Godot Engine, kuliah Game Development semester gasal 2020/2021 Fakultas Ilmu Komputer Universitas Indonesia.

Selingan Menarik (Intermezzo)

Berikut ini adalah gambar meme yang diambil dari sebuah thread di Reddit:

GUI Berbagai Game Gacha

Gambar tersebut menampilkan screenshot dari sebuah game yang diubah sehingga mengandung elemen-elemen GUI dari banyak game lain. Apa saja judul game yang bisa kamu kenali dari elemen GUI-nya pada meme tersebut? Jika kamu mengenali satu atau lebih elemen GUI di screenshot tersebut, apa fungsi elemen GUI tersebut di game aslinya?

Silakan didiskusikan dengan rekan-rekan sekelas ketika membahas materi mengenai Interface pada game, atau dijadikan bahan obrolan santai di grup pertemanan masing-masing.


Last update: 2026-03-13 07:18:15
Created: 2024-04-04 00:49:48