# RPG World — ходите по тайловой карте, говорите, открывайте, сражайтесь RPG World превращает игру в RPG на тайловых картах в духе классических двухмерных ролевых игр: вы ходите по карте из клеток, разговариваете с людьми, открываете сундуки, проходите через двери, сражаетесь с монстрами — а после боя возвращаетесь на то же место. Карта при этом остаётся обычной сценой игры, поэтому диалоговое окно, сценарии, сохранения, музыка и время суток работают на ней так же, как в визуальной новелле. На этом движке построены деревня, лес и пустыня **RPG Plus**. Сами карты и их обитатели лежат в контентных модах вроде RPG Demo; этот мод отвечает за правила. ![Исследование деревни в RPG Plus: название карты слева сверху, панель инструментов справа сверху, подсказка управления слева снизу.](assets/village.jpg) ## Как играть на карте - **Ходьба** — WASD или стрелки; с зажатым **Shift** герой бежит. - **Действие** — **E** или **F**: заговорить с тем, кто перед вами, открыть сундук, прочитать табличку. - **Шагните** на дверной проём или за край карты, чтобы попасть на следующую карту. - **Случайные бои** могут начинаться прямо на ходу в некоторых местах — например, в лесу. - После боя вы возвращаетесь на ту же клетку той же карты. - Игра сохраняет, где вы стоите; загрузка возвращает вас ровно туда же. Клетку, с которой можно взаимодействовать, обводит рамка, а подсказка слева снизу меняется на **E / F · Взаимодействовать**. ## Пример: сундук, который остаётся открытым Сундук в доме старейшины — это два события на одной клетке. Закрытый показывается, пока не установлен сюжетный флаг `rpg_house_chest`; его сценарий выдаёт три монеты и ставит флаг. С этого момента вместо закрытого сундука показывается открытый. ![До: герой рядом с закрытым сундуком в доме старейшины в полдень.](assets/chest-before.jpg) ![Текст сундука: старые носки, записка «Не трогай» и три монеты под ними.](assets/chest-text.jpg) ![После: на той же клетке теперь открытый сундук в рамке маркера взаимодействия; подсказка слева снизу гласит «E / F · Взаимодействовать».](assets/chest-after.jpg) ```json { "Id": "chest", "X": 9, "Y": 7, "Tile": 14, "Scenario": "rpg_demo/events/house_chest", "Condition": "rpg_house_chest != 1" }, { "Id": "chest_open", "X": 9, "Y": 7, "Tile": 15, "Scenario": "rpg_demo/events/chest_empty", "Condition": "rpg_house_chest == 1" } ``` ```scenario ptext "В сундуке — старые носки и записка: «Не трогай». Поздно. Под носками — три монеты." key=rpg_demo/chest/house action item.add id=money/coin count=3 flag rpg_house_chest 1 end ``` ## Авторам: карты Карта — это JSON-файл в папке `maps/` мода, плюс сцена с тем же именем в `scenes/`: она задаёт фон для боёв и фоновый звук карты. - **Три рисуемых слоя**, каждый — список строк с номерами тайлов (`.` — пусто): `Back` — земля, полы, вода; `Main` — объекты уровня персонажей: стены, стволы, заборы; `Front` — рисуется поверх персонажей: кроны деревьев, свесы крыш, арки. - **Коллизии** — слой строк, который там, где нужно, переопределяет проходимость самих тайлов: невидимая стена у края обрыва или проход в живой изгороди. - **Тайлсет** — атлас тайлов и свойства его тайлов (проходимость, поверхности, объекты). - **Spawn** — где появляется только что прибывший герой; **Zoom**; необязательный цвет **Ambient** для интерьеров (иначе карту освещает время суток) и **Atmosphere** (`woodland` добавляет листья, светлячков и рябь на воде). - **Encounters** — случайные бои: в среднем один за каждые `Steps` шагов против одной из групп `Groups`. ```json "Encounters": { "Steps": 48, "Groups": ["rpg_slime", "rpg_slime,rpg_slime"] } ``` ## Авторам: события События лежат в `map_events//*.json` любого мода. У события независимо друг от друга выбираются **внешний вид** и **эффект**: - вид: спрайт персонажа `Sprite`, один тайл из атласа `Tile`, иконка предмета `Icon`, лежащего на земле, или ничего (невидимый триггер); - эффект: `Teleport` в клетку этой или другой карты либо `Scenario` с необязательными командами `Commands` прямо в событии — весь язык сценариев, включая `action rpg.battle`, флаги и задания; - `Trigger`: `Action` (E/F, когда вы стоите к нему лицом) или `Touch` (наступить на событие); - `Solid`: блокирует ли путь (нарисованные события по умолчанию блокируют); - `Condition`: скрыть событие, пока условие не выполняется; - `Pages`: альтернативные вид и эффект, у каждого своё условие; используется последняя страница с выполненным условием; - `Route`: самостоятельное движение вроде `{"Steps": ["left", "wait", "right"], "Every": 0.8}` с направлениями `up`/`down`/`left`/`right`, режимами `random`, `toward`/`away` (к игроку и от него), а также `wait` и `face_…`; - `Light`: свечение вокруг события, `{"Radius": 3, "Color": "#ffd8a0"}`; видно в сумерках и ночью. **Дополняйте и меняйте карты чужих модов.** Файлы событий сливаются в порядке загрузки: новый `Id` добавляет событие на карту, а тот же `Id` от мода, который зависит от владельца карты, заменяет его. Именно так RPG Plus даёт старейшине из демо новые диалоги. ## Действия сценариев ```scenario action rpg.battle enemies=rpg_wolf,rpg_slime win_flag=rpg_wolf_dead action rpg.teleport map=rpg_forest x=1 y=8 dir=right ``` - `rpg.battle` запускает бой боевым ядром игры и возвращает героя на ту же клетку; при победе `win_flag` получает значение 1 — и монстр на карте, чьё условие проверяет этот флаг, исчезает. После этого действия сценарий нужно завершать. - `rpg.teleport` переносит игрока в клетку этой или другой карты. ## Настройки игры - **Внешний вид** (`rpg.player_charset`) — спрайт героя на картах, выбирается из чарсетов игры. - **Проекция карты** (`tile.renderer`) — вид сверху или изометрия; см. Tile Rendering. ## Если что-то пошло не так 1. **Персонаж или сундук не реагирует.** Встаньте к нему лицом и нажмите E или F; событие с `Touch` срабатывает, только если на него наступить. 2. **Монстр или сундук возвращается.** Его `Condition` должен проверять тот флаг, который выставляет его сценарий или `win_flag`. 3. **Не пройти туда, где вроде бы открыто.** Клетку блокирует непроходимый тайл или слой коллизий карты. 4. **Нет фона для боя.** Сцене карты в `scenes/.json` нужен `defaultBackground`.