Menggunakan sinyal
Dalam pelajaran ini, kita akan membahas sinyal. Sinyal adalah pesan yang dipancarkan node saat sesuatu yang spesifik terjadi pada node tersebut, seperti tombol yang ditekan. Node lain dapat terhubung ke sinyal tersebut dan memanggil suatu fungsi saat peristiwa tersebut terjadi.
Sinyal adalah mekanisme delegasi yang dibangun dalam Godot yang memungkinkan satu objek permainan bereaksi terhadap perubahan pada objek lain tanpa harus merujuk satu sama lain. Penggunaan sinyal membatasi penggabungan dan menjaga kode Anda tetap fleksibel.
Misalnya, Anda mungkin memiliki bilah kehidupan di layar yang mewakili kesehatan pemain. Saat pemain menerima kerusakan atau menggunakan ramuan penyembuh, Anda ingin bilah tersebut mencerminkan perubahan tersebut. Untuk melakukannya, di Godot, Anda akan menggunakan sinyal.
Seperti metode ( Callable ), sinyal adalah tipe kelas satu sejak Godot 4.0. Ini berarti Anda dapat meneruskannya sebagai argumen metode secara langsung tanpa harus meneruskannya sebagai string, yang memungkinkan pelengkapan otomatis yang lebih baik dan lebih sedikit rawan kesalahan. Lihat referensi kelas Signal untuk daftar hal yang dapat Anda lakukan dengan tipe Signal secara langsung.
Lihat juga
Seperti yang disebutkan dalam pendahuluan, sinyal adalah versi pola pengamat milik Godot. Anda dapat mempelajarinya lebih lanjut di Pola Pemrograman Game .
Sekarang kita akan menggunakan sinyal untuk membuat ikon Godot dari pelajaran sebelumnya ( Mendengarkan masukan pemain ) bergerak dan berhenti dengan menekan tombol.
Catatan
Untuk proyek ini, kami akan mengikuti konvensi penamaan Godot.
GDScript : Kelas (node) menggunakan PascalCase, variabel dan fungsi menggunakan snake_case, dan konstanta menggunakan ALL_CAPS (Lihat panduan gaya GDScript ).
C# : Kelas, variabel ekspor, dan metode menggunakan PascalCase, kolom privat menggunakan _camelCase, variabel dan parameter lokal menggunakan camelCase (Lihat panduan gaya C# ). Berhati-hatilah untuk mengetik nama metode dengan tepat saat menghubungkan sinyal.
Pengaturan adegan
Untuk menambahkan tombol ke permainan kita, kita akan membuat adegan baru yang akan menyertakan Tombol dan sprite_2d.tscnadegan yang kita buat dalam pelajaran Membuat skrip pertama Anda .
Buat adegan baru dengan masuk ke menu Adegan -> Adegan Baru.

Di dock Scene, klik tombol 2D Scene. Ini akan menambahkan Node2D sebagai root kita.

Pada dok FileSystem, klik dan seret sprite_2d.tscnberkas yang Anda simpan sebelumnya ke Node2D untuk membuat instansiasinya.

Kami ingin menambahkan node lain sebagai saudara dari Sprite2D. Untuk melakukannya, klik kanan pada Node2D dan pilih Add Child Node.

Cari simpul Tombol dan tambahkan.

Node tersebut berukuran kecil secara default. Klik dan seret gagang kanan bawah Tombol di area pandang untuk mengubah ukurannya.

Jika Anda tidak melihat pegangannya, pastikan alat pilih aktif di bilah alat.

Klik dan seret tombol itu sendiri untuk memindahkannya lebih dekat ke sprite.
Anda juga dapat menulis label pada Tombol dengan mengedit properti Teksnya di Inspektur. Masukkan .Toggle motion

Pohon pemandangan dan area pandang Anda akan terlihat seperti ini.

Simpan adegan yang baru Anda buat sebagai node_2d.tscn, jika Anda belum melakukannya. Anda kemudian dapat menjalankannya dengan F6( di macOS). Saat ini, tombol tersebut akan terlihat, tetapi tidak akan terjadi apa-apa jika Anda menekannya.Cmd + R
Menghubungkan sinyal di editor
Di sini, kita ingin menghubungkan sinyal "ditekan" Tombol ke Sprite2D kita, dan kita ingin memanggil fungsi baru yang akan mengaktifkan dan menonaktifkan gerakannya. Kita perlu memiliki skrip yang dilampirkan ke simpul Sprite2D, yang kita lakukan dari pelajaran sebelumnya.
Anda dapat menghubungkan sinyal di dock Node. Pilih node Button dan, di sisi kanan editor, klik tab bernama "Node" di samping Inspector.

Dok menampilkan daftar sinyal yang tersedia pada simpul yang dipilih.

Klik dua kali sinyal yang "ditekan" untuk membuka jendela koneksi node.

Di sana, Anda dapat menghubungkan sinyal ke simpul Sprite2D. Simpul tersebut memerlukan metode penerima, sebuah fungsi yang akan dipanggil Godot saat Tombol memancarkan sinyal. Editor akan membuatkannya untuk Anda. Berdasarkan konvensi, kami menamai metode panggilan balik ini "_on_node_name_signal_name". Di sini, namanya akan menjadi "_on_button_pressed".
Catatan
Saat menghubungkan sinyal melalui Node dock editor, Anda dapat menggunakan dua mode. Mode sederhana hanya memungkinkan Anda untuk terhubung ke node yang memiliki skrip yang dilampirkan padanya dan membuat fungsi panggilan balik baru di node tersebut.

Tampilan lanjutan memungkinkan Anda terhubung ke node mana pun dan fungsi bawaan apa pun, menambahkan argumen ke panggilan balik, dan mengatur opsi. Anda dapat mengubah mode di kanan bawah jendela dengan mengeklik tombol Lanjutan.
Catatan
Jika Anda menggunakan editor eksternal (seperti VS Code), pembuatan kode otomatis ini mungkin tidak berfungsi. Dalam kasus ini, Anda perlu menghubungkan sinyal melalui kode seperti yang dijelaskan di bagian berikutnya.
Klik tombol Connect untuk menyelesaikan koneksi sinyal dan beralih ke ruang kerja Script. Anda akan melihat metode baru dengan ikon koneksi di margin kiri.
Jika Anda mengklik ikon tersebut, sebuah jendela akan muncul dan menampilkan informasi tentang koneksi tersebut. Fitur ini hanya tersedia saat menghubungkan node dalam editor.

Mari kita ganti baris dengan passkata kunci dengan kode yang akan mengaktifkan gerakan simpul.
Sprite2D kita bergerak berkat kode dalam _process()fungsi tersebut. Godot menyediakan metode untuk mengaktifkan dan menonaktifkan pemrosesan: Node.set_process() . Metode lain dari kelas Node, is_processing(), mengembalikan truejika pemrosesan diam sedang aktif. Kita dapat menggunakan notkata kunci untuk membalikkan nilai.
func _on_button_pressed(): set_process(not is_processing())// We also specified this function name in PascalCase in the editor's connection window.private void OnButtonPressed(){ SetProcess(!IsProcessing());}Fungsi ini akan mengaktifkan pemrosesan dan, pada gilirannya, gerakan ikon menyala dan mati setelah tombol ditekan.
Sebelum mencoba permainan ini, kita perlu menyederhanakan _process()fungsi kita untuk memindahkan node secara otomatis dan tidak menunggu input pengguna. Ganti dengan kode berikut, yang kita lihat dua pelajaran lalu:
func _process(delta): rotation += angular_speed * delta var velocity = Vector2.UP.rotated(rotation) * speed position += velocity * deltapublic override void _Process(double delta){ Rotation += _angularSpeed * (float)delta; var velocity = Vector2.Up.Rotated(Rotation) * _speed; Position += velocity * (float)delta;}Kode lengkap Anda sprite_2d.gdakan terlihat seperti berikut.
extends Sprite2D
var speed = 400var angular_speed = PI
func _process(delta): rotation += angular_speed * delta var velocity = Vector2.UP.rotated(rotation) * speed position += velocity * delta
func _on_button_pressed(): set_process(not is_processing())using Godot;
public partial class MySprite2D : Sprite2D{ private float _speed = 400; private float _angularSpeed = Mathf.Pi;
public override void _Process(double delta) { Rotation += _angularSpeed * (float)delta; var velocity = Vector2.Up.Rotated(Rotation) * _speed; Position += velocity * (float)delta; }
// We also specified this function name in PascalCase in the editor's connection window. private void OnButtonPressed() { SetProcess(!IsProcessing()); }}Jalankan adegan sekarang dan klik tombol untuk melihat sprite mulai dan berhenti.
Menghubungkan sinyal melalui kode
Anda dapat menghubungkan sinyal melalui kode, bukan menggunakan editor. Hal ini diperlukan saat Anda membuat node atau membuat instance scene di dalam skrip.
Mari kita gunakan node yang berbeda di sini. Godot memiliki node Timer yang berguna untuk mengimplementasikan waktu cooldown skill, pengisian ulang senjata, dan banyak lagi.
Kembali ke ruang kerja 2D. Anda dapat mengeklik teks "2D" di bagian atas jendela atau menekan ( pada macOS).Ctrl + F1Ctrl + Cmd + 1
Di dock Scene, klik kanan pada node Sprite2D dan tambahkan node anak baru. Cari Timer dan tambahkan node yang sesuai. Scene Anda sekarang akan terlihat seperti ini.

Dengan simpul Timer dipilih, buka Inspektur dan aktifkan properti Autostart .

Klik ikon skrip di sebelah Sprite2D untuk kembali ke ruang kerja skrip.

Kita perlu melakukan dua operasi untuk menghubungkan node melalui kode:
Dapatkan referensi ke Timer dari Sprite2D.
Panggil
connect()metode pada sinyal "batas waktu" Timer.
Catatan
Untuk terhubung ke sinyal melalui kode, Anda perlu memanggil connect() metode sinyal yang ingin Anda dengarkan. Dalam kasus ini, kita ingin mendengarkan sinyal "batas waktu" Timer.
Kita ingin menghubungkan sinyal saat adegan diwujudkan, dan kita dapat melakukannya menggunakan fungsi bawaan Node._ready() , yang dipanggil secara otomatis oleh mesin saat node telah sepenuhnya diwujudkan.
Untuk mendapatkan referensi ke suatu node yang relatif terhadap node saat ini, kita menggunakan metode Node.get_node() . Kita dapat menyimpan referensi tersebut dalam suatu variabel.
func _ready(): var timer = get_node("Timer")public override void _Ready(){ var timer = GetNode<Timer>("Timer");}Fungsi ini get_node()melihat anak-anak Sprite2D dan mendapatkan simpul berdasarkan namanya. Misalnya, jika Anda mengganti nama simpul Timer menjadi "BlinkingTimer" di editor, Anda harus mengubah panggilan ke get_node("BlinkingTimer").
Sekarang kita dapat menghubungkan Timer ke Sprite2D dalam _ready()fungsi tersebut.
func _ready(): var timer = get_node("Timer") timer.timeout.connect(_on_timer_timeout)public override void _Ready(){ var timer = GetNode<Timer>("Timer"); timer.Timeout += OnTimerTimeout;}Barisnya berbunyi seperti ini: kita menghubungkan sinyal "batas waktu" Timer ke simpul tempat skrip terpasang. Saat Timer memancarkan timeout, kita ingin memanggil fungsi _on_timer_timeout(), yang perlu kita definisikan. Mari tambahkan di bagian bawah skrip kita dan gunakan untuk mengubah visibilitas sprite kita.
Catatan
Berdasarkan konvensi, kami menamai metode panggilan balik ini dalam GDScript sebagai "_on_node_name_signal_name" dan dalam C# sebagai "OnNodeNameSignalName". Di sini, akan menjadi "_on_timer_timeout" untuk GDScript dan OnTimerTimeout() untuk C#.
func _on_timer_timeout(): visible = not visibleprivate void OnTimerTimeout(){ Visible = !Visible;}Properti tersebut visibleadalah boolean yang mengontrol visibilitas node kita. Baris tersebut mengubah nilai. Jika , maka nilainya akan menjadi , dan sebaliknya.visible = not visiblevisibletruefalse
Jika Anda menjalankan adegan Node2D sekarang, Anda akan melihat sprite berkedip-kedip, dalam interval satu detik.
Naskah lengkap
Sekian demo ikon Godot yang bergerak dan berkedip! Berikut sprite_2d.gdberkas lengkapnya untuk referensi.
extends Sprite2D
var speed = 400var angular_speed = PI
func _ready(): var timer = get_node("Timer") timer.timeout.connect(_on_timer_timeout)
func _process(delta): rotation += angular_speed * delta var velocity = Vector2.UP.rotated(rotation) * speed position += velocity * delta
func _on_button_pressed(): set_process(not is_processing())
func _on_timer_timeout(): visible = not visibleusing Godot;public partial class MySprite2D : Sprite2D{private float _speed = 400;private float _angularSpeed = Mathf.Pi;public override void _Ready(){var timer = GetNode<Timer>("Timer");timer.Timeout += OnTimerTimeout;}public override void _Process(double delta){Rotation += _angularSpeed * (float)delta;var velocity = Vector2.Up.Rotated(Rotation) * _speed;Position += velocity * (float)delta;}// We also specified this function name in PascalCase in the editor's connection window.private void OnButtonPressed(){SetProcess(!IsProcessing());}private void OnTimerTimeout(){Visible = !Visible;}}
Sinyal khusus
Catatan
Bagian ini merupakan referensi tentang cara mendefinisikan dan menggunakan sinyal Anda sendiri, dan tidak membangun proyek yang dibuat dalam pelajaran sebelumnya.
Anda dapat menentukan sinyal khusus dalam skrip. Misalnya, Anda ingin menampilkan layar permainan berakhir saat kesehatan pemain mencapai nol. Untuk melakukannya, Anda dapat menentukan sinyal bernama "meninggal" atau "kesehatan_habis" saat kesehatan pemain mencapai 0.
extends Node2D
signal health_depleted
var health = 10using Godot;
public partial class MyNode2D : Node2D
{
[Signal]
public delegate void HealthDepletedEventHandler();
private int _health = 10;
}
Catatan
Karena sinyal melambangkan kejadian yang baru saja terjadi, kita umumnya menggunakan kata kerja tindakan dalam bentuk lampau pada nama sinyal tersebut.
Sinyal Anda bekerja dengan cara yang sama seperti sinyal bawaan: sinyal tersebut muncul di tab Node dan Anda dapat menghubungkannya seperti sinyal lainnya.

Untuk memancarkan sinyal dalam naskah Anda, panggil emit()sinyal tersebut.
func take_damage(amount): health -= amount if health <= 0: health_depleted.emit()public void TakeDamage(int amount){ _health -= amount;
if (_health <= 0) { EmitSignal(SignalName.HealthDepleted); }}Sinyal dapat secara opsional mendeklarasikan satu atau beberapa argumen. Tentukan nama argumen di antara tanda kurung:
extends Node2D
signal health_changed(old_value, new_value)
var health = 10using Godot;
public partial class MyNode : Node
{
[Signal]
public delegate void HealthChangedEventHandler(int oldValue, int newValue);
private int _health = 10;
}
Catatan
Argumen sinyal muncul di dock node editor, dan Godot dapat menggunakannya untuk menghasilkan fungsi panggilan balik untuk Anda. Namun, Anda tetap dapat memancarkan sejumlah argumen saat memancarkan sinyal. Jadi, terserah Anda untuk memancarkan nilai yang benar.
Untuk memancarkan nilai bersama dengan sinyal, tambahkan nilai tersebut sebagai argumen tambahan ke emit()fungsi:
func take_damage(amount): var old_health = health health -= amount health_changed.emit(old_health, health)public void TakeDamage(int amount){ int oldHealth = _health; _health -= amount; EmitSignal(SignalName.HealthChanged, oldHealth, _health);}Ringkasan
Setiap node di Godot memancarkan sinyal saat sesuatu yang spesifik terjadi pada node tersebut, seperti tombol yang ditekan. Node lain dapat terhubung ke sinyal individual dan bereaksi terhadap peristiwa yang dipilih.
Sinyal memiliki banyak kegunaan. Dengan sinyal, Anda dapat bereaksi terhadap node yang masuk atau keluar dari dunia permainan, terhadap tabrakan, terhadap karakter yang masuk atau keluar dari suatu area, terhadap elemen antarmuka yang berubah ukuran, dan masih banyak lagi.
Misalnya, Area2D yang mewakili koin memancarkan body_enteredsinyal setiap kali benda fisika pemain memasuki bentuk tumbukannya, yang memungkinkan Anda mengetahui kapan pemain mengumpulkannya.
Pada bagian berikutnya, Game 2D pertama Anda , Anda akan membuat game 2D lengkap dan mempraktikkan semua yang telah Anda pelajari sejauh ini.


Tidak ada komentar:
Posting Komentar