Menentukan lokasi akhir untuk pergerakan AI dalam grup dalam RTS 2D


8

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?


Sesuatu yang disebut "berkelompok" mungkin sangat berguna bagi Anda dan mungkin memberi Anda jenis fungsi yang Anda cari. Coba: processing.org/examples/flocking.html atau hanya google "berkelompok" atau "Boids". Itu mungkin menempatkan Anda ke arah yang benar.
Dean Knight

2
Terkait: gamedev.stackexchange.com/questions/44361 Saya akan mengatakan "gangguan" yang Anda alami berasal dari unit yang mencoba untuk pindah ke posisi yang sudah diklaim. Pastikan posisi yang mereka pindahkan bukanlah target untuk unit lain, dan Anda harus mendapatkan hasil yang lumayan.
MichaelHouse

@DeanKnight, saya sadar bagaimana berkelompok perilaku bekerja, tetapi itu mengatur bagaimana bot mendapatkan dari titik A ke titik B, bukan titik B apa.
IceCreamAnda

@ Byte56: terima kasih atas tautannya. Saya tidak benar-benar menempatkan unit ke dalam slot kotak - dalam implementasi tidak ada cara untuk beberapa unit diarahkan ke tempat yang sama. Sepertinya masalahnya lebih bahwa penyortiran kadang-kadang menjadi bingung.
IceCreamAnda

1
Gagasan lain: Swarm Pathfinding . Dalam hal ini, Anda tidak akan memberikan masing-masing unit titik akhir yang berbeda; Anda hanya perlu menghentikan mereka ketika tidak ada jalan yang tersisa ke titik akhir (karena semua unit lain di jalan), atau jangan berhenti sama sekali dan biarkan deteksi tabrakan melakukan tugasnya.
BlueRaja - Danny Pflughoeft

Jawaban:


2

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.


Jawaban yang bagus Terima kasih atas ide-ide baru. Pendekatan Squad + Unit menarik, mungkin mengharuskan unit dapat bergerak lebih cepat dalam mode "catch-up"
IceCreamAnda

Ya, solusi di sana adalah mengatur kecepatan gerakan objek "skuad" menjadi sedikit di bawah maks unit tunggal dapat bergerak, untuk memungkinkan mereka untuk berpindah jika diperlukan tanpa tertinggal.
David M

2

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 )

formasi tanduk banteng


"Masalah selanjutnya adalah memutuskan prajurit mana yang berjalan ke posisi mana dalam formasi." Sebenarnya, itulah keseluruhan masalah dari pertanyaan ini. :) Terpilih untuk saran pembentukan lingkaran daripada kotak, tapi itu tidak efektif untuk lebih dari beberapa tentara, dan memindahkan tentara ke lokasi terdekat dengan mereka menyebabkan lebih banyak konflik daripada solusi saya di atas untuk menyortir unit berdasarkan lokasi.
IceCreamAnda

0

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.


Solusi vektor yang Anda sarankan sama dengan Percobaan 2 saya di atas. Salah satu persyaratan dari pertanyaan ini adalah bahwa unit yang dipilih mungkin tidak dalam formasi.
IceCreamAnda

Dan saya menulis tentang solusi di mana mereka tidak akan bergerak dalam formasi. (Paragraf ke-2)
Spencer
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.