Як я можу реалізувати стійкий стан для об'єктів, визначених у рівні?


17

Я розробляю 2D Metroidvania, що складається з серії взаємопов'язаних рівнів, які можна переглянути.

Кожен рівень представлений файлом Tiled TMX, в якому я вказав, де породжуються різні об'єкти різних класів спрайтів (наприклад, вороги, пікапи, важелі тощо). Запускаючи нову гру, завантажуючи збережену гру або змінюючи рівень, мій цикл гри проходить через відповідний файл TMX і генерує всі об'єкти на цьому рівні.

Я обробляю зміни рівня таким чином: Якщо Playerоб'єкт перетинає Portalоб'єкт, change_map()називається метод, який завантажує нову карту (ту, що пов'язана з перерізаним порталом) і розміщує гравця у відповідній позиції на новій карті.

Деякі з моїх об'єктів мають стан, який я хотів би бути стійким через зміни рівня, збереження та вихід із гри. Наприклад, якщо гравець відчиняє двері, а атрибут стану дверей встановлений на "відкрити", я б хотів, щоб двері були відкриті, коли гравець повертається. Я хочу щось подібне для важелів, які можна встановити вліво або вправо, і різних інших об'єктів. Крім того, гравець іноді буде збирати предмети, які я не хочу відновлювати, коли гравець перегляне область.

Моє запитання полягає в тому, як я можу впоратися з такою наполегливістю?

Я працюю в Python, хоча я думаю, що ви можете абстрагуватися від цього.

Відповіді:


27

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

Потік може виглядати приблизно так:

  1. Рівень завантаження з файлу
  2. Перш ніж розміщувати плитку / об'єкт, перевірте, чи є у нього "стійке" властивість.
    1. Якщо так: Перевірте збережену пару ключ-значення на ключ, що відповідає властивості, і отримайте відповідне значення.
    2. Якщо ні: Поставте об'єкт як звичайний
  3. Коли гравець виходить з рівня / зберігає ігровий цикл через усі об'єкти з "стійким" властивістю і зберігає їх у вигляді ключа-значення пари.

Ось приклад псевдокоду на основі того, що я використовую для моєї простої 2D гри:

def load_map(map):
    for y in range(0, height):
        for x in range(0, width):
            tile = map[x, y]

            for property in tile.properties:
                if is_persistent(property.name):
                    // Name prefixed with "persistent" means that it's persistent
                    // so we load the value from out persistent storage
                    property.value = persistent_values[property.name]

def save_map(map):
    ... everything in load_map ...
    if (property.name.matches("persistent_*")):
        // Name prefixed with "persistent" means that it's persistent
        // so we save the value to persistent storage
        persistent_values[property.name] = property.value

def is_persistent(name):
    return name.matches("persistent_*") and persistent_values.contains(name)

Тоді я можу просто перевірити стан, використовуючи це властивість:

def draw():
    if properties["persistent_is_pressed"].value:
        draw_sprite(button_pressed)
    else:
        draw_sprite(button_unpressed)

def on_pressed():
    properties["persistent_is_pressed"].value = not properties["persistent_is_pressed"].value

Якщо ви користуєтесь редактором кахельних карт, таким як Черепиця, додаючи такі властивості, це дуже просто:

додавання властивості

Сподіваємось, це дасть вам уявлення про те, як реалізувати стійкий стан якомога простіше!


Це дуже корисно, хоча я намагаюся зрозуміти, як саме це застосувати до моєї ситуації. Я подумаю про це ще трохи.
GoldenGremlin

Я думаю, що у мене виникають проблеми, коли я можу змусити заощадження значень працювати. Коли я заощаджую, я не буду повторювати плитки в даних TMX. Швидше, я буду повторювати спрайт-об'єкти в моїй групі all_sprites. Коли я завантажую карти, я використовую властивості TMX об’єктів TMX як параметри при створенні моїх спрайт-об'єктів, але після цього я не торкаюся цих властивостей, тому вони не відстежують зміни в спрайт-об'єктах.
GoldenGremlin

1
@dietestus Ви, ймовірно, повинні просто дати своїм об'єктам спрайт propertiesполе, яке ви замість цього змінили, і використовувати лише плитки propertiesяк вказівку того, яке властивість потрібно змінити (але всі дані зберігаються у вашому спрайті). Ви також можете просто передати плитку своєму спрайту, щоб ви могли змінити плитку з спрайту :), якщо не зрозуміло, що я маю на увазі, я можу висміяти ще якийсь псевдокод
Charanor

3
@dietestus Як тільки ви взаємодієте зі стійкою сутністю (двері, важіль), ви зберігаєте новий стан на карті ключових значень. Не потрібно повторювати карти, коли ви зберігаєте, у вас уже все є на карті.
Гер Дерб

1
@dietestus Так, це ти :) це простий словник, де ключі є іменами властивостей, а значення (добре ... значення). Наявність декількох об'єктів на одній плитці нічого не змінить, якщо у вас є унікальні ключі.
Шаранор
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.