Advertisement
Scroll to top
Read Time: 15 min

() translation by (you can also view the original English article)

Sebuah mekanik yang umum dalam game action adalah adanya musuh yang dapat mengurangi beberapa jenis item atau hadiah saat hampir mati.  Karakter itu dapat mengumpulkan hasil curian/loot untuk mendapatkan beberapa keuntungan.  Mekanik ini banyak diharapkan dalam pertandingan, seperti RPG, karena memberikan dorongan pemain untuk menyingkirkan musuh-serta melakukan ledakan kecil dari endorfin ketika menemukan hadiah.

Dalam tutorial ini, kami akan meninjau inner mekanik tersebut dan melihat bagaimana cara untuk menerapkannya, dengan apa pun jenis permainan serta alat coding / bahasa yang Anda gunakan.

Pada contoh kali ini saya gunakan demonstrate yang dibuat menggunakan Membangun 2, sebuah alat membuat permainan HTML5, tapi tidak secara khusus dengan alat itu.  Anda harus dapat menerapkan mekanik yang sama pada bahasa coding atau alat yang digunakan.

Contoh dibuat di r167.2 dan dapat dibuka serta diedit dalam software versi gratis.  Anda dapat men-download versi terbaru dari Construct 2 disini (sejak saya mulai menulis artikel ini, setidaknya ada dua versi yang lebih baru telah dirilis) dan dengan contoh yang sesuai keinginan Anda. Sumber file contoh CAPX yang melekat pada tutorial ini dalam file bentuk zip. Sumber file contoh CAPX yang melekat pada tutorial ini dalam file bentuk zip.

The Mechanic Basic

Fungsi dipanggil Setelah kematian musuh (ketika HP kurang dari atau sama dengan nol).  Peran fungsi ini adalah untuk menentukan apakah ada penurunan atau tidak, dan, jika ada pengurangan maka jenis harus dijatuhkan.

Fungsi ini juga dapat menangani penciptaan representasi visual dari drop, pemijahan di bekas koordinat layar musuh.

Perhatikan contoh berikut:

Klik tombol Bunuhlah 100 Beasts.  Kemudian akan menjalankan proses batch yang menciptakan 100 binatang acak, bunuh mereka, dan akan menampilkan hasilnya untuk setiap binatang (yaitu, apakah binatang itu menghancurkan item, dan jika iya jenis barang apa).  Di bagian bawah tampilan layar terdapat statistic yang menyatakan berapa banyak binatang yang menjatuhkan item, dan berapa banyak setiap jenis item yang dijatuhkan.

Contoh ini adalah berisi teks yang dapat menunjukkan logika di balik fungsi, dan mekanik ini dapat diterapkan untuk semua jenis permainan, baik platformer yang mana Anda menginjak musuh, atau top-down tampilan shooter, atau RPG.

Mari kita lihat bagaimana demo ini bekerja.  Pertama, binatang dan drop masing-masing terkandung dalam aturan.  Berikut aturan binatang:

Index (X)
Name (Y-0)
Drop rate (Y-1)
Kelangkaan item (Y-2)
0 Boar 100 100
1 Goblin 75 75
2 Squire 65 55
3 ZogZog 45 100
4 Owl 15 15
5 Mastodon 35 50

 Dan inilah aturan drops:

Index (X)
Name (Y-0)
Kelangkaan item (Y-1)
0 Lollipop 75
1 Gold 50
2 Rocks 95
3 Jewel 25
4 Incense 35
5 Equipment 15

nilai X (Index kolom) menyatakan aturan yang digunakan sebagai identifikasi keunikan untuk binatang atau jenis item.  Misalnya, binatang indeks 0 adalah Boar.  Item indeks 3 adalah Jewel.

Aturan ini bertindak sebagai tabel lookup bagi kita, berisi nama atau jenis setiap binatang atau item, serta nilai-nilai lain yang memungkinkan kita untuk menentukan kelangkaan atau tingkat drop.  Dalam aturan binatang, ada dua kolom lagi setelah nama:

Drop rate adalah seberapa besar kemungkinan binatang itu menjatuhkan item saat dibunuh.  Misalnya, babi akan memiliki 100% kesempatan untuk menjatuhkan item saat dibunuh, sedangkan burung hantu memiliki 15% kesempatan untuk melakukan hal yang sama.

Kelangkaan mendefinisikan item yang jarang dijatuhkan oleh binatang ini. Misalnya, babi hutan akan cenderung drop item dengan nilai kelangkaan 100.  Sekarang, jika kita memeriksa aturan drop, kita dapat melihat bahwa batu-batu adalah item dengan kelangkaan terbesar (95).  (Meskipun tingginya nilai kelangkaan disebabkan karena cara saya program pada fungsi, dengan semakin besar jumlah kelangkaan menyatakan semakin umumnya item tersebut.  Batu akan memiliki kesempatan lebih besaruntuk dijatuhkan dibandingkan item dengan nilai kelangkaan rendah.)

Dan yang menarik bagi kita mengenai perspektif desain game. Untuk keseimbangan permainan, kami tidak ingin pemain mendapatkan akses terlalu banyak peralatan atau terlalu banyak item high-end -jika tidak seperti itu, karakter mungkin akan mudah menguasai, dan permainan akan kurang menarik untuk dimainkan .

Tabel dan nilai-nilai tersebut hanya merupakan contoh, dan Anda dapat bermain dengan menyesuaikannya sistem permainan Anda sendiri dan permainan pada umumnya.  Itu semua tergantung pada keseimbangan sistem Anda.  Jika Anda ingin mempelajari lebih lanjut masalah balancing, saya sarankan Anda mempelajari rangkaian tutorial: Balancing Turn-Based RPGs.

Sekarang mari kita lihat pseudo kode untuk demo:

1
CONSTANT BEAST_NAME = 0
2
CONSTANT BEAST_DROPRATE = 1
3
CONSTANT BEAST_RARITY = 2
4
CONSTANT DROP_NAME = 0
5
CONSTANT DROP_RATE = 1
6
//Those constants are used for a better readability of the arrays
7
8
On start of the project, fill the arrays with the correct values
9
array aBeast(6,3)   //The array that contains the values for each beast
10
array aDrop(6,2)    //The array that contains the values for each item
11
array aTemp(0)      //A temporary array that will allow us what item type to drop
12
array aStats(6)     //The array that will contain the amount of each item dropped
13
14
On button clicked
15
    Call function "SlainBeast(100)"
16
17
Function SlainBest (Repetitions)
18
    int BeastDrops = 0 //The variable that will keep the count of how many beasts did drop item
19
    Text.text = ""
20
    aStats().clear //Resets all the values contained in this array to make new statistics for the current batch
21
    Repeat Repetitions times
22
        int BeastType
23
        int DropChance
24
        int Rarity
25
        BeastType = Random(6) //Since we have 6 beasts in our array
26
        Rarity = aBeast(BeastType, BEAST_RARITY) //Get the rarity of items the beast should drop from the aBeast array
27
        DropChance = ceil(random(100)) //Picks a number between 0 and 100)
28
        Text.text = Text.text & loopindex & " _ " & aBeast(BeastType,BEAST_NAME) & "is slain"
29
        
30
        If DropChance > aBeast(BeastType,BEAST_DROPRATE)
31
            //The DropChance is bigger than the droprate for this beast
32
            Text.text = Text.text & "." & newline
33
            //We stop here, this beast is considered to not have dropped an item.
34
        
35
        If DropChance <= aBeast(BeastType,BEAST_DROPRATE)
36
           Text.text = Text.Text & " dropping " //We will put some text to display what item was dropped
37
           //On the other hand, DropChance is less or equal the droprate for this beast
38
            aTemp(0) //We clear/clean the aTemp array in which we will push entries to determine what item type to drop
39
                For a = 0 to aDrop.Width //We will loop through every elements of the aDrop array
40
                    aDrop(a,DROP_RATE) >= Rarity //When the item drop rate is greater or equal the expected Rarity
41
                        Push aTemp,a //We put the current a index in the temp array. We know that this index is a possible item type to drop
42
                int DropType
43
                DropType = random(aTemp.width) //The DropType is one of the indexes contained in the temporary array
44
                Text.text = Text.text & aDrop(DropType, DROP_NAME) & "." & newline //We display the item name that was dropped
45
                //We do some statistics
46
                aStats(DropType) = aStats(DropType) + 1
47
                BeastDrops = BeastDrops + 1
48
            TextStats.Text = BeastDrops & " beasts dropped items." & newline
49
            For a = 0 to aStats.width //Display each item amount that was dropped
50
            and aStats(a) > 0
51
                TextStats.Text = TextStats.Text & aStats(a) & " " & aDrop(a,DROP_NAME) & " "
52
    

tindakan Pertama,pengguna: mengklik tombol Bunuhlah 100 Beasts. Tombol ini memanggil fungsi dengan parameter 100, hanya karena 100 merupakan jumlah baik untuk membunuh musuh.  Dalam permainan nyata, memungkinkan Anda untuk membunuh binatang satu per satu.

Dari ini, fungsi SlainBeast dipanggil. Tujuannya adalah untuk menampilkan beberapa teks untuk memberikan feedback pada pengguna tentang apa yang terjadi.  Pertama, membersihkan yang variabel BeastDrops dan aturan aStats , yang digunakan untuk statistik.  Dalam permainan nyata, tidak mungkin Anda membutuhkan mereka.  Ini dapat membersihkan Teks juga, sehingga 100 baris akan ditampilkan untuk melihat hasil batch ini.  Dalam fungsi itu sendiri, terdapat tiga variabel numerik yang diciptakan: BeastType, DropChance, dan Kelangkaan.

BeastType merupakan indeks yang kita gunakan untuk merujuk baris tertentu dalam array aBeast; yang pada dasarnya merupakan jenis binatang yang yang harus dibunuh atau dihadapi pemain.  Kelangkaan diambil dari array aBeast juga; itu kelangkaan item binatang ini harus dijatuhkan, nilai bidang kelangkaan Item berada dalam array aBeast.

Akhirnya, DropChance adalah berisi nomor yang kami isikan secara acak antara 0 dan 100.  (Kebanyakan bahasa coding akan memiliki fungsi untuk mendapatkan nomor acak dalam jangkauan, atau setidaknya mendapatkan nomor acak antara 0 dan 1, yang bisa Anda kalikan dengan 100.)

pada titik ini, kita dapat menampilkan bit pertama yang berisi informasi dalam objek Teks: kita sudah tahu jenis binatang apa yang melahirkan dan dibunuh.  Jadi, kami menggabungkan nilai saat ini pada Text.text  BEAST_NAME dalam BeastType telah kami telah kami pilih secara acak, pada array aBeast.

Berikutnya, kita harus menentukan item yang harus dijatuhkan.  Kami melakukannya dengan membandingkan DropChancevalue dengan nilai BEAST_DROPRATE dari array aBeast.  Jika DropChance kurang dari atau sama dengan nilai ini, kita drop item.

(Saya memutuskan untuk menggunakan pendekatan "kurang dari atau sama dengan", yang telah dipengaruhi oleh pemain peran hidup ini menggunakan D&D King Artur: Pendragon set of rules sebagai gulungan dadu, tetapi Anda bisa, memutuskan drop hanya akan terjadi ketika "lebih besar atau sama".  ini hanya merupakan nilai-nilai numerik dan logika.  Namun, jangan konsisten, dan tidak mengubah setengah logika selama alogaritma anda-jika tidak, Anda bisa mendapat masalah ketika mencoba debug atau mempertahankannya.)

Jadi, ada dua baris yang dapat menentukan apakah item dijatuhkan atau tidak. Pertama:

1
DropChance > aBeast(BeastType,BEAST_DROPRATE)

Di sini, DropChance lebih besar dari DropRate, dan ini berarti ada item yang dijatuhkan.  Dari sini, satu-satunya hal yang ditampilkan di penutupan adalah "" (titik) yang berakhir dengan kalimat, "[BeastType] dibunuh.",  sebelum pindah ke musuh berikutnya dalam batch kami.

Di sisi lain:

1
DropChance <= aBeast(BeastType,BEAST_DROPRATE)

Di sini, DropChance kurang dari atau sama dengan DropRate untuk BeastType saat ini, dan hal ini berarti  item dijatuhkan.  Untuk melakukannya, kita membandingkan antara Kelangkaan item pada BeastType saat ini "diperbolehkan" untuk menjatuhkan, dan beberapa nilai kelangkaan telah kami tetapkan dalam tabel aDrop.

Kami loop melalui meja aDrop, memeriksa setiap indeks untuk melihat apakah DROP_RATE lebih besar dari atau sama dengan Kelangkaan.  (Ingat, kontra-intuitif, semakin tinggi nilai Kelangkaan berarti bahwa item tersebut lebih umum) Untuk perbandingan yang cocok setiap indeks, kita memasukkan indeks ke dalam array sementara, aTemp.

Pada akhir loop, kita harus memiliki setidaknya satu indeks dalam array aTemp.   (Jika tidak, kita perlu mendesain ulang tabel aDrop dan aBeast!).  Kita kemudian membuat variabel DropType numerik baru secara acak dengan memilih salah satu indeks dari array aTemp .; ini akan menjadi item drop kita.

Kami menambahkan nama item ke objek Text kami, membuat kalimat seperti "BeastType dibunuh, menjatuhkan DROP_NAME a.".  Kemudian, untuk contoh ini, kita menambahkan beberapa nomor  statistik kami (dalam array aStats dan BeastDrops).

Akhirnya, setelah 100 pengulangan, kami menampilkan statistik jumlah binatang (dari 100) yang menjatuhkan barang-barang, dan jumlah setiap item yang dijatuhkan.

Contoh Lain: Menjatuhkan Produk Visual

Mari kita pertimbangkan contoh lain:

Tekan Space untuk menciptakan bola api yang dapat digunakan untuk membunuh musuh.

Seperti yang Anda lihat, musuh dibuat secara acak (bestiary dari 11).  Karakter pemain (di sebelah kiri) dapat membuat serangan proyektil.  Ketika proyektil menghantam musuh, musuh mati.

Fungsi yang digunakan serupa dengan apa yang telah kita lihat dalam contoh sebelumnya. Fungsi dapat menentukan apakah musuh menjatuhkan beberapa item atau tidak, dan menentukan apa saja item tersebut.  Kali ini, juga diciptakan representasi visual dari item yang dijatuhkan, dan update statistik di bagian bawah layar.

Berikut adalah implementasi dalam pseudocode:

1
CONSTANT ENEMY_NAME = 0
2
CONSTANT ENEMY_DROPRATE = 1
3
CONSTANT ENEMY_RARITY = 2
4
CONSTANT ENEMY_ANIM = 3
5
CONSTANT DROP_NAME = 0
6
CONSTANT DROP_RATE = 1
7
//Constants for the readability of the arrays

8
9
int EnemiesSpawned = 0
10
int EnemiesDrops = 0
11
12
array aEnemy(11,4)
13
array aDrop(17,2)
14
array aStats(17)
15
array aTemp(0)
16
17
On start of the project, we roll the data in aEnemy and aDrop
18
Start Timer "Spawn" for 0.2 second
19
20
Function "SpawnEnemy"
21
    int EnemyType = 0
22
    EnemyType = random(11) //We roll an enemy type out of the 11 available

23
    Create object Enemy //We create the visual object Enemy on screen

24
    Enemy.Animation = aEnemy(EnemyType, ENEMY_ANIM)
25
    EnemiesSpawned = EnemiesSpawned + 1
26
    txtEnemy.text = aEnemy(EnemyType, ENEMY_NAME) & " appeared"
27
    Enemy.Name = aEnemy(EnemyType, ENEMY_NAME)
28
    Enemy.Type = EnemyType
29
30
Keyboard Key "Space" pressed
31
    Create object Projectile from Char.Position
32
33
Projectile collides with Enemy
34
    Destroy Projectile
35
    Enemy start Fade
36
    txtEnemy.text = Enemy.Name & " has been vanquished."
37
38
Enemy Fade finished
39
    Start Timer "Spawn" for 2.5 seconds //Once the fade out is finished, we wait 2.5 seconds before spawning a new enemy at a random position on the screen

40
    Function "Drop" (Enemy.Type, Enemy.X, Enemy.Y, Enemy.Name)
41
42
Function Drop (EnemyType, EnemyX, EnemyY, EnemyName)
43
    int DropChance = 0
44
    int Rarity = 0
45
    DropChance = ceil(random(100))
46
    Rarity = aEnemy(EnemyType, ENEMY_RARITY)
47
    txtEnemy.text = EnemyName & " dropped "
48
    
49
    If DropChance > aEnemy(EnemyType, ENEMY_DROPRATE)
50
        txtEnemy.text = txtEnemy.text & " nothing."
51
        //Nothing was dropped

52
    If DropChance <= aEnemy(EnemyType, ENEMY_DROPRATE)
53
        aTemp.clear/set size to 0
54
        For a = 0 to aDrop.Width
55
        and aDrop(a, DROP_RATE) >= Rarity
56
            aTemp.Push(a) //We push the current index into the aTemp array as possible drop index

57
        
58
        int DropType = 0
59
        DropType = Random(aTemp.Width) //We pick what is the drop index amongst the indexes stored in aTemp

60
        aStats(DropType) = aStats(DropType) + 1
61
        EnemiesDrops = EnemiesDrops + 1
62
        Create Object Drop at EnemyX, EnemyY
63
        Drop.AnimationFrame = DropType
64
        txtEnemy.Text = txtEnemy.Text & aDrop.(DropType, DROP_NAME) & "." //We display the name of the drop

65
    txtStats.text = EnemiesDrops & " enemies on " & EnemiesSpawned & " dropped items." & newline
66
    For a = 0 to aStats.width
67
    and aStats(a) > 0
68
        txtStats.text = txtStats.Text & aStats(a) & " " & aDrop(a, DROP_NAME) & " "
69
        
70
Timer "Spawn"
71
    Call Function "SpawnEnemy"

Lihatlah isi tabel aEnemy dan aDrop:

Index (X)
Name (Y-0) 
Drop rate (Y-1)
Kelangkaan item (Y-2) 
Nama animasi (Y-3)
Healer Female  100  100  Healer_F 
Healer Male  75  75  Healer_M 
Mage Female  65  55  Mage_F
 3  Mage Male  45  100  Mage_M
Ninja Female  15  15  Ninja_F 
Ninja Male  35  50  Ninja_M 
Ranger Male  75  80  Ranger_M
 7  Townfolk Female  75  15  Townfolk_F 
8  Townfolk Male  95  95  Townfolk_M 
Warrior Female  70  70  Warrior_F 
10  Warrior Male  45  55  Warrior_M
Index (X) 
Name (Y-0)  
Kelangkaan item (Y-1) 
Apple  75 
Banana  50 
2  Carrot  95
 3  Grape  85 
Empty potion  80 
Blue potion  75
 6  Red potion  70 
Green potion  60 
Pink Heart  65 
Blue pearl  15 
10  Rock  100 
11  Glove  25 
12  Armor  30
 13  Jewel  35 
14  Mage Hat  65
 15  Wood shield  85 
16  Iron axe  65

Berbeda dengan contoh sebelumnya, array yang berisi data musuh bernama aEnemy dan berisi data ENEMY_ANIM yang merupakan nama animasi musuh. Dengan cara ini, ketika pemijahan musuh, kita dapat melihat dan mengotomatisasi tampilan grafis.

Dalam lapisan yang sama, aDrop sekarang berisi 16 unsur, bukan enam, dan masing-masing indeks mengacu pada frame animasi dari objek-tapi aku bisa memiliki beberapa animasi juga, seperti untuk musuh, jika barang jatuh harus dianimasikan .

Kali ini, ada jauh lebih banyak musuh dan item dibandingkan di contoh sebelumnya.  Dapat anda lihat, data mengenai tingkat drop dan nilai-nilai kelangkaan masih ada.  Salah satu perbedaan penting adalah kita telah memisahkan pemijahan musuh dari fungsi yang dpat menghitung ada penurunan atau tidak.  Hal ini karena, dalam permainan nyata, musuh akan melakukan sesuatu yang lebih dari hanya menunggu untuk dibunuh!

Jadi sekarang kita memiliki fungsi SpawnEnemy dan fungsi Drop lain.  Penurunan sangat mirip dengan cara kita menangani "gulungan dadu" item drop pada contoh sebelumnya, tetapi saat ini membutuhkan beberapa parameter yaitu : X dan Ymerupakan koordinat musuh di layar, karena itulah tempat di mana kita menghasilkan item ketika ada drop; parameter lainnya adalah EnemyType, sehingga kita dapat melihat nama musuh dalam tabel aEnemy, dan nama karakter sebagai string, untuk membuatnya lebih cepat dalam menulis umpan balik yang kami ingin berikan kepada pemain. 

Logika fungsi Drop mirip dengan contoh sebelumnya; sebagian besar perubahan adalah cara kita menampilkan umpan balik.  Kali ini, bukan hanya menampilkan teks, kami juga menelurkan sebuah objek di layar untuk memberikan representasi visual kepada pemain. 

(Catatan:. Untuk bertelur, musuh berada pada beberapa posisi di layar, saya menggunakan obyek tak terlihat, sebagai referensi, yang terus bergerak kiri dan kanan  setiap kali fungsi SpawnEnemy dipanggil, menciptakan musuh di koordinat objek Bibit saat ini, sehingga musuh muncul dan berbagai lokasi horisontal.) 

satu hal terakhir yang dibahaas yaitu kapan tepatnya fungsi Drops dipanggil.  Saya tidak mencetuskan langsung setelah kematian musuh, tapi setelah musuh telah memudar (animasi kematian musuh). Jika Anda lebih suka Anda tentu saja dapat melakukan panggilan drop ketika musuh masih terlihat di layar; sekali lagi, ini benar benar berada di game desain anda.

Kesimpulan 

Pada level desain, memiliki musuh yang menjatuhkan beberapa jarahan menyebabkab pemain scara intensif akan menghadapi dan menghancurkan mereka.  Item drop memberikan Anda power-up, statistik, atau bahkan gol untuk pemain, apakah dengan cara langsung atau tidak langsung. 

Pada tingkat implementasi, menjatuhkan barang-barang dikelola melalui fungsi coder dengan memikirkan kapan fungsi itu dipanggil.  Fungsi melakukan pekerjaan pemeriksaan kelangkaan item yang harus dijatuhkan sesuai dengan jenis musuh yang tewas, dan juga dapat menentukan tempat dimana untuk bertelur pada layar jika dan ketika diperlukan.  Data untuk item dan musuh dapat diselenggarakan dalam struktur data seperti array, dan mendongak oleh fungsi. 

Fungsi menggunakan nomor acak untuk menentukan frekuensi dan jenis drops, dan coder memiliki kontrol atas gulungan acak mereka, dan data itu mendonga, untuk menyesuaikan nuansa drop dalam permainan. 

Saya harap Anda menikmati artikel ini dan memiliki pemahaman yang lebih baik tentang bagaimana untuk membuat monster Anda menjatuhkan loots dalam permainan Anda.  Saya tak sabar untuk melihat permainan Anda menggunakan mekanik itu. 

Referensi

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.