Acaba la migració dels std::cout/cerr a Log::*:
- core/locale, core/ui/ui_config, core/rendering/{screen,text,gif,
surface, sprite/animated_sprite, sdl3gpu/*}.
- game/{options, debug_config, editor/editor_config, levels/level_manager,
map/{map,tilemap,paint_layer}, entities/entity_manager_loadlevel}.
Severitats coherents: warns per a configs absents amb fallback,
errors per a YAML malformat o E/S fallida, infos per a estats.
Resultat:
- 0 occurrences de std::cout/std::cerr a source/.
- Cap #include <iostream> orfà (eliminat de surface.cpp).
- Output funcional idèntic al històric; AEE_LOG filtra (ex.
`AEE_LOG=warn` només mostra warnings, `AEE_LOG=*:warn,Tag:info`
combina globals i overrides).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- resource_pack.cpp i resource_cache.cpp: tots els std::cerr passen a
Log::error.
- director.cpp: std::cout/cerr/fprintf → Log::info / error / critical
segons severitat.
- printWithDots (utils.cpp): ara és un wrapper sobre Log::info que
manté l'amplada total (~50 chars) reproduint l'alineació de punts.
Els callers pasen el tag sense " : " (ja l'afegeix el logger).
- pack_resources: afegit log.cpp i SDL3 al target perquè
resource_pack.cpp ara depèn de Log::.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
screenshot.cpp ara només inclou les declaracions de stb_image_write.h;
la macro STB_IMAGE_WRITE_IMPLEMENTATION viu a un .cpp nou dins de
source/external/, que ja està exclòs del pre-commit hook (clang-format
i clang-tidy) i cobert pel seu .clang-tidy amb Checks: '-*'. Així
podem retirar la desactivació global de clang-analyzer-optin.portability
.UnixAPI i el check queda actiu arreu del nostre propi codi.
Captura de pantalla amb F9: volca el canvas ARGB a
screenshots/scr_<timestamp>.png via stb_image_write.
Tot el tema d'UI (colors, timings, fonts, flag hud.bg_enabled)
passa a data/ui.yaml via UiConfig; els valors de Defaults::UI
queden com a fallbacks si el fitxer falta o li manca alguna clau.
Retocs estètics: paleta "uzebox" per a la UI, strings del HUD
(P1/P2/V/T/PIRAMIDE/SALA) traduïts a locale, i fons del marcador
opcional amb backdrop continu de franja per evitar el trencament
visual durant el shake o l'animació d'entrada dels panells.
Fix: gif.cpp no desfeia l'interlace, trinxava qualsevol GIF entrellaçat
(tota la sortida de Pillow). Afegeix Defaults::UI::Font per centralitzar
noms/rutes i mou data/font → data/fonts.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Sprite: nou hook virtual `collisionBox() -> SDL_FRect` (default
`pos_`). Subclasses amb falsa perspectiva el sobreescriuen amb una
sub-caixa més petita.
- MovingSprite: nou `tryMove(dx, dy, CollisionFn)` que aplica eix a
eix i reverteix l'eix que col·lisiona; deixa lliscar el sprite
contra obstacles.
- Player: override `collisionBox()` retornant `getBaseBox()` i
`update()` reescrita per fer `animate(dt) + tryMove(vx*dt, vy*dt,
collidesFn)` en lloc del patró antic `update + revertir + reaplicar`.
El comportament observable és idèntic: la integració `v*dt` parteix
de la mateixa posició (post-snap), els revertits per col·lisió són
els mateixos i el `MOVED` que controla l'animació stand/walk segueix
comparant amb `FRAME_START_X/Y`.
Smoke tests 13/13 OK; log Game start → Bye! sota xvfb-run idèntic al
baseline. clang-tidy i cppcheck nets sobre els fitxers modificats.
Refs: docs/audit-game.md (PATCH-01).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Afegit `Defaults::UI::` amb els 5 índexs (RENDER_INFO_TEXT/SHADOW,
CANVAS_BG, NOTIFICATION_TEXT/BG, EXIT_TEXT/BG) i 2 durades
(NOTIFICATION_TIME_MS, EXIT_TIME_MS). `ui_palette.hpp` i
`notification_presets.hpp` queden com a alias: canviar el tema global
és tocar un sol bloc. Equivalent a tenir un "tema" (vindria d'un YAML el
dia que calga).
El fitxer definia presets del Notifier (que ja viu a core/rendering/), però
estava a game/ i era consumit únicament per core/input/global_inputs.cpp
— una dependència invertida core→game. El mogueu al costat del component
que consumeix; el comentari de `notifier.hpp` hi apunta. `game/ui/` es
queda només amb `ui_palette.hpp`.
Notifier::init i RenderInfo::init cridaven Resource::Cache::get() i
construïen cadascun la seua pròpia instància de Text a partir de
"8bithud.gif" + "data/font/8bithud.fnt" (strings hardcoded). Notifier
també llegia la paleta "ui" a cada render().
Ara:
- Director construeix una sola std::shared_ptr<Text> compartida.
- RenderInfo::init(Frame, shared_ptr<Text>) i Notifier::init
(shared_ptr<Text>, const Palette&) reben els recursos injectats.
- Notifier desa la Palette una volta i la consulta localment a
render(), sense tocar el cache global.
Resultat: els overlays perden la dependència dels noms dels assets
i del cache; el cicle de vida queda controlat pel Director. El camp
intern text_ passa a shared_ptr<Text>.
El document d'auditoria es tanca:
- PATCH-02, COUP-05 → DEFERRED (feature beyond cleanup scope).
- INC-04 → WONTFIX (coexistència justificada de writeDX/write*).
- Estat global: neteja completada.
Build + smoke 5s xvfb OK (exit 124).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Notifier::TEXT_SIZE i el TEXT_SIZE del namespace anònim de render_info
declaraven, els dos, "8" com l'alçada del glif de 8bithud. Ara
Rendering::Hud::FONT_SIZE_PX (a core/rendering/hud_constants.hpp) és
l'única font de veritat; Notifier i RenderInfo l'inclouen.
HC-04 (moure la resta de constants HUD a YAML) es marca DEFERRED al
document: és una feature de runtime-config, no pura neteja.
Build + smoke 5s xvfb OK (exit 124).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Els defaults del shader CRT-Pi es duplicaven entre CrtPiParams
(shader_backend.hpp) i CrtPiUniforms (crtpi_pipeline.hpp). Ara
CrtPiUniforms es value-initializa a zeros i CrtPiPipeline::init(),
un cop el pipeline està creat, aplica setParams(CrtPiParams{}) per
a fixar els defaults canònics abans del primer render. Així queda
una sola font de veritat (els defaults del struct CrtPiParams al
interface ShaderBackend).
Build + smoke 5s xvfb OK (exit 124).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
crtpi_frag.msl tenia la línia
float filter_width = (768.0f / u.texture_height) / 3.0f;
amb dues constants soltes (768 i 3) sense explicar. Ara es declaren
al mateix shader com CRT_REFERENCE_HEIGHT i SUBPIXEL_DIV amb un
comentari explicant que 768 és l'alçada CRT de referència on es va
tarar el filtre i 3 el nombre de subpíxels (R/G/B) del multisample.
Build + smoke 5s xvfb OK (exit 124).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- MovingSprite: el ctor delegat Sprite(surface, pos) ja assigna pos_;
el Sprite::pos_ = pos; manual que seguia era redundant (INC-06).
- Sprite(surface) usava initializer posicional {0.0F, 0.0F, ...} mentre
la resta del projecte usa designated initializers ({.x = ..., .y = ...}).
Unificat (INC-07).
INC-05 (el static_cast<int> de pos_.x a MovingSprite::move i setters)
es marca WONTFIX al document: és snap intencional a píxel per al
pixel-art, divergent només al setter per SDL_FRect que es reserva per
a posicionament directe sense arrodoniment.
Build + smoke 5s xvfb OK (exit 124).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Surface i Screen repetien el bit d'alpha opac com a 0xFF000000U o com
(0xFFU << 24). S'afegeix inline constexpr Rendering::OPAQUE_ALPHA a
canvas.hpp i s'usa a les tres ocurrències.
Build + smoke 5s xvfb OK (exit 124).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- DUP-01: les tres branques del switch d'extensions que saltaven el
mateix (bloc fix + sub-blocs) es substitueixen per una crida a
skipExtensionBlock(); com que totes les extensions comparteixen
layout, el switch desapareix i el codi es redueix a una línia.
- DUP-06: el constructor Surface(file_path) llegia el fitxer dues
voltes (una via loadSurface per pixels i una altra via
loadPaletteFromGif per la paleta); ara carrega el buffer una sola
vegada i n'extrau pixels + paleta en passades separades sobre la
memòria. Surface::loadSurface passa a no existir públicament (no
tenia callers externs).
- HC-03: les màscares i talls màgics del decoder LZW i del Screen
Descriptor passen a constants nominals (LZW_MIN/MAX_CODE_LENGTH,
LZW_MASK_INITIAL, LZW_MASK_OVERFLOW, SCREEN_GCT_FLAG,
SCREEN_GCT_SIZE_MASK, GCT_BYTES_PER_ENTRY).
- HC-10: processImageDescriptor tenia gct i resolution_bits
[[maybe_unused]] vestigials; se'n treu la signatura. L'struct RGB,
que només servia per a aquests args, també s'elimina.
- PATCH-05: el comentari "reemplaçar macro READ" (migració parcial des
de C) passa a ser un comentari neutre sobre el que fa readBytes.
Build + smoke 5s xvfb OK (exit 124).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
render_info.cpp tenia diverses "cifres soltes" amb significat
estructural:
- Índex 0/1/2/3 dins segments_ per a FPS/driver/shader/temps — ara
FPS_SEGMENT, DRIVER_SEGMENT, SHADER_SEGMENT, TIME_SEGMENT (HC-06).
- +1,+1 per a la ombra del text — ara SHADOW_OFFSET_PX (HC-09).
- % 3 al cicle de posicions de global_inputs.cpp — ara
Defaults::RENDER_INFO_POSITION_COUNT (HC-07).
A més, init() assignava mono_digits=true al segment de temps que
refreshSegments() ja marca a cada crida, inclosa la primera d'update()
abans de render. S'elimina el doblegat (PATCH-08); el comentari
explica la garantia.
Build + smoke 5s xvfb OK (exit 124).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
gif.hpp declarava Extension, GraphicControlExtension, ApplicationExtension
i PlaintextExtension com a tipus "empaquetats" per a llegir blocs del
stream GIF. El parser a gif.cpp, però, processa els bytes cru (avança
el punter i llig block_size + sub-blocs manualment) sense instanciar-los
mai. Les struct eren code pattern orientat a reus futurs que no va
arribar a materialitzar-se.
Build + smoke 5s xvfb OK (exit 124).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Eliminats mètodes sense callers:
- Sprite::getRect() (DEAD-04)
- Sprite::incX / incY (DEAD-05)
- AnimatedSprite::getCurrentAnimationSize() (DEAD-07)
- Surface::getSurfaceData() (DEAD-08)
Sprite::update passa a ser virtual amb cos buit inline al header, en
lloc de la definició a .cpp amb (void)delta_time; desapareix una línia
de "parxejament" sense alterar la polimorfia (Player::update, heretat
via AnimatedSprite/MovingSprite, continua fent override correctament).
Això tanca DEAD-10 i PATCH-04 alhora.
Els ctors per defecte Sprite()/MovingSprite() s'apunten com WONTFIX al
document: són necessaris per a la cadena de construcció base d'Animated
Sprite (que no delega explícitament al ctor parametritzat).
Build + smoke 5s xvfb OK (exit 124).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Eliminats cinc mètodes sense callers externs:
- writeShadowed / writeCentered: la funcionalitat viu a writeDX(flags,
...) que és l'API reutilitzable; ningú crida aquestes variants
discretes.
- glyphWidth / getGlyphClip: getters per glif no consumits enlloc.
- codepointToUtf8: helper de serialització UTF-8 no consumit (només es
consumeix el parser nextCodepoint, que queda).
Build + smoke 5s xvfb OK (exit 124).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Surface::renderWithColorReplace usava Screen::get().getCanvasArgb() i
companys per a obtenir el buffer destí. S'introdueix una abstracció
mínima:
- source/core/rendering/canvas.hpp: struct Canvas amb pixels/width/
height i la fàbrica activeCanvas() que retorna el canvas actiu.
- source/core/rendering/canvas.cpp: implementació que delega a Screen.
Surface ara inclou canvas.hpp en lloc de screen.hpp i crida
Rendering::activeCanvas(). L'indirecció permet, més endavant, empènyer
canvases alternatius (off-screen, efectes) sense tocar Surface; ara
mateix es comporta idèntic al codi anterior.
Build + smoke 5s xvfb OK (exit 124).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Screen ja no inclou sdl3gpu/sdl3gpu_shader.hpp ni instancia la classe
concreta. S'afegeix la fàbrica Rendering::makeDefaultShaderBackend()
declarada a shader_backend.hpp i implementada a sdl3gpu_shader.cpp
(únic fitxer que encara coneix la classe concreta).
Per a que Screen no necessite static_cast, releaseWindow() passa a ser
mètode virtual pur de la interfície ShaderBackend (abans només existia
a SDL3GPUShader). SDL3GPUShader::releaseWindow marca override.
Build + smoke 5s xvfb OK (exit 124).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Text tenia cinc mètodes (write, writeColored, writeMonoDigits, length,
lengthMonoDigits) i dos getters (glyphWidth, getGlyphClip) que repetien
el mateix patró de resolució de codepoint: find(cp), fallback a '?' si
no hi és. Extret a un helper privat resolveGlyph(cp) que centralitza
aquesta lògica; totes les funcions passen a usar-lo.
write() ara delega directament a writeColored(...) passant el color per
defecte, eliminant ~19 línies del bucle UTF-8 duplicades.
Els literals 1 (índex de "tinta" al PNG) i 15 (color per defecte a la
paleta) passen a ser Text::INK_COLOR_INDEX i Text::DEFAULT_TEXT_COLOR
(HC-01).
Build + smoke 5s xvfb OK (exit 124).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>