Membuat Game Match-3 dalam Construct 2: Points, Matching, dan Gravity
Indonesian (Bahasa Indonesia) translation by Suci Rohini (you can also view the original English article)
Dalam tutorial sebelumnya, kami mengintegrasikan sistem deteksi-pertandingan dasar ke dalam game Match-3. Sementara kita dalam perjalanan untuk memiliki permainan yang dapat dimainkan, masih ada beberapa elemen permainan penting yang kita butuhkan sebelum kita benar-benar dapat menyebutnya sebagai "game". Artikel ini akan fokus pada pengisian beberapa detail yang hilang, dan membuat kita lebih dekat dengan produk akhir.
Demo Game Final
Berikut ini adalah demo game yang sedang dikerjakan di seluruh seri ini:
1. Pemberian Poin
Kita akan membahas poin-poin sebelum memulai memperbaiki sistem yang cocok, karena akan lebih mudah untuk melihat masalah pertama dalam sistem pencocokan saat ini jika kita menerapkan sistem poin.
Sistem poin dalam permainan kita akan sangat sederhana, untuk setiap Blok yang digunakan untuk membentuk grup tertentu, pemain akan menerima 10 poin. Dalam tutorial nanti kami juga akan menambahkan sistem yang memungkinkan pemain untuk mendapatkan lebih banyak poin dengan merantai bersama beberapa grup, tetapi untuk saat ini kita akan fokus hanya dengan memperkenalkan sistem poin sederhana untuk pemain.
Sebelum mulai mengedit event, kita perlu menambahkan tampilan Poin, jadi pertama-tama buka Layout 1 dan lakukan yang berikut:
- Masukkan objek Sprite baru.
- Buka gambar Game Field Images/ScoreArea.png dari paket grafis.
- Tutup editor animasinya.
- Atur posisi
491, 383
.
- Masukkan objek Text baru.
- Setel Font ke
Calibri, Bold, 22
menggunakan drop-down. - Setel Name menjadi
ScoreText
- Atur Color ke
White
atau255, 255, 255
- Setel Position ke
419, 398
. - Atur Size menjadi
200, 50
. - Setel Text ke
0
.
- Setel Font ke
Layout 1 seharusnya sekarang terlihat seperti ini:



Sekarang kita memiliki sesuatu untuk memberi tahu pemain apa arti teks titik, dan objek teks untuk menampilkan skor pemain, kita dapat melanjutkan untuk benar-benar memberikan poin pemain. Buka Event Sheet 1 dan buat Variabel Global baru.
Global Variable Name: "Score" Type = Number Value = 0
Variabel harus seperti ini:



Ini adalah variabel yang akan dimodifikasi setiap kali kita memberikan poin pemain. Selanjutnya, kita akan membuat fungsi baru yang, ketika dipanggil, akan mendeteksi berapa banyak Blok yang telah dicocokkan pemain ke dalam grup, dan memberi mereka jumlah poin yang sesuai.
Event: Condition: Function> On Function Name = "GivePoints" Condition: System>For Each Object = Block Condition: Block>Is boolean instance variable set Instance Variable = IsMatched Action: System> Add to Variable = Score Value = 10 Action: ScoreText>Set text Text = Score
Kode Anda akan terlihat seperti ini:



Jadi, untuk mengulangi, acara ini terlihat di setiap Blok. Setiap kali menemukan Blok yang telah IsMatched
ke true
- yang berarti telah dikonfirmasi untuk menjadi bagian dari grup - itu memberi pemain 10 poin untuk Blok itu, dan memperbarui teks skor.
Jika Anda menguji game Anda pada titik ini, tampaknya fungsi tersebut tidak berfungsi. Alasannya adalah karena kita belum benar-benar memanggil fungsi di mana saja dalam kode, sehingga poin tidak pernah bertambah, dan teks tidak pernah diperbarui. Buka fungsi FindMatches
Anda dan tambahkan Action baru ke awal sub-event final untuk fungsi ini.
Action: Function>Call function Name = "GivePoints"
Fungsi FindMatches
Anda seharusnya sekarang terlihat seperti ini:



Catatan: Pastikan Anda telah menambahkan Tindakan baru ini di awal Sub-Acara. Jika Anda menambahkan Tindakan ini sampai akhir, itu tidak akan berfungsi karena semua Blok yang dicocokkan akan dihancurkan sebelum fungsi GivePoints
dipanggil. Ini berarti bahwa, ketika mencari Blok yang cocok, itu tidak akan menemukan apapun dan jadi pemain tidak akan menerima poin.
Pada titik ini Anda dapat menguji permainan Anda lagi dan Anda akan melihat pembaruan teks poin, dan bahwa pemain menerima jumlah poin yang benar untuk setiap pertandingan yang mereka buat.
2. Meningkatkan Deteksi Pertandingan
Sekarang kita memiliki sistem poin, saya ingin Anda menjalankan game, dan membuat skenario yang ditunjukkan di bawah ini.

Sekarang tukar Blok yang saya soroti di sini, dan perhatikan skor Anda untuk melihat berapa banyak poin yang Anda peroleh.

Ketika Anda membentuk pertandingan ini, Anda seharusnya telah melihat bahwa Anda memperoleh 50 poin. Hal ini karena, saat ini, sistem poin memberikan pemain 10 poin untuk setiap Blok yang ditandai sebagai IsMatched
, sebagai lawan memberikan pemain 10 poin untuk setiap Blok yang digunakan dalam setiap pertandingan, seperti sistem yang saya jelaskan di atas.
Jika sistem poin bekerja dengan benar, itu akan memberikan pemain 60 poin: 30 untuk kelompok vertikal dari tiga Blok, dan 30 untuk kelompok horizontal dari tiga Blok. Masalah ini berasal dari fakta bahwa sistem pertandingan tidak memiliki cara menandai ketika Blok dicocokkan secara horisontal dan vertikal; hanya tahu jika Blok sama sekali.
Untuk mengatasi masalah ini, pertama-tama kita akan menambahkan dua Instance Variables baru ke objek Blok kami, MatchedX
dan MatchedY
.
Instance Variable: Name = MatchedX Type = Boolean Initial Value = false Instance Variable: Name = MatchedY Type = Boolean Initial Value = false
Variabel Anda akan terlihat seperti ini:



Variabel-variabel ini akan digunakan bersama dengan IsMatched
untuk memberi tahu sistem ketika Blok adalah bagian dari horizontal, atau X, grup, dan ketika Blok adalah bagian dari vertikal, atau Y, kelompok. Sekarang kita memiliki variabel, kita akan memodifikasi fungsi CheckMatches
sehingga ketika label Block IsMatched
karena menemukan grup yang cukup besar, itu juga akan mencantumkan bahwa Block sebagai bagian dari grup X atau Y tergantung pada apakah Parameter 3 atau Parameter 4 adalah 1.
Buka fungsi CheckMatches
dan ganti cek NumMatchesFound
asli dengan dua sub-acara baru ini:
Sub-Event: Condition: System>Compare two values First value = Function.Param(3) Comparison = Equal to Second value = 1 Condition: System>Compare variable Variable = NumMatchesFound Comparison = Greater or equal Value = 3 Action: Block>Set Boolean Instance variable = IsMatched Value = True Action: Block>Set Boolean Instance variable = MatchedX Value = True Sub-Event: Condition: System>Compare two values First value = Function.Param(4) Comparison = Equal to Second value = 1 Condition: System>Compare variable Variable = NumMatchesFound Comparison = Greater or equal Value = 3 Action: Block>Set Boolean Instance variable = IsMatched Value = True Action: Block>Set Boolean Instance variable = MatchedY Value = True
Fungsi CheckMatch
Anda seharusnya sekarang terlihat seperti ini:



Jadi versi baru dari fungsi CheckMatches
dengan cara yang sama seperti yang sebelumnya, kecuali sekarang juga memeriksa untuk melihat apakah Blok ditemukan untuk menjadi pertandingan dalam kelompok vertikal atau grup horizontal, dan label Blok sesuai dengan variabel baru MatchedX
dan MatchedY
.
Pemberian Poin Ekstra untuk Memblokir Dua Kali Pertandingan Itu
Sekarang kita memiliki cara untuk menentukan kapan Blok dicocokkan secara vertikal, dicocokkan secara horizontal, dan dicocokkan di kedua arah, sebagai lawan hanya mengetahui telah dicocokkan dalam grup, kita perlu menambahkan sub-acara ke fungsi GivePoints
yang akan mendistribusikan 10 poin tambahan untuk Blok yang memiliki MatchedX
dan MatchedY
yang disetel ke true.
Buka fungsi GivePoints
dan tambahkan sub-acara ini:
Sub-Event: Condition: Block>Is Boolean instance variable set Instance variable = MatchedX Condition: Block>Is Boolean instance variable set Instance variable = MatchedY Action: System>Add to Variable = Score Value = 10 Action: Text>Set text Value = Score
Fungsi GivePoints
Anda seharusnya sekarang terlihat seperti ini:



Jika Anda menjalankan permainan Anda dan kembali membuat skenario yang saya gambarkan di atas, skor Anda sekarang harus benar meningkat sebesar 60 poin.
3. Menambahkan Gravity
Sekarang setelah kita menerapkan sistem Poin, dan telah memperbarui sistem pencocokan, kita akan mulai meningkatkan aspek penting lainnya dari permainan. Jika Anda menghabiskan waktu bermain dengan permainan hingga titik ini, Anda akan tahu bahwa salah satu masalah terbesar adalah ketika Blok dihancurkan, tidak ada yang terjadi pada Blok di atas mereka. Khususnya, Blok di atas ruang kosong tidak jatuh untuk mengisi ruang-ruang tersebut.
Ini baik-baik saja dalam tes, tetapi dalam versi final itu akan merugikan gameplay untuk meninggalkan hal-hal sebagaimana adanya, jadi hal berikutnya yang akan kita tambahkan adalah "gravitasi" yang akan menyebabkan Blok jatuh dan mengisi ruang kosong ketika Blok lainnya dihancurkan.
Cara kita akan menerapkan sistem ini sebenarnya cukup sederhana. Kita akan melakukan pemeriksaan menggunakan Block > Is overlapping at offset
untuk melihat apakah ada Blok di bawah Blok yang dilihat. Jika tidak menemukan Blok, kita akan memindahkan Blok yang dilihat ke bawah untuk mengisi ruang kosong; jika tidak, tak perlu melakukan apa-apa.
Untuk membuat karya ini kita akan membuat Event baru:
Event: Condition: INVERT>Block>Is overlapping at offset Object = Block Offset X = 0 Offset Y = 8 Action: Block>Move at angle Angle = 90 Distance = (Block.Width + 2)/2
Kode Anda akan terlihat seperti ini:



Jika Anda menjalankan game saat ini, Anda akan melihat bahwa saat gamedimulai, semua Blok jatuh dari layar! Alasannya adalah karena kita tidak memasukkan apa pun ke dalam kode untuk mengatakan di mana "lantai" dari bidang game.
Jadi intinya, Blok di baris bawah menyadari tidak ada Blok di bawah mereka dan jatuh dengan sendirinya. Kemudian, setelah baris Blok terendah jatuh, baris terendah berikutnya melihat sekarang tidak ada Blok di bawah mereka, dan mereka juga jatuh. Proses ini berlanjut, sampai semua Blok telah jatuh, dan meninggalkan layar sepenuhnya kosong.
Anda dapat melihat versi yang sedikit diperlambat ini dalam aksi di GIF di bawah ini:



Untuk memperbaikinya, kita akan menambahkan kondisi kedua ke Acara.
Event: Condition: Block>Compare Y Comparison = Less or equal Y = SPAWNY - 1
Kode Anda seharusnya sekarang terlihat seperti ini:



Dengan menambahkan kondisi baru ini kita memastikan bahwa hanya Blok yang berada di atas posisi Y dari baris terendah dipengaruhi oleh "gravitasi". Meskipun perbaikan ini, kita masih memiliki beberapa masalah.
Berurusan dengan Dragging
Masalah utamanya adalah bahwa acara yang terlihat untuk melihat apakah ada ruang kosong di bawah Blok tidak memiliki apa pun untuk mengatakannya menjadi tidak aktif ketika pemain menyeret Blok. Ini berarti, jika Anda menyeret Blok terlalu jauh tanpa melepaskannya, Blok pada posisi di atas tempat Anda menyeretnya akan jatuh ke ruang yang tersisa oleh Blok yang Anda seret. Di atas itu, Blok yang Anda seret juga akan memiliki masalah jika Anda mengeluarkannya dari bidang game, dan ia akan mulai jatuh dari kursor mouse karena tidak ada Blok di bawahnya.
Untuk memperbaiki masalah ini kita perlu menambahkan variabel global baru untuk memberitahu sistem ketika kita memindahkan Blok, tindakan baru ke Blok menyeret dan menjatuhkan peristiwa untuk mengatur variabel global ini, dan kondisi ketiga untuk kejadian gravitasi sehingga dibutuhkan variabel ini ke akun sebelum diaktifkan.
Pertama, mari kita buat variabel global:
Global Variable: Name = BlockBeingMoved Type = Number Initial Value = 0
Variabel Anda akan terlihat seperti ini:



Sekarang, masuk ke event On DragDrop drag start
dan tambahkan Action baru:
Action: System>Set Value Variable = BlockBeingMoved Value = 1
Juga, masuk ke acara On DragDrop drop
dan tambahkan Aksi baru ke acara utama:
Action: System>Set Value Variable = BlockBeingMoved Value = 0
Dengan garis yang ditambahkan, peristiwa DragDrop Anda seharusnya sekarang terlihat seperti ini:



Akhirnya, pergi ke Acara gravitasi dan tambahkan kondisi baru:
Condition: System>Compare Variable Variable = BlockBeingMoved Comparison = Equal to Value = 0
Kode gravitasi Anda sekarang seharusnya terlihat seperti ini:



Variabel baru yang dibuat, BlockBeingMoved
, digunakan untuk memberi tahu sistem ketika Blok sedang dipindahkan oleh Player. Jika variabel sama dengan 0
berarti tidak ada Blok yang dipindahkan dan dapat menjalankan skrip gravitasi seperti biasa. Jika variabel sama dengan 1
, itu berarti Blok sedang dipindahkan, dan skrip gravitasi tidak boleh dijalankan.
Jika Anda menjalankan permainan pada titik ini, Anda akan melihat bahwa tidak peduli di mana Anda memindahkan Blok saat Anda menyeretnya, tidak ada masalah yang terjadi.
Memeriksa Untuk Pertandingan Baru
Sekarang kita hanya memiliki satu masalah terakhir yang berkaitan dengan sistem gravitasi. Jalankan game dan buat skenario yang serupa dengan ini:

Sekarang, buat swap yang saya soroti pada gambar selanjutnya ini.

Anda harus memperhatikan bahwa ketika kelompok Blok Hijau/Bintang dihancurkan, Blok Oranye/Heksagon jatuh dan membentuk kelompok tiga Blok, tetapi tidak hancur.
Alasan mengapa Blok ini tidak dihancurkan adalah karena kita tidak pernah memanggil fungsi FindMatches
untuk kedua kalinya untuk melihat apakah ada kecocokan baru yang terbentuk ketika Blok jatuh untuk mengisi ruang kosong. Untuk memperbaiki ini, pergi ke Acara yang memeriksa ruang-ruang kosong di bawah Blok dan tambahkan Event Else ini:
Event: Condition: System>Else Action: Function>Call function Name= "FindMatches"
Kode Anda akan terlihat seperti ini:



Pernyataan lain ini berarti bahwa, setiap kali menemukan tidak ada ruang kosong, itu akan melakukan pemeriksaan untuk melihat apakah ada kelompok yang dihancurkan. Acara ini akan secara otomatis berjalan setiap kali Blok jatuh ke posisi baru karena diaktifkan oleh pernyataan Else yang terkait dengan cek itu, dan hanya akan diaktifkan setelah yakin semua Blok telah jatuh ke tempatnya.
Jika Anda menjalankan permainan pada titik ini Anda akan menemukan bahwa Anda sekarang dapat membuat rantai Blok dengan menghancurkan Blok dengan cara yang kelompok akan terbentuk ketika Blok yang tersisa jatuh. Di atas itu, Anda juga akan menemukan bahwa ketika Anda pertama kali memulai permainan, setiap grup yang awalnya dipicu akan dihancurkan juga. Seperti yang saya katakan di tutorial sebelumnya, kita akhirnya akan menghilangkan pertandingan yang sudah jadi, jadi masalah ini tidak akan berpengaruh pada akhirnya.
Menghapus Blok Dari Layout Awal
Akhirnya, kita harus melakukan satu hal lagi sebelum kita dapat mempertimbangkan sistem gravitasi kita selesai. Tergantung pada di mana Anda menempatkan sprite Blok awal ketika Anda menyelesaikan tutorial pertama, Anda mungkin memperhatikan bahwa ketika Anda memulai permainan itu jatuh dan menjadi terlihat.
Jika Anda tidak tahu apa yang saya maksud, pergi ke Layout 1, atur posisi Block sprite Anda ke 521, -32
, dan jalankan game. Saat Anda memainkan game, Anda harus melihat Blok asli di posisi yang saya soroti pada gambar di bawah ini:



Seperti yang Anda lihat pada gambar di atas, Blok awal jatuh dari posisinya di luar layar dan menjadi terlihat. Kita tidak menginginkan ini karena ini hanya akan menyebabkan masalah bagi kita nantinya. Untuk mengatasi masalah kecil ini kita akan menambahkan Aksi ke On start of layout
yang akan menghancurkan Blok apa pun yang ada di Tata Letak saat awalnya dimuat.
Action: Block>Destroy
Acara Anda seharusnya sekarang terlihat seperti ini:



Sekarang ketika Anda menjalankan game, Anda seharusnya tidak lagi melihat Blok. Anda mungkin bertanya pada diri sendiri mengapa kami tidak menghapus blok dari Layout sehingga kami tidak perlu khawatir tentang masalah ini sama sekali. Alasan kami tidak melakukan ini adalah karena Construct 2 tidak dapat membuat salinan jenis objek apa pun dengan Peristiwa, kecuali sudah ada turunan dari jenis Objek itu dalam game saat pertama kali dimuat. Dengan menghapusnya dalam suatu peristiwa, kita menghapusnya sehingga tidak menjadi masalah nantinya, dan kami memungkinkan untuk menelurkan sebanyak mungkin Blok yang dibutuhkan melalui kode.
Kesimpulan
Kita membahas banyak topik dalam tutorial ini, dan sementara ada lebih banyak yang bisa dilakukan, saya pikir penting untuk beristirahat dan membiarkan info ini meresap. Dalam angsuran berikutnya, kita akan memperbaiki beberapa masalah kecil, membuat teks floating point mewah yang mungkin Anda perhatikan ada di demo akhir, dan mengatur sistem chaining.
Saya harap Anda mendapat banyak bagian dari seri ini, dan saya akan melihat Anda kembali ke sini minggu depan.
Subscribe below and we’ll send you a weekly email summary of all new Game Development tutorials. Never miss out on learning about the next big thing.
Update me weekly