Menciptakan Game Puzzle Berbasis Grid Seperti Minesweeper dengan Menggunakan Unity: Kemenangan
Indonesian (Bahasa Indonesia) translation by Kaso Toluppa (you can also view the original English article)
Di bagian akhir dari seri ini, kami menempatkan sentuhan akhir pada permainan puzzle Unity berbasis grid, dan membuatnya dapat dimainkan. Pada akhir bagian ini, pemain akan bisa menang atau kalah dalam permainan.
Sekarang setelah Anda menyelesaikan tutorial sebelumnya, permainan kami bisa menciptakan bidang tile, dan menetapkan ranjau secara acak ke mereka. Kami juga memiliki efek cahaya yang bagus saat pemain melayang di atas tile dengan mouse, dan mungkin juga untuk menempatkan dan melepaskan bendera.
Secara internal, setiap tile juga tahu tentang tile yang berdekatan, dan
sudah bisa menghitung berapa banyak ranjau yang berada di dekatnya.
Mengungkap Ubin
Kami sudah menambahkan kemampuan untuk menempatkan bendera dengan klik kanan. Sekarang, mari tambahkan kemampuan untuk mengungkap tile dengan klik kiri.
Pada fungsi OnMouseOver (),
di mana kita memiliki kode pengenal klik,
kita perlu mengenali klik kiri. Sesuaikan fungsinya agar terlihat seperti ini:
function OnMouseOver() { if(state == "idle") { renderer.material = materialLightup; if (Input.GetMouseButtonDown(0)) UncoverTile(); if (Input.GetMouseButtonDown(1)) SetFlag(); } else if(state == "flagged") { renderer.material = materialLightup; if (Input.GetMouseButtonDown(1)) SetFlag(); } }
Saat tombol kiri mouse ditekan, fungsi
UncoverTile ()
akan dipanggil. Pastikan Anda membuat fungsi ini, sehingga hal
ini tidak menyebabkan bug!
function UncoverTile() { if(!isMined) { state = "uncovered"; displayText.renderer.enabled = true; renderer.material = materialUncovered; } else Explode(); }
Untuk tahap ini, kita membutuhkan material baru.
public var materialUncovered: Material;
Buatlah
sesuatu yang memiliki warna berbeda dari tile dasar-sehingga jika tile dasar
Anda berwarna biru, Anda bisa memilih hijau untuk keadaan yang tidak terungkap.
Tapi jangan gunakan warna merah; Kita akan membutuhkannya nanti untuk
menunjukkan bahwa kita telah memicu janjau.
Saat memanggil fungsi itu, hal berikut akan terjadi:
- Pertama, kita periksa apakah tile benar-benar diranjau.
- Jika tidak, kami mengatur agar
posisi
tidak terungkap
, mengaktifkan tampilan teks yang menunjukkan jumlah ranjau di dekatnya, dan mengatur materi ke materi yang tidak ditemukan. - Setelah itu, tile tidak bisa diklik lagi, dan juga tidak akan menyala lagi, yang berarti umpan balik pasif dari tile yang bereaksi terhadap kursor mouse hanya akan terjadi pada tile yang sebenarnya bisa kita klik.
Sebelum kita bisa mencoba ini, kita perlu
memastikan bahwa materi tidak berubah saat kursor mouse keluar dari tile. Untuk
ini, sesuaikan fungsi OnMouseExit ()
seperti dibawah ini:
function OnMouseExit() { if(state == "idle" || state == "flagged") renderer.material = materialIdle; }
Dengan cara ini, warnanya hanya akan dinyalakan
kembali jika tile belum terbongkar.
Cobalah! Anda harus bisa membuka tile. Jika sebuah tile diranjau, maka tidak akan terjadi apa-apa sekarang.

Membuat tile Kosong Membuka
Satu Sama Lain
Ini akan sedikit rumit. Di Minesweeper, saat Anda menemukan tile tanpa ranjau di sebelahnya, akan membuka semua ubin yang bersebelahan dengan itu yang juga tidak memiliki ranjau, dan tile yang berdekatan dengan mereka yang tidak memiliki ranjau, dan seterusnya.
Pertimbangkan bidang ini:

Kita tidak benar-benar melihat angka atau ranjau, hanya tile biasa.

Bila tile dengan nol di dekat ranjau ditemukan, semua tile di sampingnya harus secara otomatis terbuka juga. Tile yang tidak terbuka kemudian membuka semua tetangganya.

tile yang baru ditemukan ini kemudian akan
memeriksa tetangga mereka juga, dan, jika tidak ada ranjau, maka bukalah semua.

Ini akan bergejolak melalui bidang sampai kita mencapai tile yang benar-benar memiliki ranjau yang berdekatan dengan mereka, di mana ia akan berhenti.

Ini menciptakan area kosong yang bisa kita lihat di Minesweeper.
Untuk membuat karya ini, kita memerlukan dua fungsi lagi,
UncoverAdjacentTiles ()
dan UncoverTileExternal ():
private function UncoverAdjacentTiles() { for(var currentTile: Tile in adjacentTiles) { //uncover all adjacent nodes with 0 adjacent mines if(!currentTile.isMined && currentTile.state == "idle" && currentTile.adjacentMines == 0) currentTile.UncoverTile(); //uncover all adjacent nodes with more than 1 adjacent mine, then stop uncovering else if(!currentTile.isMined && currentTile.state == "idle" && currentTile.adjacentMines > 0) currentTile.UncoverTileExternal(); } } public function UncoverTileExternal() { state = "uncovered"; displayText.renderer.enabled = true; renderer.material = materialUncovered; }
Kita juga perlu melakukan modifikasi ini pada
fungsi UncoverTile ():
function UncoverTile() { if(!isMined) { state = "uncovered"; displayText.renderer.enabled = true; renderer.material = materialUncovered; if(adjacentMines == 0) UncoverAdjacentTiles(); } }
Saat kita menemukan tile, dan tidak ada ranjau di sebelahnya, kita
memanggil fungsi UncoverAdjacentTiles ()
. Ini kemudian memeriksa setiap tile didekatnya
untuk melihat apakah ia memiliki ranjau atau tidak. Jika
tidak ada, ia juga akan menemukan tile ini, dan memulai pemeriksaan lainnya.
Jika ada ranjau di dekatnya, itu akan membuka tile yang ditemukan saat itu.
Sekarang, cobalah. Untuk mendapatkan kesempatan yang baik dari sebuah bidang
kosong yang muncul, buatlah bidang yang agak besar dengan beberapa ranjau -
katakanlah, 81 tile, dengan sembilan tile per baris, dan 10 ranjau secara
total.

Anda sebenarnya bisa memainkan ini sebagai permainan, kecuali bahwa Anda
belum bisa memicu ranjau. Kami akan menambahkan fitur itu selanjutnya.
Memicu Ranjau
Saat kita menemukan tile yang diranjau, permainan berhenti dan pemainnya kalah. Selain itu, semua tile bekas lainnya terlihat. Agar hal ini terjadi, kita membutuhkan satu material lagi, untuk tile ranjau yang diledakkan:
public var materialDetonated: Material;
Saya sarankan menggunakan sesuatu yang merah untuk ini.
Selain itu, kita perlu menambahkan dua fungsi lagi untuk menangani ledakan semua ranjau:
function Explode() { state = "detonated"; renderer.material = materialDetonated; for (var currentTile: Tile in Grid.tilesMined) currentTile.ExplodeExternal(); } function ExplodeExternal() { state = "detonated"; renderer.material = materialDetonated; }
Kami memicu metode tersebut di fungsi
UncoverTile ():
function UncoverTile() { if(!isMined) { state = "uncovered"; displayText.renderer.enabled = true; renderer.material = materialUncovered; if(adjacentMines == 0) UncoverAdjacentTiles(); } else Explode(); }
Jika tile diranjau, tilenya akan meledak.
Fungsi Explode ()
kemudian mengirimkan perintah "meledak" ke semua
tile lain dengan ranjau, membuka semuanya.

Memenangkan Game
Pertandingan dimenangkan begitu semua tile dengan ranjau telah ditandai
dengan benar. Pada titik ini, semua tile yang tidak ditemukan juga terbongkar.
Jadi bagaimana kita melacak itu?
Mari kita mulai dengan menambahkan variabel state
ke Gridclass
, sehingga kita bisa melacak bagian permainan
mana yang sedang kita mainkan (masih diputar, hilang, atau dimenangkan).
static var state: String = "inGame";
Sementara kita melakukannya, kita juga bisa mulai menambahkan GUI sederhana, sehingga kita bisa menampilkan informasi yang diperlukan di layar. Unity hadir dengan sistem GUI tersendiri yang akan kita gunakan untuk ini.
function OnGUI() { GUI.Box(Rect(10,10,100,50), state); }
Ini
akan menunjukkan kepada kita posisi bagian mana kita berada saat ini. Kita akan
memanggil posisi-posisi ini dalamGame
, gameOver
, dan gameWon
.
Kita
juga bisa menambahkan cek ke Tile, untuk memastikan kita hanya bisa
berinteraksi dengantile ketika posisi permainan saat ini adalah inGame.
Pada fungsi OnMouseOver ()
dan OnMouseExit,
pindahkan semua kode yang
ada ke dalam sebuah
blok untuk memeriksa apakah Grid.state
saat ini adalah inGame,
seperti:
function OnMouseOver() { if(Grid.state == "inGame") { if(state == "idle") { renderer.material = materialLightup; if (Input.GetMouseButtonDown(0)) UncoverTile(); if (Input.GetMouseButtonDown(1)) SetFlag(); } else if(state == "flagged") { renderer.material = materialLightup; if (Input.GetMouseButtonDown(1)) SetFlag(); } } } function OnMouseExit() { if(Grid.state == "inGame") { if(state == "idle" || state == "flagged") renderer.material = materialIdle; } }
Sebenarnya ada dua cara untuk memeriksa apakah
permainan telah dimenangkan: kita dapat menghitung berapa banyak tambang yang
ditandai dengan benar, atau kita dapat memeriksa apakah semua tile yang bukan ranjau
telah ditemukan. Untuk itu, kita membutuhkan variabel berikut; tambahkan mereka
ke Grid
class:
static var minesMarkedCorrectly: int = 0; static var tilesUncovered: int = 0; static var minesRemaining: int = 0;
Jangan lupa untuk mengatur minesRemaining
dalam
fungsi Start ()
ke numberOfMines
, dan variabel lainnya menjadi 0
. Fungsi Start
()
sekarang seharusnya terlihat seperti ini:
function Start() { CreateTiles(); minesRemaining = numberOfMines; minesMarkedCorrectly = 0; tilesUncovered = 0; state = "inGame"; }
Baris terakhir menetapkan status untuk permainan. (Ini akan menjadi
penting saat kita ingin memperkenalkan fungsi "restart" nanti.)
Kita kemudian akan memeriksa kondisi akhir
permainan di fungsi Update ()
:
function Update() { if(state == "inGame") { if((minesRemaining == 0 && minesMarkedCorrectly == numberOfMines) || (tilesUncovered == numberOfTiles - numberOfMines)) FinishGame(); } }
Kitamenyelesaikan permainan dengan menetapkan
status untuk gameWon
, membuka semua tile yang
tersisa, dan menandai semua tambang yang tersisa:
function FinishGame() { state = "gameWon"; //uncovers remaining fields if all nodes have been placed for(var currentTile: Tile in tilesAll) if(currentTile.state == "idle" && !currentTile.isMined) currentTile.UncoverTileExternal(); //marks remaining mines if all nodes except the mines have been uncovered for(var currentTile: Tile in Grid.tilesMined) if(currentTile.state != "flagged") currentTile.SetFlag(); }
Agar semua ini berhasil, kita perlu
meningkatkan variabel yang melacak kemajuan kita di tempat yang tepat.
Adaptasikan fungsi UncoverTile ()
untuk melakukan itu:
function UncoverTile() { if(!isMined) { state = "uncovered"; displayText.renderer.enabled = true; renderer.material = materialUncovered; Grid.tilesUncovered += 1; if(adjacentMines == 0) UncoverAdjacentTiles(); } else Explode(); }
Lakukan juga hal yang sama pada fungsi UncoverTileExternal()
:
function UncoverTileExternal() { state = "uncovered"; displayText.renderer.enabled = true; renderer.material = materialUncovered; Grid.tilesUncovered += 1; }
Kita juga perlu menaikkan dan menurunkan
variabel minesMarkedCorrectly
dan minesRemaining
tergantung
pada apakah sebuah bendera telah ditetapkan:
function SetFlag() { if(state == "idle") { state = "flagged"; displayFlag.renderer.enabled = true; Grid.minesRemaining -= 1; if(isMined) Grid.minesMarkedCorrectly += 1; } else if(state == "flagged") { state = "idle"; displayFlag.renderer.enabled = false; Grid.minesRemaining += 1; if(isMined) Grid.minesMarkedCorrectly -= 1; } }
Kekalahan pada Game
Dengan cara yang sama, kita perlu membuat kemungkinan kekalahan game.
Kami melakukannya melalui fungsi Explode ()
di dalam tile.
Cukup tambahkan baris ini ke fungsi Explode ():
Grid.state = "gameOver";
Begitu garis itu dijalankan, keadaan permainan
beralih ke gameOver
, dan tile tidak dapat lagi berinteraksi dengannya.
Menambahkan GUI yang Lebih Fungsional
Kami menggunakan GUI dari Unity untuk memberi tahu pemain mana status permainan yang sedang mereka masuki. Sekarang kami akan memperluasnya untuk menampilkan beberapa pesan aktual.
Kerangka untuk ini terlihat seperti berikut:
function OnGUI() { if(state == "inGame") { } else if(state == "gameOver") { } else if(state == "gameWon") { } }
Bergantung pada posisi, pesan berbeda bisa
ditampilkan di GUI. Jika permainan kalah atau menang, misalnya kita bisa
menampilkan pesan yang mengatakan demikian:
function OnGUI() { if(state == "inGame") { } else if(state == "gameOver") { GUI.Box(Rect(10,10,200,50), "You lose"); } else if(state == "gameWon") { GUI.Box(Rect(10,10,200,50), "You rock!"); } }
Kita juga dapat menunjukkan jumlah ranjau yang
ditemukan sejauh ini, atau menambahkan tombol yang memuat ulang level setelah
permainan selesai:
function OnGUI() { if(state == "inGame") { GUI.Box(Rect(10,10,200,50), "Mines left: " + minesRemaining); } else if(state == "gameOver") { GUI.Box(Rect(10,10,200,50), "You lose"); if(GUI.Button(Rect(10,70,200,50), "Restart")) Restart(); } else if(state == "gameWon") { GUI.Box(Rect(10,10,200,50), "You rock!"); if(GUI.Button(Rect(10,70,200,50), "Restart")) Restart(); } } function Restart() { state = "loading"; Application.LoadLevel(Application.loadedLevel); }
Anda bisa mencobanya semuanya dalam tutorial terakhir ini!
Kesimpulan
itulah kuncinya! Kita telah menciptakan permainan puzzle sederhana dengan Unity, yang bisa Anda gunakan sebagai dasar untuk menciptakan milik Anda sendiri. Saya harap Anda menikmati serial ini; tolong ajukan pertanyaan yang anda punya di komentar!
Envato Tuts+ tutorials are translated into other languages by our community members—you can be involved too!
Translate this post