Mengkodekan pemain
Dalam pelajaran ini, kita akan menambahkan pergerakan pemain, animasi, dan mengaturnya untuk mendeteksi tabrakan.
Untuk melakukannya, kita perlu menambahkan beberapa fungsi yang tidak bisa kita dapatkan dari node bawaan, jadi kita akan menambahkan skrip. Klik Playernode dan klik tombol "Lampirkan Skrip":

Di jendela pengaturan skrip, Anda dapat membiarkan pengaturan default apa adanya. Cukup klik "Buat":
Catatan
Jika Anda membuat skrip C# atau bahasa lainnya, pilih bahasa dari menu tarik-turun bahasa sebelum menekan buat.

Catatan
Jika ini pertama kalinya Anda menggunakan GDScript, silakan baca Bahasa skrip sebelum melanjutkan.
Mulailah dengan mendeklarasikan variabel anggota yang dibutuhkan objek ini:
extends Area2D
@export var speed = 400 # How fast the player will move (pixels/sec).var screen_size # Size of the game window.using Godot;
public partial class Player : Area2D{ [Export] public int Speed { get; set; } = 400; // How fast the player will move (pixels/sec).
public Vector2 ScreenSize; // Size of the game window.}Menggunakan exportkata kunci pada variabel pertama speedmemungkinkan kita untuk menetapkan nilainya di Inspektur. Ini berguna untuk nilai yang ingin Anda sesuaikan seperti properti bawaan node. Klik node Player dan Anda akan melihat properti tersebut sekarang muncul di Inspektur di bagian baru dengan nama skrip. Ingat, jika Anda mengubah nilai di sini, itu akan menggantikan nilai yang ditulis dalam skrip.
Peringatan
Jika Anda menggunakan C#, Anda perlu (membuat ulang) rakitan proyek setiap kali Anda ingin melihat variabel atau sinyal ekspor baru. Pembuatan ini dapat dipicu secara manual dengan mengeklik tombol Build di kanan atas editor.


Skrip Anda player.gdseharusnya sudah berisi _ready()dan _process()fungsi. Jika Anda tidak memilih templat default yang ditampilkan di atas, buat fungsi-fungsi ini sambil mengikuti pelajaran.
Fungsi ini _ready()dipanggil saat sebuah node memasuki pohon adegan, yang merupakan waktu yang tepat untuk menemukan ukuran jendela permainan:
func _ready(): screen_size = get_viewport_rect().sizepublic override void _Ready(){ ScreenSize = GetViewportRect().Size;}Sekarang kita dapat menggunakan _process()fungsi tersebut untuk menentukan apa yang akan dilakukan pemain. _process()dipanggil setiap frame, jadi kita akan menggunakannya untuk memperbarui elemen permainan kita, yang kita harapkan akan sering berubah. Untuk pemain, kita perlu melakukan hal berikut:
Periksa masukan.
Bergerak ke arah yang diberikan.
Putar animasi yang sesuai.
Pertama, kita perlu memeriksa input - apakah pemain menekan tombol? Untuk permainan ini, kita memiliki 4 input arah untuk diperiksa. Tindakan input didefinisikan dalam Pengaturan Proyek di bawah "Peta Input". Di sini, Anda dapat mendefinisikan peristiwa khusus dan menetapkan tombol yang berbeda, peristiwa tetikus, atau input lainnya ke dalamnya. Untuk permainan ini, kita akan memetakan tombol panah ke empat arah.
Klik Project -> Project Settings untuk membuka jendela pengaturan proyek dan klik tab Input Map di bagian atas. Ketik "move_right" di bilah atas dan klik tombol "Add" untuk menambahkan move_righttindakan.

Kita perlu menetapkan kunci untuk tindakan ini. Klik ikon "+" di sebelah kanan, untuk membuka jendela pengelola acara.

Kolom "Mendengarkan Input..." akan otomatis dipilih. Tekan tombol "kanan" pada keyboard Anda, dan menu akan terlihat seperti ini sekarang.

Pilih tombol "ok". Tombol "kanan" sekarang dikaitkan dengan move_righttindakan.
Ulangi langkah-langkah ini untuk menambahkan tiga pemetaan lagi:
move_leftdipetakan ke tombol panah kiri.move_updipetakan ke tombol panah atas.Dan
move_downdipetakan ke tombol panah bawah.
Tab peta masukan Anda akan terlihat seperti ini:

Klik tombol "Tutup" untuk menutup pengaturan proyek.
Catatan
Kami hanya memetakan satu tombol untuk setiap tindakan input, tetapi Anda dapat memetakan beberapa tombol, tombol joystick, atau tombol mouse ke tindakan input yang sama.
Anda dapat mendeteksi apakah tombol ditekan menggunakan Input.is_action_pressed(), yang akan menampilkan trueapakah tombol ditekan atau falsetidak.
func _process(delta): var velocity = Vector2.ZERO # The player's movement vector. if Input.is_action_pressed("move_right"): velocity.x += 1 if Input.is_action_pressed("move_left"): velocity.x -= 1 if Input.is_action_pressed("move_down"): velocity.y += 1 if Input.is_action_pressed("move_up"): velocity.y -= 1
if velocity.length() > 0: velocity = velocity.normalized() * speed $AnimatedSprite2D.play() else: $AnimatedSprite2D.stop()public override void _Process(double delta){ var velocity = Vector2.Zero; // The player's movement vector.
if (Input.IsActionPressed("move_right")) { velocity.X += 1; }
if (Input.IsActionPressed("move_left")) { velocity.X -= 1; }
if (Input.IsActionPressed("move_down")) { velocity.Y += 1; }
if (Input.IsActionPressed("move_up")) { velocity.Y -= 1; }
var animatedSprite2D = GetNode<AnimatedSprite2D>("AnimatedSprite2D");
if (velocity.Length() > 0) { velocity = velocity.Normalized() * Speed; animatedSprite2D.Play(); } else { animatedSprite2D.Stop(); }}Kita mulai dengan menetapkan velocityke - secara default, pemain tidak boleh bergerak. Kemudian kita periksa setiap masukan dan tambahkan/kurangi dari untuk memperoleh arah total. Misalnya, jika Anda menahan dan pada saat yang sama, vektor yang dihasilkan akan menjadi . Dalam kasus ini, karena kita menambahkan gerakan horizontal dan vertikal, pemain akan bergerak lebih cepat secara diagonal daripada jika hanya bergerak secara horizontal.(0, 0)velocityrightdownvelocity(1, 1)
Kita dapat mencegahnya jika kita menormalkan kecepatan, yang berarti kita menetapkan panjangnya menjadi , 1lalu mengalikannya dengan kecepatan yang diinginkan. Ini berarti tidak ada lagi gerakan diagonal yang cepat.
Tip
Jika Anda belum pernah menggunakan matematika vektor sebelumnya, atau butuh penyegaran, Anda dapat melihat penjelasan tentang penggunaan vektor di Godot di Matematika vektor . Ada baiknya untuk diketahui tetapi tidak akan diperlukan untuk sisa tutorial ini.
Kami juga memeriksa apakah pemain sedang bergerak sehingga kami dapat memanggil play()atau stop()pada AnimatedSprite2D.
Tip
$adalah kependekan dari get_node(). Jadi dalam kode di atas, $AnimatedSprite2D.play()sama dengan get_node("AnimatedSprite2D").play().
Dalam GDScript, $mengembalikan node pada jalur relatif dari node saat ini, atau mengembalikan nulljika node tidak ditemukan. Karena AnimatedSprite2D adalah anak dari node saat ini, kita dapat menggunakan $AnimatedSprite2D.
Sekarang setelah kita memiliki arah gerakan, kita dapat memperbarui posisi pemain. Kita juga dapat menggunakan clamp()untuk mencegahnya meninggalkan layar. Menjepit nilai berarti membatasinya pada rentang tertentu. Tambahkan yang berikut di bagian bawah fungsi _process(pastikan tidak menjorok di bawah else ):
position += velocity * deltaposition = position.clamp(Vector2.ZERO, screen_size)Position += velocity * (float)delta;Position = new Vector2( x: Mathf.Clamp(Position.X, 0, ScreenSize.X), y: Mathf.Clamp(Position.Y, 0, ScreenSize.Y));
Tip
Parameter delta dalam fungsi _process() mengacu pada panjang frame - jumlah waktu yang dibutuhkan frame sebelumnya untuk selesai. Menggunakan nilai ini memastikan bahwa gerakan Anda akan tetap konsisten meskipun frame rate berubah.
Klik "Jalankan Adegan Saat Ini" ( F6, di macOS) dan konfirmasikan bahwa Anda dapat menggerakkan pemutar di sekitar layar ke segala arah.Cmd + R
Peringatan
Jika Anda mendapatkan kesalahan di panel "Debugger" yang mengatakan
Attempt to call function 'play' in base 'null instance' on a null instance
ini kemungkinan berarti Anda salah mengeja nama node AnimatedSprite2D. Nama node peka huruf besar-kecil dan $NodeNameharus sesuai dengan nama yang Anda lihat di pohon adegan.
Memilih animasi
Sekarang pemain dapat bergerak, kita perlu mengubah animasi mana yang dimainkan AnimatedSprite2D berdasarkan arahnya. Kita memiliki animasi "berjalan", yang memperlihatkan pemain berjalan ke kanan. Animasi ini harus dibalik secara horizontal menggunakan flip_hproperti untuk gerakan ke kiri. Kita juga memiliki animasi "atas", yang harus dibalik secara vertikal flip_vuntuk gerakan ke bawah. Mari kita tempatkan kode ini di akhir fungsi _process():
if velocity.x != 0: $AnimatedSprite2D.animation = "walk" $AnimatedSprite2D.flip_v = false # See the note below about the following boolean assignment. $AnimatedSprite2D.flip_h = velocity.x < 0elif velocity.y != 0: $AnimatedSprite2D.animation = "up" $AnimatedSprite2D.flip_v = velocity.y > 0if (velocity.X != 0){ animatedSprite2D.Animation = "walk"; animatedSprite2D.FlipV = false; // See the note below about the following boolean assignment. animatedSprite2D.FlipH = velocity.X < 0;}else if (velocity.Y != 0){ animatedSprite2D.Animation = "up"; animatedSprite2D.FlipV = velocity.Y > 0;}
Catatan
Penetapan nilai boolean dalam kode di atas merupakan singkatan umum bagi para programmer. Karena kita melakukan uji perbandingan (boolean) dan juga menetapkan nilai boolean, kita dapat melakukan keduanya secara bersamaan. Pertimbangkan kode ini dibandingkan dengan penetapan nilai boolean satu baris di atas:
if velocity.x < 0: $AnimatedSprite2D.flip_h = trueelse: $AnimatedSprite2D.flip_h = falseif (velocity.X < 0){ animatedSprite2D.FlipH = true;}else{ animatedSprite2D.FlipH = false;}
Putar kembali adegan tersebut dan periksa apakah animasi sudah benar di setiap arah.
Tip
Kesalahan umum di sini adalah salah mengetik nama animasi. Nama animasi di panel SpriteFrames harus sesuai dengan apa yang Anda ketik di kode. Jika Anda memberi nama animasi "Walk", Anda juga harus menggunakan huruf kapital "W" di kode.
Bila Anda yakin pergerakannya berjalan dengan benar, tambahkan baris ini ke _ready(), sehingga pemain akan disembunyikan saat permainan dimulai:
hide()Mempersiapkan diri menghadapi tabrakan
Kami ingin Playermendeteksi saat diserang musuh, tetapi kami belum membuat musuh! Tidak apa-apa, karena kami akan menggunakan fungsi sinyal Godot agar berfungsi.
Tambahkan yang berikut di bagian atas skrip. Jika Anda menggunakan GDScript, tambahkan setelah . Jika Anda menggunakan C#, tambahkan setelah :extends Area2Dpublic partial class Player : Area2D
signal hit
// Don't forget to rebuild the project so the editor knows about the new signal.
[Signal]public delegate void HitEventHandler();Ini mendefinisikan sinyal khusus yang disebut "hit" yang akan dipancarkan (dikirim) oleh pemain saat bertabrakan dengan musuh. Kita akan menggunakannya Area2Duntuk mendeteksi tabrakan. Pilih Playernode dan klik tab "Node" di samping tab Inspector untuk melihat daftar sinyal yang dapat dipancarkan pemain:

Perhatikan sinyal "hit" kustom kita juga ada di sana! Karena musuh kita akan menjadi RigidBody2Dnode, kita menginginkan sinyalnya. Sinyal ini akan dipancarkan saat tubuh menyentuh pemain. Klik "Connect.." dan jendela "Connect a Signal" akan muncul.body_entered(body: Node2D)
Godot akan membuat fungsi dengan nama yang sama persis langsung dalam skrip untuk Anda. Anda tidak perlu mengubah pengaturan default saat ini.
Peringatan
Jika Anda menggunakan editor teks eksternal (misalnya, Visual Studio Code), ada bug yang mencegah Godot melakukannya. Anda akan diarahkan ke editor eksternal, tetapi fungsi baru tidak akan ada di sana.
Dalam kasus ini, Anda perlu menuliskan sendiri fungsi tersebut ke dalam berkas skrip Player.

Perhatikan ikon hijau yang menunjukkan bahwa sinyal tersambung ke fungsi ini; ini tidak berarti fungsi tersebut ada, hanya saja sinyal akan mencoba tersambung ke fungsi dengan nama tersebut, jadi periksa kembali apakah ejaan fungsi tersebut sama persis!
Selanjutnya, tambahkan kode ini ke fungsi:
func _on_body_entered(body): hide() # Player disappears after being hit. hit.emit() # Must be deferred as we can't change physics properties on a physics callback. $CollisionShape2D.set_deferred("disabled", true)// We also specified this function name in PascalCase in the editor's connection window.private void OnBodyEntered(Node2D body){ Hide(); // Player disappears after being hit. EmitSignal(SignalName.Hit); // Must be deferred as we can't change physics properties on a physics callback. GetNode<CollisionShape2D>("CollisionShape2D").SetDeferred(CollisionShape2D.PropertyName.Disabled, true);}Setiap kali musuh menyerang pemain, sinyal akan dipancarkan. Kita perlu menonaktifkan tabrakan pemain agar kita tidak memicu sinyal hitlebih dari satu kali.
Catatan
Menonaktifkan bentuk tabrakan area dapat menyebabkan kesalahan jika terjadi di tengah pemrosesan tabrakan mesin. Menggunakan set_deferred()memberi tahu Godot untuk menunggu hingga aman untuk menonaktifkan bentuk tersebut.
Bagian terakhir adalah menambahkan fungsi yang dapat kita panggil untuk mengatur ulang pemain saat memulai permainan baru.
func start(pos): position = pos show() $CollisionShape2D.disabled = falsepublic void Start(Vector2 position){ Position = position; Show(); GetNode<CollisionShape2D>("CollisionShape2D").Disabled = false;}Setelah pemain bekerja, kita akan menangani musuh di pelajaran berikutnya.


Tidak ada komentar:
Posting Komentar