Как хранить уровень шмупа?

12

Я разрабатываю 2D Shmup (т.е. Aero Fighters ), и мне было интересно, каковы различные способы хранения уровня. Предполагая, что враги определены в их собственном XML-файле, как бы вы определили, когда враг появляется на уровне?

Будет ли это основано на времени? Обновления? Расстояние?

В настоящее время я делаю это на основе «времени уровня» (количество времени, в течение которого работает уровень - пауза не обновляет время). Вот пример (сериализация была сделана 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>

Каждый элемент врага - это, в основном, волна определенных типов врагов. Тип определяется в EnemyType, тогда как SpawnTime - это «время уровня», при котором должна появляться эта волна. NumberOfSpawns и SpawnOffset - это количество врагов, которые появятся, и время, которое требуется между каждым появлением соответственно.

Это может быть хорошей идеей или может быть лучше. Я не уверен. Я хотел бы увидеть некоторые мнения и идеи.

У меня две проблемы: правильно создать врага и создать редактор уровней. Редактор уровней - это совершенно другая проблема (о которой я, вероятно, опубликую в будущем: P).

Что касается правильного нереста, проблема заключается в том, что у меня переменное время обновления, и поэтому мне нужно убедиться, что я не пропустил вражеский спавн, потому что смещение спавна слишком мало, или потому что обновление заняло немного больше времени , Я вроде как исправил это по большей части, но мне кажется, что проблема в том, как я храню уровень.

Итак, есть идеи? Комментарии?

Заранее спасибо.

пекин
источник

Ответы:

4

Один из способов сделать это состоит в том, чтобы основать спавна не вовремя, а на пройденном горизонтальном расстоянии (при условии боковой прокрутки). Вы можете хранить вражеские волны в очереди с триггерным расстоянием; когда пройденное расстояние вашего игрока больше, чем расстояние срабатывания объекта в передней части очереди, вытолкните его из очереди и вызовите его.

Это решение больше подходит для интеграции с графическим редактором уровней, чем решение на основе времени. Было бы намного проще сопоставлять конкретные точки на фоне прокрутки с появлением врагов.

Билл
источник
4
И в качестве бонуса, если вы измените скорость прокрутки, либо глобально, либо для части уровня, это будет держать более поздних врагов в их правильных позициях появления, потому что, если бы это было основано на времени, враги появлялись бы в правильных местах.
AttackingHobo
2

Я предлагаю вам изучить код PowerManga в качестве справочного материала. У них есть два вида уровней: уровни с боковой прокруткой (похожие на тириану), где объекты расположены на определенном расстоянии от начала уровня, и другие вещи генерируются случайным образом, и уровни "неподвижных" (как в галаге), где анализируется только одна волна после того, как предыдущий закончил свой образец.

Конечно, волновые паттерны можно эффективно планировать с помощью последовательных кривых Безье (для объяснения этого на странице википедии есть аккуратная анимация).

Если бы я мог позволить себе последний комментарий, я бы полностью отбросил здесь XML в пользу чего-то более выразительного, более легкого в обслуживании и более полезного в программировании игр, такого как сценарий LUA.

НТН.


источник
Я уже использую кривые Безье для хранения движений противника (которые также сериализуются в xml). Я в основном использую XML, потому что .NET и XNA имеют встроенную поддержку сериализации / десериализации. Сценарий LUA звучит хорошо, но потребует больше работы. Тем не менее, я всегда планировал использовать его, поэтому после того, как я закончу какой-то базовый движок, я обязательно его изучу. Наконец, идея порождать волну после предыдущей звучит интересно.
Пек
2
XML хорошо, если он генерируется инструментом, а не редактируется вручную. Хотя языки сценариев могут быть полезны для особых случаев (например, боссов), это совершенно отдельная проблема для определения стандартных шаблонов атак, не так ли?
Bluescrn
0

Рассмотрим процедурно генерирующих врагов. Я знаю, что он сильно отличается от ответа, который вы хотите, и косвенно решает проблему полностью.

Если бы я это сделал, я бы назначил каждому вражескому отряду значение «баллов», как трудно это сделать, а затем назначил бы уровни некоторого количества очков - 100 очков стоили бы врагам в 1 очко или одному врагу в 100 пунктов, или что-нибудь промежуточное.

Возможно, вам нужно будет немного ограничить это, чтобы вы не получили босса в 100 очков на первом уровне или чтобы у вас было какое-то минимальное количество врагов, и вы, вероятно, хотите периодически опрашивать список оставшихся врагов и тянуть следующий на экране.

Вы могли бы сделать еще один шаг вперед, имея формирования: наборы позиций и точек, например. семь одноточечных врагов в одну линию (строку или столбец) или пятиточечный в окружении двух 3-точечных.

ashes999
источник