#pragma once // ----------------------------------------------------------------------------- // Всё render-only состояние живёт здесь и только здесь. // // Зачем отдельная структура: правило «эффекты не текут в симуляцию» должно // проверяться компилятором, а не вниманием. RenderGame принимает Game по // КОНСТАНТНОЙ ссылке — значит ни свет, ни трассеры, ни тряска камеры физически // не могут изменить состояние симуляции. Headless-прогоны (--accept, --headless) // View не создают вообще, поэтому цифры приёмки остаются цифрами симуляции. // ----------------------------------------------------------------------------- #include "render/anim.h" #include "render/atmos.h" #include "render/blood.h" #include "engine/framebuffer.h" #include "render/fx.h" #include "engine/view2d.h" #include "render/lighting.h" #include "render/post.h" #include "render/scene.h" struct Game; class SpriteLibrary; struct View { v2d::Camera cam; Scene scene; Lighting lighting; FxSystem fx; PostFx post; Dread dread; BloodField blood; // вечные декали, запечённые в спрайты пола Atmosphere atmos; // пепел в воздухе // Дельты считаются по накопительным счётчикам метрик: за один кадр рендера // проходит до MAX_STEPS_PER_FRAME шагов, поэтому флаг «выстрелил» не годится. int prevShots = 0; int prevKills = 0; int prevFriendly = 0; int prevMeleeHits = 0; // Здоровье отряда прошлого кадра: урон приходит от тварей россыпью, флага // «ударили» ни у кого нет, а дельта суммы честно ловит любой источник. float prevSquadHp = -1.0f; int prevSquadAlive = NUM_AGENTS; bool horrorEnabled = true; // F5 — аварийный возврат к прежнему кадру bool showSight = false; // F6 — показать диски обзора // --- анимация тварей ------------------------------------------------------- // Библиотека спрайтов, если игру запустили с собранными ассетами. Пусто — // рисуем процедурные спрайты, и это рабочий режим по умолчанию, а не отказ. const SpriteLibrary* forge = nullptr; // Состояние проигрывателя на КАЖДУЮ цель. Живёт в View, а не в Target, // ровно по правилу этого файла: фаза шага — свойство картинки, и попав в // симуляцию, она поехала бы в цифрах приёмки. Animator enemyAnim[MAX_TARGETS]; Animator agentAnim[NUM_AGENTS]; // Где тварь была в прошлом кадре: шаг проигрывается, только когда она идёт. // Скорости у Target нет (vel — это отдача от удара), поэтому движение // определяется единственным честным способом — сравнением позиций. Vec2 enemyPrevPos[MAX_TARGETS]; bool enemyPosKnown[MAX_TARGETS] = {}; // Гамма и усиление меняют САМУ таблицу рампы: без перепечатки ручки молчат. float rampGamma = -1.0f; float rampGain = -1.0f; void Init(); void RefreshRamp(); void Reset(const Game& game); }; void RenderGame(const Game& game, View& view, Framebuffer& fb, float alpha, float frameDt);