it-swarm.com.de

Pacman: Wie finden die Augen zurück zum Monsterloch?

Ich habe viele Hinweise auf die KI der Geister in Pacman gefunden, aber keiner von ihnen erwähnte, wie die Augen zum zentralen Geisterloch zurückfinden, nachdem ein Geist von Pacman gefressen wurde.

In meiner Implementierung habe ich eine einfache, aber schreckliche Lösung implementiert. Ich habe gerade an jeder Ecke hart codiert, in welche Richtung man gehen soll.

Gibt es eine bessere/oder die beste Lösung? Vielleicht eine generische, die mit verschiedenen Level-Designs funktioniert?

321

Eigentlich würde ich sagen, dass Ihr Ansatz eine ziemlich großartige Lösung ist, mit einem Zeitaufwand von fast null im Vergleich zu jeder Art von Wegfindung.

Wenn Sie es für die Verallgemeinerung auf beliebige Karten benötigen, können Sie einen beliebigen Pfadfindungsalgorithmus verwenden - die Breitensuche ist beispielsweise einfach zu implementieren - und damit berechnen, welche Richtungen an jeder Ecke zu codieren sind, bevor das Spiel ausgeführt wird.

BEARBEITEN (11. August 2010): Ich wurde gerade auf eine sehr detaillierte Seite über das Pacman-System verwiesen: The Pac-Man Dossier , und da ich die akzeptierte Antwort hier habe, hatte ich das Gefühl, ich sollte sie aktualisieren. Der Artikel scheint die Rückkehr zum Monsterhaus nicht explizit zu behandeln, besagt jedoch, dass die direkte Wegfindung in Pac-Man ein Fall von Folgendem ist:

  • bewegen Sie sich weiter in Richtung der nächsten Kreuzung (obwohl dies im Wesentlichen ein Sonderfall ist, wenn Sie eine Wahl haben, wählen Sie die Richtung, in der Ihre Richtung nicht umgekehrt wird, wie im nächsten Schritt gezeigt).
  • schauen Sie sich an der Kreuzung die angrenzenden Ausgangsquadrate an, mit Ausnahme derjenigen, von der Sie gerade gekommen sind.
  • wählen Sie eine, die dem Ziel am nächsten ist. Wenn mehr als eine gleich nah am Ziel ist, wählen Sie die erste gültige Richtung in dieser Reihenfolge aus: oben, links, unten, rechts.
151
Kylotan

Ich habe dieses Problem für generische Levels folgendermaßen gelöst: Bevor das Level startet, fülle ich das Monsterloch mit einer Art "Flood Fill". Jedes Plättchen des Labyrinths, das keine Wand ist, erhält eine Nummer, die angibt, wie weit es vom Loch entfernt ist. Wenn sich die Augen also auf einem Feld mit einem Abstand von 68 befinden, schauen sie, welches der benachbarten Felder einen Abstand von 67 hat. Das ist der richtige Weg.

85

Als Alternative zu herkömmlichen Algorithmen zur Pfadfindung können Sie das (entsprechend benannte!) Pac-Man Scent Antiobject-Muster betrachten.

Sie könnten beim Start den Monster-Hole-Duft im Labyrinth verteilen und die Augen nach Hause verfolgen lassen.

Sobald der Geruch eingerichtet ist, sind die Laufzeitkosten sehr niedrig.


Bearbeiten: Leider wurde der Wikipedia-Artikel gelöscht, also WayBack-Maschine zur Rettung ...

42
Dan Vinton

Sie sollten sich einen Pfadfindungsalgorithmus ansehen, wie Dijkstra's Algorithmus oder A * -Algorithmus . Dies ist, was Ihr Problem ist: ein Graph/Pfad-Problem.

18

Jede einfache Lösung, die funktioniert, wartbar, zuverlässig und leistungsfähig genug ist, ist eine gute Lösung. Es hört sich für mich so an, als hätten Sie bereits eine gute Lösung gefunden ...

Eine Pfadfindungslösung ist wahrscheinlich komplizierter als Ihre aktuelle Lösung und erfordert daher mit größerer Wahrscheinlichkeit ein Debugging. Es wird wahrscheinlich auch langsamer sein.

IMO, wenn es nicht kaputt ist, repariere es nicht.

EDIT

IMO, wenn das Labyrinth repariert ist, dann ist Ihre aktuelle Lösung ist guter/eleganter Code. Machen Sie nicht den Fehler, "gut" oder "elegant" mit "klug" gleichzusetzen. Einfacher Code kann auch "gut" und "elegant" sein.

Wenn Sie konfigurierbare Labyrinth-Ebenen haben, sollten Sie die Pfadfindung möglicherweise erst bei der Erstkonfiguration der Labyrinthe durchführen. Am einfachsten wäre es, den Labyrinthdesigner von Hand dazu zu bringen. Ich würde mich nur darum kümmern, dies zu automatisieren, wenn Sie eine Unmenge von Labyrinthen haben ... oder Benutzer sie entwerfen können.

(Abgesehen davon: Wenn die Routen von Hand konfiguriert werden, könnte der Labyrinth-Designer ein Level mit suboptimalen Routen interessanter machen ...)

18
Stephen C

Im ursprünglichen Pacman fand der Ghost den gelben Pillenfresser durch seinen "Geruch", er würde eine Spur auf der Karte hinterlassen, der Ghost würde zufällig herumlaufen, bis sie den Geruch fanden, dann würden sie einfach dem Geruchspfad folgen, zu dem sie direkt führten der Spieler. Jedes Mal, wenn Pacman sich bewegte, wurden die "Geruchswerte" um 1 verringert.

Eine einfache Möglichkeit, den gesamten Vorgang umzukehren, wäre eine "Pyramide des Geistergeruchs", deren höchster Punkt in der Mitte der Karte liegt. Dann bewegt sich der Geist einfach in Richtung dieses Geruchs.

14
Ivo Wetzel

Angenommen, Sie haben bereits die erforderliche Logik, um Pacman zu jagen, warum sollten Sie das nicht wiederverwenden? Ändern Sie einfach das Ziel. Es scheint viel weniger Arbeit zu sein, als mit genau der gleichen Logik eine völlig neue Routine zu erstellen.

5
John Gardeniers

Dies war die beste Quelle, die ich finden konnte, wie es tatsächlich funktionierte.

http://gameai.com/wiki/index.php?title=Pac-Man#Respawn Wenn die Geister getötet werden, kehren ihre körperlosen Augen zu ihrem Ausgangspunkt zurück. Dies wird einfach erreicht, indem das Zielplättchen des Geistes auf diesen Ort gesetzt wird. Die Navigation verwendet die gleichen Regeln.

Es macht tatsächlich Sinn. Vielleicht nicht die effizienteste der Welt, aber eine gute Möglichkeit, sich keine Sorgen um einen anderen Staat oder etwas Ähnliches zu machen, wenn Sie nur das Ziel ändern.

Randnotiz: Mir war nicht klar, wie großartig diese Pac-Man-Programmierer waren, als sie im Grunde ein komplettes Nachrichtensystem auf sehr kleinem Raum mit sehr begrenztem Speicher bauten ... das ist erstaunlich.

3
Midpipps

Wie wäre es mit jedem Quadrat mit einem Abstand zum Zentrum? Auf diese Weise können Sie für jedes gegebene Quadrat Werte von Quadraten des unmittelbaren Nachbarn in alle möglichen Richtungen erhalten. Sie wählen das Quadrat mit dem niedrigsten Wert und bewegen sich zu diesem Quadrat.

Die Werte würden unter Verwendung eines verfügbaren Algorithmus vorberechnet.

3
mvbl fst

Es ist ein Wegfindungsproblem. Einen gängigen Algorithmus finden Sie unter http://wiki.gamedev.net/index.php/A* .

3
Marijn

der Vorschlag von dtb23, an jeder Ecke nur eine zufällige Richtung zu wählen, und schließlich werden Sie feststellen, dass das Monsterloch fürchterlich unzulänglich klingt.

Sie können jedoch den ineffizienten Return-to-Home-Algorithmus verwenden, um das Spiel unterhaltsamer zu gestalten, indem Sie die Schwierigkeitsstufe des Spiels abwechslungsreicher gestalten. Sie würden dies tun, indem Sie einen der oben genannten Ansätze wie Ihre Wegpunkte oder die Überflutungsfüllung anwenden, dies jedoch nicht deterministisch. Sie können also an jeder Ecke eine Zufallszahl generieren, um zu entscheiden, ob Sie den optimalen Weg oder eine zufällige Richtung wählen.

Je weiter der Spieler voranschreitet, desto geringer ist die Wahrscheinlichkeit, dass eine zufällige Richtung eingeschlagen wird. Dies würde einen weiteren Hebel für den allgemeinen Schwierigkeitsgrad hinzufügen, zusätzlich zu Level-Geschwindigkeit, Geister-Geschwindigkeit, Pausen zum Essen von Pillen (usw.). Sie haben mehr Zeit zum Entspannen, während die Geister nur harmlose Augen sind, aber diese Zeit wird immer kürzer, je weiter Sie kommen.

2
imoatama

Kurze Antwort, nicht sehr gut. :) Wenn Sie das Pac-Man-Labyrinth ändern, werden die Augen nicht unbedingt zurückkehren. Einige der herumschwebenden Hacks haben dieses Problem. Es ist also abhängig von einem kooperativen Labyrinth.

2
dwidel

Ich denke, Ihre Lösung ist richtig für das Problem, einfacher ist es, eine neue Version "realistischer" zu machen, bei der Geisteraugen durch Wände gehen können =)

2
Hernán Eche

Hier ist eine analoge und Pseudocode zur Flood-Fill-Idee von ammoQ.

queue q
enqueue q, ghost_Origin
set visited

while q has squares
   p <= dequeue q
   for each square s adjacent to p
      if ( s not in visited ) then
         add s to visited
         s.returndirection <= direction from s to p
         enqueue q, s
      end if
   next
 next

Die Idee ist, dass es sich um eine Breitensuche handelt. Jedes Mal, wenn Sie auf ein neues benachbartes Quadrat s stoßen, ist der beste Weg durch p. Es ist O(N) Ich glaube.

2
Mark Peters

Ich weiß nicht viel darüber, wie Sie Ihr Spiel implementiert haben, aber Sie könnten Folgendes tun:

  1. Bestimmen Sie die Position der Augen relativ zum Tor. d.h. ist es oben gelassen? Gleich darunter?
  2. Bewegen Sie dann die Augen gegen eine der beiden Richtungen (z. B. bewegen Sie sie nach links, wenn sie sich rechts vom Tor und unterhalb des Tors befindet), und überprüfen Sie, ob es Wände gibt, die Sie daran hindern.
  3. Wenn es Wände gibt, die Sie daran hindern, bewegen Sie sie in die entgegengesetzte Richtung (z. B. wenn die Koordinaten der Augen in Bezug auf die Stecknadel genau im Norden liegen und sie sich gerade nach links bewegen, aber eine Wand im Weg ist, um dies zu tun bewege dich nach Süden.
  4. Denken Sie daran, bei jeder Bewegung zu überprüfen, wo sich die Augen in Bezug auf das Tor befinden, und zu überprüfen, ob keine Breitengradkoordinate vorhanden ist. es ist nur über dem Tor.
  5. In dem Fall, dass es nur über dem Tor ist, gehen Sie nach unten, wenn es eine Wand gibt, bewegen Sie sich entweder nach links oder rechts und machen Sie diese Nummer 1 - 4 weiter, bis die Augen in der Höhle sind.
  6. Ich habe noch nie eine Sackgasse in Pacman gesehen. Dieser Code berücksichtigt keine Sackgasse.
  7. Außerdem habe ich eine Lösung für den Fall eingefügt, dass die Augen in meinem Pseudocode zwischen einer Wand "wackeln", die sich über den Ursprung erstreckt.

Ein Pseudocode:

   x = getRelativeOppositeLatitudinalCoord()
   y
   origX = x
    while(eyesNotInPen())
       x = getRelativeOppositeLatitudinalCoordofGate()
       y = getRelativeOppositeLongitudinalCoordofGate()
       if (getRelativeOppositeLatitudinalCoordofGate() == 0 && move(y) == false/*assume zero is neither left or right of the the gate and false means wall is in the way */)
            while (move(y) == false)
                 move(origX)
                 x = getRelativeOppositeLatitudinalCoordofGate()
        else if (move(x) == false) {
            move(y)
    endWhile
2
thyrgle

Ich würde vorschlagen, dass der Geist den Weg speichert, den er vom Loch zum Pacman genommen hat. Sobald der Geist stirbt, kann er diesem gespeicherten Pfad in umgekehrter Richtung folgen.

2
Fischer Ludrian
  1. Speichern Sie die Knoten (Kreuzungen) in der Karte, bevor das Spiel beginnt
  2. Wenn das Monster stirbt, nimm den Punkt (die Koordinaten) und finde den nächsten Knoten in deiner Knotenliste
  3. Berechnen Sie alle Pfade, die von diesem Knoten zum Loch beginnen
  4. Nehmen Sie den kürzesten Weg in der Länge
  5. Fügen Sie die Länge des Abstands zwischen dem Punkt und dem nächsten Knoten hinzu
  6. Zeichne und bewege dich auf dem Weg

Genießen!

1
GingerHead

Mein Ansatz ist ein wenig speicherintensiv (aus Sicht der Pacman-Ära), aber Sie müssen nur einmal rechnen und er funktioniert für jedes Level-Design (einschließlich Sprüngen).

Knoten einmal beschriften

Wenn Sie zum ersten Mal einen Level laden, beschriften Sie alle Knoten der Monster-Höhle mit 0 (entspricht der Entfernung von der Höhle). Beschriften Sie die verbundenen Knoten 1, die mit ihnen verbundenen Knoten 2 usw. nach außen, bis alle Knoten beschriftet sind. (Hinweis: Dies funktioniert auch, wenn die Höhle mehrere Eingänge hat)

Ich gehe davon aus, dass Sie bereits Objekte haben, die jeden Knoten und die Verbindungen zu ihren Nachbarn darstellen. Pseudocode könnte ungefähr so ​​aussehen:

public void fillMap(List<Node> nodes) { // call passing lairNodes
    int i = 0;

    while(nodes.count > 0) {
        // Label with distance from lair
        nodes.labelAll(i++);

        // Find connected unlabelled nodes
        nodes = nodes
            .flatMap(n -> n.neighbours)
            .filter(!n.isDistanceAssigned());
    }
}

Flood-fill out from lair

Augen bewegen sich zum Nachbarn mit dem Etikett mit dem geringsten Abstand

Sobald alle Knoten beschriftet sind, ist das Routen der Augen trivial ... wählen Sie einfach den benachbarten Knoten mit der niedrigsten Entfernungsbeschriftung aus (Hinweis: Wenn mehrere Knoten den gleichen Abstand haben, spielt es keine Rolle, welcher ausgewählt wird). Pseudocode:

public Node moveEyes(final Node current) {
    return current.neighbours.min((n1, n2) -> n1.distance - n2.distance);
}

Vollständig beschriftetes Beispiel

Complete map

1
AjahnCharles

Wenn Sie wissen, dass Pacman-Pfade nicht zufällig sind (dh, dass jede bestimmte Stufe 0-255, inky, blinky, pinky und clyde genau denselben Pfad für diese Stufe verwenden).

Ich würde dies nehmen und dann vermuten, dass es ein paar Master-Pfade gibt, die sich um das gesamte Labyrinth wickeln, als "Rückweg", den ein Augapfel-Objekt nimmt, bis es dort ist, wo der Pac-Man den Geist gefressen hat.

1
Incognito

Die Geister in Pacman folgen mehr oder weniger vorhersehbaren Mustern in Bezug auf den Versuch, zuerst auf X oder Y zu passen, bis das Ziel erreicht wurde. Ich bin immer davon ausgegangen, dass dies für die Augen, die zurückfinden, genau das Gleiche ist.

1
plinth

Für mein PacMan-Spiel habe ich etwas " shortest multiple path home "Algorithmus, der für jedes Labyrinth funktioniert, das ich ihm zur Verfügung stelle (innerhalb meines Regelwerks). Er funktioniert auch über Tunnel hinweg.

Wenn der Level geladen ist, werden alle path home data in every crossroad ist leer (Standardeinstellung) und sobald die Geister das Labyrinth erkunden, werden sie crossroad path home information wird jedes Mal aktualisiert, wenn sie auf eine "neue" Kreuzung stoßen oder von einem anderen Weg auf ihre bekannte Kreuzung stoßen.

0
iNyuu