Selamat datang di bagian ke 7 dari seri
tutorial membuat RPG di Construct 2. Kali ini aku akan mencoba
mengimplementasikan AI seperti yang sudah aku desain sebelumnya. Aku
akan mencoba membuatnya dalam 1 blog post, tapi kalau nggak bisa,
berarti blog post ini cuma mencakup AI penyerang fisik.
Pertama-tama aku ingin memastikan bahwa
semua petarung di battle scene tahu tentang musuh-musuhnya, karena AI
kedua tipe musuh juga akan bergantung dari data ini. Awalnya aku
berencana memakai family buat keperluan ini. Tapi ternyata aku nggak
bisa menambah / mengurangi member family ini lewat event, padahal
buat kebutuhan ini aku harus bisa mengganti member family secara
dinamis lewat event (karena tiap battle, musuhnya beda-beda, dan
party member pun bisa diganti secara bebas oleh pemain). Jadi untuk
mengatasi ini, aku akan membuat array yang berisi data petarung dari
party member dan juga dari musuh, array ini bernama enemyPartyArr
dan playerPartyArr. Kedua array ini
hanya berisi maksimal 4 elemen, karena kita memang membatasi jumlah
petarung di sisi player dan musuh dalam battle. Ini juga mengubah
fungsi family Friendly, dulunya family ini berisi semua party member
yang bertarung, tapi sekarang mungkin lebih cocok berisi semua
character dalam game yang bisa bergabung bersama pemain.
Aku mengubah apa yang terjadi di event
on start of layout, sekarang kita memberi nama pada battleName musuh
dan juga mengisi kedua array petarung, saat ini isinya hanya ada satu
tapi nanti isinya akan berbeda-beda.
Kemudian aku membuat instance variable
enemySelection di kedua family. Untuk
memudahkan kita untuk membedakan nantinya, di family Enemies akan aku
namai playerSelection sedangkan di
family Friendly aku namai enemySelection.
Keduanya memiliki nilai awal "closest". Di bagian bawah,
aku membuat function baru bernama "enemySelTarget" yang
akan digunakan oleh musuh untuk mencari target pemain. Fungsi ini
menerima dua parameter, yaitu nama musuh yang akan mengganti target,
dan AI pemilihan target si musuh.
Di awal function ini, kita langsung
menyimpan posisi musuh sekarang ke dalam dua local variable, kita
mendapat instance musuh dari battleName musuh yang sama dengan
parameter pertama (index 0), ini nanti akan kita gunakan untuk
menghitung jarak dengan karakter pemain. Kemudian kita melihat isi
parameter kedua dan menjalankan kode mencari target sesuai dengan
nama AI. Pertama-tama kita melihat apakah nama AI adalah "closest",
jika benar maka kita mulai mencari karakter pemain yang paling dekat
dengan musuh ini. Kita me-loop dari 1 sampai 4 (karena jumlah party
member maksimal adalah 4), kemudian jika ada member family Friendly
yang bernama sama dengan elemen playerPartyArr, berarti itu adalah
objek karakter pemain atau party member yang ikut dalam battle, kita
akan langsung hitung jaraknya dengan musuh dengan expression
distance(), hasilnya akan kita buat positif dengan expression abs()
untuk kemudian kita masukkan dalam array playerDistance. Kenapa
hasilnya harus kita buat positif dengan abs() lebih dulu? Karena
sewaktu fungsi ini dipanggil, posisi karakter pemain bisa saja di
kiri atau kanan pemain, sehingga nilai distance bisa negatif atau
positif. Untuk memastikan musuh selalu memilih karakter terdekat
tidak peduli apakah karakter itu ada di kiri atau kanan musuh,
nilainya harus aku buat absolut.
Sesudah itu ada satu event lagi sewaktu
loopindex bernilai 4, ini berarti loop sudah berakhir dan sudah
waktunya untuk mencari nilai terendah dari jarak pemain. Untuk
melakukannya mudah saja, kita masukkan nilai-nilai jarak tadi ke
dalam expression min(), yang akan mengembalikan nilai terkecil dari
nilai-nilai yang dimasukkan ke dalamnya, hasilnya akan kita simpan
dalam local variable closestDistance.
Sesudah kita mendapat jarak terdekat,
kita perlu tahu karakter pemain mana yang berjarak terdekat ini.
Caranya mudah, karena kita sudah mengisi playerDistance dengan jarak
pemain di index yang sama dengan index nama pemainnya, kita tinggal
me-loop array playerDistance untuk mencari nilai closestDistance.
Kalau ketemu, berarti kita dapat indexnya karakter pemain, isi local
variable selectedTarget dengan elemen array playerPartyArr di index
yang sama. Lalu kita kembalikan selectedTarget untuk digunakan oleh
si musuh, dan akhiri loop-nya.
Setelah itu ada event untuk mencari
karakter pemain yang terjauh dari musuh. Ini sebenarnya sama saja
seperti fungsi untuk mencari musuh terdekat, hanya bedanya di akhir
loop playerPartyLoop (sewaktu loopindex bernilai 4), kita mencari
nilai terbesar untuk menemukan karakter terjauh, jadi kita mengganti
expression min() dengan max(). Sesudah itu, kita mengembalikan nilai
selectedTarget untuk digunakan oleh si musuh.
Dua event berikutnya adalah untuk
mencari karakter dengan current HP terbanyak dan tersedikit. Logika
yang dipakai di dua event ini sama saja dengan yang dipakai di logika
pencarian pemain berdasarkan jarak, hanya variabelnya saja yang
berbeda. Kalian pasti bisa mengerti dengan mudah. Terakhir untuk
pencarian karakter penyihir ("mages"), aku rasa aku perlu
semacam tag untuk menandai karakter mana yang penyihir atau bukan,
mungkin akan aku tambahkan nanti.
Sesudah kita mendapatkan nama targetnya
musuh, kita akan mulai menggunakan variabel ini. Pertama-tama
tambahkan dulu instance variable targetName di family Enemies. Lalu
kita harus menentukan di mana kita menggunakan function
enemySelTarget, mungkin di awal layout adalah pilihan yang bagus,
jadi panggil enemySelTarget dengan dua parameter, battleName dan juga
playerSelection si yellow wolf.
Berikutnya kita akan menambahkan event
untuk mendekati target (pemain) seperti sebelumnya, tapi kali ini
dengan bantuan sistem AI baru. Buatlah event baru yang mengecek
jikalau targetName dari Enemies tidak sama dengan kosong, kalau nggak
kosong cari member family Friendly yang memiliki nama yang sama, lalu
dekati dia. Kita belum mengatur soal cara musuh menyerang karena kita
belum menyentuh AI penyerangan. Kalau begitu, mari kita mulai
menyentuh AI menyerang.
Pertama-tama kita buat dulu instance
variable di family Enemies bernama attackMethod, untuk menyimpan AI
untuk menyerang, nilai default-nya adalah "normals". Di
event yang membuat musuh mendekati target (pemain), sesudah musuh
cukup dekat dengan targetnya tambahkan event-event baru yang mengecek
nilai attackMethod musuh.
Sesudah in ikita akan mencoba membuat
musuh menyerang, tapi sebelum itu kita harus menentukan di mana
attack effect buat serangan musuh akan muncul. Jadi, double click di
objek yellowWolf (bukan di sprite-nya) dan tambahkan dua lagi image
point bernama Attack1 dan Attack2, masing-masing untuk menyerang di
kanan dan kiri. Lalu kita juga harus membuat family baru bernama
EnemyAttackFX yang berisi efek serangan musuh, ini sama seperti yang
dimiliki pemain.
Sekarang tambahkan action di event
Enemies | attackMethod = "normals". Saat ini kita baru bisa
menambahkan serangan fisik karena kita belum merumuskan daftar skill
musuh dan bagaimana menggunakannya. Cara musuh menyerang sama seperti
pemain, dan nantinya kita juga masih harus memikirkan bagaimana cara
musuh memilih attack effect, karena ga mungkin semua musuh menyerang
dengan cara menggigit.
Terakhir adalah memberikan kemampuan
bertahan pada musuh. Pertama-tama kita akan membuat family instance
variable bernama defenseMethod dengan nilai default "defenseless".
Sesudah itu kita akan membuat function baru bernama on
enemyDefenseMethod. Function ini akan menerima satu parameter, yaitu
nama AI pertahanan musuh, nanti function ini akan mengembalikan entah
nilai 0 atau 1, kalau nilainya 0 musuh tidak akan bertahan tapi kalau
1 maka musuh akan bertahan.
Untuk membuat musuh bisa bertahan,
berarti harus ada state-nya, buat satu lagi family instance variable
di Enemies bernama state, nanti nilai state ini tergantung dari nilai
kembalian dari on enemyDefenseMethod, kita juga perlu mengganti
animasinya nanti. Kita juga harus mengatur berapa lama pemain
bertahan (atau diam saja, seperti state rest karakter pemain), jadi
tambahkan satu family behaviour, yaitu timer.
Sekarang, kita panggil function tadi
sesudah musuh menyerang, lalu kita lihat apa return value-nya dan
menentukan apa yang akan dilakukan oleh musuh sesudah itu.
Dan sama seperti karakter pemain, kita
juga harus menghilangkan state musuh ketika waktunya berakhir.
Kemudian kita harus menulis code dengan
cara sedemikian rupa supaya musuh nggak menyerang sewaktu mereka lagi
rest atau defending. Karena itu, kita akan ubah sedikit code di
bagian sewaktu pemain mulai menyerang.
Yak, seharusnya kode-kode dasar untuk
AI musuh sudah selesai, tapi karena aku lagi capek dan sudah lama
nggak update blog, untuk sementara aku tinggalkan seperti ini dan
akan lanjut di lain waktu. Silahkan mencoba dan kalau ada bug kamu
bisa menulisnya di komentar, atau mencoba mengatasi bug-nya sendiri,
atau menunggu blog post-ku yang menulis soal blog itu. Sampai ketemu
di post berikutnya.
(by the way, capx terbaru bisa diambil di https://dl.dropboxusercontent.com/u/22420086/My%20RPG%20project.capx )
Tidak ada komentar:
Posting Komentar