80 lines
3.0 KiB
C++
80 lines
3.0 KiB
C++
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "game/entities/event_bus.hpp"
|
|
|
|
class Tilemap;
|
|
|
|
// Capa visual de "pintat" sobre el tilemap base. Quan el jugador (o
|
|
// qualsevol altre actor futur) publica `on_tile_entered` amb payload
|
|
// `PaintedTile{col, row, tile_index}`, el PaintLayer filtra per
|
|
// `Map::isPaintable`, marca el tile i re-publica `tile_painted` amb
|
|
// només `TilePos` — abstracció del "el tile s'ha pintat" independent de
|
|
// qui ho ha fet. Els sarcòfags escolten aquest segon event per comptar
|
|
// el seu perímetre.
|
|
//
|
|
// Font única de veritat del pintat: evita duplicar l'estat dins de cada
|
|
// sarcòfag i permet que el render mostri l'efecte al instant.
|
|
//
|
|
// Geometria: hereta `tile_size`, origen i dimensions del Tilemap
|
|
// (mateixa graella). Reutilitza el tileset del Tilemap per blitejar els
|
|
// tiles pintats a un buffer ARGB propi, anàleg a `Tilemap::pixels_`.
|
|
//
|
|
// Política de repintat: el primer que pinta un tile guanya. Intents
|
|
// posteriors (amb el mateix índex o un altre) no tenen efecte —
|
|
// garanteix coherència visual i evita notificar dos cops al mateix sarc.
|
|
class PaintLayer {
|
|
public:
|
|
PaintLayer(const Tilemap& tilemap, EventBus* bus);
|
|
~PaintLayer();
|
|
|
|
PaintLayer(const PaintLayer&) = delete;
|
|
PaintLayer(PaintLayer&&) = delete;
|
|
auto operator=(const PaintLayer&) -> PaintLayer& = delete;
|
|
auto operator=(PaintLayer&&) -> PaintLayer& = delete;
|
|
|
|
// Còpia del buffer ARGB sobre el canvas del Screen, respectant alpha
|
|
// (píxels no pintats queden al buffer amb alpha=0 i no s'escriuen).
|
|
// Pensat per cridar entre `Tilemap::render()` i el bloc d'actors.
|
|
void render() const;
|
|
|
|
// Intent de pintat directe (exposat per a tests i actors que pinten
|
|
// sense passar pel bus). Retorna true si el tile és pintable i no
|
|
// estava ja pintat; en aquest cas, publica `tile_painted`.
|
|
auto tryPaint(int col, int row, int tile_index, int player_id = -1) -> bool;
|
|
|
|
[[nodiscard]] auto isPainted(int col, int row) const -> bool;
|
|
|
|
// Buida el pintat acumulat. Marca tots els tiles com a no pintats i
|
|
// reseteja el buffer ARGB a alpha=0 (transparent). Cridat per
|
|
// GameScene a la transició ROOM_OUTRO → ROOM_INTRO. La subscripció
|
|
// al bus es manté — el PaintLayer continuarà reaccionant a
|
|
// `on_tile_entered` un cop els jugadors hagin reaparegut.
|
|
void clear();
|
|
|
|
private:
|
|
void blitPaintTile(int col, int row, int tile_index);
|
|
|
|
EventBus* bus_{nullptr};
|
|
EventBus::SubId on_tile_sub_{0};
|
|
|
|
int cols_{0};
|
|
int rows_{0};
|
|
int tile_size_{0};
|
|
int origin_x_{0};
|
|
int origin_y_{0};
|
|
int width_px_{0};
|
|
int height_px_{0};
|
|
int tileset_cols_{0};
|
|
std::string tileset_path_;
|
|
|
|
// `-1` = no pintat. Altres valors = índex de tile del tileset usat
|
|
// per pintar. No cal per al render (el buffer `pixels_` ja el conté),
|
|
// però facilita consultes ràpides d'estat i futures extensions.
|
|
std::vector<std::vector<int>> painted_;
|
|
std::vector<std::uint32_t> pixels_;
|
|
};
|