Jak przechowywać poziom shmup?

12

Tworzę shmup 2D (tj. Aero Fighters ) i zastanawiałem się, jakie są różne sposoby przechowywania poziomu. Zakładając, że wrogowie są zdefiniowani we własnym pliku xml, jak zdefiniowałbyś, kiedy wróg pojawia się na poziomie?

Czy byłoby oparte na czasie? Aktualizacje Dystans?

Obecnie robię to na podstawie „czasu poziomu” (czasu, przez jaki poziom działa - pauza nie aktualizuje czasu). Oto przykład (serializacji dokonał XNA):

<?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>

Każdy element wroga jest w zasadzie falą określonych typów wrogów. Typ jest zdefiniowany w EnemyType, a SpawnTime to „czas poziomu”, jaki powinna pojawić się fala. NumberOfSpawns i SpawnOffset to odpowiednio liczba przeciwników, którzy się pojawią, oraz czas między każdym spawnem.

To może być dobry pomysł lub mogą istnieć lepsze. Nie jestem pewny. Chciałbym poznać opinie i pomysły.

Mam z tym dwa problemy: prawidłowe odrodzenie wroga i utworzenie edytora poziomów. Edytor poziomów to zupełnie inny problem (który prawdopodobnie opublikuję w przyszłości: P).

Jeśli chodzi o prawidłowe odradzanie, problem polega na tym, że mam zmienny czas aktualizacji, dlatego muszę się upewnić, że nie przegapię odrodzenia wroga, ponieważ przesunięcie odrodzenia jest zbyt małe lub dlatego, że aktualizacja zajęła trochę więcej czasu . W pewnym sensie to naprawiłem, ale wydaje mi się, że problem polega na tym, jak przechowuję poziom.

Jakieś pomysły? Komentarze?

Z góry dziękuję.

pek
źródło

Odpowiedzi:

4

Jednym ze sposobów, aby to zrobić, byłoby oparcie spawna nie na czasie, ale na odległości poziomej (zakładając przewijanie w bok). Możesz przechowywać fale wroga w kolejce z odległością wyzwalania; gdy przebyty dystans gracza jest większy niż odległość wyzwalania obiektu z przodu kolejki, oderwij go od kolejki i spawnuj.

To rozwiązanie bardziej pasowałoby do integracji z edytorem poziomu graficznego niż do rozwiązania opartego na czasie. Znacznie łatwiej byłoby dopasować określone punkty na przewijanym tle do momentu odrodzenia się wrogów.

Rachunek
źródło
4
A jako bonus, jeśli zmienisz prędkość przewijania, globalnie lub dla części poziomu, utrzyma on późniejszych wrogów na swoich prawidłowych pozycjach odradzania, ponieważ gdyby było to zależne od czasu, wrogowie odrodziliby się w odpowiednich miejscach.
AttackingHobo
2

Proponuję przestudiować kod PowerManga jako odniesienie. Mają dwa rodzaje poziomów: poziomy przewijania (podobne do tyryjskich), na których rzeczy są ustawiane w określonej odległości od początku poziomu, a inne rzeczy są generowane losowo, oraz poziomy „nieruchome” (à la galaga), gdzie tylko jedna fala jest analizowana po zakończeniu poprzedniego wzoru.

Wzory fal mogą oczywiście być skutecznie planowane przez kolejne krzywe Beziera (strona wikipedia ma fajną animację, aby to wyjaśnić).

Jeśli stać mnie na ostatni komentarz, całkowicie upuszczę tutaj XML na rzecz czegoś bardziej ekspresyjnego, łatwiejszego w utrzymaniu i bardziej przydatnego w programowaniu gier, takiego jak skrypt LUA.

HTH.


źródło
Już używam krzywych Beziera do przechowywania ruchów wroga (co jest również serializowane w formacie xml). Używam głównie XML, ponieważ zarówno .NET, jak i XNA mają wbudowaną obsługę serializacji / deserializacji. Skrypt LUA brzmi dobrze, ale będzie wymagał więcej pracy. Zawsze jednak planowałem go używać, więc po skończeniu podstawowego silnika na pewno się nim zajmę. Finallt, pomysł odrodzenia fali po poprzedniej brzmi interesująco.
pek
2
XML jest w porządku, o ile jest generowany przez narzędzie, a nie ręcznie edytowany. Podczas gdy języki skryptowe mogą być przydatne w szczególnych przypadkach (np. Bossowie), jest to zupełnie odrębny problem w definiowaniu standardowych wzorców ataku, prawda?
bluescrn
0

Zastanów się nad generowaniem proceduralnym wrogów. Wiem, że różni się ona od odpowiedzi, której szukasz, i pośrednio całkowicie rozwiązuje problem.

Gdybym to zrobił, przypisałbym każdej wrogiej jednostce wartość „punktową” jej stopnia trudności, następnie przypisałem poziomom pewną liczbę punktów - 100 punktów jest wartych stu 1-punktowych wrogów lub jednego 100-punktowego wroga, lub cokolwiek pośredniego.

Prawdopodobnie musiałbyś to nieco ograniczyć, aby nie dostać 100-punktowego bossa na pierwszym poziomie lub mieć minimalną liczbę wrogów i prawdopodobnie chcesz okresowo sondować listę pozostawionych wrogów i pociągać następny na ekranie.

Możesz pójść o krok dalej, mając formacje: zbiory pozycji i punktów, np. siedmiu jednopunktowych wrogów w jednym wierszu (rzędzie lub kolumnie), lub pięciopunktowy flankowany przez dwa 3-punktowe.

ashes999
źródło