Ich mache ein RTS-Spiel und wie die meisten RTS können Sie nur dann sehen, was in einem Teil einer Karte vor sich geht, wenn Sie dort eine Einheit haben.
Ich habe nur wenige Ideen, wie dies erreicht werden kann, aber es gibt Probleme damit.
Probleme sind:
- Der Algorithmus muss effizient sein.
- Ich muss Spieler (über das Netzwerk) benachrichtigen, wenn ein Feind in Sicht kommt.
- Wie berücksichtige ich Hindernisse, die die Sicht behindern (z. B. Klippen)?
Ein naiver Ansatz wäre wie folgt:
// pseudocode
func calculate_visibility:
vector<Bitfield> visible;
for all units on map:
let unit = enumerated unit
for all human players:
let player = enumerated player
for all units of player:
let player_unit = enumerated unit
if player_unit sees unit
visible[unit.id][player.id] = true
process next player
Führen Sie diese Berechnung dann in jedem Frame aus, vergleichen Sie die Ergebnisse mit dem vorherigen Frame und senden Sie Ereignisse wie "erkannte feindliche Einheit" aus.
Ich habe ein Benchmarking durchgeführt, und die Verwendung eines solchen Ansatzes kann bis zu 2/3 eines Frames dauern, was nicht akzeptabel ist.
Ich habe einen besseren Weg gefunden, um zu berechnen, welche Einheiten sichtbar sind. Bei diesem Ansatz wird eine Sichtbarkeitskarte verwendet.
- Unterteilen Sie die Karte in N × M-Zellen.
- Jede Zelle ist durch IDs von Spielern gekennzeichnet, die die Zelle sehen können.
- Um festzustellen, welche Spieler eine Einheit sehen können, muss ich nur Zellen überprüfen, die eine bestimmte Einheit enthalten.
Ich weiß jedoch nicht, wie ich die Karte überhaupt füllen soll. Ich könnte alle Einheiten durchlaufen und einen Kreiszeichnungsalgorithmus verwenden.
Aber ich muss die Sichtbarkeitskarte in jedem Frame neu zeichnen, damit dies nicht viel effizienter aussieht als der erste Ansatz. Es sei denn, ich aktualisiere es mit einer niedrigeren Rate, aber dann gibt es ein Problem mit sich schnell bewegenden Einheiten.
Und wie erkenne ich, wann eine Einheit in Sichtweite des Spielers kommt, außer dass ich jede Einheit durchlaufe und mit dem vorherigen Frame vergleiche?
Wie wird dies in modernen RTS wie StarCraft 2 gemacht?