#pragma once // ----------------------------------------------------------------------------- // Изометрия существует ТОЛЬКО здесь и в рендере. Симуляция, ИИ и коллизии // работают в декартовом мире (top-down) и об этом файле не знают. // // sx = (wx - wy) * 16 // sy = (wx + wy) * 8 // ----------------------------------------------------------------------------- #include #include #include "core/math.h" #include "render/framebuffer.h" #include "tuning.h" namespace iso { inline Vec2 WorldToScreen(Vec2 w) { return {(w.x - w.y) * float(TILE_HALF_W), (w.x + w.y) * float(TILE_HALF_H)}; } inline Vec2 ScreenToWorld(Vec2 s) { const float a = s.x / float(TILE_W); // = (wx - wy) / 2 const float b = s.y / float(TILE_H); // = (wx + wy) / 2 return {b + a, b - a}; } // Ключ сортировки по глубине: чем больше, тем «ближе к камере». inline float Depth(Vec2 w) { return w.x + w.y; } // Направление в ЭКРАННЫХ осях -> направление в мире (WASD, спек 5). inline Vec2 ScreenDirToWorld(Vec2 screenDir) { return Normalized(ScreenToWorld(screenDir)); } // Камера следует за якорем со сглаживанием; смещение округляется до пикселя. struct Camera { Vec2 pos{}; bool snapped = false; void SnapTo(Vec2 target) { pos = target; snapped = true; } void Follow(Vec2 target, float dt, float smooth) { if (!snapped) { SnapTo(target); return; } const float k = 1.0f - std::exp(-smooth * dt); pos = Lerp(pos, target, k); } void ScreenOffset(int& ox, int& oy) const { const Vec2 c = WorldToScreen(pos); ox = int(std::lround(INTERNAL_W * 0.5f - c.x)); oy = int(std::lround(INTERNAL_H * 0.5f - c.y)); } }; // Один элемент списка отрисовки: и стены, и сущности идут в общий список. struct DrawItem { float depth = 0.0f; const Sprite* spr = nullptr; int x = 0; int y = 0; uint32_t tint = 0; bool hasTint = false; // явный флаг: RGBA(0,0,0,0) — легальный цвет bool shaded = false; // рисовать через световую рампу ShadeQuad quad{}; }; inline void SortByDepth(std::vector& items) { std::stable_sort(items.begin(), items.end(), [](const DrawItem& a, const DrawItem& b) { return a.depth < b.depth; }); } inline void FlushDrawList(Framebuffer& fb, const std::vector& items) { for (const DrawItem& it : items) { if (!it.spr) continue; if (it.hasTint) fb.BlitTinted(*it.spr, it.x, it.y, it.tint); else if (it.shaded) fb.BlitShaded(*it.spr, it.x, it.y, it.quad); else fb.Blit(*it.spr, it.x, it.y); } } } // namespace iso