refactor(tilemap): índexs directes al YAML en lloc de llegenda ASCII

`data` passa a ser una llista de files d'enters (tile index lineal),
sense la indirecció `legend:` + símbols. Desapareix el límit implícit
de ~60 tiles distints i el grid segueix llegint-se com a matriu visual
gràcies al padding de 3 dígits. `-1` marca cel·la buida.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
JailDesignerandClaude Opus 4.7 committed 2026-04-23 09:11:21 +02:00
1 parent 4da05b3d76
commit 243ba06351
3 files changed
+52 -96

No files matched your search

+20 -44
View File
@@ -2,11 +2,10 @@
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <unordered_map>
#include <utility>
#include <vector>
#include "core/rendering/screen.hpp"
#include "core/rendering/surface.hpp"
@@ -16,35 +15,6 @@
namespace {
// Cada símbol del grid es mapeja a (col, fila) dins del tileset.
using TileCoord = std::pair<int, int>;
using Legend = std::unordered_map<char, TileCoord>;
auto splitLines(const std::string& text) -> std::vector<std::string> {
std::vector<std::string> lines;
std::istringstream iss(text);
std::string line;
while (std::getline(iss, line)) {
if (!line.empty()) { lines.push_back(line); }
}
return lines;
}
// La llegenda usa índexs lineals del tileset (esq→dre, dalt→baix).
// Els convertim a (col, fila) amb el nombre de tiles per fila del tileset.
auto parseLegend(const fkyaml::node& node, int tileset_cols) -> Legend {
Legend legend;
for (auto it = node.begin(); it != node.end(); ++it) {
const auto KEY_STR = it.key().get_value<std::string>();
if (KEY_STR.empty()) { continue; }
const auto INDEX = it.value().get_value<int>();
const int COL = INDEX % tileset_cols;
const int ROW = INDEX / tileset_cols;
legend[KEY_STR.front()] = {COL, ROW};
}
return legend;
}
// Copia un tile (col, fila) del tileset al buffer ARGB a la posició de
// destí (dest_x, dest_y). Els píxels amb l'índex de transparència del
// tileset es deixen com estan al buffer (alpha=0 per defecte).
@@ -84,17 +54,21 @@ Tilemap::Tilemap(const std::string& yaml_path) {
// Carreguem el tileset al cache (idempotent) i el pillem per accedir
// als seus píxels i paleta. La paleta del tileset ve del GIF mateix.
// Ens cal abans de la llegenda per saber quants tiles per fila té.
// Ens cal abans de llegir `data` per saber quants tiles per fila té.
const auto& cache_name = TILESET_PATH;
Resource::Cache::get().loadSurface(cache_name, TILESET_PATH);
const auto TILESET = Resource::Cache::get().getSurface(cache_name);
const int TILESET_COLS = TILESET->getWidth() / TILE_SIZE;
const auto LEGEND = parseLegend(yaml["legend"], TILESET_COLS);
const auto LINES = splitLines(yaml["data"].get_value<std::string>());
const int ROWS = static_cast<int>(LINES.size());
const int COLS = ROWS > 0 ? static_cast<int>(LINES.front().size()) : 0;
// `data` és una seqüència de seqüències d'enters: cada fila és una
// llista d'índexs lineals al tileset (esq→dre, dalt→baix). Un valor
// negatiu (per convenció -1) deixa la cel·la buida (alpha=0).
const auto& data = yaml["data"];
if (!data.is_sequence() || data.empty()) {
throw std::runtime_error("Tilemap: `data` buit o amb format incorrecte a " + yaml_path);
}
const int ROWS = static_cast<int>(data.size());
const int COLS = static_cast<int>(data[0].size());
width_px_ = COLS * TILE_SIZE;
height_px_ = ROWS * TILE_SIZE;
pixels_.assign(
@@ -102,12 +76,14 @@ Tilemap::Tilemap(const std::string& yaml_path) {
0U);
for (int row = 0; row < ROWS; ++row) {
const auto& line = LINES[row];
for (int col = 0; col < COLS && col < static_cast<int>(line.size()); ++col) {
const char SYMBOL = line[col];
const auto IT = LEGEND.find(SYMBOL);
if (IT == LEGEND.end()) { continue; }
blitTile(*TILESET, TILE_SIZE, IT->second.first, IT->second.second, pixels_, width_px_, col * TILE_SIZE, row * TILE_SIZE);
const auto& line = data[row];
const int LINE_COLS = static_cast<int>(line.size());
for (int col = 0; col < COLS && col < LINE_COLS; ++col) {
const int INDEX = line[col].get_value<int>();
if (INDEX < 0) { continue; }
const int SRC_COL = INDEX % TILESET_COLS;
const int SRC_ROW = INDEX / TILESET_COLS;
blitTile(*TILESET, TILE_SIZE, SRC_COL, SRC_ROW, pixels_, width_px_, col * TILE_SIZE, row * TILE_SIZE);
}
}