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

Pergerakan Karakter Heksagonal Menggunakan Koordinat Aksial

by
Difficulty:IntermediateLength:LongLanguages:

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

Final product image
What You'll Be Creating

Di bahagian pertama siri ini, kami meneroka sistem koordinat yang berbeza untuk permainan berasaskan jubin heksagon dengan bantuan permainan Tetris heksagonal. Satu perkara yang mungkin anda perhatikan ialah kita masih bergantung pada koordinat offset untuk menarik tahap ke skrin menggunakan array levelData.

Anda juga mungkin ingin tahu bagaimana kita boleh menentukan koordinat paksi jubin heksagon dari koordinat piksel pada skrin. Kaedah yang digunakan dalam tutorial penyapu ranjau heksagon bergantung pada koordinat offset dan bukan penyelesaian mudah. Sebaik sahaja kami memikirkannya, kami akan meneruskan untuk mencipta penyelesaian untuk pergerakan karakter heksagon dan pathfinding.

1. Menukar Koordinat Antara Piksel dan Paksi

Ini akan melibatkan beberapa matematik. Kami akan menggunakan susun atur mendatar untuk keseluruhan tutorial. Mari kita mulakan dengan mencari hubungan yang sangat baik antara lebar dan ketinggian heksagon biasa. Sila rujuk imej di bawah.

Hexagonal tile its angles lengths are displayed

Pertimbangkan heksagon biasa biru di sebelah kiri imej. Kita sudah tahu bahawa semua pihak mempunyai panjang yang sama. Semua sudut dalaman 120 darjah. Menyambung setiap sudut ke pusat segi enam akan menghasilkan enam segi tiga, salah satunya ditunjukkan dengan menggunakan garis merah. Segitiga ini mempunyai semua sudut dalaman yang sama dengan 60 darjah.

Oleh kerana garisan merah memecah kedua sudut sudut di tengah, kita mendapat 120/2 = 60. Sudut ketiga adalah 180- (60 + 60) = 60 kerana jumlah semua sudut dalam segitiga harus 180 darjah. Oleh itu pada asasnya segitiga adalah segitiga sama sisi, yang selanjutnya bermakna bahawa setiap sisi segitiga mempunyai panjang yang sama. Oleh itu, dalam segi enam biru, dua garis merah, garis hijau dan setiap segmen garis biru mempunyai panjang yang sama. Daripada imej, jelas bahawa garis hijau adalah hexTileHeight/2.

Berpindah ke segi segi enam di sebelah kanan, kita dapat melihat bahawa sebagai panjang sampingan sama dengan hexTileHeight/2, ketinggian bahagian segi tiga teratas harus hexTileHeight/4 dan ketinggian bahagian segi tiga bawah harus hexTileHeight/4, yang mana jumlah hingga ketinggian penuh hexagon, hexTileHeight.

Sekarang pertimbangkan segitiga sudut bersudut kecil di bahagian atas sebelah kiri dengan satu sudut hijau dan satu biru. Sudut biru adalah 60 darjah kerana ia adalah separuh sudut sudut, yang seterusnya bermaksud sudut hijau adalah 30 darjah (180- (60 + 90)). Menggunakan maklumat ini, kami tiba di hubungan antara ketinggian dan lebar segi enam tetap.

Menukar Axial ke Koordinat Piksel

Sebelum kita mendekati penukaran itu, mari kita lihat semula susun atur heksagon mendatar di mana kita telah menyerlahkan baris dan lajur di mana salah satu koordinat tetap sama.

Horizontal hexagonal layout with rows and columns highlighted where coordinates remain same

Memandangkan nilai skrin y, kita dapat melihat bahawa setiap baris mempunyai y offset dari 3*hexTileHeight/4, sementara turun ke garisan hijau, satu-satunya nilai yang berubah adalah i. Oleh itu, kita boleh membuat kesimpulan bahawa nilai piksel y hanya bergantung kepada koordinat paksi i.

Di mana s adalah panjang sampingan, yang dijumpai sebagai hexTileHeight/2.

Nilai x skrin sedikit lebih rumit daripada ini. Apabila mempertimbangkan jubin dalam satu baris, setiap jubin mempunyai x offset dari hexTileWidth, yang jelas hanya bergantung pada koordinat j paksi. Tetapi setiap baris alternatif mempunyai tambahan offset hexTileWidth/2 bergantung pada koordinat paksi i.

Sekali lagi mengingat garis hijau, jika kita bayangkan ia adalah grid persegi maka garis itu akan menegak, memuaskan persamaan x = j*hexTileWidth. Sebagai satu-satunya koordinat yang berubah-ubah di sepanjang garisan hijau adalah i, offset akan bergantung padanya. Ini membawa kami kepada persamaan berikut.

Jadi di sini kita mempunyai mereka: persamaan untuk menukar koordinat paksi untuk koordinat skrin. Fungsi penukaran yang sepadan adalah seperti di bawah.

Kod yang disemak untuk menggambar grid heksagon adalah seperti berikut.

Menukar Pixel ke Koordinat Aksial

Membalikkan persamaan dengan penggantian mudah satu pembolehubah akan membawa kita ke skrin untuk persamaan penukaran paksi.

Walaupun koordinat paksi yang diperlukan adalah bilangan bulat, persamaan akan menghasilkan nombor titik terapung. Jadi kita perlu mengelilingi mereka dan menggunakan beberapa pembetulan, bergantung kepada persamaan utama kita x + y + z = 0. Fungsi penukaran adalah seperti di bawah.

Semak elemen interaktif, yang menggunakan kaedah ini untuk memaparkan jubin dan mengesan paip.

2. Pergerakan Karakter

Konsep utama pergerakan watak dalam mana-mana grid adalah sama. Kami mengundi untuk input pengguna, menentukan arah, cari posisi yang terhasil, periksa jika kedudukan yang terhasil jatuh di dalam dinding dalam grid, lain-lain bergerakkan karakter ke kedudukan itu. Anda boleh merujuk kepada tutorial pergerakan watak isometrik saya untuk melihat ini dalam tindakan berkenaan dengan penukaran koordinat isometrik.

Satu-satunya perkara yang berbeza di sini ialah penukaran koordinat dan arah gerakan. Untuk grid heksagon yang melintang, terdapat enam arah untuk gerakan. Kita boleh menggunakan kekunci papan kekunci A, W, E, D, X, dan Z untuk mengawal setiap arah. Susun atur papan kekunci lalai sepadan dengan arahan dengan sempurna, dan fungsi yang berkaitan adalah seperti di bawah.

Arah gerakan pepenjuru membuat sudut 60 darjah dengan arah melintang. Oleh itu, kita boleh mengira kedudukan baru dengan menggunakan trigonometri dengan menggunakan Cos 60 dan Sine 60. Dari movementVector ini, kami mengetahui kedudukan baru yang dihasilkan dan periksa jika ia jatuh di dalam dinding dalam grid seperti di bawah.

Kami menambah Vektor pergerakan ke vektor kedudukan wira untuk mendapatkan kedudukan baru untuk pusat sprit wira. Kemudian kita dapati kedudukan empat sudut sprite pahlawan dan periksa apakah mereka bertabrakan. Sekiranya tidak ada pertembungan, maka kami akan menetapkan kedudukan baru untuk sprite pahlawan. Mari kita lihat bahawa dalam tindakan.

Biasanya, pergerakan bebas seperti ini tidak dibenarkan dalam permainan berasaskan grid. Biasanya, aksara bergerak dari jubin ke jubin, iaitu, jubin pusat ke pusat jubin, berdasarkan arahan atau ketik. Saya percaya bahawa anda boleh memikirkan penyelesaian itu sendiri.

3. Pathfinding

Jadi di sini kita berada pada topik pemfailan laluan, topik yang sangat menakutkan untuk sesetengah orang. Dalam tutorial saya sebelum ini, saya tidak pernah cuba untuk membuat penyelesaian laluan laluan baru tetapi selalu memilih untuk menggunakan penyelesaian yang sedia ada yang berperang diuji.

Kali ini, saya membuat pengecualian dan akan mencipta semula roda, terutamanya kerana terdapat pelbagai mekanik permainan yang mungkin dan tiada penyelesaian tunggal akan memberi manfaat kepada semua. Oleh itu, adalah berguna untuk mengetahui bagaimana segala-galanya dilakukan untuk melahirkan penyelesaian khusus anda untuk mekanik permainan anda.

Algoritma yang paling asas digunakan untuk laluan laluan di grid adalah Algoritma Dijkstra. Kami mula di simpul pertama dan mengira kos yang terlibat dalam pemindahan ke semua nod jiran yang mungkin. Kami menutup nod pertama dan berpindah ke node tetangga dengan kos terendah yang terlibat. Ini diulangi untuk semua nod yang tidak ditutup sehingga kami mencapai destinasi. Satu variasi ini ialah A*algoritma, di mana kita juga menggunakan heuristik sebagai tambahan kepada kos.

A heuristik digunakan untuk mengira jarak jarak dari nod semasa ke nod destinasi. Oleh kerana kita tidak benar-benar mengetahui laluan, pengiraan jarak ini sentiasa menjadi penghampiran. Jadi heuristik yang lebih baik akan sentiasa menghasilkan jalan yang lebih baik. Sekarang, yang dikatakan, penyelesaian terbaik tidak perlu menjadi yang menghasilkan jalan terbaik kerana kita perlu mempertimbangkan penggunaan sumber dan prestasi algoritma juga, apabila semua pengiraan perlu dilakukan dalam masa nyata atau sekali setiap kemas kini gelung.

Heuristik yang paling mudah dan mudah ialah Manhattan heuristik atau jarak Manhattan. Dalam grid 2D, ini sebenarnya jarak antara nod awal dan nod akhir sebagai lalat gagak, atau bilangan blok yang perlu kita jalankan.

Varian Hexagonal Manhattan

Untuk grid heksagon kita, kita perlu mencari variasi untuk heuristik Manhattan untuk menghampiri jarak. Ketika kami berjalan di jubin heksagon, ide ini adalah untuk mencari bilangan jubin yang kita perlukan untuk mencapai tujuan. Izinkan saya tunjukkan kepada anda penyelesaiannya terlebih dahulu. Sila gerakkan tetikus ke atas unsur interaktif di bawah untuk melihat sejauh mana jubin lain dari jubin di bawah tetikus.

Dalam contoh di atas, kita dapati jubin di bawah tetikus dan mencari jarak semua jubin lain daripadanya. Logiknya ialah untuk mencari perbezaan koordinat i dan j bersama paksi kedua, katakan di dan dj. Cari nilai mutlak perbezaan, absi dan absj, kerana jarak sentiasa positif.

Kami perhatikan bahawa apabila kedua-dua di dan dj adalah positif dan apabila kedua-dua di dan dj adalah negatif, jaraknya absi + absj. Apabila di dan dj adalah tanda bertentangan, jarak adalah nilai yang lebih besar di kalangan absi dan absj. Ini membawa kepada fungsi pengiraan heuristik getHeuristic seperti di bawah.

Satu perkara yang perlu diperhatikan ialah kita tidak mempertimbangkan sama ada jalan itu benar-benar boleh dilalui atau tidak; kami hanya menganggap bahawa ia boleh dilayari dan menetapkan nilai jarak.

Mencari Laluan Heksagonal

Mari kita meneruskan penjejakan laluan untuk grid heksagon kita dengan kaedah heuristik yang baru dijumpai. Satu perkara yang perlu diperhatikan ialah kita tidak mempertimbangkan sama ada jalan itu benar-benar boleh dilalui atau tidak; kami hanya menganggap bahawa ia boleh dilayari dan menetapkan nilai jarak.

  • Kami mempunyai fungsi rekursif, katakan findPath (jubin), yang mengambil satu jubin heksagon, yang merupakan jubin semasa. Pada mulanya ini akan menjadi jubin permulaan.
  • Jika jubin adalah sama dengan jubin akhir, rekursi berakhir dan kami telah menemui jalan. Sekiranya kita meneruskan pengiraan.
  • Kami mendapati semua jiran yang boleh dilayari jubin itu. Kami akan gelung melalui semua jubin jiran dan memohon logik selanjutnya kepada setiap daripada mereka kecuali mereka ditutup.
  • Jika jiran tidak pernah melawat sebelumnya dan tidak ditutup, kita dapati jarak jubin jiran ke jubin akhir menggunakan heuristik kami. Kami menetapkan biaya jubin jiran untuk kos jubin semasa + 10. Kami menetapkan jubin jiran seperti yang dikunjungi. Kami menetapkan jubin jubin sebelum ini sebagai jubin semasa. Kami melakukan ini untuk jiran yang pernah dikunjungi sebelum ini jika kos jubin semasa + 10 kurang daripada kos jiran itu.
  • Kami mengira jumlah kos sebagai jumlah nilai jubin jubin dan nilai jarak heuristik. Di antara semua jiran, kami memilih jiran yang memberikan jumlah kos terendah dan panggilan findPath pada jubin jiran itu.
  • Kami menetapkan jubin semasa ditutup supaya tidak dipertimbangkan lagi.
  • Dalam sesetengah kes, kami akan gagal mencari sebarang jubin yang memenuhi syarat, dan kemudian kami menutup jubin semasa, buka jubin sebelumnya dan buat semula.

Terdapat keadaan kegagalan yang jelas dalam logik apabila lebih daripada satu jubin memenuhi syarat. Algoritma yang lebih baik akan menemui semua laluan yang berlainan dan memilih satu dengan panjang terpendek, tetapi kami tidak akan melakukannya di sini. Semak jalan lencongan dalam tindakan di bawah.

Untuk contoh ini, saya menghitung jiran-jiran yang berbeza daripada contoh Tetris. Apabila menggunakan koordinat paksi, jubin jiran mempunyai koordinat yang lebih tinggi atau lebih rendah dengan nilai 1.

Fungsi rekursif findPath adalah seperti di bawah.

Ia mungkin memerlukan pembacaan lebih lanjut dan berbilang untuk memahami dengan betul apa yang sedang berlaku, tetapi percayalah, ini adalah usaha yang baik. Ini hanya penyelesaian yang sangat asas dan boleh dipertingkatkan. Untuk memindahkan watak di sepanjang laluan yang dikira, anda boleh merujuk kepada laluan isometrik saya mengikuti tutorial.

Menandakan laluan dilakukan menggunakan fungsi rekursif mudah yang lain, paintPath (jubin), yang pertama kali dipanggil dengan jubin akhir. Kami hanya menandakan sebelumnyaNode jubin jika ada.

Kesimpulan

Dengan bantuan semua tiga tutorial heksagonal yang saya kongsi, anda sepatutnya dapat memulakan permainan berasaskan ubin heksagon yang seterusnya.

Sila maklumkan bahawa terdapat pendekatan lain juga, dan terdapat banyak bacaan lanjut di sana jika anda bersedia untuk itu. Tolong beritahu saya melalui komen jika anda memerlukan apa-apa lagi untuk diterokai berhubung dengan permainan berasaskan jubin heksagon.

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.