70 lines
4.2 KiB
C
70 lines
4.2 KiB
C
|
|
#pragma once
|
|||
|
|
// -----------------------------------------------------------------------------
|
|||
|
|
// Тайлы пола и стен — по набору на каждую тему отделки.
|
|||
|
|
//
|
|||
|
|
// Живёт в движке, а не в render/sprites.h, ровно по одной причине: этим
|
|||
|
|
// набором рисует и игра, и редактор комнат. Редактор линкуется только с
|
|||
|
|
// движком и про бойцов, тварей и предметы не знает, поэтому тащить ради двух
|
|||
|
|
// спрайтов весь SpriteSet он не может и не должен.
|
|||
|
|
//
|
|||
|
|
// Выбор варианта плиты — чистая функция от координат тайла, без состояния и без
|
|||
|
|
// генератора: пол обязан быть одинаковым в любом прогоне, иначе запечённая
|
|||
|
|
// кровь легла бы после перезапуска на другую плиту (render/blood.h).
|
|||
|
|
// -----------------------------------------------------------------------------
|
|||
|
|
#include <cstdint>
|
|||
|
|
|
|||
|
|
#include "engine/hash.h"
|
|||
|
|
#include "engine/theme.h"
|
|||
|
|
#include "engine/framebuffer.h"
|
|||
|
|
#include "engine/config.h"
|
|||
|
|
|
|||
|
|
class SpriteLibrary;
|
|||
|
|
|
|||
|
|
// Сколько разных «рисунков» может лежать на плите пола: ровная, треснувшая,
|
|||
|
|
// решётка, засыпанная трухой. Шахматка при этом остаётся — вариант ложится
|
|||
|
|
// ПОВЕРХ неё, а не вместо: без чередования двух тонов изометрическая сетка
|
|||
|
|
// перестаёт читаться, и пол превращается в кашу.
|
|||
|
|
constexpr int FLOOR_VARIANTS = 4;
|
|||
|
|
|
|||
|
|
struct TileSet
|
|||
|
|
{
|
|||
|
|
// [тема][чётность шахматки][вариант рисунка].
|
|||
|
|
Sprite floor[THEME_COUNT][2][FLOOR_VARIANTS];
|
|||
|
|
Sprite wall[THEME_COUNT][2]; // industrial / biomass-infested, 32x32
|
|||
|
|
|
|||
|
|
// Процедурный набор. Не зависит ни от одного файла на диске: игра и
|
|||
|
|
// редактор обязаны запускаться на голом репозитории.
|
|||
|
|
void Generate();
|
|||
|
|
|
|||
|
|
// Заменить базовую тему на тайлы из библиотеки SpriteForge и пересобрать
|
|||
|
|
// по ней остальные. Всё или ничего: при любой осечке набор остаётся тем,
|
|||
|
|
// что дал Generate(), и возвращается false. Вызывать только после Generate().
|
|||
|
|
bool LoadFromForge(const SpriteLibrary& lib);
|
|||
|
|
|
|||
|
|
const Sprite& Floor(int tx, int ty, uint8_t theme) const
|
|||
|
|
{
|
|||
|
|
// Раскладка намеренно неравномерная: ровная плита занимает больше
|
|||
|
|
// половины карты. Равные доли превращают пол в пёстрый ковёр, на
|
|||
|
|
// котором не видно ни крови, ни тварей.
|
|||
|
|
static const int kPick[8] = {0, 0, 0, 0, 0, 1, 2, 3};
|
|||
|
|
const uint32_t h = Hash2(uint32_t(tx) * 2654435761u, uint32_t(ty));
|
|||
|
|
return floor[Clamp(theme)][(tx + ty) & 1][kPick[h & 7u]];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const Sprite& Wall(int tx, int ty, uint8_t theme) const
|
|||
|
|
{
|
|||
|
|
// Редкие заражённые блоки, детерминированно по координате.
|
|||
|
|
const uint32_t h = Hash2(uint32_t(tx) * 2246822519u, uint32_t(ty));
|
|||
|
|
return wall[Clamp(theme)][(h & 7u) == 0u ? 1 : 0];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
// Комната может сослаться на тему, которой в этой сборке движка ещё нет.
|
|||
|
|
// Падать из-за этого нельзя: неизвестная тема рисуется базовой.
|
|||
|
|
static int Clamp(uint8_t theme) { return (theme < THEME_COUNT) ? int(theme) : 0; }
|
|||
|
|
|
|||
|
|
// Темы 1..N-1 — перекраска темы 0. Вызывается и после Generate(), и после
|
|||
|
|
// LoadFromForge(): иначе привезённые тайлы остались бы только в базовой.
|
|||
|
|
void BuildThemes();
|
|||
|
|
};
|