Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Game Development
  2. Game Development
Gamedevelopment

Primer Dikemaskini untuk Mencipta Dunia Isometrik, Bahagian 2

by
Difficulty:IntermediateLength:LongLanguages:
This post is part of a series called Primer for Creating Isometric Worlds.
An Updated Primer for Creating Isometric Worlds, Part 1

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

Final product image
What You'll Be Creating

Dalam bahagian akhir siri tutorial ini, kami akan membina tutorial pertama dan belajar tentang melaksanakan pickup, pencetus, bertukar tahap, mencari jalan, laluan berikut, menatal tahap, ketinggian isometrik, dan projektil isometrik.

1. Pickup

Pickup adalah item yang boleh dikumpulkan dalam tahap, biasanya dengan hanya berjalan di atasnya-contohnya, duit syiling, permata, wang tunai, peluru, dll.

Data pikap boleh ditempatkan terus ke dalam data tahap kami seperti di bawah:

Dalam data tahap ini, kami menggunakan 8 untuk menandakan pickup pada jubin rumput (1 dan 0 mewakili dinding dan jubin walkable masing-masing, seperti sebelumnya). Ini mungkin satu imej jubin tunggal dengan jubin rumput yang dilapisi dengan imej pikap. Melangkah dengan logik ini, kita akan memerlukan dua jubin yang berbeza untuk setiap jubin yang mempunyai pikap, iaitu satu dengan pikap dan satu tanpa harus ditunjukkan selepas pickup akan dikumpulkan.

Artis isometrik tipikal akan mempunyai pelbagai jubin yang boleh dilalui - katakan kita mempunyai 30. Pendekatan di atas bermaksud bahawa jika kita mempunyai N pickups, kita akan memerlukan N x 30 jubin selain daripada 30 jubin asli, kerana setiap jubin perlu mempunyai satu versi dengan pickup dan satu tanpa. Ini tidak begitu berkesan; sebaliknya, kita harus cuba membuat kombinasi ini secara dinamik.

Untuk menyelesaikannya, kami boleh menggunakan kaedah yang sama yang kami gunakan untuk meletakkan wira dalam tutorial pertama. Apabila kita menjumpai jubin pikap, kita akan meletakkan jubin rumput terlebih dahulu dan kemudian meletakkan jongkok di atas jubin rumput. Dengan cara ini, kita hanya perlu jubin N pickup selain daripada 30 jubin walkable, tetapi kita memerlukan nilai nombor untuk mewakili setiap kombinasi dalam data tahap. Untuk menyelesaikan keperluan untuk nilai perwakilan N x 30, kami boleh menyimpan pickupArray berasingan untuk menyimpan data piksel secara eksklusif selain dari levelData. Peringkat siap dengan pickup ditunjukkan di bawah:

Isometric level with coin pickup

Sebagai contoh, saya menjaga perkara-perkara yang mudah dan tidak menggunakan array tambahan untuk pickup.

Picking Up Pickups

Mengesan pickup dilakukan dengan cara yang sama seperti mengesan jubin perlanggaran, tetapi setelah menggerakkan karakter.

Dalam fungsi onPickupTile(), kami periksa sama ada nilai array levelData pada koordinat heroMapTile adalah jubin pikap atau tidak. Nombor dalam array levelData pada koordinat jubin yang menandakan jenis pikap. Kami menyemak perlanggaran sebelum memindahkan watak tetapi perlu menyemak pickup selepas itu, kerana dalam hal perlanggaran watak tidak boleh menduduki tempat jika ia telah diduduki oleh jubin perlanggaran, tetapi dalam hal pickup watak itu bebas bergerak atasnya.

Perkara lain yang perlu diperhatikan ialah data perlanggaran biasanya tidak pernah berubah, tetapi data pickup berubah setiap kali kita mengambil item. (Ini biasanya hanya melibatkan mengubah nilai dalam array levelData dari, katakan, 8 hingga 0.)

Ini membawa kepada masalah: apa yang berlaku apabila kita perlu memulakan semula tahap, dan dengan itu menetapkan semula semua pick kembali ke kedudukan asal mereka? Kami tidak mempunyai maklumat untuk melakukan ini, kerana array levelData telah berubah apabila pemain mengambil item. Penyelesaiannya adalah menggunakan array duplikat untuk tahap semasa dalam permainan dan untuk menjaga tahap levellData asal utuh. Sebagai contoh, kami menggunakan levelData dan levelDataLive[], clone yang terakhir daripada yang pertama pada permulaan tahap, dan hanya menukar levelDataLive[] semasa bermain.

Sebagai contoh, saya memancarkan pickup rawak pada jubin rumput kosong selepas setiap pickup dan menambah pickupCount. Fungsi pickupItem kelihatan seperti ini.

Anda harus perhatikan bahawa kami menyemak pickup setiap kali watak berada di ubin itu. Ini boleh berlaku berkali-kali dalam satu saat (kita semak hanya apabila pengguna bergerak, tetapi kita boleh pergi bulat dan bulat dalam jubin), tetapi logik di atas tidak akan gagal; kerana kita menetapkan data array levelData ke 0 pada kali pertama kita mengesan pickup, semua cek berikutnya padaPickupTile () akan kembali palsu untuk jubin itu. Lihat contoh interaktif di bawah:

2. Mencetuskan Jubin

Seperti namanya, mencetuskan jubin menyebabkan sesuatu berlaku apabila pemain melangkah ke arahnya atau menekan kunci semasa mereka. Mereka mungkin teleport pemain ke lokasi yang berbeza, membuka pintu masuk, atau menembak musuh, untuk memberikan beberapa contoh. Dalam erti kata, pickup hanyalah satu bentuk khas jubin pencetus: apabila pemain melangkah pada jubin yang mengandungi duit syiling, koin hilang dan kaunter duit syiling mereka meningkat.

Mari lihat bagaimana kita dapat melaksanakan pintu yang membawa pemain ke tahap yang berbeza. Jubin di sebelah pintu akan menjadi jubin pencetus; apabila pemain menekan kekunci x, mereka akan meneruskan ke peringkat seterusnya.

Isometric level with doors trigger tiles

Untuk menukar tahap, semua yang perlu kita lakukan ialah menukar aras levelData semasa dengan tahap yang baru, dan tetapkan kedudukan dan arahMapTile yang baru untuk arahan watak pahlawan. Katakan terdapat dua peringkat dengan pintu untuk membolehkan lulus antara mereka. Oleh kerana jubin tanah di sebelah pintu akan menjadi jubin pencetus di kedua-dua peringkat, kita boleh menggunakan ini sebagai kedudukan baru untuk watak apabila mereka muncul di peringkat.

Logik pelaksanaan di sini adalah sama seperti untuk pickup, dan sekali lagi kami menggunakan array levelData untuk menyimpan nilai pencetus. Untuk contoh kami, 2 menandakan jubin pintu, dan nilai di sebelahnya adalah pencetus. Saya telah menggunakan 101 dan 102 dengan konvensyen asas bahawa mana-mana jubin dengan nilai lebih daripada 100 adalah jubin pencetus dan nilai tolak 100 boleh menjadi tahap yang ia menuju kepada:

Kod untuk memeriksa peristiwa pencetus ditunjukkan di bawah:

Fungsi triggerListener() memeriksa apakah nilai array data pemicu pada koordinat yang diberikan lebih besar dari 100. Jika ya, kita menemukan level mana yang perlu kita alihkan dengan mengurangkan 100 dari nilai petak. Fungsi ini menemukan petak pemicu di levelData baru, yang akan menjadi tempat bertelur bagi jagoan kita. Saya telah membuat pemicu untuk diaktifkan ketika x dilepaskan; jika kita hanya mendengarkan kunci yang ditekan, maka kita akan berakhir dalam satu lingkaran di mana kita bertukar antara level selama kunci ditekan, karena karakter selalu memunculkan di tingkat baru di atas ubin pemicu.

Ini demo kerja. Cobalah mengambil item dengan berjalan di atasnya dan menukar level dengan berdiri di samping pintu dan menekan x.

3. Projektil

Sebuah proyektil adalah sesuatu yang bergerak dalam arah tertentu dengan kecepatan tertentu, seperti peluru, mantra sihir, bola, dll. Segala sesuatu tentang proyektil adalah sama dengan karakter pahlawan, selain dari ketinggian: daripada berguling sepanjang tanah, proyektil sering mengapung di atasnya pada ketinggian tertentu. Peluru akan bergerak di atas tingkat pinggang karakter, dan bahkan bola mungkin perlu terpental.

Satu hal yang menarik untuk dicatat adalah bahwa tinggi isometrik sama dengan tinggi pada sisi 2D, meskipun lebih kecil nilainya. Tidak ada konversi rumit yang terlibat. Sekiranya bola adalah 10 piksel di atas tanah dalam koordinat Cartesian, ia boleh menjadi 10 atau 6 piksel di atas tanah dalam koordinat isometrik. (Dalam kes kita, paksi yang berkaitan adalah sumbu-y.)

Mari kita cuba untuk melancarkan bola memantul di padang rumput kita. Sebagai sentuhan realisme, kami akan menambah bayangan untuk bola. Apa yang perlu kita lakukan ialah menambah nilai ketinggian lantunan kepada nilai Y isometrik bola kita. Nilai ketinggian lompat akan berubah dari bingkai ke bingkai bergantung kepada graviti, dan apabila bola menjejaskan tanah, kita akan membalikkan halaju semasa sepanjang paksi-y.

Sebelum kita melantun dalam sistem isometrik, kita akan melihat bagaimana kita dapat melaksanakannya dalam sistem Cartesian 2D. Mari kita mewakili kekuatan melompat bola dengan zValue variabel. Bayangkan, untuk memulakan, bola mempunyai kuasa melompat 100, jadi zValue = 100.

Kami akan menggunakan dua lagi pembolehubah: incrementValue, yang bermula pada 0, dan graviti, yang mempunyai nilai -1. Setiap bingkai, kita tolak incrementValue dari zValue, dan tolak graviti dari incrementValue untuk menghasilkan kesan pelembab. Apabila zValue mencapai 0, ia bermakna bola telah mencapai tanah; pada ketika ini, kita menolak tanda tambahanValue dengan mengalikannya dengan -1, mengubahnya menjadi nombor positif. Ini bermakna bola akan bergerak ke atas dari bingkai seterusnya, dengan itu memantul.

Inilah caranya dalam kod:

Kod tetap sama untuk pandangan isometrik juga, dengan sedikit perbezaan yang anda boleh menggunakan nilai yang lebih rendah untuk zValue untuk bermula dengan. Lihat di bawah bagaimana zValue ditambah kepada nilai y isometrik bola semasa membuat rendering.

Lihat contoh interaktif di bawah:

Adakah anda faham bahawa peranan yang dimainkan oleh bayangan adalah sesuatu yang sangat penting yang menambah realisme ilusi ini. Juga ambil perhatian bahawa kita kini menggunakan dua koordinat skrin (x dan y) untuk mewakili tiga dimensi dalam koordinat isometrik-paksi-y dalam koordinat skrin juga paksi z dalam koordinat isometrik. Ini boleh mengelirukan!

4. Menemukan dan Mengikuti Laluan

Penemuan jalan dan laluan berikut adalah proses yang agak rumit. Terdapat pelbagai pendekatan menggunakan algoritma yang berbeza untuk mencari jalan antara dua titik, tetapi sebagai levelData kami adalah array 2D, perkara-perkara lebih mudah daripada yang mereka mungkin sebaliknya. Kami mempunyai nod yang jelas dan unik yang dimainkan oleh pemain, dan kami dapat dengan mudah memeriksa sama ada mereka boleh dilayari.

Post Berkaitan

Tinjauan terperinci mengenai algoritma pathfinding adalah di luar skop artikel ini, tetapi saya akan cuba menerangkan cara yang paling biasa ia berfungsi: algoritma jalan terpendek, yang algoritma A * dan Dijkstra adalah pelaksanaan yang terkenal.

Kami berhasrat untuk mencari nod yang menyambungkan nod awal dan simpulan nod. Dari nod awal, kami melawat semua lapan nod tetangga dan menandakan semuanya seperti yang dikunjungi; proses teras ini diulang untuk setiap nod yang baru dilawati, secara rekursif.

Setiap benang menjejaki nod yang dilawati. Apabila melompat ke nod jiran, nod yang telah dilawati dilangkau (rekursi berhenti); jika tidak, proses itu berterusan sehingga kita mencapai nod yang berakhir, di mana rekursi berakhir dan laluan penuh diikuti dikembalikan sebagai array nod. Kadang-kadang nod akhir tidak pernah dicapai, dalam hal ini penemuan jalan gagal. Kita biasanya akan menemui pelbagai laluan antara kedua-dua nod, di mana kita mengambil satu dengan nombor terkecil nod.

Mencari Jalan

Tidak bijak untuk mencipta semula roda apabila terdapat algoritma yang jelas, jadi kami akan menggunakan penyelesaian yang ada untuk tujuan mencari jalan. Untuk menggunakan Phaser, kami memerlukan penyelesaian JavaScript, dan yang saya pilih ialah EasyStarJS. Kami memulakan enjin pencarian jalan seperti di bawah.

Oleh kerana levelData kami hanya mempunyai 0 dan 1, kami boleh terus lulus sebagai array nod. Kami menetapkan nilai 0 sebagai nod yang boleh dilalui. Kami membolehkan keupayaan berjalan pepenjis tetapi melumpuhkan ini apabila berjalan dekat dengan sudut-sudut jubin yang tidak dapat dilayari.

Ini kerana, jika diaktifkan, wira boleh dipotong ke dalam jubin yang tidak dapat dilalui ketika melakukan berjalan diagonal. Dalam kes sedemikian, pengesanan perlanggaran kami tidak akan membenarkan wira melaluinya. Juga, sila ambil perhatian bahawa dalam contoh saya telah memadam pengesanan perlanggaran sepenuhnya kerana itu tidak lagi diperlukan untuk contoh berjalan berasaskan AI.

Kami akan mengesan paip pada sebarang jubin percuma di dalam tahap dan mengira laluan menggunakan fungsi findPath. Plot kaedah panggil balikAndMove menerima pelbagai nod laluan yang dihasilkan. Kami menandakan minimap dengan laluan yang baru dijumpai.

Isometric level with the newly found path highlighted in minimap

Laluan Mengikuti

Sebaik sahaja kita mempunyai jalan sebagai array nod, kita perlu membuat watak mengikutnya.

Katakanlah kita mahu membuat watak berjalan ke jubin yang kita klik. Kita terlebih dahulu perlu mencari jalan antara nod yang watak yang ada sekarang dan nod yang kita klik. Sekiranya jalan yang berjaya ditemui, maka kita perlu memindahkan watak ke nod pertama dalam pelbagai nod dengan menetapkannya sebagai destinasi. Sebaik sahaja kita sampai ke nod destinasi, kita periksa sama ada terdapat lebih banyak nod dalam array nod dan, jika ya, tetapkan nod seterusnya sebagai destinasi-dan sebagainya sehingga kita mencapai nod akhir.

Kami juga akan mengubah arah pemain berdasarkan nod semasa dan nod destinasi baru setiap kali kita mencapai nod. Antara nod, kita hanya berjalan mengikut arah yang diperlukan sehingga kita mencapai nod destinasi. Ini adalah AI yang sangat mudah, dan dalam contoh ini dilakukan dalam kaedah aiWalk ditunjukkan sebahagiannya di bawah.

Kami perlu melakukan menapis mata klik yang sah dengan menentukan sama ada kami telah mengklik di kawasan yang boleh dilayari, bukannya jubin dinding atau jubin lain yang tidak dapat dilalui.

Satu lagi titik yang menarik untuk pengekodan AI: kita tidak mahu wataknya beralih ke muka jubin seterusnya dalam array nod sebaik sahaja dia tiba di saat ini, kerana giliran segera menghasilkan watak kita berjalan di sempadan jubin. Sebaliknya, kita harus menunggu sehingga watak itu beberapa langkah di dalam jubin sebelum kita mencari destinasi seterusnya. Ia juga lebih baik untuk menempatkan wira secara manual di tengah-tengah jubin semasa sebelum kita berpaling, untuk menjadikannya semua yang sempurna.

Lihat demo kerja di bawah:

5. Menatal Isometrik

Apabila kawasan tahap jauh lebih besar daripada kawasan skrin yang ada, kita perlu membuatnya tatal.

Isometric level with 12x12 visible area

Kawasan skrin yang boleh dilihat boleh dianggap sebagai segi empat yang lebih kecil dalam segiempat yang lebih besar dari kawasan tahap lengkap. Menggulung adalah, pada dasarnya, hanya memindahkan segi empat dalam dalam yang lebih besar. Biasanya, apabila penggiliran itu berlaku, kedudukan wira kekal sama dengan segi empat tepat skrin, biasanya di pusat skrin. Menariknya, semua yang kita perlukan untuk melaksanakan menatal ialah untuk mengesan titik sudut segiempat dalam.

Titik sudut ini, yang kami mewakili dalam koordinat Cartesian, akan jatuh dalam jubin dalam data tahap. Untuk menatal, kami menambah kedudukan x dan y dari titik sudut dalam koordinat Cartesian. Sekarang kita boleh menukar titik ini ke koordinat isometrik dan menggunakannya untuk menarik skrin.

Nilai yang baru ditukar, dalam ruang isometrik, perlu menjadi sudut skrin kami juga, yang bermaksud mereka adalah yang baru (0,0). Oleh itu, semasa menghuraikan dan menarik data tahap, kita menolak nilai ini dari kedudukan isometrik bagi setiap jubin, dan boleh menentukan sama ada jawatan baru jubin berada dalam skrin.

Sebagai alternatif, kita boleh membuat keputusan bahawa kita akan hanya membuat grid jubin isometrik X x Y pada skrin untuk menjadikan gelung lukisan berkesan untuk tahap yang lebih tinggi.

Kita dapat menyatakannya dalam langkah seperti ini:

  • Kemas kini koordinat x- dan y-titik sudut Cartesian
  • Tukar ini ke ruang isometrik.
  • Kurangkan nilai ini dari kedudukan cabutan isometrik bagi setiap jubin.
  • Lukiskan hanya bilangan jubin yang telah ditetapkan terlebih dahulu pada skrin bermula dari sudut baru ini.
  • Pilihan: Lukis jubin hanya jika kedudukan isometrik menarik berada dalam skrin.

Sila ambil perhatian bahawa titik sudut bertambah di arah yang bertentangan dengan kemas kini kedudukan pahlawan ketika dia bergerak. Ini memastikan bahawa wira tetap berada di mana dia berkaitan dengan skrin. Semak contoh ini (gunakan anak panah untuk menatal, ketik untuk meningkatkan grid yang kelihatan).

Beberapa nota:

  • Semasa menatal, kami mungkin perlu membuat ubin tambahan di sempadan skrin, atau kami mungkin melihat jubin menghilang dan muncul di skrin ekstrem.
  • Jika anda mempunyai jubin yang mengambil lebih dari satu ruang, maka anda perlu menarik lebih banyak jubin di sempadan. Sebagai contoh, jika jubin terbesar di seluruh langkah ditetapkan X oleh Y, maka anda perlu menggambar X lebih banyak jubin ke kiri dan kanan dan Y lebih banyak jubin ke bahagian atas dan bawah. Ini memastikan bahawa sudut jubin yang lebih besar masih akan kelihatan apabila menatal masuk atau keluar dari skrin.
  • Kami masih perlu memastikan bahawa kami tidak mempunyai ruang kosong pada skrin semasa kami melangkah berhampiran sempadan peringkat.
  • Tahap hanya perlu tatal sehingga jubin paling ekstrim akan ditarik pada skrin yang bersesuaian-selepas ini, watak itu harus terus bergerak dalam ruang skrin tanpa tahap menatal. Untuk ini, kita perlu mengesan semua empat sudut persegi panjang skrin dalaman, dan mendirikan logik pergerakan dan pergerakan pemain dengan sewajarnya. Adakah anda menghadapi cabaran untuk mencuba melaksanakannya untuk diri sendiri?

Kesimpulan

Siri ini terutamanya bertujuan untuk pemula yang cuba meneroka dunia permainan isometrik. Banyak konsep yang dijelaskan mempunyai pendekatan alternatif yang agak rumit, dan saya sengaja memilih yang paling mudah.

Mereka mungkin tidak memenuhi kebanyakan senario yang mungkin anda hadapi, tetapi pengetahuan yang diperoleh dapat digunakan untuk membina konsep-konsep ini untuk membuat penyelesaian yang lebih rumit. Sebagai contoh, penyortiran kedalaman yang mudah dilaksanakan akan rosak apabila kita mempunyai tahap bertingkat dan jubin platform bergerak dari satu cerita ke yang lain.

Tetapi itu adalah tutorial untuk masa yang lain.

Advertisement
Advertisement
Advertisement
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.