2d Java Line of Sight yang efisien untuk banyak entitas?


7

Masalah saya hari ini adalah ini:

Gambar satu ton orang di peta

Saya memiliki banyak warga sipil di sekitar, mereka adalah kelas yang disimpan oleh daftar susunan.

Idenya adalah ketika mereka melihat kepanikan warga sipil, mereka akan mulai panik dan itu akan menyebar.

Pertama saya memanggil setiap Step()fungsi kelas dengan perulangan melalui iterator. Kemudian pada Step()fungsi ia melewati iterator sipil lain. Saat ia berjalan, ia mencoba mendeteksi apakah ia dapat melihat warga sipil lain di iterator, di sinilah waktu kinerja berjalan dari 0 hingga 50 Milidetik karena memiliki 100 warga sipil.

Ini adalah masalah yang harus saya perbaiki, saya mencoba membuat cara mudah untuk mendeteksi apakah ada benda yang menghalangi titik a ke titik b.

Berikut kode untuk saling berhadapan:

public static Object LOS(int x, int y, int x2, int y2, String Scan, Object Me, Object You) {
   DirectionX = (x-x2)/Quality;
   DirectionY = (y-y2)/Quality;
   CurrentX = x;
   CurrentY = y;
   String[] ScanArray = Scan.split(":");
   for(int I=0;I<=Quality;I++) {
      for(String Type: ScanArray) {
         if(Type.equals("Boxs")) {
            Iterator it=Level.Boxs.iterator();
            while(it.hasNext()) {
               Box Box = (Box)it.next();
               if(Me!=Box&&You!=Box) {
                  //Collision = Tools.Collision((int)(CurrentX-(Width/2)), (int)(CurrentY-(Width/2)), Width, Width, Box.GetX(), Box.GetY(), Box.GetWidth(), Box.GetHeight(), 1);
                  boolean Col = Tools.BasicCollision((int)(CurrentX-(Width/2)), (int)(CurrentY-(Width/2)), Width, Width, Box.GetX(), Box.GetY(), Box.GetWidth(), Box.GetHeight());
               }
            }
         }
      }

      CurrentX-=DirectionX;
      CurrentY-=DirectionY;
   }
   return null;
}

Jika Anda sakit kepala, dasarnya adalah:

Ia menemukan 10 poin di antaranya dan mendeteksi apakah ada di dalam, menggunakan BasicCollision:

public static boolean BasicCollision(int x, int y, int width, int height, int x2, int y2, int width2, int height2) {
   if(x<x2+width&&x+width>x2&&y<y2+height&&y+height>y2) {
      return true;
   } else {
      return false;
   }
}

Pertanyaan saya adalah: Apakah ada cara yang lebih mudah untuk mendeteksi Line of Sight ini yang tidak terlalu memengaruhi kinerja saya dalam jumlah besar? Ada umpan balik?


2
1. 404 pada LOS.txt2. Kami tidak ingin melihat semua kode Anda. Berikan SSCCE .
Matt Ball

Terima kasih atas bantuan pengeditan Matt, saya memperbaiki 404 :) Saya hanya menunjukkan kode yang penting.

Jawaban:


5

Satu pemikiran adalah mempertahankan orang yang tidak panik dan panik dalam daftar N dan P yang terpisah, dan kemudian membatasi pemeriksaan LOS Anda menjadi <n, p> ∈ N × P. Dengan cara itu Anda tidak pernah memeriksa orang dengan status yang sama, yang akan mempercepat berbagai hal naik.

Hal lain (yang mungkin sudah Anda lakukan - tidak yakin) adalah memastikan bahwa setelah Anda menentukan bahwa nonpanicker telah menjadi panicker, segera hentikan cek yang tersisa untuk mantan nonpanicker itu. Ini akan membantu skala algoritme Anda dengan meningkatkan ukuran populasi untuk peta tetap. Ketika populasi menjadi sangat besar maka Anda harus segera menuju 100% panik, yang berarti tidak diperlukan lagi pemeriksaan seperti yang tercantum dalam komentar di bawah ini.


Saran bagus, saya baru saja menambahkan filter itu, pada 0% panik itu pada 1Millisecond, pada 100% itu mencapai 50, tapi ini pasti membuatnya praktis, terima kasih.

Sesuatu tidak terdengar benar - jumlah cek seharusnya (tp) * p, di mana t = total, p = panik. Jadi ketika p = t maka jumlah cek harus 0. Secara intuitif, setelah semua orang panik, tidak ada alasan untuk melakukan pemeriksaan lagi. Apakah Anda yakin bahwa daftar N Anda berisi non- panelis, bukan berisi seluruh populasi? Saya menduga bahwa pada 100% Anda membandingkan setiap panicker dengan seluruh populasi, itulah sebabnya lebih lambat.

2

Dari uraian Anda, sepertinya kode Anda mengulangi setiap kemungkinan pemasangan dua warga sipil. Gambar menunjukkan bahwa ini tidak perlu. Anda dapat menggunakan semacam pengindeksan geometris untuk melacak warga sipil terdekat. Lalu ujilah terlebih dahulu. Jika mereka berada di LOS, maka panik. Kalau tidak, uji lebih jauh warga sipil.


Terima kasih, saya sudah melakukan itu, sebelum optimisasi mencapai 100 milidetik.

0

Anda memiliki beberapa opsi:

A) Asumsikan bahwa orang dapat panik juga mendengar orang lain menjerit, sehingga garis pandang kode XD tidak begitu penting.

B) Dalam hal A bukan pilihan, Anda harus melakukan ini untuk setiap warga sipil:

  1. Hitung jika segmen antara dua warga sipil memiliki panjang kurang atau sama dengan nilai konstan.
  2. Hitung jika segmen ini bersinggungan dengan poligon (persegi panjang, dalam kasus Anda).

Anda harus melakukan 1 sebelum 2 karena sangat mengurangi jumlah pekerjaan, mengingat 2 adalah perhitungan yang paling mahal. Anda juga harus mempertimbangkan semacam "memori" tentang perhitungan yang telah Anda buat, misalnya: Jika Anda baru saja memproses segmen C1-C2, jangan lakukan lagi C2-C1.

Selain itu, Anda harus mengoptimalkan 2. Pengujian jika segmen bersinggungan dengan persegi panjang sama dengan menguji apakah segmen tertentu bersinggungan dengan 4 segmen. Ketika Anda telah berpotongan dengan salah satu dari mereka, kami yakin warga sipil tidak saling bertemu, jadi tidak masuk akal untuk memproses segmen yang tersisa dalam persegi panjang.

Karena ini adalah masalah geometris yang khas, yang dikenal sebagai masalah persimpangan segmen garis , Anda dapat menemukan banyak kode sumber terbuka di internet. Kebanyakan orang menggunakan algoritma garis sapu bersama dengan beberapa struktur data.


Terima kasih atas wawasannya yang luas, saya sedang melakukan riset wiki pada algoritma ini sekarang.
user940982

0

Jika Anda memperlakukan kamar sebagai zona, bergabung dengan portal , Anda hanya perlu melakukan pemindaian visibilitas di setiap kamar dan bagian-bagian kamar yang berdampingan yang terlihat melalui portal yang telah ditentukan sebelumnya.

Garis pandang Anda sepertinya tidak memperhitungkan arah yang dihadapi warga sipil? Dalam kasus seperti itu, jika Anda membagi kamar yang berisi rintangan seperti pilar atau mengelilingi sudut menjadi zona cembung yang terpisah dan dengan asumsi bahwa semua warga sipil di zona yang sama semuanya terlihat satu sama lain. Anda dapat mengambil lebih jauh dengan memiliki zona cekung yang tumpang tindih dan memungkinkan warga sipil berada di lebih dari satu zona sekaligus untuk menemukan sebanyak mungkin di zona yang sama dengan warga sipil lainnya untuk menghindari semua pemeriksaan visibilitas lainnya.

Jika medan Anda tidak rata dan Anda memiliki sejumlah besar agen, maka Anda mungkin tertarik dengan sapuan O (n) ini (di mana N adalah rincian dari kisi yang telah Anda bagikan medan):masukkan deskripsi gambar di sini

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.