Saya telah menulis sebuah game RTS (sebuah demo untuk mesin permainan sejenis, sebenarnya) di mana interaksi dasar pengguna dengan permainan adalah untuk memilih sekelompok tentara dan kemudian klik kanan pada peta untuk memindahkan mereka ke lokasi yang ditentukan. Ini dalam JavaScript dan Anda bisa bermain dengannya di sini ( kode ).
Mengabaikan masalah bagaimana tentara bergerak dari lokasi mereka saat ini ke tujuan mereka, pertanyaan saya adalah tentang menentukan apa tujuan sebenarnya mereka. Inilah yang saya coba sejauh ini:
- Percobaan 1: Beritahu semua prajurit yang dipilih untuk bergerak ke koordinat yang diklik mouse. Ini memiliki perilaku aneh bahwa semua prajurit kemudian akan mengelompok di sekitar target secara tidak wajar.
- Percobaan 2: Temukan koordinat rata-rata dari semua tentara yang dipilih, kemudian temukan offset dari titik pusat untuk setiap prajurit, dan akhirnya terjemahkan bahwa offset di sekitar koordinat mouse. Ini berfungsi dengan baik kecuali bahwa jika prajurit yang Anda pilih berjauhan mereka tidak akan mendekati target.
- Percobaan 3: Bangun kisi-kisi di sekitar koordinat mouse dan tempatkan setiap prajurit yang dipilih ke dalam sel kisi. Jika setiap prajurit berhasil masuk ke sel yang ditugaskan kepada mereka, ini akan berhasil. Namun, tentara ditugaskan ke sel-sel jaringan dalam urutan prajurit dilahirkan, jadi kadang-kadang mereka bertabrakan (yaitu semua tentara di sisi kanan akan mencoba untuk pergi ke sisi kiri) yang terlihat tidak wajar.
- Usaha 4: Gunakan kisi-kisi seperti sebelumnya, tetapi pertama-tama sortir tentara berdasarkan lokasi sehingga mereka berbaris dengan bijaksana, yaitu jika Anda mengklik di bawah grup, maka prajurit di bagian bawah grup akan berakhir di bagian bawah kisi ketika mereka mencapai tujuan mereka. Ini bekerja cukup baik tetapi kadang-kadang ada gangguan dan saya tidak yakin mengapa.
Berikut adalah fungsi yang menentukan koordinat tujuan:
function moveSelectedSoldiersToMouse() {
var w = 0, h = 0, selected = [];
// Get information about the selected soldiers.
myTeam.soldiers.forEach(function(soldier) {
if (soldier.selected) {
selected.push(soldier);
w += soldier.width;
h += soldier.height;
}
});
var numSelected = selected.length, k = -1;
if (!numSelected) return;
// Build a grid of evenly spaced soldiers.
var sqrt = Math.sqrt(numSelected),
rows = Math.ceil(sqrt),
cols = Math.ceil(sqrt),
x = Mouse.Coords.worldX(),
y = Mouse.Coords.worldY(),
iw = Math.ceil(w / numSelected), // grid cell width
ih = Math.ceil(h / numSelected), // grid cell height
wg = iw*1.2, // width of gap between cells
hg = ih*1.2; // height of gap between cells
if ((rows-1)*cols >= numSelected) rows--;
w = iw * cols + wg * (cols-1); // total width of group
h = ih * rows + hg * (rows-1); // total height of group
// Sort by location to avoid soldiers getting in each others' way.
selected.sort(function(a, b) {
// Round to 10's digit; specific locations can be off by a pixel or so
var ax = a.x.round(-1), ay = a.y.round(-1), bx = b.x.round(-1), by = b.y.round(-1);
return ay - by || ax - bx;
});
// Place the grid over the mouse and send soldiers there.
for (var i = 0; i < rows; i++) {
for (var j = 0; j < cols; j++) {
var s = selected[++k];
if (s) {
var mx = x + j * (iw+wg) - w * 0.5 + s.width * 0.5,
my = y + i * (ih+hg) - h * 0.5 + s.height * 0.5;
// Finally, move to the end destination coordinates
s.moveTo(mx, my);
}
}
}
}
Anda dapat menempelkan fungsi ini ke konsol JavaScript browser Anda saat melihat demo dan mengacaukannya untuk mengubah perilaku tentara.
Pertanyaan saya adalah: adakah cara yang lebih baik untuk menentukan lokasi target untuk setiap prajurit untuk pindah?
sumber
Jawaban:
Inilah saran saya tentang ide-ide Anda:
Percobaan 1: Untuk memperbaiki situasi ini, Anda dapat menerapkan ide "cukup dekat" yang diajukan Spencer. Saya akan melakukan sesuatu seperti menggambar gelembung di sekitar titik akhir, yang tumbuh berdasarkan rasio jumlah dan ukuran unit yang sudah ada di dalamnya. Katakanlah gelembung mulai ukuran satu unit, kemudian ketika yang pertama sampai di sana, jari-jari menggandakan untuk dua unit berikutnya, dll.
Percobaan 2: Perbaikan untuk yang satu ini, akan mengambil jarak rata-rata grup dari satu sama lain, kemudian memotong jarak outlier untuk itu, sehingga grup berakhir lebih banyak daripada sebelumnya (metrik bisa lebih pendek / lebih lama dari rata-rata, apa pun yang membuatnya tampak layak, atau mungkin menetapkan ukuran bentuk maksimum berdasarkan jumlah / ukuran pasukan lagi) Satu-satunya hal yang harus Anda khawatirkan adalah ketika Anda mengubah jalur pencilan, Anda harus Aku harus memeriksa dan memastikan itu tidak mengganggu jalan lain
Percobaan 3: Anda memperbaiki yang ini dalam upaya 4
Percobaan 4: Kedengarannya seperti ini akan bekerja dengan baik jika Anda menemukan gangguan apa pun yang membuangnya. Saya akan merekomendasikan bermain dengan spahes selain dari hanya formasi grid, untuk membuat gerakan terlihat sedikit lebih alami, kecuali jika Anda menggunakan gaya realisme / militer, dalam hal ini mungkin rapi untuk memilikinya "membentuk" "Sebelum pindah, tapi itu mungkin mengganggu pemain setelah beberapa saat.
Upaya 4 tampaknya yang paling dekat dengan menghilangkan perilaku penggilingan dalam masalah Anda, tetapi dalam hal menjaga gerakan mengalir tanpa penyesuaian apa pun selain yang diperlukan, favorit saya mungkin adalah usaha 2.
Tetapi sebagai solusi yang sama sekali berbeda, Anda dapat memiliki dua jenis objek ketika datang ke pathfinding; setiap unit, serta objek "pasukan" yang tidak terlihat.
Skuadron - Anda membangun objek skuadron di tengah-tengah grup, seperti solusi lain, dan menggunakan pathfinding Anda untuk mengarahkannya ke tujuan.
Unit - Unit mengabaikan tujuan sepenuhnya, dan sebagai gantinya menggunakan pathfinding untuk menjaga jarak tertentu (atau formasi, atau metrik lainnya berakhir membuat gerakan terlihat terbaik) dari objek skuad.
Ini memisahkan aspek-aspek berbeda dari pathfinding, dan memungkinkan Anda untuk men-tweak kedua sisi secara terpisah untuk lebih mengontrol bagaimana tampilannya.
sumber
Percobaan 3 bisa berhasil, tetapi perlu sedikit penyempurnaan.
Pikirkan konsep formasi (kisi Anda adalah awal). Formasi harus memiliki lokasi (mis. Koordinat klik, atau tentara target / bangunan) dan rotasi (ini bisa diperbaiki, acak atau deterministik). Formasi harus memiliki jumlah posisi yang sama dengan jumlah prajurit yang dipilih.
Contoh formasi sederhana dapat berupa lingkaran di sekitar target. Posisi ruang sama rata dan meningkatkan jari-jari lingkaran agar sesuai dengan semua prajurit tanpa bertabrakan.
Masalah selanjutnya adalah menentukan prajurit mana yang berjalan ke posisi mana dalam formasi. Solusi sederhana bisa membuat setiap prajurit bergerak ke posisi yang paling dekat dengannya. Jika yang itu sudah 'dipilih' oleh tentara lain, ambil posisi terdekat berikutnya, dll.
Formasi bisa menjadi sangat menarik. Di bawah ini adalah gambar 'formasi tanduk banteng' yang digunakan dengan sangat sukses oleh Shaka the Zulu . (Gambar berasal dari TotalWar Formation Mod )
sumber
Setelah pengguna mengklik, gambar vektor dari setiap prajurit ke lokasi yang diklik. Dapatkan sudut vektor rata-rata dari vektor yang diambil untuk setiap prajurit dan pindahkan setiap prajurit dengan panjang masing-masing vektor ke arah itu dengan sudut yang sama. Ini akan memberikan tampilan unit bergerak dalam formasi ke titik dan harus menjaga unit tidak menggumpal.
Jika Anda ingin unit keluar dari formasi, Anda dapat mengarahkan sudut setiap prajurit langsung ke lokasi yang diklik. Namun, tanpa tabrakan unit akan mulai menyatu. Untuk mengatasi ini, tambahkan tabrakan dan paksa unit untuk berhenti bergerak begitu mereka "cukup dekat" ke titik yang diklik. Unit pertama yang tiba akan tepat pada titik dan yang terakhir tiba harus diarahkan untuk berhenti bergerak begitu mereka cukup dekat atau sejumlah waktu telah berlalu.
Anda dapat menghitung panjang jalur dan kecepatan unit untuk menentukan kapan satu unit harus tiba dan kemudian memaksa unit untuk berhenti bergerak jika melebihi waktu itu dengan jumlah tertentu. Anda harus bermain dengan angka itu sedikit.
sumber