Peta
Saya membuat RPG berbasis ubin dengan Javascript, menggunakan perlin noise noise tinggi, kemudian menetapkan jenis ubin berdasarkan ketinggian suara.
Peta akhirnya terlihat seperti ini (dalam tampilan minimap).
Saya memiliki algoritma yang cukup sederhana yang mengekstraksi nilai warna dari setiap piksel pada gambar dan mengubahnya menjadi bilangan bulat (0-5) tergantung pada posisinya antara (0-255) yang sesuai dengan ubin di kamus ubin. Array 200x200 ini kemudian diteruskan ke klien.
Mesin kemudian menentukan ubin dari nilai-nilai dalam array dan menariknya ke kanvas. Jadi, saya berakhir dengan dunia menarik yang memiliki fitur tampak realistis: gunung, laut dll.
Sekarang hal berikutnya yang ingin saya lakukan adalah menerapkan semacam algoritma pencampuran yang akan menyebabkan ubin berbaur mulus dengan tetangga mereka, jika tetangga tidak dari jenis yang sama. Contoh peta di atas adalah apa yang dilihat pemain di minimapnya. Pada layar mereka melihat versi yang diberikan dari bagian yang ditandai oleh kotak putih; di mana ubin diberikan dengan gambar mereka daripada sebagai piksel warna tunggal.
Ini adalah contoh dari apa yang akan dilihat pengguna di peta tetapi ini bukan lokasi yang sama dengan yang ditampilkan di viewport!
Dalam pandangan inilah saya ingin transisi terjadi.
Algoritma
Saya datang dengan algoritma sederhana yang akan melintasi peta di dalam viewport dan membuat gambar lain di atas setiap ubin, asalkan itu di sebelah ubin dari jenis yang berbeda. (Tidak mengubah peta! Hanya merender beberapa gambar tambahan.) Gagasan algoritma ini adalah untuk profil tetangga ubin saat ini:
Ini adalah contoh skenario dari apa yang mungkin mesin render, dengan ubin saat ini yang ditandai dengan X.
Array 3x3 dibuat dan nilai-nilai di sekitarnya dibaca. Jadi untuk contoh ini array akan terlihat seperti.
[
[1,2,2]
[1,2,2]
[1,1,2]
];
Gagasan saya adalah untuk mengerjakan serangkaian kasus untuk kemungkinan konfigurasi ubin. Pada tingkat yang sangat sederhana:
if(profile[0][1] != profile[1][1]){
//draw a tile which is half sand and half transparent
//Over the current tile -> profile[1][1]
...
}
Yang memberikan hasil ini:
Yang berfungsi sebagai transisi dari [0][1]
ke [1][1]
, tetapi tidak dari [1][1]
ke [2][1]
, di mana tepi yang keras tetap. Jadi saya pikir dalam hal itu ubin sudut harus digunakan. Saya membuat dua lembar sprite 3x3 yang saya pikir akan menampung semua kombinasi ubin yang mungkin diperlukan. Lalu saya meniru ini untuk semua ubin yang ada di dalam game (Area putih transparan). Ini akhirnya menjadi 16 ubin untuk setiap jenis ubin (Ubin tengah pada setiap spritesheet tidak digunakan.)
Hasil Yang Ideal
Jadi, dengan ubin baru ini dan algoritma yang benar, bagian contoh akan terlihat seperti ini:
Namun, setiap upaya yang saya lakukan gagal, selalu saja ada kekurangan dalam algoritme dan pola yang aneh. Saya sepertinya tidak bisa menyelesaikan semua kasus dengan benar dan secara keseluruhan sepertinya cara yang buruk untuk melakukannya.
Sebuah solusi?
Jadi, jika ada yang bisa memberikan solusi alternatif tentang bagaimana saya bisa membuat efek ini, atau arah apa yang harus dilakukan untuk menulis algoritma profil, maka saya akan sangat berterima kasih!
sumber
Jawaban:
Ide dasar dari algoritma ini adalah menggunakan langkah pra-pemrosesan untuk menemukan semua tepi dan kemudian memilih ubin penghalusan yang benar sesuai dengan bentuk tepi.
Langkah pertama adalah menemukan semua sisi. Pada contoh di bawah ubin tepi ditandai dengan X semua ubin hijau dengan ubin tan sebagai satu atau lebih dari delapan ubin tetangga mereka. Dengan berbagai jenis medan, kondisi ini dapat diterjemahkan ke ubin yang menjadi ubin tepi jika memiliki tetangga dengan angka medan yang lebih rendah.
Setelah semua ubin tepi terdeteksi, hal selanjutnya yang harus dilakukan adalah memilih ubin penghalusan yang tepat untuk setiap ubin tepi. Ini representasi saya tentang ubin smoothing Anda.
Perhatikan bahwa sebenarnya tidak ada banyak jenis ubin yang berbeda. Kita membutuhkan delapan ubin luar dari salah satu kotak 3x3 tetapi hanya empat kotak sudut dari yang lain karena ubin tepi lurus sudah ditemukan di kotak pertama. Ini berarti ada total 12 kasus berbeda yang harus kita bedakan.
Sekarang, melihat satu ubin tepi kita dapat menentukan ke arah mana batas berbelok dengan melihat empat ubin tetangga terdekat. Menandai ubin tepi dengan X seperti di atas kami memiliki enam kasus berikut.
Kasing ini digunakan untuk menentukan ubin smoothing yang sesuai dan kami dapat menghitung ubin smoothing yang sesuai.
Masih ada pilihan a atau b untuk setiap kasus. Ini tergantung pada sisi mana rumput itu berada. Salah satu cara untuk menentukan ini bisa dengan melacak orientasi batas tetapi mungkin cara paling sederhana untuk melakukannya adalah dengan memilih satu ubin di sebelah tepi dan melihat warna apa yang dimilikinya. Gambar di bawah ini menunjukkan dua case 5a) dan 5b) yang dapat dibedakan antara dengan misalnya memeriksa warna ubin kanan atas.
Penghitungan akhir untuk contoh asli akan terlihat seperti ini.
Dan setelah memilih ubin tepi yang sesuai perbatasan akan terlihat seperti ini.
Sebagai catatan terakhir saya bisa mengatakan bahwa ini akan berfungsi selama batasnya agak teratur. Lebih tepatnya, ubin tepi yang tidak memiliki tepat dua ubin tepi karena tetangga mereka harus diperlakukan secara terpisah. Ini akan terjadi untuk ubin tepi di tepi peta yang akan memiliki tetangga tepi tunggal dan untuk potongan medan yang sangat sempit di mana jumlah ubin tepi tetangga bisa tiga atau bahkan empat.
sumber
Kotak berikut mewakili pelat logam. Ada "lubang panas" di sudut kanan atas. Kita dapat melihat bagaimana suhu titik ini tetap konstan, pelat logam menyatu ke suhu konstan di setiap titik, secara alami lebih panas di dekat bagian atas:
Masalah menemukan suhu di setiap titik dapat diselesaikan sebagai "masalah nilai batas". Namun cara paling sederhana untuk mengetahui panas pada setiap titik adalah dengan memodelkan pelat sebagai kisi. Kami tahu titik-titik di grid pada suhu konstan. Kami mengatur suhu semua titik yang tidak diketahui menjadi suhu kamar (seolah-olah ventilasi baru saja dihidupkan). Kami kemudian membiarkan panas menyebar melalui piring sampai kami mencapai konvergensi. Ini dilakukan dengan iterasi: kita beralih melalui setiap poin (i, j). Kami menetapkan titik (i, j) = (titik (i + 1, j) + titik (i-1, j) + titik (i, j + 1) + titik (i, j-1)) / 4 [kecuali titik (i, j) memiliki lubang panas dengan suhu konstan]
Jika Anda menerapkan ini untuk masalah Anda, ini sangat mirip, hanya warna rata-rata, bukan suhu. Anda mungkin membutuhkan sekitar 5 iterasi. Saya sarankan menggunakan kotak 400x400. Thats 400x400x5 = kurang dari 1 juta iterasi yang akan cepat. Jika Anda hanya menggunakan 5 iterasi, Anda mungkin tidak perlu khawatir tentang memegang titik warna konstan, karena mereka tidak akan terlalu banyak bergeser dari aslinya (pada kenyataannya hanya titik dalam jarak 5 dari warna yang dapat dipengaruhi oleh warna). Kode palsu:
sumber
Ok, jadi pemikiran pertama adalah bahwa mengotomatisasi solusi sempurna untuk masalah ini membutuhkan beberapa matematika interpolasi yang agak gemuk. Berdasarkan fakta bahwa Anda menyebutkan gambar ubin yang sudah dibuat sebelumnya, saya berasumsi bahwa solusi interpolasi lengkap tidak diperlukan di sini.
Di sisi lain seperti yang Anda katakan, menyelesaikan peta dengan tangan akan menghasilkan hasil yang baik ... tapi saya juga berasumsi bahwa setiap proses manual untuk memperbaiki gangguan juga bukan merupakan pilihan.
Berikut ini adalah algoritma sederhana yang tidak memberikan hasil yang sempurna, tetapi itu sangat bermanfaat berdasarkan upaya rendah yang diperlukan.
Alih-alih mencoba untuk mencampur SETIAP ubin tepi, (yang berarti bahwa Anda harus mengetahui hasil dari pencampuran ubin yang berdekatan terlebih dahulu - interpolasi, atau Anda perlu memperbaiki seluruh peta beberapa kali dan tidak dapat mengandalkan ubin yang dibuat sebelumnya) mengapa tidak mencampur ubin dalam pola checker-board bergantian?
Yaitu hanya memadukan ubin yang membintangi matriks di atas?
Dengan asumsi bahwa satu-satunya langkah yang diizinkan dalam nilai adalah satu per satu, Anda hanya memiliki beberapa ubin untuk dirancang ...
Akan ada total 16 pola. Jika Anda mengambil keuntungan dari simetri rotasi dan reflektif, maka akan semakin sedikit.
'A' akan menjadi ubin gaya [1] polos. 'D' akan menjadi diagonal.
Akan ada diskontinuitas kecil di sudut ubin, tetapi ini akan kecil dibandingkan dengan contoh yang Anda berikan.
Jika saya bisa, saya akan memperbarui posting ini dengan gambar nanti.
sumber
Saya bermain-main dengan sesuatu yang mirip dengan ini, itu tidak selesai karena sejumlah alasan; tetapi pada dasarnya itu akan mengambil matriks 0 dan 1, 0 sebagai tanah dan 1 menjadi dinding untuk aplikasi generator maze di Flash. Karena AS3 mirip dengan JavaScript, tidak akan sulit untuk menulis ulang di JS.
Pada dasarnya ini memeriksa setiap ubin di sekitarnya dari kiri ke kanan, atas ke bawah dan mengasumsikan bahwa ubin tepi selalu 1. Saya juga mengambil kebebasan mengekspor gambar sebagai file untuk digunakan sebagai kunci:
Ini tidak lengkap dan mungkin cara yang sulit untuk mencapai ini, tapi saya pikir itu mungkin bermanfaat.
Sunting: Screenshot dari hasil kode itu.
sumber
Saya akan menyarankan beberapa hal:
tidak masalah apa ubin "tengah" itu, kan? itu bisa 2, tetapi jika yang lainnya 1, itu akan menunjukkan 1?
itu hanya masalah apa sudutnya, ketika ada perbedaan tetangga terdekat ke atas atau samping. Jika semua tetangga terdekat adalah 1, dan sudutnya adalah 2, itu akan menunjukkan 1.
Saya mungkin akan menghitung ulang semua kemungkinan kombinasi tetangga, membuat array indeks 8 dengan empat yang pertama menunjukkan nilai-nilai tetangga atas / bawah, dan yang kedua menunjukkan diagonal:
tepi [N] [E] [S] [W] [NE] [SE] [SW] [NW] = apa pun yang diimbangi menjadi sprite
jadi dalam kasus Anda, [2] [2] [1] [1] [2] [2] [1] [1] = 4 (sprite ke-5).
dalam hal ini, [1] [1] [1] [1] akan menjadi 1, [2] [2] [2] [2] akan menjadi 2, dan sisanya harus diselesaikan. Tetapi pencarian untuk ubin tertentu akan sepele.
sumber