Es gibt einige Probleme, auf die ich in meinem Perlin-Spiel gestoßen bin. Schauen Sie sich den beigefügten Screenshot unten an.
Die weißen Bereiche, die Sie sehen, sind Wände und die schwarzen Bereiche sind begehbar. Das Dreieck in der Mitte ist der Spieler.
Ich habe die Physik in dieses Spiel implementiert, indem ich sie auf eine Textur (weiße oder schwarze Pixel) gezeichnet und diese dann von der CPU abgerufen habe.
Jetzt stehe ich jedoch vor einem anderen Problem. Ich möchte, dass Einheiten (oder Creeps, wie auch immer Sie sie nennen) ständig am Rand des Bildschirms erscheinen. Der Punkt hier ist, dass es im letzten Spiel einen "Nebel des Krieges" geben wird, der es dem Spieler sowieso nicht erlaubt, so weit zu sehen.
Ich dachte, ich könnte einfach die Pixel am Rand des Bildschirms scannen und sehen, ob ihre physikalische Textur schwarz ist, und dann willkürlich dort Zeug erzeugen. Wenn Sie sich jedoch den Screenshot noch einmal ansehen, gibt es (in der oberen linken Ecke) ein Beispiel dafür, wo ich nicht möchte, dass die Gänsehaut entsteht (da sie den Spieler von dort aus nicht erreichen können). .
Ist es möglich, dass die GPU diese Spawn-Spots für mich bestimmt oder auf eine andere Art und Weise? Ich überlegte, Vektoren zwischen dem vorgeschlagenen Punkt am Rand des Bildschirms und dem Player zu erstellen und sie dann alle 10 Voxel zu verfolgen und zu prüfen, ob eine Wand kollidiert, bevor ich dort eine Einheit hervorbringe.
Die oben vorgeschlagene Lösung ist jedoch möglicherweise zu CPU-intensiv.
Irgendwelche Vorschläge zu diesem Thema?
Hinweis 1 Für die geborenen Einheiten möchte ich keine Pfadfindung verwenden, um Wandkollisionen zu vermeiden, da diese Einheiten auf den Spieler zu rennen. Daher müssen die Einheiten am Rand des Bildschirms erscheinen, an einem Ort, an dem das Gehen in einer geraden Linie in Richtung des Spielers nicht mit Wänden kollidieren würde.
quelle
Antworten:
Für diesen Job gibt es einen ziemlich nützlichen Algorithmus, der viel effizienter ist als der Flutungsalgorithmus in dieser Situation (seine Komplexität ist die Laufzeit proportional zur Grenzgröße und nicht zum überfluteten Bereich): Es ist der Marschquadrat-Algorithmus. Das Konzept ist einfach: Beginne den Ort des Spielers (Mittelpunkt des Bildschirms), wähle eine Richtung und gehe, bis du eine Wand findest. Wenn Sie mit der Wand kollidieren, starten Sie den Algorithmus: Sie wählen eine Ausrichtung (nach oben oder unten) und beginnen, über die Grenze dieses Bereichs zu marschieren und die Pixel hervorzuheben. Dies gibt Ihnen die innere Grenze für den erlaubten Bereich. Anschließend prüfen Sie einfach, ob die Kandidatenpunkte für Laicheinheiten an dieser Grenze liegen.
Dies ist das Prinzip, dem Sie beim Ausführen der Grenze folgen sollten:
http://en.wikipedia.org/wiki/File:Marchsquares.png (meh ich kann noch keine Bilder posten)
Beschreibung von Wikipedia (obwohl es viel komplexer ist, weil es für andere Anwendungen verwendet wird):
http://en.wikipedia.org/wiki/Marching_squares
quelle
Machen Sie eine Flutfüllung von der Position des Spielers; Jeder "überflutete" Bereich ist dann ein gültiger Spielbereich, und alle anderen sind Wände.
EDIT: Was die zusätzliche Anforderung "in einer geraden Linie erreichbar" angeht, denken Sie daran, dass Sie diese in einem diskreten Raum etwas weiter definieren müssen. Zum Beispiel könnten alle oben genannten Pfade in einer solchen Umgebung eine gültige "Gerade" sein, und ich habe gesehen, dass sie alle in einem Spiel irgendwann verwendet wurden:
Insbesondere sind die meisten von ihnen nicht kommutativ. Das bedeutet nicht, dass Sie A auch von B aus erreichen können, nur weil Sie B von A aus in einer "geraden Linie" erreichen können. Weder ist das Gegenteil unbedingt der Fall.
Außerdem stellt sich die Frage, wie Sie mit diagonalen Bewegungen umgehen, wenn einer oder beide "Seiten" -Punkte blockiert sind.
quelle
Wie wäre es, wenn Sie die Brut einfach passieren lassen? Darin sehe ich kein besonderes Problem.
quelle
Wenn es wichtig ist, dass Sie nur Punkte mit einer gültigen geraden Linie für den Player markieren, können Sie einen Algorithmus wie den folgenden verwenden (es ist ein C ++ - Code), der mehr verbraucht als normales Floodfill. Es kann einige kleinere Fehler geben (ich bin froh, wenn jemand sie korrigiert), da ich den Code nicht selbst getestet habe, aber Sie werden auf die Idee kommen.
quelle
Sie können die Karte mit Farben füllen, die konvexe Bereiche darstellen. Auf diese Weise können Sie Ihre Einheit erzeugen, wenn sie im selben Bereich liegt. Oder Sie können leichter nach erreichbaren Bereichen suchen.
Dies sind statische Daten, damit Sie sie vorberechnen können.
Sie mussten die Bildfindungspunkte füllen, an denen es zu einem Wechsel von konvav zu konvex kommt. Optisch scheint es einfach zu finden. Sie haben zwei Situationen:
quelle
Hier ist etwas, das ich tatsächlich in meinem eigenen Spiel verwendet habe (2d simplex Noise Generated World, fast genau wie deins) - Rays. Beginne beim Spieler, bestimme eine Orientierung (zufällig, wenn du willst) und gehe entlang dieser Linie, bis du auf etwas triffst (Bildschirmrand ODER Asteroid). Wenn Sie auf den Bildschirmrand treffen (und nicht auf einen Asteroiden / weißen Fleck), wissen Sie, dass eine gerade, offene Linie vom Bildschirmrand zum Player verläuft. Dann laichen Sie ein Monster an der Stelle, an der Sie getroffen haben. Wenn Sie einen Asteroiden treffen, wiederholen Sie den Test.
quelle
Eine andere (nicht GPU-) Lösung, die Sie verwenden können, ist die Pfadfindung. Suchen Sie vor dem Zeichnen der Karte von jedem potenziellen Startpunkt an jedem Rand der Karte aus nach Pfaden und prüfen Sie, ob es einen Pfad zur Mitte gibt. Eine * -Pfadfindung ist in Bezug auf Kosten / Leistung in Ordnung, aber Sie können dies tun, bevor das Spiel beginnt, wenn dies ein Problem ist.
Jeder Spawnpunkt, der keinen Pfad hat, kann in eine Ausschlussliste aufgenommen werden. oder umgekehrt (jeder Punkt mit einem Pfad kann auf eine Einschlussliste gesetzt werden).
quelle