Wie speichere ich ein shmup-Level?


12

Ich entwickle ein 2D-Shmup (dh Aero Fighters ) und habe mich gefragt, wie ich ein Level auf verschiedene Arten speichern kann. Angenommen, Feinde sind in ihrer eigenen XML-Datei definiert, wie würden Sie definieren, wann ein Feind im Level erscheint?

Würde es auf Zeit basieren? Aktualisierung? Entfernung?

Momentan mache ich dies basierend auf der "Level-Zeit" (die Zeitdauer, in der das Level läuft - Pause aktualisiert die Zeit nicht). Hier ist ein Beispiel (die Serialisierung wurde von XNA durchgeführt):

<?xml version="1.0" encoding="utf-8"?>
<XnaContent xmlns:level="pekalicious.xanor.XanorContentShared.content.level">
  <Asset Type="level:Level">
    <Enemies>
      <Enemy>
        <EnemyType>data/enemies/smallenemy</EnemyType>
        <SpawnTime>PT0S</SpawnTime>
        <NumberOfSpawns>60</NumberOfSpawns>
        <SpawnOffset>PT0.2S</SpawnOffset>
      </Enemy>
      <Enemy>
        <EnemyType>data/enemies/secondenemy</EnemyType>
        <SpawnTime>PT0S</SpawnTime>
        <NumberOfSpawns>10</NumberOfSpawns>
        <SpawnOffset>PT0.5S</SpawnOffset>
      </Enemy>
      <Enemy>
        <EnemyType>data/enemies/secondenemy</EnemyType>
        <SpawnTime>PT20S</SpawnTime>
        <NumberOfSpawns>10</NumberOfSpawns>
        <SpawnOffset>PT0.5S</SpawnOffset>
      </Enemy>
      <Enemy>
        <EnemyType>data/enemies/boss1</EnemyType>
        <SpawnTime>PT30S</SpawnTime>
        <NumberOfSpawns>1</NumberOfSpawns>
        <SpawnOffset>PT0S</SpawnOffset>
      </Enemy>
    </Enemies>
  </Asset>
</XnaContent>

Jedes feindliche Element ist im Grunde eine Welle spezifischer Feindtypen. Der Typ wird in EnemyType definiert, während SpawnTime die "Level Time" ist, zu der diese Wave erscheinen soll. NumberOfSpawns und SpawnOffset ist die Anzahl der Feinde, die angezeigt werden, und die Zeit, die zwischen den einzelnen Spawns vergeht.

Dies könnte eine gute Idee sein oder es könnte bessere da draußen geben. Ich bin mir nicht sicher. Ich würde gerne einige Meinungen und Ideen sehen.

Ich habe zwei Probleme damit: Einen Feind richtig spawnen und einen Level-Editor erstellen. Die Leveleditor-Sache ist ein ganz anderes Problem (das ich wahrscheinlich in Zukunft posten werde: P).

Was das korrekte Laichen betrifft, liegt das Problem in der Tatsache, dass ich eine variable Aktualisierungszeit habe und daher sicherstellen muss, dass ich keinen gegnerischen Laich verpasse, weil der Versatz für das Laichen zu gering ist oder weil das Aktualisieren etwas länger gedauert hat . Ich habe es größtenteils irgendwie behoben, aber es scheint mir, dass das Problem darin besteht, wie ich den Level speichere.

Also irgendwelche Ideen? Bemerkungen?

Danke im Voraus.

Antworten:


4

Eine Möglichkeit, dies zu tun, besteht darin, den Spawn nicht auf der Zeit, sondern auf der horizontal zurückgelegten Distanz (unter der Annahme eines Side-Scrolling) zu gründen. Sie können Ihre feindlichen Wellen in einer Warteschlange mit einer Abzugsentfernung speichern. Wenn die zurückgelegte Distanz Ihres Spielers größer ist als die Auslöseentfernung des Objekts an der Vorderseite der Warteschlange, entfernen Sie es aus der Warteschlange und erzeugen Sie es.

Diese Lösung eignet sich eher für die Integration in einen Editor für grafische Ebenen als für eine zeitbasierte Lösung. Dies würde es viel einfacher machen, bestimmte Punkte entlang des scrollenden Hintergrunds mit dem Laichen der Feinde abzugleichen.


4
Und als Bonus, wenn Sie die Bildlaufgeschwindigkeit entweder global oder für einen Teil des Levels ändern, werden spätere Feinde in ihren korrekten Spawnpositionen gehalten, denn wenn es zeitbasiert wäre, würden die Feinde an den richtigen Stellen spawnen.
AttackingHobo

2

Ich schlage vor, Sie studieren den Code von PowerManga als Referenz. Sie haben zwei Arten von Ebenen: Side-Scrolling-Ebenen (tyrianisch), bei denen die Dinge in einem bestimmten Abstand vom Start der Ebene positioniert sind und andere Dinge zufällig generiert werden, und "ruhige" Ebenen (à la galaga), bei denen nur eine Welle analysiert wird nachdem der vorherige sein muster beendet hat.

Wellenmuster können natürlich effizient durch aufeinanderfolgende Bézier-Kurven geplant werden (Wikipedia-Seite hat eine nette Animation, um das zu erklären).

Wenn ich mir einen abschließenden Kommentar leisten kann, würde ich XML hier komplett weglassen, um etwas aussagekräftigeres, einfacher zu pflegendes und nützlicheres in der Spielprogrammierung wie einem LUA-Skript zu erhalten.

HTH.


Ich verwende bereits Bezier-Kurven, um feindliche Bewegungen zu speichern (die auch in XML serialisiert sind). Ich verwende hauptsächlich XML, da sowohl .NET als auch XNA integrierte Unterstützung für die Serialisierung / Deserialisierung haben. LUA-Skript klingt gut, erfordert aber mehr Arbeit. Ich hatte jedoch immer vor, es zu verwenden, also werde ich es auf jeden Fall untersuchen, nachdem ich einige grundlegende Motoren fertiggestellt habe. Schließlich klingt die Idee, eine Welle nach der vorherigen zu laichen, interessant.
pek

2
XML ist in Ordnung, solange es von einem Tool generiert und nicht von Hand bearbeitet wird. Während Skriptsprachen für Sonderfälle (z. B. Bosse) nützlich sein können, ist dies ein völlig anderes Problem als die Definition von Standard-Angriffsmustern, nicht wahr?
Bluescrn

0

Erwägen Sie, prozedural Feinde zu erzeugen. Ich weiß, es ist ganz anders als die Antwort, die Sie wollen, und es löst das Problem indirekt vollständig.

Wenn ich das tun würde, würde ich jeder feindlichen Einheit einen "Punkt" -Wert zuweisen, der angibt, wie schwierig es ist. Dann würde ich Levels eine bestimmte Anzahl von Punkten zuweisen - 100 Punkte sind hundert 1-Punkt-Feinde wert, oder einen 100-Punkt-Feind. oder irgendetwas dazwischen.

Sie müssten dies wahrscheinlich ein wenig einschränken, damit Sie keinen 100-Punkte-Boss im ersten Level bekommen oder eine Mindestanzahl an Feinden haben und Sie möchten wahrscheinlich regelmäßig die Liste der verbleibenden Feinde abrufen und ziehen der nächste auf dem Bildschirm.

Sie könnten noch einen Schritt weiter gehen, indem Sie Formationen haben: Sammlungen von Positionen und Punkten, z. Sieben Ein-Punkt-Gegner in einer einzigen Linie (Reihe oder Spalte) oder ein Fünf-Punkt-Gegner, flankiert von zwei Drei-Punkt-Gegnern.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.