Wie implementiert man die "Spezialeffektkarten" eines Sammelkartenspiels?

16

Ich versuche hier eine Art Sammelkartenspiel zu schreiben, in gewisser Weise ähnelt es Magic The Gathering oder Yu-Gi-Oh! Kartenspiel.

Für diejenigen unter Ihnen, die nicht mit dem Spiel vertraut sind, gibt es im Grunde genommen eine spezielle Art von Karte (Zauberkarten / Fallenkarten / usw.), die Spezialeffekte haben, die die Spielregeln verbiegen können. Ich habe überhaupt keine Ahnung, wie die Logik dieser Karten implementiert werden soll. Ich habe eine Idee, die Daten der Karte mit einigen Flags zu speichern, die anzeigen, über welche Fähigkeiten sie verfügt, aber die Möglichkeiten sind sehr begrenzt (möglicherweise nur einige einfache Statistikänderungen).

Um Ihnen eine Vorstellung davon zu geben, welche Effekte diese Karten haben können, finden Sie hier ein Beispiel für die Zauberkarteneffekte, die im Yu-Gi-Oh! Kartenspiel:

  • Belebe eine zerstörte Kreatur wieder
  • Übernimm die Kontrolle über die Kreatur des Gegners
  • Ändere die Werte der Kreatur basierend auf bestimmten Bedingungen (z. B. Anzahl der Kreaturen mit bestimmten Namen, die zerstört wurden).
  • Beschwöre eine bestimmte Kreatur als Spezialbeschwörung, wenn einige Bedingungen erfüllt sind.
  • Füge zwei oder mehr Kreaturen zu einer stärkeren Kreatur zusammen.
  • Immunität gegen einige Effekte der Spezialkarten.

Konami hat mehrere Videospiele des Spiels entwickelt, darunter die KI und Tausende von Karten. Ich denke nicht, dass es tatsächlich möglich ist, die gesamte Datenbank fest zu codieren, oder?

Natürlich versuche ich nicht, so komplexe Spiele zu entwickeln, aber ich bin gespannt, wie sie diese umsetzen.

hndr
quelle

Antworten:

17

Es gibt mehrere Open-Source-Projekte dieser Art mit unterschiedlichen Ansätzen zur Umsetzung der Regeln. Hier ist ein Blogeintrag des Erstellers einer der bekannteren MtG-Implementierungen, CardForge. Es ist möglicherweise keine vollständige Liste, enthält jedoch mehrere Open-Source-Projekte, in denen Sie einfach den Code durchsuchen oder in den Foren nach bestimmten Fragen suchen können.

Als tatsächliche Antwort: Ihre beste Wahl für ein robustes Framework ist die strikte Anwendung der objektorientierten Programmierung. Jede Aktion, jeder Auslöser, jede Fähigkeit ist ein Objekt. Zonen wie Hand oder Bibliothek sind natürlich auch Objekte. Übergeben Sie in der Regel-Engine niemals dumme Objekte wie Zeichenfolgen oder Ganzzahlen, um Spielobjekte zu beschreiben, sondern nur Ihre Objekte.

Jede Aktion legt eine Anzahl von Auslösern auf einen Stapel, wobei jede andere Fähigkeit prüfen kann, ob sie sich um diesen bestimmten Auslöser kümmert oder nicht. In diesem Fall lösen sie ihre eigenen Aktionen aus, wodurch möglicherweise neue Auslöser erstellt werden.

Dann arbeitest du diese Stapel gemäß den Spielregeln ab, bis der Stapel leer ist. Dann können neue Aktionen ausgeführt werden usw.

Wenn Sie die Spielregeln perfekt umsetzen, enthält Ihr Regelcode im Idealfall keine einzige fest codierte Karte. Durch Hardcodierung von Karten können praktische Verknüpfungen erstellt werden. Auf lange Sicht kann dies jedoch Ihren Code aufblähen und potenzielle Fallstricke verursachen, z. B. wenn neue Karten veröffentlicht werden, die auf neuartige Weise mit diesen Karten interagieren. In einem Spiel wie MtG mit über 12.000 einzigartigen Karten und ohne absehbares Ende gibt es VIELE solcher Interaktionen.

Hackworth
quelle
1
Gute Antwort. Aus der funktionalen Programmierwelt kommend, hätte ich jede Karte zu einem Closure über die Spielumgebung gemacht, um noch lächerlicher zu sein. Zum Beispiel könnte eine Karte akzeptabel einen neuen "Bereich" erstellen, indem der Liste der Bereiche eine Liste von Karten hinzugefügt wird. Konkret: Zombie-Monster-Chaos: Alle besiegten Kreaturen werden auf dem neuen "Gemeinschaftsfriedhof" ohne ihre besonderen Fähigkeiten wiederbelebt und greifen einen Spieler zufällig an, basierend auf dem Würfelwurf.
Brice
Weiterführender Link: github.com/Fluorohydride/ygopro-core für eine berühmte Open-Source-YGO-Implementierung, da YGO auch in der Frage erwähnt wurde.
SK19
2

Es ist ziemlich vergeblich zu versuchen, all das nur mit Schaltern und Variablen zu integrieren. Sie müssten entweder Hardcode-Funktionen verwenden oder wahrscheinlich ein Skript, das Sie zur Laufzeit interpretieren. Sie würden dem Skript die erforderlichen Funktionen zum Überprüfen des Status des Brettes, der Decks und der Friedhöfe sowie die Funktionen zum Ausführen von Aktionen usw. zur Verfügung stellen. Das Skript ist dann nur eine einfache Zeichenfolge, die zusammen mit den anderen mit der Karte verknüpften Variablen gespeichert werden kann.

Toni
quelle
Oder wie Hackworth vorgeschlagen hat, mit einer Art von gemeinsamen Blöcken, die kombiniert werden, um das erforderliche Verhalten zu erhalten. Es würde zusätzlich zu dem, was er vorgeschlagen hat, auch einige Logikblöcke erfordern, denke ich. Gemeinsame Verhaltensblöcke könnten das Filtern nach Karten mit gemeinsamen Eigenschaften erleichtern.
Toni
1

Ich plane auch Kartenspiele mit Web-Sprachen mit MySQL DB. Ich arbeite derzeit an einem sehr allgemeinen Setup, damit es für neue einzigartige Karten sehr flexibel bleibt. Zum Beispiel anstelle von:

reduceHitPoints() { } 
reduceMana() { }
reduceSpeed() { }

es könnte leicht sein:

reduce($attacker, $target, $reduceWhat, $amount) { }
massReduce($attacker, Array $targets, $reduceWhat, $amount) { }

Wenn Sie dieses Konzept für alle Aktionen anwenden, werden die Klassen vereinfacht, und Sie können neue Karten erstellen, indem Sie einfach eine einzelne Zeile in Ihren Kartentisch einfügen.

Alle Optionen und Fähigkeiten werden in der Datenbank in dieser einzelnen Zeile definiert.

appthat
quelle