squad-proto/src/render/scene.h

47 lines
2.4 KiB
C
Raw Normal View History

Прототип боевого ядра: отряд, хоррор-слой, ближний бой Тактический отряд с автоматическим огнём в изометрии, собственный софтверный растеризатор (raylib только окно, ввод и финальный блит). Ядро (спек, раздел 6): - LaneClear: проверка линии огня по своим, стенам и дальности; - решатель огневых позиций с гистерезисом и коммитом; - резервирование линий огня и расступание из чужих секторов; - пули-снаряды, дружественный урон физически возможен. Хоррор-слой (render-only): свет и туман войны с памятью карты, светящиеся трассеры, кровь, виньетка, зерно, напряжение. Ближний бой: сектор удара, три фазы, связка из трёх ударов, своя дисциплина «не бить сквозь своего». Проверка: squad_proto.exe --accept прогоняет критерии приёмки раздела 11 плюс блок M7 по ближнему бою — все PASS, FRIENDLY_HITS = 0 за 3 минуты боя. Сборка: cmake -S . -B build && cmake --build build --config Release raylib 6.0 подтягивается через FetchContent. Документация — CLAUDE.md как оглавление, содержание в docs/. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 17:00:49 +07:00
#pragma once
// -----------------------------------------------------------------------------
// Сборка кадра: сплошной проход по полу, затем общий список стен и сущностей,
// отсортированный по глубине (wx + wy).
// -----------------------------------------------------------------------------
#include <vector>
#include "render/blood.h"
#include "render/framebuffer.h"
#include "render/iso.h"
#include "render/sprites.h"
#include "render/lighting.h"
#include "world/tilemap.h"
struct Scene
{
std::vector<iso::DrawItem> items;
int ox = 0; // смещение камеры в пикселях (целое)
int oy = 0;
void Begin(const iso::Camera& cam);
// world — мировая позиция «подошвы» сущности;
// pixelLift — подъём спрайта по экрану (пули летят не по земле);
// depthBias — ручная правка ключа сортировки.
void Add(const Sprite* spr, Vec2 world, int pixelLift = 0, float depthBias = 0.0f);
// Тот же элемент, но с патчем света.
void AddShaded(const Sprite* spr, Vec2 world, const ShadeQuad& quad, int pixelLift = 0,
float depthBias = 0.0f);
void Flush(Framebuffer& fb);
};
// Пол — первым сплошным проходом, в список сортировки не попадает.
// Полностью тёмные тайлы пропускаются: ступень 0 рампы совпадает с цветом
// очистки, поэтому результат пиксель-в-пиксель тот же, а рисовать дешевле.
//
// blood == nullptr — крови нет. Иначе у запачканных тайлов берётся запечённая
// копия ромба. Стоимость кадра от этого не меняется: тот же один блит на тайл,
// сколько бы крови ни накопилось (render/blood.h).
void DrawFloor(Framebuffer& fb, const SpriteSet& sprites, const Tilemap& map, int ox, int oy,
const Lighting& light, const BloodField* blood);
// Все WALL-тайлы уходят в общий список вместе с сущностями.
void CollectWalls(Scene& scene, const SpriteSet& sprites, const Tilemap& map,
const Lighting& light);