Compare commits

...

387 Commits

Author SHA1 Message Date
JailDesigner 9c0502eefb feat(enemy): sistema d'events declaratius via YAML 2026-05-25 13:34:48 +02:00
JailDesigner 9b3da3a6e7 Merge branch 'feat/enemy-star': afegir tipus STAR i 3 nous shapes 2026-05-25 12:42:06 +02:00
JailDesigner bc41169176 feat(enemy): afegir tipus STAR (estrella de 5 puntes) i 3 nous shapes
- Nou enemic STAR amb shape star_5.shp, escala 0.7 i color groc pur.
  Reusa el comportament zigzag del Pentagon i carrega via EnemyRegistry.
- DistribucioEnemics estesa amb camp 'star' opcional (default 0) per
  mantenir compat amb stages antics.
- Stage 1 reconfigurat a 25/25/25/25 per mostrar els 4 tipus.
- Afegits també shapes bullet_long.shp i bullet_double.shp (encara no
  utilitzats; preparats per futures variants de bala).
2026-05-25 12:36:26 +02:00
JailDesigner b3a1afce06 Merge branch 'feat/entities-yaml-enemy-shared': paràmetres compartits dels enemics a cada YAML 2026-05-25 11:59:28 +02:00
JailDesigner 4b6dc8a47a feat(entities): migrar paràmetres compartits dels enemics a cada YAML 2026-05-25 11:54:40 +02:00
JailDesigner 3dadd5fc1a Merge branch 'feat/entities-yaml-bullet': migració de la bala a YAML 2026-05-25 11:47:36 +02:00
JailDesigner bea844d51e feat(entities): migrar bullet a data/entities/bullet/bullet.yaml 2026-05-25 11:42:43 +02:00
JailDesigner 5fb6c68df4 Merge branch 'feat/entities-shape-scale': collision_radius derivat del shape + scale al YAML 2026-05-25 11:33:52 +02:00
JailDesigner 866a057704 feat(entities): derivar collision_radius del shape + scale/collision_factor al YAML 2026-05-25 11:29:43 +02:00
JailDesigner da8eab330d Merge branch 'feat/entities-yaml-enemies': configuració dels enemics en YAML 2026-05-25 10:15:34 +02:00
JailDesigner 39bda0775e feat(entities): migrar la configuració dels 3 enemics a data/entities/<type>/*.yaml 2026-05-25 10:01:12 +02:00
JailDesigner ed4d3a3915 Merge branch 'feat/entities-yaml-player': configuració del player en YAML 2026-05-25 09:39:39 +02:00
JailDesigner 6447932212 feat(entities): migrar la configuració del player a data/entities/player/player.yaml 2026-05-25 08:32:49 +02:00
JailDesigner 9f278772bb Merge branch 'feat/pack-resources-align': alinear pack_resources amb projectes germans 2026-05-25 07:55:49 +02:00
JailDesigner 2d073b6055 feat(pack): alinear sortida i build amb projectes germans 2026-05-25 07:55:30 +02:00
JailDesigner 99b18d208d chore: bump version a 0.8.0
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 22:41:25 +02:00
JailDesigner 1321566910 Merge branch 'feature/sistema-gestio-inputs': sistema de gestio d'inputs
Modul DefineInputs per redefinir teclat i mando amb overlay modal,
pagina CONTROLS al menu de servei (picker de mando amb llista, swap
automatic en conflicte, slot SENSE MANDO, rebind per jugador), so
accept en cada captura, navegacio del menu amb dpad/stick i triggers
L2/R2, glyphs ( ) i / al charset, autoassignacio de mando al primer
arranque, i diversos fixes de pipeline d'events.
2026-05-24 22:39:47 +02:00
JailDesigner cefafe99e4 feat(service_menu): triggers L2/R2 navegables + so al rebind
El menu de servei nomes processava AXIS_MOTION dels sticks i descartava
els triggers. Com SDL3 mai emet button events per a L2/R2 (nomes axis),
rebindar FIRE o ACCEL a un trigger feia que no funcionaren al menu, fins
i tot estant correctament al joc per via del poll de Input::checkTriggerInput.
Afegim edge-detect dels dos triggers al handleGamepadAxis i, quan creuen
el llindar, mirem si el codi virtual (100=L2, 101=R2) coincideix amb el
binding de FIRE → activateCurrent, o ACCEL → popPage. Estat held per
trigger per evitar repeticions mentre es mante premut.

DefineInputs ara reprodueix el so accept del menu en cada captura
valida, que estava silent i no donava feedback al rebind.

Tambe extraiem processStickX/Y i processTriggerEdge per mantenir
handleGamepadAxis com a dispatcher i sota el llindar de complexitat
cognitiva del clang-tidy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 22:38:10 +02:00
JailDesigner daa7eaf811 feat(service_menu): glyphs () + tanca picker al seleccionar mando
Afegim els glyphs ( i ) a VectorText (char_lparen.shp, char_rparen.shp,
arcs de 4 trams dins la caixa 20x40) perque el sufix (P1)/(P2) de la
picker de mando es renderitze net sense warnings.

A mes, al triar un mando o "SENSE MANDO" a la picker fem popPage
automatic, perque l'usuari no haja de tornar enrere a ma després
d'una assignacio.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 22:20:29 +02:00
JailDesigner 3dcf5c3a99 feat(service_menu): picker de mando per llista i fix SENSE MANDO
El cycle anterior fallava al desasignar perque Input::resolvePlayerGamepad
tenia un fallback per slot que reasignava gamepads_[player_index] quan
name+path eren buits. Això el contradeia el slot "SENSE MANDO" del cycle:
el YAML quedava buit pero el runtime seguia lligant el mando. Treure el
fallback i moure l'autoassignacio inicial al boot (nomes si tots dos
jugadors venen buits) restaura la semàntica: buit vol dir buit.

Sobre el fix, redissenyem la UX dels items MANDO P1/P2: ja no son CYCLE
sino SUBMENU que obrin una pàgina-llista (estil RESOLUCIÓ) amb tots els
mandos detectats. Cada item porta sufix (P1)/(P2) nomes si el mando el
te l'altre jugador, perque sapigues que assignar-lo li'l "robarà".
L'ultim item es "SENSE MANDO" per a desassignar explícitament. La
lògica de swap automatic en conflicte queda extreta a assignPadToPlayer
i es reutilitza des de la picker.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 22:12:53 +02:00
JailDesigner 99d0f62ab5 feat(service_menu): slot 'sense mando' al cycle i swap automatic en conflicte
El CYCLE de la pagina CONTROLS ara inclou un slot virtual al final que
desassigna el mando (gamepad_name + gamepad_path buits → padDisplayName
mostra "SENSE MANDO"). Aixi l'usuari pot recuperar el control teclat
sense haver d'editar el YAML.

A mes, si en assignar un mando l'altre jugador ja el tenia, fem swap
automatic: l'altre jugador rep l'assignacio previa d'aquest, evitant
que dos jugadors comparteixen el mateix dispositiu. La deteccio
prioritza path (mateixa branca que resolvePlayerGamepad).

Extracta tambe reapplyBindings per mantenir cyclePlayerPad llegible.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 21:22:23 +02:00
JailDesigner 85050c8da4 fix(define-inputs): deixa passar QUIT i ESC al pipeline global
L'overlay de redefinicio engolia tots els events mentre estava actiu, fet
que impedia tancar la finestra amb l'aspa (SDL_EVENT_QUIT) i deixava
prendre ESC com a cancel-lacio del rebind. Ara:
- QUIT i WINDOW_CLOSE_REQUESTED passen sempre al global per tancar
  l'aplicacio des de l'aspa.
- ESC ja no cancel-la la sequencia; cau al global on obre el prompt
  d'eixida com a la resta del joc.
- isReservedScancode (ESC/F1-F12/RETURN/BACKSPACE/TAB) deixa passar.

Tambe ajusta DISPAR -> DISPARAR a ca.yaml i treu el hint "ESC PER
CANCEL-LAR" del modal i les claus de locale corresponents.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 21:20:25 +02:00
JailDesigner 120c5502fd feat(vector-text): afegeix el glyph / al charset
El progres "i/n" del modal de redefinicio (ex. 1/4) sortia com a "14"
perque VectorText no tenia shape per a la barra i emetia un warning.
Afegim font/char_slash.shp (diagonal de baix-esquerra a dalt-dreta dins
de la caixa 20x40) i el registrem al loader i al getShapeFilename.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 20:58:52 +02:00
JailDesigner 64a6599e81 fix(title): manten animacions amb menu obert, bloqueja nomes els polls d'input
El fix anterior pausava tot el title quan el menu de servei estava obert,
trencant l'efecte d'animacio de fons. Ara title segueix animant-se i
nomes guardem handleSkipInput/handleStartInput mentre el menu o el modal
de rebind estan actius, per evitar START fantasma sense congelar el render.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 20:54:04 +02:00
JailDesigner a4b567588f feat(service_menu): navegacio amb mando (dpad, stick, fire = enter, accelerate = back)
ServiceMenu::handleEvent ara accepta tambe SDL_EVENT_GAMEPAD_BUTTON_DOWN
i SDL_EVENT_GAMEPAD_AXIS_MOTION. Mapeig: dpad UP/DOWN/LEFT/RIGHT mouen
el cursor, el boto FIRE configurat per qualsevol jugador equival a ENTER
(activa l'item), ACCELERATE equival a BACK (popPage). El stick esquerre
fa nav amb edge-detect: cal tornar a centre per disparar una altra entrada.
GlobalEvents::forwardToServiceMenu envia tots aquests events al menu
quan esta obert.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 20:42:33 +02:00
JailDesigner 2e74fea2d5 feat(input): stick com a font alternativa de LEFT/RIGHT al mando
LEFT i RIGHT no son redefinibles al mando i s'assumeix dpad O stick.
Input::update() ara llegeix SDL_GAMEPAD_AXIS_LEFTX i fa OR amb l'estat
del dpad: qualsevol de les dos fonts dispara l'accio. Llindar 30000
(coherent amb el constant AXIS_THRESHOLD ja existent).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 20:38:26 +02:00
JailDesigner c4933875dd fix(input): impedeix que els events traspassin al joc en acabar el rebind
El menu de servei queda obert per sota de l'overlay DefineInputs durant
tot el rebind (en lloc de tancar-se al activar la accio), de manera que
absorbeix qualsevol KEY_DOWN que arribi un cop l'overlay s'auto-cancela.
La pantalla de titol tambe pausa la seua logica mentre el menu de servei
esta obert, igual que GameScene, per evitar que detecti un START fantasma
si l'usuari encara te una tecla pulsada al moment de tancar-se el modal.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 20:36:51 +02:00
JailDesigner 10a54aef91 fix(ui): nom del mando en majuscules a la UI sense modificar el config
VectorText nomes admet ASCII en majuscules; els noms dels mandos (i el
git hash) passaven pel toUpperAscii local del service_menu, pero les
notificacions de hot-plug i el text del CYCLE de la pagina CONTROLS
es mostraven amb el case original. Mou el helper a un utils compartit i
l'aplica a tots els punts de display sense tocar gamepad_name al config.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 20:33:01 +02:00
JailDesigner 34be79192c feat(service_menu): pagina CONTROLS amb assignacio de pad i rebind per jugador
Afegeix submenu CONTROLS al menu de servei amb 2 items CYCLE per
seleccionar el mando assignat a cada jugador (persistit per name + path)
i 4 items ACTION per arrancar DefineInputs (teclat/mando per a P1/P2).

Tambe afegeix:
- Director: init/update/draw/destroy del singleton DefineInputs.
- GlobalEvents: routing prioritari de tots els events a DefineInputs
  mentre l'overlay esta actiu.
- Locale ca/en: claus del submenu CONTROLS i de l'overlay de rebind.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 20:18:49 +02:00
JailDesigner fcf13591be feat(input): modul DefineInputs per redefinir teclat i mando
Singleton inspirat en aee_arcade DefineButtons: pinta una caixa central
modal, captura events SDL i avança per una sequencia fixa d'accions per
jugador. Teclat: LEFT/RIGHT/FIRE/ACCELERATE. Mando: FIRE/ACCELERATE/
START/MENU. ESC cancel-la, duplicats dins la sessio es rebutgen.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 20:17:30 +02:00
JailDesigner 3e8f2f35bf feat(input): accio MENU i assignacio de mando per path + name
Afegeix l'accio MENU a InputAction (obre el menu de servei des del mando,
equivalent a F12 al teclat) i els camps gamepad.button_start i
gamepad.button_menu al config per jugador. Tambe afegeix gamepad_path
per distingir dos mandos del mateix model i prioritza path > name >
slot a applyPlayerNBindings via el nou resolvePlayerGamepad.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 19:56:59 +02:00
JailDesigner e5a91825b1 feat(input): notifica connexio/desconnexio de mandos via Notifier
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 19:55:42 +02:00
JailDesigner b3271b17a2 Merge branch 'feat/preload-resources': precàrrega completa al boot 2026-05-24 19:32:04 +02:00
JailDesigner d4117e3505 feat(boot): precàrrega de música, sons i shapes a l'arrencada 2026-05-24 19:31:35 +02:00
JailDesigner 73c7e4ea76 Merge branch 'fix/fps-rounding': FPS arrodonit 2026-05-24 19:20:14 +02:00
JailDesigner 23cc5ce68d fix(debug-hud): FPS arrodonit en lloc de truncat 2026-05-24 19:20:06 +02:00
JailDesigner e42059e486 chore(sounds): normalitza sons a pcm_u8 48 kHz mono peak -1 dB 2026-05-24 19:11:43 +02:00
JailDesigner 00f40d194b Merge branch 'feat/audio-persistence': persistència d'àudio + toggles com a mute pur 2026-05-24 19:06:43 +02:00
JailDesigner 31f348328e fix(audio): toggles són mute pur, no aturen la reproducció 2026-05-24 18:52:05 +02:00
JailDesigner 8c48a9a772 feat(config): persistència de les opcions d'àudio al config.yaml 2026-05-24 18:40:33 +02:00
JailDesigner bacfbe6eac Merge branch 'tweak/debug-hud-layout': FPS gran, RES i DRIVER al HUD de debug 2026-05-24 14:15:05 +02:00
JailDesigner 63d08aef46 tweak(debug-hud): FPS més gran, afegeix RES i DRIVER 2026-05-24 14:14:50 +02:00
JailDesigner 87f818ef96 Merge branch 'feat/service-menu': menu de servei F12 amb VIDEO/AUDIO/OPCIONS/SISTEMA 2026-05-24 12:32:55 +02:00
JailDesigner 7eafe21623 feat(service-menu): submenu RESOLUCIO amb canvi en calent de l'offscreen 2026-05-24 12:30:47 +02:00
JailDesigner 22827c28fa feat(service-menu): pobla SISTEMA amb reinici, eixir i confirmacions 2026-05-24 12:18:39 +02:00
JailDesigner 8c21345f14 feat(service-menu): pobla OPCIONS amb idioma i toggle del HUD de debug 2026-05-24 11:56:11 +02:00
JailDesigner 56d7d4af52 feat(service-menu): pobla AUDIO amb toggles i sliders de volum 2026-05-24 11:49:14 +02:00
JailDesigner 71c43ec6fe feat(service-menu): pobla VIDEO amb zoom, fullscreen, vsync, AA i postfx 2026-05-24 11:37:36 +02:00
JailDesigner 443b461974 feat(service-menu): esquelet amb F12, brackets sci-fi i highlight animat 2026-05-24 11:25:09 +02:00
JailDesigner cc16908b86 Merge branch 'feat/locale-system': sistema i18n amb canvi al vol 2026-05-24 10:36:54 +02:00
JailDesigner c4c6881bd6 feat(locale): canvi d'idioma al vol amb F7 i persistència 2026-05-24 10:35:39 +02:00
JailDesigner 35d720bb77 feat(locale): sistema i18n YAML amb català i anglès 2026-05-24 10:28:56 +02:00
JailDesigner 274ce1ca63 Merge branch 'refactor/english-identifiers': identificadors valencians/castellans a anglès 2026-05-24 08:12:56 +02:00
JailDesigner 252e881e93 refactor: renombra jugador*/zona/radi/MARGE/origen/letra residuals a anglès 2026-05-24 08:09:41 +02:00
JailDesigner d36ad7d1c5 refactor(scenes): renombra ancho/altura/centre_punt residuals a anglès 2026-05-24 08:03:28 +02:00
JailDesigner 7305d2f5dc refactor(scenes): renombra identificadors valencians de logo/title a anglès 2026-05-24 08:00:40 +02:00
JailDesigner 4cfad053f0 refactor(effects): renombra temps_vida/temps_max a elapsed_time/max_lifetime 2026-05-24 07:59:14 +02:00
JailDesigner 807f71ffa7 refactor(defaults): renombra VELOCITAT/CANVI_ANGLE/MAX_BALES a anglès 2026-05-24 07:57:12 +02:00
JailDesigner d12f24d798 refactor(enemy): renombra esta_/animacio_/timer_invulnerabilitat_ a anglès 2026-05-24 07:56:35 +02:00
JailDesigner f9d2539a45 refactor(enemy): renombra drotacio/rotacio/FACTOR_HERENCIA a anglès 2026-05-24 07:52:21 +02:00
JailDesigner 87bfccd14f refactor(enemy): renombra palpitacio* a pulse* 2026-05-24 07:46:07 +02:00
JailDesigner e5e3729215 refactor(enemies): renombra QUADRAT/MOLINILLO a SQUARE/PINWHEEL 2026-05-24 07:40:54 +02:00
JailDesigner 6210985548 Merge branch 'fix/shaders-glslc-optional': glslc opcional si els headers SPV ja estan al repo 2026-05-23 12:55:51 +02:00
JailDesigner 20250a0d6d fix(cmake): glslc opcional si els headers SPV ja estan commiteats al repo 2026-05-23 12:55:48 +02:00
JailDesigner e5616f7c3a Merge branch 'tweak/misc-adjustments': retocs varis (paleta, glow, audio, física, destell del títol) 2026-05-22 23:48:59 +02:00
JailDesigner 3b1e469a4f feat(title): destell hiperespacial al VP quan la nau desapareix (sparkle 4-puntes còncau) 2026-05-22 23:46:56 +02:00
JailDesigner 70ca19eb87 fix(wounded-chain): amplifier 1.25 perquè la cadena agafi el contacte post-rebot 2026-05-22 23:32:28 +02:00
JailDesigner 7e52eaeddb tweak(friendly-fire): la bala empeny la nau abans de morir → els debris hereten la inèrcia 2026-05-22 23:24:42 +02:00
JailDesigner d618b6d561 feat(audio): so propi per a la nau a HURT (hurt.wav, separat del HIT de bala) 2026-05-22 23:20:18 +02:00
JailDesigner e954d4ea59 tweak(playfield): rejilla violeta synthwave + brillos +5%; starfield unificat al color del títol 2026-05-22 23:10:06 +02:00
JailDesigner b1ee23cd20 tweak(stage-messages): missatges level start/completed amb color ambre del PRESS START 2026-05-22 23:02:23 +02:00
JailDesigner d86b10c14e tweak(collision): impuls extra a l'enemic en el moment que mata la nau (factor 0.3·mass·vel) 2026-05-22 22:59:27 +02:00
JailDesigner 1ea38d4f6a fix(ship-death): debris hereten inèrcia (captura velocitat abans del markHit) i comparteixen dispersió amb enemics 2026-05-22 22:47:02 +02:00
JailDesigner 26bd5a9efa tweak(playfield): el grid principal es dibuixa sobre el subgrid a les interseccions 2026-05-22 22:43:32 +02:00
JailDesigner 4b0d85c010 tweak(palette): colors neon purs per als 3 enemics (cyan/roig/magenta) 2026-05-22 22:39:04 +02:00
JailDesigner 149b485a9b Merge branch 'tweak/enemy-mix-stage1': ajustos d'enemics (mix stage 1, spawn col·lidible, ull al cuadrado) 2026-05-22 22:34:54 +02:00
JailDesigner 6b1f064cda tweak(cuadrado): ull amb pupil·la al centre del rombe 2026-05-22 22:34:54 +02:00
JailDesigner 1cef6a2c23 tweak(enemy): durant l'spawn ja poden ser abatuts i rebotar amb la nau (sense fer dany) 2026-05-22 22:27:44 +02:00
JailDesigner 007460dc51 tweak(stages): stage 1 amb mix dels 3 tipus d'enemic (34/33/33) 2026-05-22 22:12:17 +02:00
JailDesigner 10057a82de tweak(audio): amplifica hit.wav +6dB i puja canals simultanis a 50 2026-05-22 22:09:03 +02:00
JailDesigner 73fa5bf1d1 Merge branch 'tweak/firework-glow': halo neon per a fireworks amb color propi 2026-05-22 21:57:36 +02:00
JailDesigner c32b564da1 feat(firework): halo neon per partícula amb color de glow propi (explosió enemic: línia blanca + halo daurat) 2026-05-22 21:57:11 +02:00
JailDesigner 7b9b5ce569 Merge branch 'tweak/pentagon-design': halo neon proporcional i pentàgon doble 2026-05-22 21:38:29 +02:00
JailDesigner f0b3a1fbc4 feat(render): halo neon proporcional al bounding_radius de la shape (opt-out a text) 2026-05-22 21:35:01 +02:00
JailDesigner 869b4374ba tweak(pentagon): pentàgon doble concentric (interior rotat 36°) 2026-05-22 20:11:29 +02:00
JailDesigner ea192cd9de tweak(debug): l'overlay arranca ocult sempre; F11 segueix alternant-lo 2026-05-22 19:53:26 +02:00
JailDesigner 5d30f6be68 Merge branch 'tweak/playfield-grid': ones d'aigua + starfield parallax al fons 2026-05-22 19:52:07 +02:00
JailDesigner a342d79b86 feat(starfield): mou estrelles amb la mitjana de velocitats de les naus 2026-05-22 19:51:40 +02:00
JailDesigner 1db7368c9f feat(starfield): capa parallax al fons del playfield amb tint blanc-cyan 2026-05-22 19:46:57 +02:00
JailDesigner 88b002b277 feat(playfield): ones d'aigua a la rejilla per explosions i pas de nau 2026-05-22 19:22:09 +02:00
JailDesigner 044a3a3bbf tweak(playfield): subdivisions de 5 a 4 a la subgraella 2026-05-22 18:56:24 +02:00
JailDesigner 49070aa843 Merge branch 'fix/bullet-collision-swept': col·lisió bales swept + debris 2026-05-22 18:43:46 +02:00
JailDesigner 18e05e36e6 feat(bullet): debris en trencar-se amb so HIT mogut des d'enemy.herir() 2026-05-22 18:42:23 +02:00
JailDesigner bf79eecca0 fix(bullet): col·lisió swept, sense grace_timer, mor al border visual 2026-05-22 18:24:54 +02:00
JailDesigner b80216dce1 Merge branch 'feat/ship-hurt-state': estat HURT a la nau 2026-05-22 17:32:04 +02:00
JailDesigner 87138f9a1f feat(ship): la nau entra a HURT al xocar amb un enemic, mor en un segon impacte 2026-05-22 17:30:33 +02:00
JailDesigner c6560514d8 Merge branch 'feat/title-intro-sequence': intro coreografiada al títol 2026-05-22 14:05:57 +02:00
JailDesigner 839f73e1ef feat(title): intro amb path Z (zoom+pivot al VP) en lloc d'offset Y
El logo i el footer ara entren simulant un moviment 3D des de l'usuari
cap al VP: arrenquen grans i a la posició projectada extrema (factor
d'escala SCALE_START > 1, pivot al centre de pantalla) i convergeixen
a la seva mida i posició finals. Substitueix l'offset Y lineal anterior.
2026-05-22 14:03:28 +02:00
JailDesigner 2ca2062011 feat(title): intro coreografiada amb logo, footer i naus escalonats
Logo cau des de dalt; quan aterra, JAILGAMES i COPYRIGHT pugen des de
baix amb stagger pam-pam; després arrenquen les naus i, en aterrar
elles, apareix PRESS START. Magic numbers a Defaults::Title::Sequence.
2026-05-22 13:51:09 +02:00
JailDesigner 03209ee23b Merge branch 'feat/title-neon-palette': paleta neon synthwave a títol 2026-05-22 13:25:18 +02:00
JailDesigner c61299f17f feat(title): paleta neon synthwave per element a l'escena de títol 2026-05-22 13:04:11 +02:00
JailDesigner 880af293ef log: primer missatge 'Game start', últim 'Bye!' 2026-05-22 12:50:53 +02:00
JailDesigner 67c59992c9 Merge branch 'feat/sdl-callbacks': migració a SDL_MAIN_USE_CALLBACKS 2026-05-22 12:48:39 +02:00
JailDesigner be3d696f60 feat(main): activa SDL_MAIN_USE_CALLBACKS
main.cpp queda amb les 4 callbacks de SDL3: AppInit construeix el
Director, AppEvent enruta cada event a handleEvent(), AppIterate crida
iterate(), AppQuit reabsorbeix la propietat amb unique_ptr.
El Director::run() i el bucle while interns desapareixen; el bootstrap
de SDLManager/Audio/Context/DebugOverlay/Notifier viu ara al final del
constructor. SDL_Quit() ja no es crida explícitament — SDL ho fa
després de SDL_AppQuit.
2026-05-22 12:45:12 +02:00
JailDesigner 6b8f6a267d refactor(director): migra la persistència ConfigYaml al Director
main.cpp queda només amb 'Director director(argc, argv); return director.run()'.
El Director crida ConfigYaml::* directament; l'struct ConfigPersistence
desapareix de engine_config.hpp. La separació core/game es relaxa al
Director, que és EL programa, no part del motor.
2026-05-22 12:41:05 +02:00
JailDesigner 120b8ada38 refactor(director): extreu iterate/handleEvent/advanceScene del runFrameLoop
run() ara delega a iterate() i handleEvent() per cada frame.
runFrameLoop desapareix; la seva lògica es divideix entre els tres
nous mètodes. La primera escena es construeix lazy via advanceScene()
dins d'iterate(). Cap canvi de comportament visible.
2026-05-22 12:38:16 +02:00
JailDesigner 8bb052981d refactor(director): locals de run() a membres unique_ptr
Preparació per a SDL_MAIN_USE_CALLBACKS: SDLManager, SceneContext,
DebugOverlay i l'escena actual ja viuen com a membres del Director.
El flux de run() és idèntic; només canvia el storage.
2026-05-22 12:35:19 +02:00
JailDesigner 7fc8e48596 Merge branch 'feat/title-3d': escena del títol migrada a 3D real 2026-05-22 12:12:22 +02:00
JailDesigner ff518195f8 fix(title): comentari trencat per la substitució sed del cleanup 2026-05-22 12:06:48 +02:00
JailDesigner 54d3e683a1 refactor(title): la 3D és l'única — elimina backup 2D i renomena als noms canònics 2026-05-22 12:04:16 +02:00
JailDesigner a29c2b9cc2 fix(ship-3d): exit convergeix al VP sense travessar-lo (sense creuament entre naus) 2026-05-22 11:57:16 +02:00
JailDesigner 85e7e70767 feat(title-3d): horitzó ampliat (starfield Z=1500, naus exiting travessen el VP) 2026-05-22 11:50:26 +02:00
JailDesigner 3f10c61e22 tweak(ship-3d): SHIP_FLOAT_SCALE a 2.0 2026-05-22 11:40:47 +02:00
JailDesigner 5de9a5003b tweak(ship-3d): descans més amunt i naus més grans (FLOAT_SCALE 1.5, TARGET_DIST 480) 2026-05-22 11:30:54 +02:00
JailDesigner d3076fbdec tweak(ship-3d): descans prop de P-PRESS / Y-PLAY, més mida, pitch +14° lift 2026-05-22 10:20:39 +02:00
JailDesigner 26c6decd74 fix(ship-3d): path únic VP→les7/les5 perquè initial, target i VP siguen col·lineals 2026-05-22 10:06:06 +02:00
JailDesigner 54702a5afe feat(ship-3d): look-at dinàmic, naus alineades amb el path (punta+cul) 2026-05-22 09:52:14 +02:00
JailDesigner b45390a8d1 tweak(ship-3d): tornar a extruir amb depth 1.0 (més baixa que 1.5) 2026-05-22 09:48:57 +02:00
JailDesigner 2faa3ede84 tweak(ship-3d): pitch -120° i naus planes (sense extrusió) 2026-05-22 09:39:19 +02:00
JailDesigner 85e1933a83 fix(ship-3d): oscil·lació contínua entre ENTERING i FLOATING (sense salt) 2026-05-22 09:31:28 +02:00
JailDesigner 07788ab3b6 tweak(ship-3d): pitch -108°, Z 90, X 25 (més inclinació, més lluny) 2026-05-22 09:30:39 +02:00
JailDesigner 2ed7463069 tweak(ship-3d): pitch a -100° per inclinar el cul avall i veure el dors 2026-05-22 09:24:53 +02:00
JailDesigner e533387ce5 fix(title-3d): naus rotades cap al VP, alçada mínima, eix X de càmera corregit 2026-05-22 09:11:26 +02:00
JailDesigner b654fd0428 feat(title-3d): TitleScene3D, SceneType::TITLE_3D i trigger ORNI_TITLE_3D 2026-05-22 08:22:36 +02:00
JailDesigner 7a3a71e1dc feat(ship-animator3d): animador 3D de naus per al títol amb extrusió de ship.shp 2026-05-22 08:14:29 +02:00
JailDesigner 8722a46d06 feat(starfield3d): camp d'estrelles 3D amb octaedres rotants cap a càmera 2026-05-22 08:10:52 +02:00
JailDesigner e20bdec470 feat(wireframe3d): mesh3d + drawWireframe + factories octaedre i extrusió 2026-05-22 08:07:47 +02:00
JailDesigner 86708e0ed5 feat(camera3d): afig Vec3 i Camera3D amb projecció perspectiva en CPU 2026-05-22 08:04:45 +02:00
JailDesigner 51797e0ea7 Merge branch 'feat/playfield-reactions': el playfield reacciona al pas de la nau i als fireworks 2026-05-21 23:04:25 +02:00
JailDesigner 20f5b83649 feat(playfield): reaccions orbit al pas de la nau i pulse al spawn de fireworks 2026-05-21 23:03:48 +02:00
JailDesigner ffeff3d69d Merge branch 'feat/border-bumps': border amb reaccions a impactes i explosions 2026-05-21 22:49:42 +02:00
JailDesigner a44748c0c4 feat(border): bump del border per explosions properes a la paret 2026-05-21 22:48:49 +02:00
JailDesigner e678f8d538 feat(border): refactor a Graphics::Border amb bumps i flash verd clar per impactes contra les parets 2026-05-21 22:39:08 +02:00
JailDesigner ccda7113c1 Merge branch 'feat/playfield-grid': fons playfield amb graella animada 2026-05-21 22:06:08 +02:00
JailDesigner 5c8a583e24 tune(playfield): ona diagonal amb easing i cap brillant 2026-05-21 22:06:02 +02:00
JailDesigner 07985228b2 feat(playfield): refactor a Playfield amb animació de creació durant l'INIT_HUD 2026-05-21 20:44:17 +02:00
JailDesigner dc389037f8 feat(grid): sub-graella amb 5 subdivisions i ajust de brillos 2026-05-21 20:21:46 +02:00
JailDesigner f30b195778 feat(grid): graella verda fosca de fons al playfield (16x8) 2026-05-21 20:16:44 +02:00
JailDesigner 95ac4606d5 Merge branch 'enhancements': debug overlay, àudio a 48000 i typewriter ràpid 2026-05-21 20:04:43 +02:00
JailDesigner 2bc07f8e8d tune(stage): typewriter ràpid però visible al missatge de nivell completat 2026-05-21 20:02:02 +02:00
JailDesigner ca6f863c0f tune(audio): efectes a 48000 Hz u8 mono i ajust de volums per defecte 2026-05-21 19:58:45 +02:00
JailDesigner 66faa07c00 tune(debug): overlay més endins del playfield i en color daurat 2026-05-21 19:50:45 +02:00
JailDesigner 72158c7c3f Merge branch 'fix/p2-join-physics': el P2 ja pot accelerar després de fer join 2026-05-21 19:44:52 +02:00
JailDesigner 8b32a0a404 fix(join): registrar el cos físic del jugador al món quan s'uneix 2026-05-21 19:44:29 +02:00
JailDesigner abb7b8fe8c Merge branch 'feat/ship-trail': estela de partícules daurada/vermella darrere la nau 2026-05-21 19:40:36 +02:00
JailDesigner 51308fa25e tune(trail): vida més llarga, offset darrere i paleta vermella per al P2 2026-05-21 19:40:15 +02:00
JailDesigner 74d855357d feat(trail): estela daurada de partícules quan la nau accelera 2026-05-21 19:29:32 +02:00
JailDesigner a9593a0fd9 Merge branch 'tune/gameplay': balas, velocitat, stage 1 i so hit 2026-05-21 19:05:53 +02:00
JailDesigner dec72340de feat(audio): so hit.wav quan l'enemic passa a ferit 2026-05-21 19:05:42 +02:00
JailDesigner 7646daef3d tune(stages): stage 1 a 50 enemics i puja el cap de validació a 200 2026-05-21 18:58:33 +02:00
JailDesigner 1c1fd1273b tune(ship): puja MAX_VELOCITY de 120 a 180 px/s 2026-05-21 18:55:01 +02:00
JailDesigner e6eaf870c6 tune(bullets): puja MAX_BALES a 50 i deshardcoded el slot per jugador 2026-05-21 18:51:55 +02:00
JailDesigner 23eff1585c chore: neteja de notes obsoletes a l'arrel 2026-05-21 18:46:55 +02:00
JailDesigner 4d51c13e46 Merge branch 'tune/glow': bloom separable + preserve-core + paleta neon + F6 toggle 2026-05-21 18:46:20 +02:00
JailDesigner 625cb19cba feat(postfx): toggle F6 per activar/desactivar el postprocessat 2026-05-21 18:45:29 +02:00
JailDesigner ae946b578e feat(bloom): glow separable two-pass amb composite preserve-core i paleta neon 2026-05-21 18:39:16 +02:00
JailDesigner 8b4683b77b Merge branch 'feat/fireworks': starburst d'explosió d'enemic 2026-05-21 17:41:52 +02:00
JailDesigner 0cc1f7623a feat(fireworks): burst radial blanc al explotar enemic + tuning 2026-05-21 17:41:10 +02:00
JailDesigner 56ce1a3236 feat(fireworks): infraestructura (manager + pool + render, sin spawn aún) 2026-05-21 17:22:46 +02:00
JailDesigner 5aab26f2ca Merge branch 'feat/enemy-death': muerte d'enemics amb herida prèvia + debris físic 2026-05-21 17:16:16 +02:00
JailDesigner 2869c63517 tune(debris): N=1, shrink completo y sin herencia angular en enemigos 2026-05-21 17:11:08 +02:00
JailDesigner 87b96b8226 fix(debris): bugs rotacion cuadratica y shrink exponencial (geometria autoritativa) 2026-05-21 14:05:10 +02:00
JailDesigner 7505de074c feat(debris): rebote contra los limites del playarea (restitution 0.7) 2026-05-21 13:55:32 +02:00
JailDesigner ae1d1397b1 revert: vuelve al modelo de efd18ff + ENEMY_LIFETIME 3.0 -> 4.5 2026-05-21 13:46:25 +02:00
JailDesigner 0c8a9b744e tune(debris): un poco mas de rotacion + shrink mas rapido (1.4s) 2026-05-21 13:41:20 +02:00
JailDesigner 9b25e875f3 fix(debris): bug rotacion cuadratica + shrink exponencial; geometria autoritativa 2026-05-21 13:37:12 +02:00
JailDesigner e84f555a66 fix(debris): rotación visual decae con fricción + modulada por size_factor 2026-05-21 13:23:16 +02:00
JailDesigner 048263a1d0 feat(debris): modelo INTACTO→MENGUANDO→0 (sin pop, fade-out por tamaño) 2026-05-21 12:53:01 +02:00
JailDesigner efd18ff852 feat(debris): vida híbrida (mínima + umbral velocidad) + multiplier para enemigos 2026-05-21 12:07:50 +02:00
JailDesigner 44aa4e76e2 fix(physics): salta body-body collision quan algun cos té radius=0
resolveBodyPair afegeix early-out per a parells on a.radius<=0 o b.radius<=0.
Honra el comentari de bullet.cpp:30 ("radius=0 → sin colisión física,
cinemática pura") que abans no s'aplicava: amb bala radius=0 + enemic
radius=ENEMY_RADIUS, SUM_R era enemic radius i el body-body disparava
si la bala (a 700 px/s) penetrava el cos l'enemic entre frames.

Símptomes corregits:
- Pentagon: la bala "rebotava espectacularment" en lloc d'impactar.
- Quadrat: rebut un impulse double del cantó de la física que es
  sumava (o cancel·lava, segons l'angle) al manual, fent l'efecte
  inconsistent.

Ara la gameplay collision (Physics::checkCollision amb entity radius,
que ja és més generós) és l'única que tracta el parell bala-enemic.

A més: IMPACT_MOMENTUM_FACTOR 2.0 → 3.0 per compensar la pèrdua del
rebot físic i donar més empenta:
  - Pentagon (m=5) Δv = 210 px/s
  - Quadrat  (m=8) Δv = 131 px/s
  - Molinillo (m=4) Δv = 262 px/s

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 11:45:59 +02:00
JailDesigner e3af88ea8c tune(enemy): més empenta + cos inert quan està herit
- IMPACT_MOMENTUM_FACTOR: 1.0 → 2.0 (doble del moment de la bala).
  Pentagon Δv = 140 px/s (≈4× la seva velocity base), prou clar.
- Enemy::update: salta el switch de behavior (Pentagon zigzag,
  Quadrat tracking, Molinillo proximity-spin) mentre wounded_timer_>0.
  El enemic herit és un "cos mort" inert: només respon a la inèrcia
  del impulse rebut i a les col·lisions físiques resoltes per
  PhysicsWorld. Abans, el Quadrat renormalitzava la velocity cada 1s
  cap al ship, esborrant la inèrcia.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 11:33:03 +02:00
JailDesigner ff5dfab94d tune(bullet): empuje cuasi-físico (momento real de la bala)
Sustitueix IMPACT_IMPULSE (magnitud arbitrària radial) per
IMPACT_MOMENTUM_FACTOR (factor de transferència del moment de la bala).

El impulse ara és bullet.body.velocity * (bullet.body.mass * factor),
és a dir el moment lineal real de la bala, dirigit cap a on viatjava.
Amb factor=1.0 i la bala (m=0.5, v=700 px/s):
  - Pentagon (m=5)  → Δv = 70 px/s (doble de la seva velocity base)
  - Quadrat  (m=8)  → Δv = 44 px/s
  - Molinillo (m=4) → Δv = 88 px/s

Visiblement notable durant el segon de "ferit" abans de l'explosió.
El factor és tunable per pujar/baixar segons gusts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 10:37:23 +02:00
JailDesigner 2cf5292b16 feat(collision): cadena herit→sa via fregada física (Fase 6)
Systems::Collision::detectWoundedChain itera parells d'enemics: si
exactament un està herit i toquen (Physics::checkCollision), el sa entra
en estat herit propagant last_hit_by_ → la cascada de morts segueix
acreditant el shooter original. El rebot físic ja el gestiona
PhysicsWorld; aquí només propaguem l'estat.

Hook a detectAll just després de detectBulletEnemy: les balles tenen
prioritat sobre la cadena del mateix frame.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 10:29:29 +02:00
JailDesigner 7b24bfae94 feat(enemy): parpadeig dorat quan està herit (Fase 4)
Enemy::draw() ara, si wounded_timer_ > 0, alterna entre el color del
tipus i Defaults::Palette::WOUNDED (dorat) a Wounded::BLINK_HZ usant
fmod sobre el periode del cicle — patró reutilitzat del Ship::draw()
d'invulnerabilitat però aplicat a color en lloc de visibilitat.

A 10 Hz amb DURATION=1s dóna ~10 parpadeigs visibles abans d'explotar.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 10:27:56 +02:00
JailDesigner 5cb547db0a feat(collision): primer impacte fereix, segon mata; mort diferida via timer (Fase 3)
- Defaults::Physics::Debris::ENEMY_VELOCITY_INHERITANCE (placeholder 1.0).
- Enemy::herir(shooter_id) emmagatzema last_hit_by_ per a atribució posterior.
- collision_system: helper anònim explodeNow(ctx, enemy, shooter_id) que
  llegeix velocity/dades ABANS de destruir() (corregeix bug latent: el codi
  anterior llegia getVelocityVector() després de destruir, que zera velocity
  → l'explosió mai heretava inèrcia).
- detectBulletEnemy: primer impacte aplica impulse + herir(); segon impacte
  sobre enemy ferit dispara explodeNow immediata.
- processWoundedDeaths: explota enemics amb wound timer expirat aquest frame.
- detectAll: processWoundedDeaths abans de detectBulletEnemy (les expiracions
  maten primer; les bales del mateix frame ja no toquen el cos destruït).

Puntos s'atribueixen a la mort real, no a l'impacte inicial.

Build neta i smoke test xvfb OK.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 10:26:13 +02:00
JailDesigner dc2824a095 feat(collision): la bala transmet impulse mass-aware al enemic (Fase 2)
- Defaults::Physics::Bullet::IMPACT_IMPULSE (50 px·s placeholder)
- detectBulletEnemy: calcula normal bullet→enemy, normalitza
  (fallback a direcció de bala o (0,-1) si estan solapats) i crida
  enemy.applyImpulse(normal * IMPACT_IMPULSE) abans de destruir.

El destruir() immediat encara zera la velocity, així que l'efecte
visual no es nota: serà visible quan la Fase 3 difereixi la mort.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 10:22:25 +02:00
JailDesigner d169a1997c feat(enemy): afegeix estat "wounded" amb timer i API base (Fase 1)
- Defaults::Palette::WOUNDED ({255,215,0}) dorat per a parpadeig
- Defaults::Enemies::Wounded::{DURATION, BLINK_HZ}
- Enemy: wounded_timer_, wound_expired_this_frame_
- API: herir(), isWounded(), getWoundedTimer(),
  woundExpiredThisFrame(), consumeWoundExpired(), applyImpulse()
- update() decrementa timer i marca expiració al creuar 0
- destruir() reseteja l'estat wounded

Sense efectes visuals ni canvis de comportament: cap callsite invoca
encara herir() ni applyImpulse(). Build verda i smoke test xvfb OK.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 10:20:42 +02:00
JailDesigner 23bcd0816f tune(bullet): augmenta velocitat de la bala (×5) 2026-05-21 09:55:07 +02:00
JailDesigner 93baead066 Merge branch 'feat/centralize-defaults' 2026-05-21 09:51:02 +02:00
JailDesigner bb21191c5b refactor(defaults): substitueix els 999.0F restants per HIT_TIMER_INACTIVE_PLAYER 2026-05-21 09:48:20 +02:00
JailDesigner 7139dea7f6 refactor(defaults): centralitza init hud, tips, hit timer, line thickness i debug overlay 2026-05-21 09:45:55 +02:00
JailDesigner 08100f60e8 refactor(defaults): centralitza constants de bullet, ship, enemy, hud i notifier 2026-05-21 09:39:36 +02:00
JailDesigner 61ae211dab chore(iwyu): subheaders concrets i pragma exports al umbrella
Reemplaça core/defaults.hpp pels subheaders concrets a director.cpp i
config_yaml.cpp (silencia unused-includes de clangd). Marca el umbrella
amb IWYU pragma: begin_exports/end_exports per evitar falsos positius
als consumidors transitius.
2026-05-21 08:52:19 +02:00
JailDesigner 5d1dae1d86 feat(render): resolució d'offscreen configurable via YAML
Separa el tamany lògic (1280×720) del render target offscreen. Llista
tancada de 5 presets 16:9 (720p/900p/1080p/1440p/2160p) llegida de
rendering.render_{width,height} amb fallback a 1280×720 si invàlida.
Inclou API resizeRenderTarget() preparada per al menú de servei futur.
2026-05-21 08:46:22 +02:00
JailDesigner 4252f3327f fix(notifier): ESC només confirma sobre el propi prompt de sortida 2026-05-21 08:24:22 +02:00
JailDesigner 9a79fb9774 chore(shaders): regenera postfx_frag_spv.h 2026-05-21 08:18:12 +02:00
JailDesigner 6629e9b9aa fix(warnings): cast RAND_MAX a float per evitar conversió implícita 2026-05-21 08:16:55 +02:00
JailDesigner afc91425bc Merge branch 'feat/metal-msl-support': suport Metal/MSL a macOS 2026-05-20 23:07:57 +02:00
JailDesigner 6259f594c8 feat(gpu): suport Metal/MSL a macOS i shaders SPIR-V embedits 2026-05-20 23:07:49 +02:00
JailDesigner ac5434fc30 Merge branch 'feat/notifications': sistema de notificacions toast
Toasts centrats al centre-superior amb fons semitransparent, slide-in/out
amb easings cubic, integrats als toggles F1-F5 i a la doble pulsació
d'ESC per confirmar la sortida.
2026-05-20 22:30:49 +02:00
JailDesigner d1ca0df1ab tune(notifier): notifyInfo en cian i text una mica més gran
- COLOR_INFO passa de blanc neutre (230,230,230) a cian (80,230,255)
  per a diferenciar més els toasts informatius dels d'avís/error.
- TEXT_SCALE de 0.4 → 0.55 perquè el text sigui més llegible amb
  l'aspect-fit del viewport.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 22:30:36 +02:00
JailDesigner 9eb8c58d87 feat(notifier): doble pulsació d'ESC per confirmar sortida
La primera ESC ja no tanca el joc directament: dispara un toast
"PREMEU ESC UN ALTRE COP PER EIXIR" en vermell. Mentre el toast està
entrant o aguantant (Notifier::isActiveWindow()), una segona ESC
confirma i tanca. Si l'usuari espera a que el toast comenci a sortir
o desaparegui, ESC torna a obrir la finestra de confirmació sense
tancar — només una doble pulsació consecutiva tanca.

Si el Notifier no existeix (no hauria de passar dins runFrameLoop),
ESC manté el comportament antic de tancar directament.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 22:11:43 +02:00
JailDesigner 470d2b85a4 feat(notifier): notificacions visuals als toggles F1-F5
Substitueixen els std::cout dels handlers per crides a notifyInfo() del
Notifier:
- F1/F2: ZOOM: X.YX (amb el valor actual)
- F3: PANTALLA COMPLETA / MODE FINESTRA
- F4: VSYNC ACTIU / VSYNC INACTIU
- F5: AA ACTIU / AA INACTIU

Tots els missatges en majúscules perquè la font vectorial actual només
té glyphs A-Z. Es manté la lògica de toggle i de persistència de cfg;
únicament canvia el canal de feedback (consola → toast HUD).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 22:10:24 +02:00
JailDesigner 81330f8432 feat(notifier): infrastructura del sistema de notificacions toast
- Notifier singleton (System::init/get/destroy) que dibuixa un cuadre
  centrat al centre-superior amb fons semitransparent (derivat oscur del
  color del text) i bordes en línies.
- Màquina d'estats HIDDEN → ENTERING → HOLDING → EXITING amb easing
  outCubic (entrada) i inCubic (sortida), slide de 300 ms.
- pushRect() afegit a GpuFrameRenderer (2 triangles, edge_dist=0) per
  poder pintar el fons opac/semitransparent reutilitzant el pipeline de
  línies — sense afegir cap pipeline nou.
- VectorText::render/renderCentered admeten color RGBA explícit
  (default {0,0,0,0} preserva el comportament previ amb oscil·lador
  global de color).
- Easing header-only a core/utils/easing.hpp (outCubic, inCubic).
- Director crea Notifier just després del DebugOverlay i el draweja com
  a última capa per damunt de l'escena i el debug.

Encara cap consumer el crida; els F1-F5 i la doble pulsació d'ESC
arriben en commits posteriors.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 22:07:56 +02:00
JailDesigner 799a97930c Merge branch 'fix/vsync-fullscreen-antialias': viewport fullscreen, VSync fallback i AA geomètric
Tres fronts arreglats a la rama:

- Fullscreen: el viewport ja no depèn de zoom_factor_ (capat per max_zoom_),
  sinó que és aspect-fit de la mida física actual. Afegit
  SetWindowFullscreenMode(nullptr) i preservació del zoom_factor_ de windowed
  durant transicions.
- VSync: setVSync ara consulta SDL_WindowSupportsGPUPresentMode i fa fallback
  IMMEDIATE → MAILBOX → VSYNC quan el driver/compositor força VSync. Loggeja
  el mode efectiu.
- Antialias geomètric a les línies: edge attribute + smoothstep al fragment.
  Toggle runtime amb F5, indicador 'AA: ON/OFF' al debug overlay (F11).
2026-05-20 21:42:53 +02:00
JailDesigner 1ef9ca551f feat(antialias): toggle F5 i indicador AA al debug overlay
Permet alternar l'AA geomètric en runtime:

- Action::TOGGLE_ANTIALIAS bound a F5.
- GlobalEvents::handle reacciona al scancode F5 cridant sdl.toggleAntialias().
- SDLManager::toggleAntialias muta cfg_->rendering.antialias i propaga a
  gpu_renderer_.setAntialias().
- GpuFrameRenderer manté l'estat antialias_enabled_ (true per defecte) i
  pushLine adapta extrusió i edge_dist en funció del flag — geometria nua
  quan està OFF, fade als bords quan està ON.
- RenderingConfig guanya el camp `antialias{1}` per coherència amb vsync;
  l'estat NO es persisteix al YAML de moment (decisió volgudament conservadora,
  podem afegir-ho en un commit a part si cal).
- DebugOverlay (F11) mostra una tercera línia "AA: ON/OFF" sota VSYNC per
  poder comparar a temps real.
2026-05-20 21:39:24 +02:00
JailDesigner b10f2da647 feat(antialias): AA geomètric a les línies amb edge attribute i smoothstep
Afegim antialias geomètric (sense MSAA) al pipeline de línies aprofitant
que la línia ja es construeix com a quad extruït a CPU:

- LineVertex: nou camp edge_dist (±1 als laterals del quad, 0 al centre).
- pushLine: extrudeix 0.5px extra per banda (AA_PADDING) per allotjar el
  fade sense menjar gruix nominal.
- line.vert: passa l'edge_dist al fragment com a varying.
- line.frag: alpha *= 1 - smoothstep(0.7, 1.0, |edge_dist|) — fade Hermite
  C¹ als bords, sense banding.

AA actiu per defecte. El toggle a runtime (F5) ve en el commit següent.
2026-05-20 20:25:12 +02:00
JailDesigner 6063309932 fix(vsync): comprovar suport de present mode i loggejar el mode efectiu
setVSync demanava SDL_GPU_PRESENTMODE_IMMEDIATE sense comprovar suport.
A SDL_GPU només VSYNC està garantit; IMMEDIATE i MAILBOX són opcionals.
Si no estaven suportats (típicament Wayland/X11 amb compositor), SDL
retornava error i la swapchain es quedava en VSYNC sense que ho sabéssim.

Ara:
- Consultem SDL_WindowSupportsGPUPresentMode abans de fer la crida.
- En VSync OFF: provem IMMEDIATE → fallback a MAILBOX → si cap, ens
  quedem en VSYNC i avisem (driver/compositor força VSync).
- Loggejem sempre el mode efectiu (no només els errors), perquè ara mateix
  no hi havia forma de saber des de fora si el toggle havia tingut efecte.
2026-05-20 20:17:28 +02:00
JailDesigner 7c2499cd91 fix(fullscreen): preservar zoom_factor_ de windowed durant transicions a fullscreen
Quan arribava un SDL_EVENT_WINDOW_RESIZED en fullscreen, recalculàvem
zoom_factor_ a partir de la mida física i el clampàvem a max_zoom_. Això
"consumia" el zoom_factor_ que tenia l'usuari en windowed, així que en
tornar a windowed (F3) la mida quedava la del clamp, no la prèvia.

Ara, en fullscreen, zoom_factor_ i windowed_*_ es deixen intactes (no
participen del càlcul del viewport, que ja és aspect-fit sobre la mida
física). En windowed, comportament inalterat.
2026-05-20 20:15:28 +02:00
JailDesigner e0f8cf78ee fix(fullscreen): seleccionar mode 'borderless desktop' explícitament en toggleFullscreen
A SDL3, SDL_SetWindowFullscreen(true) sol hereta el SDL_DisplayMode que tingués
la finestra. Sense una crida prèvia a SDL_SetWindowFullscreenMode(win, nullptr),
el comportament és no determinista entre invocacions (i pot acabar en mode
exclusiu si abans hi havia hagut un mode setejat).

Afegim la crida amb mode=nullptr just abans d'activar el fullscreen perquè
sempre entrem en "borderless desktop" (cobrint el monitor on viu la finestra).
2026-05-20 20:12:33 +02:00
JailDesigner 20cfadeb0b fix(viewport): deslligar el viewport de zoom_factor_ (aspect-fit per pantalla física)
El viewport del pase final es calculava com `Game::WIDTH * zoom_factor_`. Però
`zoom_factor_` està capat a `max_zoom_`, que es deriva de `display - 100px`
(marge per a decoracions). En fullscreen això deixa marc negre als 4 costats:
amb display 1920×1080 max_zoom_≈1.25 → viewport 1600×900 dins de 1920×1080.

Ara l'escala es calcula directament de la finestra física actual com a
aspect-fit (`min(curW/1280, curH/720)`), de manera que el viewport sempre
omple un eix i lletraboxeja l'altre, independentment del zoom_factor_. El
zoom_factor_ continua dimensionant la finestra en mode windowed (F1/F2).
2026-05-20 20:10:10 +02:00
JailDesigner cf4fbf7153 Merge branch 'refactor/code-review-cleanup'
Atac sistemàtic al CODE_REVIEW.md generat tras tancar el cicle de lint.
10 hallazgos del audit + 3 side-roads del hook, en 18 commits atòmics.

Hallazgos del audit cerrats:
- #1   Scene::init() lifecycle (fusionat al ctor de GameScene)
- #11  Ship::isAlive/isHit/isActive consolidats en isActive()
- #16  Rotation3D mort (eliminat struct + paràmetre + apply3dRotation)
- #18  ShapeLoader::resolvePath + BASE_PATH morts
- #21  Options::physics/audio/gameplay morts (cap reader en runtime)
- #22+#30  defaults.hpp partit en 15 subfitxers + umbrella
- #24  aliases morts de game/constants.hpp (MARGIN_*, VELOCITAT*)
- #25  Defaults::Physics::*_SPEED legacy del Pascal
- #28  inversió de dependència core→game per a Options:
       Config::EngineConfig (POD) viu a core/config/, els sistemes
       (Director, SDLManager, DebugOverlay, Input) reben referència
       injectada. La capa YAML viu a game/config_yaml.{hpp,cpp}
       (renomenat des d'Options).
- #34  doble inicialització d'enemies_ a GameScene
- #37  Director::run() ja no estàtica (lateral de #28)

Out of scope (per un hallazgo separat):
- core/system/director.cpp encara inclou game/scenes/*.hpp;
  cal factory pattern per a escenes.

Side-roads del hook:
- relative path a cppcheck del pre-commit
- alineació amb --suppress=useStlAlgorithm de make cppcheck
- std::ranges::fill surfat per cppcheck a GameScene ctor

Verificat: compila clean, clang-tidy + cppcheck zero hits nous
(32 NOLINTs preexistents igual que abans).
2026-05-20 19:58:14 +02:00
JailDesigner 329ae7a38e refactor(#28): renombrar Options → ConfigYaml + netejar aliases
Pas 7 final del hallazgo #28. La capa de game/options havia esdevingut
exclusivament una capa de persistència YAML que llegia i escrivia
Config::EngineConfig. El nom "Options" no reflectia bé aquest rol.

Canvis:

- Renomenats fitxers: game/options.{hpp,cpp} → game/config_yaml.{hpp,cpp}
  (preservant la història de git via mv).
- Renomenat namespace: Options → ConfigYaml.
- Esborrades del .hpp les referències-alias inline (window, rendering,
  player1, player2, keyboard_controls, gamepad_controls, console) que
  ja no tenien call-sites externs (només existien per a la transició).
  El .hpp ara només exposa engine_config + version + path + funcions.
- A config_yaml.cpp s'introdueixen aliases internes (anonymous namespace)
  per mantenir llegible el codi de la implementació, sense exposar-les.
- Actualitzat main.cpp per a usar ConfigYaml::*.
- Actualitzats els comentaris stale a sdl_manager.hpp, director.hpp,
  engine_config.hpp i audio.hpp.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 19:47:18 +02:00
JailDesigner 41ce3fece5 refactor(#28): Director rep EngineConfig + ConfigPersistence, main orquestra
Pas 5/N del hallazgo #28.

Director deixa d'incloure game/options.hpp i les seves crides a
Options::*. El seu ctor accepta ara:
- Config::EngineConfig& cfg     → la struct runtime (window, console, ...).
- Config::ConfigPersistence     → 4 lambdes (init/set_path/load/save)
  que delegen la persistència a la capa concreta (game/Options::*).

Cap més referència a Options:: ni a "game/..." dins del Director:
- cfg_->* substitueix tot Options::* (window, console, player1/2,
  rendering, engine_config).
- persistence_.{init,save,load,set_path} substitueix les funcions
  d'I/O de YAML.

run() i checkProgramArguments deixen de ser estàtics (necessiten
accés a cfg_ i persistence_). Això també desfà el smell del
hallazgo #37 (Director::run estàtic que llegia estat d'instància).

main.cpp queda com a orquestrador: construeix la struct
ConfigPersistence amb lambdes que enllacen amb Options::* i la
injecta al Director.

Afegit: Config::ConfigPersistence a engine_config.hpp.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 19:40:52 +02:00
JailDesigner fdd34eb943 refactor(#28): SDLManager rep Config::EngineConfig + on_persist callback
Pas 4/N del hallazgo #28.

SDLManager deixa d'incloure game/options.hpp. El ctor accepta ara una
Config::EngineConfig& (per llegir/mutar window i rendering) i un
opcional std::function<void()> on_persist callback.

Canvis funcionals:
- Es mantenen les mutacions de window.{width,height,zoom_factor,fullscreen}
  però ara sobre cfg_->window en lloc d'Options::window. Comportament
  idèntic perquè Options::window és un alias a engine_config.window.
- toggleVSync deixa de cridar Options::saveToFile() directament i
  invoca on_persist_ si està connectat. El Director li passa una lambda
  que fa la persistència (mantenint sdl_manager agnòstic).
- initWindowAndGpu (free function) rep el vsync inicial per paràmetre.
- Eliminat el ctor per defecte (SDLManager()) que no era cridat des de
  cap call-site del projecte.

Cleanup preexistent surfat per clang-tidy en treure el ctor default:
- finestra_, max_width_, max_height_, max_zoom_ passen a tindre
  default member initializers; eliminat el seu ctor mem-init redundant.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 19:35:35 +02:00
JailDesigner d118218662 refactor(#28): Input rep Config::PlayerBindings per paràmetre
Pas 3/N del hallazgo #28.

Input deixa d'incloure game/options.hpp. Els antics applyPlayerXFromOptions
es renombren a applyPlayerXBindings(const Config::PlayerBindings&) i
reben els bindings per paràmetre en lloc de llegir-los del global
Options::*. El Director hi passa Options::player1/2 als call-sites.

Esborrats applyKeyboardBindingsFromOptions i applyGamepadBindingsFromOptions
que no eren cridats per ningú (dead code aprofitat).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 19:30:55 +02:00
JailDesigner 2f0b148380 build: alinear cppcheck del hook amb el de make cppcheck
Afegit --suppress=useStlAlgorithm al hook, que ja estava al
target cppcheck de CMakeLists.txt:297. La regla és sorollosa
(suggereix std::find_if/std::any_of/std::transform a qualsevol
raw loop que es podria fer més curt) i el projecte ja va decidir
desactivar-la a nivell de pasada completa.

Segon desencontre entre el hook i el target CMake (el primer va
ser el -I absolut vs relatiu). Mantenim el hook i make cppcheck
coherents per no fer veure problemes que no n'hi ha.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 19:30:38 +02:00
JailDesigner ecb41cbc3a refactor(#28): DebugOverlay rep Config::RenderingConfig per referència
Pas 2/N del hallazgo #28.

DebugOverlay deixa d'incloure game/options.hpp i passa a rebre un
const Config::RenderingConfig& en el seu constructor. El Director li
passa Options::rendering (que ja és un alias d'engine_config.rendering).

Eliminat: include "game/options.hpp" des de core/system/debug_overlay.cpp.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 19:25:01 +02:00
JailDesigner 5f6d51b6cb refactor: introduir Config::EngineConfig com a struct POD a core/
Pas 1/N del hallazgo #28. Sense canvi de comportament:

Nou: source/core/config/engine_config.hpp
- Defineix Config::EngineConfig (POD) amb les sub-structs WindowConfig,
  RenderingConfig, KeyboardBindings, GamepadBindings, PlayerBindings i
  el flag console.
- Sense singletons ni virtuals; la inversió real es fa en commits
  posteriors injectant Config::EngineConfig& per constructor.

Modificat: source/game/options.hpp
- Elimina les struct definitions locals (Window, Rendering, ...).
- Afegeix Options::engine_config (única font de veritat).
- Conserva Options::window, Options::rendering, player1, player2,
  keyboard_controls, gamepad_controls i console com a referències
  inline a camps d'engine_config. Cost runtime zero, callsites
  existents no requereixen cap canvi.

Hallazgo #28 de CODE_REVIEW.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 19:24:06 +02:00
JailDesigner aa0abd9ae1 refactor: partir defaults.hpp en source/core/defaults/*.hpp (umbrella)
defaults.hpp tenia 527 línies amb 17 namespaces de dominis distints
(Window, Game, Zones, Entities, Palette, Ship, Physics, Math,
Brightness, Rendering, Audio, Music, Sound, Controls, Enemies, Title,
FloatingScore). 22 .cpp/.hpp l'incloïen, així que tocar una constant
forçava recompilar pràcticament tot.

Es divideix en 15 subfitxers (un per namespace, fusionant Music/Sound
a audio.hpp i unificant els dos blocs Game duplicats en un sol):

  defaults/window.hpp          defaults/audio.hpp
  defaults/game.hpp            defaults/controls.hpp
  defaults/zones.hpp           defaults/enemies.hpp
  defaults/entities.hpp        defaults/title.hpp
  defaults/palette.hpp         defaults/floating_score.hpp
  defaults/ship.hpp            defaults/math.hpp
  defaults/physics.hpp         defaults/brightness.hpp
  defaults/rendering.hpp

Cross-deps explícites (#include en lloc d'order-of-declaration):
  zones.hpp -> game.hpp        (per Game::WIDTH/HEIGHT)
  enemies.hpp -> entities.hpp  (per SHIP_RADIUS)
  title.hpp -> game.hpp, math.hpp + <cmath>

defaults.hpp queda com a umbrella que inclou els 15 subfitxers. Els
22 includers existents no requereixen cap canvi. Codi nou pot
incloure el subfitxer concret per millorar la compilació incremental.

Hallazgos #22 i #30 de CODE_REVIEW.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 18:45:10 +02:00
JailDesigner f777017460 refactor: esborrar Defaults::Physics::{ENEMY,BULLET}_SPEED i VELOCITY_SCALE
Constants legacy heretades del Pascal, en unitats/frame, que la
migració a SDL3 va deixar sense ús real:
- ENEMY_SPEED i BULLET_SPEED només es llegien des d'Options::physics
  (esborrat al #21) i des de Constants::VELOCITAT/VELOCITAT_MAX
  (esborrat al #24). Ara amb zero callers.
- VELOCITY_SCALE no tenia callers (les velocitats efectives es
  calculen a Bullet::BULLET_SPEED = 140 px/s i a
  Defaults::Enemies::{Pentagon,Cuadrado,Molinillo}::VELOCITAT).

S'ajusta el comentari del namespace per reflectir que ara conté
només la física del control de la nau.

Hallazgo #25 de CODE_REVIEW.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 18:27:38 +02:00
JailDesigner a0c1c8342f refactor: esborrar aliases morts de game/constants.hpp (#24)
Esborrats:
- Constants::MARGIN_LEFT/RIGHT/TOP/BOTTOM (zero callers; tots els
  call-sites llegeixen Defaults::Zones::PLAYAREA directament).
- Constants::VELOCITAT i VELOCITAT_MAX (zero callers; eren els últims
  lectors de Defaults::Physics::ENEMY_SPEED/BULLET_SPEED).

Es mantenen MAX_ORNIS, MAX_BALES (sí usats a game_scene.hpp) i PI,
més els helpers de zona.

Habilita el hallazgo #25 (eliminar Defaults::Physics::ENEMY_SPEED /
BULLET_SPEED / VELOCITY_SCALE) — ja sense lectors.

Hallazgo #24 de CODE_REVIEW.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 18:18:12 +02:00
JailDesigner 11e9d6569b refactor: eliminar Options::physics/audio/gameplay (codi mort)
Aquestes tres seccions s'estaven carregant del YAML, parsejant,
validant i escrivint, però cap d'elles tenia consumidor en runtime:
- Options::physics: l'únic call-site era un std::cout informatiu a
  director.cpp:109. Ship/Enemy/Bullet llegeixen Defaults::Physics
  directament.
- Options::audio: explícitament desacoblat (audio.hpp:22-25) — la
  font de configuració era Defaults::Audio via Audio::Config.
- Options::gameplay: zero readers. Els arrays són compile-time.

Esborrats:
- Structs Physics/Gameplay/Music/Sound/Audio i les globals.
- Defaults a init(), helpers loadXxxConfigFromYaml, secció escrita
  a saveToFile, crides al loadFromFile.
- La línia "Física: rotation=..." del console output del Director.

Es manté Options::window i Options::rendering (sí utilitzats).

Hallazgo #21 de CODE_REVIEW.md (opció a: borrar).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 18:07:27 +02:00
JailDesigner e4b6d2df6a build: corregir cppcheck del pre-commit (path relatiu)
Amb -I "\$REPO_ROOT/source" (path absolut), cppcheck no resolia bé el
<cstdint> i emetia un syntaxError fals sobre les capçaleres del tipus
"enum class X : std::uint8_t {" (afecta scene_context.hpp i d'altres
que tenen enums tipats).

El bug estava latent des del commit c45e524 ("clang-tidy --fix
mecánico (... enum size)"), que va afegir els underlying-types als
enums. Cap commit posterior va tocar fitxers que els inclogueren,
així que ningú l'havia activat fins ara.

Resolt amb path relatiu (els git hooks corren sempre des del repo
root, així que "source" és suficient).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 18:06:51 +02:00
JailDesigner 97c98272c9 refactor: consolidar Ship::isAlive/isHit/isActive en isActive()
Els tres mètodes retornaven el mateix bool a partir d'is_hit_:
  isActive() = !is_hit_   (override de Entity)
  isAlive()  = !is_hit_
  isHit()    =  is_hit_

Eren tres formes diferents de preguntar el mateix, repartides sense
criteri pels call-sites (collision_system, game_scene). Conservem
isActive() perquè és l'override polimòrfic d'Entity i esborrem els
altres dos. Actualitzats els 5 call-sites externs.

Hallazgo #11 de CODE_REVIEW.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 17:37:37 +02:00
JailDesigner e1d6cd1bb9 refactor: fusionar GameScene::init() al ctor (coherent amb Scene)
L'interfície Scene només declara handleEvent/update/draw/isFinished.
GameScene::init() era un mètode públic addicional que ningú (ni el
Director) cridava externament: només el propi ctor el cridava al
final. El comentari del header ("llamado por Director tras crear la
escena") era fals: el Director mai l'invoca.

TitleScene i LogoScene ja inicialitzen tot al ctor sense exposar
init(). Aquesta diferència trencava l'expectativa del lifecycle.

Movem tot el cos de init() al ctor i esborrem la declaració i la
definició. Aprofitem per:
- Eliminar el guard "if (!stage_config_)" que pressuposava re-init,
  cas que mai s'arribava a donar.
- Treure el comentari DEPRECATED sobre spawn_position_ (residu).

Hallazgo #1 de CODE_REVIEW.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 17:25:02 +02:00
JailDesigner e3b0958d10 refactor: eliminar doble inicialització d'enemies_ a GameScene
El ctor de GameScene ja construïa cada Enemy amb el renderer, però
init() (cridat des del propi ctor) tornava a assignar
enemies_[i] = Enemy(sdl_.getRenderer()) sobre la mateixa instància.
Treball perdut, a més d'incoherent amb ships_ i bullets_, que no es
reassignen a init() sinó que es limiten a init()/addBody.

Eliminem la reassignació i deixem només setShipPosition i addBody,
alineat amb la resta d'entitats.

Hallazgo #34 de CODE_REVIEW.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 17:11:47 +02:00
JailDesigner 88bb6afab1 refactor: convertir loops del ctor de GameScene a std::ranges::fill
Cppcheck (style: useStlAlgorithm) marcava els raw loops d'assignació
sobre std::array com a candidats clars per std::fill/std::generate.
Amb fill només es construeix la temporal una vegada i es copia a cada
element, en lloc de construir N temporals.

Preexistent, no introduït per cap commit recent, però el hook ho
demanava en tocar el fitxer. Es resolt el root cause en lloc de
suprimir.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 17:10:59 +02:00
JailDesigner 707fd29b97 refactor: eliminar Rotation3D i el seu camí de codi (codi mort)
L'struct Rotation3D, la funció apply3dRotation i el paràmetre opcional
rotation_3d de renderShape mai s'activaven en cap caller:
- Ship, Enemy i Bullet passaven explícitament nullptr.
- Title scene, logo scene, starfield, vector_text i ship_animator
  usaven el default nullptr (set els 7 callers).

CLAUDE.md descriu un sistema 3D del title screen que ja no està viu —
el comentari en ship_animator.cpp aclareix que la perspectiva s'ha
bakeat dins de la shape, així que la rotació dinàmica era residu
històric.

Esborrats: struct Rotation3D + ctors + hasRotation(), apply3dRotation(),
la branca rotation_3d a transformPoint() i el seu paràmetre, el
paràmetre rotation_3d de renderShape, i els arguments nullptr als
3 callers d'entitats.

Hallazgo #16 de CODE_REVIEW.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 16:50:03 +02:00
JailDesigner 682c27c07c refactor: eliminar ShapeLoader::resolvePath i BASE_PATH (codi mort)
Cap caller invocava resolvePath fora de la seua pròpia definició.
A més, BASE_PATH apuntava a "data/shapes/" mentre que load() ja
construeix el path amb el prefix "shapes/" directament — el helper
mai s'hauria activat encara que es cridara.

Hallazgo #18 de CODE_REVIEW.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 16:37:07 +02:00
JailDesigner 9e54dde490 docs: añadir CODE_REVIEW.md con auditoría arquitectónica (40 hallazgos)
Reporte completo de la pasada de revisión arquitectónica realizada por
el subagente Plan tras cerrar el ciclo de lint. Organiza los 40
hallazgos en 8 áreas (escenas, sistemas, entidades, renderizado,
configuración, naming, headers, bugs latentes), cada uno con prioridad,
tipo (estructural/opinable), file:line, problema, propuesta y esfuerzo
estimado.

Incluye:
- Top picks de bugs latentes y limpieza con impacto
- Lista de hallazgos que requieren verificación profunda
- Lista de hallazgos opinables (potencialmente rechazables)
- Resumen de lo ya resuelto en chore/lint
- Plan de ataque sugerido para iterar

Permite continuar el code review en otro equipo sin perder el contexto.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 16:13:18 +02:00
JailDesigner 15bd480d4c Merge branch 'chore/lint': frame loop al Director, debug overlay, copyrights, lint a 0
Squash conceptual de la rama chore/lint, mergeada con --no-ff para
preservar la historia de los 8 commits del trabajo de linting y refactor:

- efbf245 cppcheck (25 hits) + compiler warnings
- c45e524 tidy --fix mechanical (trailing/init/auto/enum-size/starts-with)
- 424d0d2 bugs reales + uint8_t enums + use-equals-default
- 1214599 helpers file-static y constexpr locales traducidos al inglés
- c80212a locales (constants + const-ref vars)
- 6d0df85 47 métodos privados → camelBack + traducidos
- 4e5ab6b 20 convert-to-static
- bbbb8d4 rename públicos al inglés + refactor cognitive-complexity + unused-includes

Resultado final: cppcheck 0 hits, clang-tidy 0 warnings visibles,
3 NOLINT únicos justificados (stb_vorbis externo + static class member
con sufijo `_`). También se introdujo en la rama:

- Plan A: frame loop al Director con interfaz Scene
- Debug overlay (F11) con FPS+VSync
- Limpieza de copyrights a "© 2026 JailDesigner"

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 14:00:39 +02:00
JailDesigner bbbb8d47ae Lint: rename públicos al inglés + refactor cognitive-complexity + unused-includes
Identifier-naming: rename de métodos públicos y cross-file al inglés
(camelBack), traducción de campos y locales en el proceso (TitleShip,
StageManager, SpawnController, ShipAnimator, helpers de PlayArea, etc.).

Refactor por cognitive-complexity (>25): GameScene::draw (59→3) con 9
helpers de estado, PhysicsWorld::resolveBodyCollisions (35→5) extrayendo
resolveBodyPair, Options::load{Window,Physics,Audio}ConfigFromYaml
(32/49/57→5/2/3) con templates readField, TitleScene::update (68→4) con
5 sub-pasos por estado + handleSkipInput/handleStartInput +
triggerExitForJoinedPlayers, DebrisManager::explode (39→3) con
extractSegments/spawnDebris/applyAngularVelocity/applyVisualRotation.

use-anyofallof: bucles → std::ranges::any_of/all_of en Input,
ShipAnimator y SpawnController.

readability-static-accessed-through-instance: Director::run y
VectorText::getTextWidth/Height invocados por clase.

readability-convert-member-functions-to-static: ResourcePack::decryptData.

unused-includes: eliminación de <utility>, <cstdint>, <vector>,
<iostream>, defaults.hpp y otros no usados directamente en headers y
unidades de traducción. Restablecido core/defaults.hpp en title_scene.cpp
(falsa "unused" del header).

Bug fix: eliminado isActive() duplicado en Bullet (redeclaración tras
rename de esta_activa→isActive que chocaba con el override de Entity).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 13:41:33 +02:00
JailDesigner 4e5ab6be1d Lint: convert-member-functions-to-static (20 hits)
Métodos privados que no consultan estado de la instancia pasan a 'static'
en la declaración del header. Las definiciones en el .cpp pierden el 'const'
trailing (incompatible con static). Cero callsites afectados: las
llamadas via 'this->method()' o sin qualifier siguen siendo válidas para
métodos estáticos.

Aplicado en:
- Shape: trim, startsWith, extractValue, parsePoints.
- VectorText: getShapeFilename, get_text_width, get_text_height.
- Pack: readFile, calculateChecksum, encryptData.
- DebrisManager: computeExplosionDirection.
- Enemy: attemptSafeSpawn.
- LogoScene / TitleScene: checkSkipButtonPressed (consulta Input singleton).
- SpawnController: get_enemics_vius.
- StageManager: processPlaying.
- ShipAnimator: updateEntering, updateFloating, updateExiting,
  configureShipP1, configureShipP2, computeOffscreenPosition.
- Director: run (los miembros executable_path_ / system_folder_ se fijan
  en el ctor y no se vuelven a leer en el loop principal).

Verificado previamente con grep que ningún '&Class::method' los usa como
function pointer (cambiar a estático cambiaría su tipo).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 12:22:37 +02:00
JailDesigner 6d0df85e5e Lint: rename de métodos privados (camelBack + traducción al inglés)
Tanda grande de identifier-naming: 47 métodos privados pasan de
snake_case (en su mayoría catalán/spanish) a camelBack inglés. Solo
afecta a sus archivos hpp+cpp; ningún símbolo cruza fichero (los
públicos quedan para una pasada manual con VS Code).

Renames por clase:

- ShapeLoader: resolve_path → resolvePath.
- VectorText: load_charset → loadCharset, get_shape_filename →
  getShapeFilename.
- Shape: starts_with → startsWith (cuidado de no tocar
  std::string::starts_with que también usaba), extract_value →
  extractValue, parse_center → parseCenter, parse_points → parsePoints.
- Starfield: inicialitzar_estrella → initStar, fora_area →
  isOutsideArea, calcular_escala → computeScale, calcular_brightness →
  computeBrightness.
- TitleScene: actualitzar_animacio_logo → updateLogoAnimation,
  inicialitzar_titol → initTitle.
- LogoScene: inicialitzar_lletres → initLetters, actualitzar_explosions
  → updateExplosions, canviar_estat → changeState,
  totes_lletres_completes → allLettersComplete.
- SpawnController: generar_spawn_events → generateSpawnEvents,
  seleccionar_tipus_aleatori → selectRandomType, spawn_enemic →
  spawnEnemy, aplicar_multiplicadors → applyMultipliers.
- ShipAnimator: actualitzar_entering/floating/exiting →
  updateEntering/Floating/Exiting, configurar_nau_p1/p2 →
  configureShipP1/P2, calcular_posicio_fora_pantalla →
  computeOffscreenPosition.
- GameScene: dibuixar_marges → drawMargins, dibuixar_marcador →
  drawScoreboard, disparar_bala → fireBullet, obtenir_punt_spawn →
  getSpawnPoint, unir_jugador → joinPlayer, dibuixar_continue →
  drawContinue, dibuixar_missatge_stage → drawStageMessage.
- StageLoader: parse_metadata/stage/spawn_config/distribution/multipliers/
  spawn_mode → parseMetadata/Stage/SpawnConfig/Distribution/Multipliers/
  SpawnMode, validar_config → validateConfig.
- StageManager: canviar_estat → changeState,
  processar_init_hud/level_start/playing/level_completed →
  processInitHud/LevelStart/Playing/LevelCompleted, carregar_stage →
  loadStage.

Métodos públicos y funciones libres (cross-file) quedan a propósito sin
tocar — los renombrará el usuario con la herramienta de rename de VS Code.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 11:55:21 +02:00
JailDesigner c80212adb9 Lint: rename de locales (constants + const-ref vars)
Tanda de identifier-naming de variables y constantes locales a funciones
o archivos. Ninguno cross-file (los símbolos públicos quedan para una
pasada manual con VS Code).

- audio_adapter.cpp: path → PATH (const local en 3 funciones).
- vector_text.cpp: symbols → SYMBOLS, char_width_scaled → CHAR_WIDTH_SCALED,
  char_height_scaled → CHAR_HEIGHT_SCALED, spacing_scaled → SPACING_SCALED
  (const locales en render/renderCentered/get_text_width).
- physics_world.cpp: acceleration → ACCELERATION (const local en update).
- constants.hpp::dins_zona_joc: point → POINT.
- game_scene.cpp:
  - stepGameOver: game_over_text → GAME_OVER_TEXT.
  - dibuixar_marcador: scale/spacing → SCALE/SPACING (const), y la ref
    local 'scoreboard' (const SDL_FRect&) → 'scoreboard_zone' para no
    colisionar con Defaults::Zones::SCOREBOARD (las refs no son
    "constant" según el .clang-tidy y deben ser lower_case).
  - dibuixar_missatge_stage: max_width → MAX_WIDTH (const local).
  - dibuixar_continue: continue_text/counter_str/continues_text →
    UPPER_CASE.
- title_scene.cpp::draw (sección MAIN): spacing → SPACING, main_text →
  MAIN_TEXT, escala_main → MAIN_SCALE.
- shape_renderer.cpp: const Vec2& SHAPE_CENTRE → shape_centre (es ref,
  no constant).
- collision_system.cpp: const Vec2& POS_ENEMIC → enemy_pos (ref + traducción).
- init_hud_animator.cpp: refs ZONA → zone (en 2 funciones), SCOREBOARD →
  scoreboard_zone (sin colisionar con Defaults::Zones::SCOREBOARD).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 11:50:58 +02:00
JailDesigner 1214599c4c Lint: rename de helpers file-static y constexpr locales
Tanda local de identifier-naming: ningún símbolo cross-file, todo
contenido en su propio TU. De paso traduce los catalán/spanish a inglés
allá donde aplica.

- shape_renderer.cpp: apply_3d_rotation → apply3dRotation, transform_point
  → transformPoint, perspective_factor → PERSPECTIVE_FACTOR (constexpr).
- debris_manager.cpp: transform_point → transformPoint (otro file-static
  con el mismo nombre, no comparte símbolo con shape_renderer).
- logo_scene.cpp: calcular_progress_letra → computeLetterProgress.
- vector_text.cpp: char_width/char_height → BASE_CHAR_WIDTH/BASE_CHAR_HEIGHT
  (el sufijo BASE_ evita el conflicto con la macro CHAR_WIDTH de Windows
  headers que clang-tidy detectó).
- floating_score_manager.cpp::draw: constexpr scale/spacing → SCALE/SPACING.
- game_scene.cpp::dibuixar_missatge_stage: escala_base/spacing →
  BASE_SCALE/SPACING (constexpr locales).
- game_scene.cpp::dibuixar_continue: constexpr spacing → SPACING.
- game_scene.cpp en stepGameOver: constexpr scale/spacing → SCALE/SPACING.
- ship_animator.cpp::actualizar_exiting: constexpr Vec2 punt_fuga →
  VANISHING_POINT.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 11:45:50 +02:00
JailDesigner 424d0d2b89 Lint: bugs reales + enums uint8_t + use-equals-default
Resuelve la categoría de findings de tidy que son bugs reales o cambios
de tipo concretos, no transforms automáticos:

Bugs reales (bugprone-* y clang-diagnostic-*):

- bugprone-empty-catch en postfx_config.cpp: el catch silencioso del
  parser RGB era intencional (fallback a defaults si el array no parsea
  como int). Marcado con @INTENTIONAL (keyword ya configurado en
  .clang-tidy via bugprone-empty-catch.IgnoreCatchWithKeywords) y
  comentario ampliado explicando la decisión.

- clang-diagnostic-unused-private-field en Starfield: el campo
  'densitat_' se asignaba en el constructor pero nunca se leía. El
  parámetro 'densitat' se reparte directamente en las CapaConfig al
  construir, así que el field era código muerto. Eliminado.

- bugprone-branch-clone en vector_text.cpp: el switch de
  get_shape_filename tenía dos grupos consecutivos (dígitos 0-9 y
  mayúsculas A-Z) con cuerpo idéntico. Fusionados en un único case con
  comentario explicando que comparten path porque la shape se llama
  igual que el caracter.

- bugprone-switch-missing-default-case en Input::handleEvent: el switch
  manejaba solo SDL_EVENT_GAMEPAD_ADDED/REMOVED y caía por fall-through
  a un return {} fuera del switch. Añadido default: explícito con
  comentario sobre qué hace Input vs el resto del sistema.

- bugprone-implicit-widening-of-multiplication-result en
  GameScene::bullets_ y Collision::Context::bullets: 'MAX_BALES * 2'
  es int*int y se widening implícitamente a std::size_t para el
  template arg de std::array. Cast explícito a size_t en ambos sitios.

Otros mecánicos:

- performance-enum-size: 10 enums sin tipo subyacente pasaron a
  ': std::uint8_t' (PrimitiveType, InputAction, Mode, SceneType,
  Option, AnimationState, TitleState, ModeSpawn, EstatStage,
  ShipState). #include <cstdint> añadido donde faltaba.

- modernize-use-equals-default en SpawnController: el ctor por
  defecto tenía cuerpo vacío ({}). Pasado a '= default;'.

Cero supresiones. La única "marca" es @INTENTIONAL en el empty-catch,
que es el mecanismo configurado en el .clang-tidy del proyecto para
distinguir intencionales de accidentales.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 11:23:49 +02:00
JailDesigner c45e524109 Lint: clang-tidy --fix mecánico (trailing return, default member init, auto, enum size)
Pase automático de clang-tidy --fix sobre el conjunto de checks que son
puro transform de sintaxis y no rompen API. Invocado con
--format-style=none para que clang-tidy NO arrastre clang-format sobre
las líneas tocadas (evita la regla NamespaceIndentation: All del
.clang-format reformateando solo trozos del archivo).

Checks aplicados:

- modernize-use-trailing-return-type (193 hits): 'int foo()' →
  'auto foo() -> int'. Estilo coherente con la convención del proyecto.
- modernize-use-default-member-init (36 hits): inicialización de
  miembros pasa de la lista del constructor a la declaración. Reduce
  duplicación cuando hay varios constructores con los mismos defaults.
- modernize-use-auto (6 hits): tipos largos sustituidos por auto donde
  el tipo es evidente del contexto (new T, dynamic_cast, etc).
- modernize-use-starts-ends-with (2 hits): s.rfind(x) == 0 →
  s.starts_with(x), aprovechando C++20.
- performance-enum-size (10 hits): enums pequeños declaran tipo
  subyacente (uint8_t / similar) para reducir tamaño y precisar layout.

NO aplicado en este pase (riesgo de cambios semánticos o de API):
- readability-identifier-naming (renames pueden romper callsites parciales)
- readability-convert-member-functions-to-static (cambia firma)
- readability-use-anyofallof (reescribe loops, side effects)
- readability-function-cognitive-complexity (requiere refactor manual)
- bugs reales (bugprone-*, clang-diagnostic-*) → uno a uno

Cambios manuales asociados:
- SDLManager::clear() ahora devuelve bool: propaga el resultado de
  beginFrame al caller para que Director::runFrameLoop salte
  draw+present cuando la swapchain no esté disponible (ventana
  minimizada). Antes la función ignoraba el [[nodiscard]] del
  beginFrame y los vértices se acumulaban en el batch sin nadie que
  los consumiera.
- vector_text.cpp: borrada la línea suelta "// Test pre-commit hook"
  que quedó como cruft.

clang-tidy crashea en LLVM 19.1 con performance-noexcept-move-constructor
(recursión infinita en ExceptionSpecAnalyzer al procesar std::set);
check deshabilitado en .clang-tidy con comentario explicativo.

Build limpio, smoke test OK.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 10:59:56 +02:00
JailDesigner efbf2457a1 Lint: inicializadores + retornos const-ref + warnings preexistentes
Primera tanda mecánica sobre el lint pendiente. Arregla la causa raíz, no
silencia diagnósticos. Detalle por categoría:

- Uninit members (cppcheck warnings) → inicializadores en declaración:
  Bullet (esta_, owner_id_, grace_timer_), Enemy (drotacio_, rotacio_,
  esta_, type_, tracking_timer_, ship_position_, tracking_strength_,
  direction_change_timer_, timer_invulnerabilitat_), Ship (is_hit_,
  invulnerable_timer_), Shape (escala_defecte_) y TitleShip (todos los
  miembros del struct, que viven dentro de un std::array<,2>).

- returnByReference (cppcheck performance) → return const T&:
  Shape::getName, ResourceLoader::getBasePath. De paso, Shape::get_nom
  se renombra a getName y get_num_primitives a getNumPrimitives para
  cumplir la convención camelBack del proyecto (lint del .clang-tidy).

- useInitializationList (cppcheck performance) →
  Starfield::shape_estrella_ pasa a la lista de inicialización (reordenada
  según la declaración para no disparar -Wreorder-ctor).

- noExplicitConstructor (cppcheck style) → explicit en ctores de 1 arg:
  Bullet(Renderer*), Enemy(Renderer*), Ship(Renderer*,...) y VectorText(Renderer*).

- variableScope (cppcheck style) → en vector_text.cpp se elimina la
  variable 'c' intermedia y se usa el literal '\\xA9' directamente en el
  único punto donde se necesita.

- constParameterReference (cppcheck style) → drawScoreboardAnimated pasa
  el VectorText por const ref (la API render/renderCentered es const).

- Warnings preexistentes del compilador (resueltos de paso):
  - stage_config.hpp: stage_id <= 255 sobre uint8_t era siempre true; se
    elimina la comparación redundante y se explica con comentario.
  - director.cpp: 'struct stat st = {.st_dev = 0};' disparaba
    -Wmissing-field-initializers; pasa a 'struct stat st{};' (zero-init
    completo, robusto a las variantes específicas del SO).
  - game_scene.cpp: stepDeathSequence devolvía un bool [[nodiscard]] que
    el caller ignoraba; el valor era puramente interno. Cambiada la
    firma a void.

- cppcheck: añadido --suppress=useStlAlgorithm. Las 26 sugerencias
  'Consider using std::any_of/find_if/count_if' son cosméticas y no
  aportan claridad sobre las raw loops actuales.

- .clang-tidy de source/core/audio/ eliminado: deshabilitaba todos los
  checks en ese subdirectorio por dependencia de jail_audio.hpp, pero
  impedía ejecutar 'make tidy' (clang-tidy aborta con "no checks
  enabled" al primer archivo del directorio). El proyecto pasa a usar
  el mismo patrón de CCAE: solo source/external/ y source/legacy/
  quedan fuera del lint.

- lint-reports/ añadido a .gitignore. Carpeta donde 'make tidy' y
  'make cppcheck' vuelcan su salida completa para inspección posterior.

Build limpio, cero warnings activos.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 10:29:36 +02:00
JailDesigner d3cb93bdba Merge branch 'chore/copyrights'
Limpieza completa de copyrights:
- Pantalla de título: una sola línea "© 2026 JAILDESIGNER" + logo
  JAILGAMES pequeño encima.
- Cabeceras de todos los archivos .cpp/.hpp/.h/.in en source/
  unificadas a "// © 2026 JailDesigner".
- data/, tools/, release/macos/Info.plist y ejemplos en CLAUDE.md
  alineados al mismo formato.
- Project::COPYRIGHT_ORIGINAL y Project::COPYRIGHT_PORT eliminados de
  project.h.in (ya no se referenciaban).
- Defaults::Title::Layout gana JAILGAMES_SCALE y JAILGAMES_COPYRIGHT_GAP.

Las menciones narrativas sobre el origen Pascal 1999 en README.md y
CLAUDE.md se mantienen como historia del proyecto.
2026-05-20 10:01:45 +02:00
JailDesigner e8c253d953 Copyrights: barrido mecánico fuera de source/
Misma normalización aplicada al resto del árbol: cabeceras de data/
(shapes y stages), tooling, plist de macOS y los ejemplos del CLAUDE.md.
Todos pasan a "© 2026 JailDesigner".

Detalle:
- data/shapes/{ship3,star,enemy_pinwheel}.shp: cabeceras unificadas.
- data/stages/stages.yaml: cabecera unificada.
- tools/pack_resources/pack_resources.cpp: cabecera unificada.
- release/macos/Info.plist: NSHumanReadableCopyright actualizado.
- CLAUDE.md: snippets de PROJECT_COPYRIGHT, project.h y window title puestos
  al día (eran ejemplos con valores stale del esquema anterior).

Las menciones narrativas en README.md y CLAUDE.md sobre el origen Pascal
1999 se mantienen deliberadamente — son historia del proyecto, no
declaraciones de copyright. SDL3 vendoreado y source/legacy/ tampoco
se tocan.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 10:01:09 +02:00
JailDesigner b746578bc8 Cabeceras: unificar copyright a "© 2026 JailDesigner" en todo source/
Sustituye en bloque las cabeceras de los archivos por una sola línea de
copyright. Cero rastro de "Visente", "Sergi" o "1999" en el árbol del
proyecto. Se eliminan también las variantes "© 2025 Port a C++20", "© 2025
Port a C++20 con SDL3" y "© 2025 Orni Attack" (con todas sus colas
descriptivas como "Arquitectura de entidades" o "Sistema de física"), que
en este punto eran ruido histórico.

Aplicado con un par de sed (find -type f, excluyendo source/external y
source/legacy):

  1. \|^// © 1999 Visente i Sergi (versión Pascal)$|d
  2. s|^// © 2025 (Port a C++20.*|Orni Attack.*)$|// © 2026 JailDesigner|

Verificado: la única variante de cabecera tras el sweep es
"// © 2026 JailDesigner".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 09:51:46 +02:00
JailDesigner 8c251d2246 Title screen: copyright único + logo JAILGAMES encima
Sustituye las dos líneas de copyright (Pascal original 1999 + port 2025)
por una sola línea "© 2026 JAILDESIGNER" centrada en la posición de la
antigua primera línea. Encima, en el espacio liberado, se muestra el
logo vectorial JAILGAMES en pequeño (escala 0.25, las mismas letras
que usa LogoScene).

Cambios:
- CMakeLists.txt: PROJECT_COPYRIGHT pasa a "© 2026 JailDesigner".
  Eliminadas las variables intermedias PROJECT_COPYRIGHT_ORIGINAL y
  PROJECT_COPYRIGHT_PORT (ya no se referenciaban en otro sitio).
- project.h.in: fuera Project::COPYRIGHT_ORIGINAL y Project::COPYRIGHT_PORT.
- Defaults::Title::Layout: nuevas constantes JAILGAMES_SCALE (0.25) y
  JAILGAMES_COPYRIGHT_GAP (1.5% de la altura lógica) para el espaciado.
- TitleScene: nuevo helper inicialitzarJailgames() que carga las 9
  letras y las posiciona centradas justo encima de la línea de copyright.
  El bloque del pie del título sale del draw() a un dibuixarPeuTitol()
  para mantener la complejidad cognitiva por debajo del umbral del linter.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 09:46:38 +02:00
JailDesigner 89a9f06324 Merge branch 'rewrite/physics-gpu'
Reescritura completa de la capa de rendering y la arquitectura del juego.
Aportaciones principales por fases:

- Fase 1: rename masivo a CamelCase/camelBack (clang-tidy)
- Fase 2: resolución lógica 1280×720 (16:9)
- Fase 3: subsistema de audio importado de AEEA
- Fases 5/6: sistema de física vectorial; Ship/Enemy/Bullet sobre RigidBody
- Fase 7: migración atómica de SDL_Renderer a SDL3 GPU (Vulkan/Metal)
- Fase 8: paleta semántica por entidad y postpro completo (bloom + flicker
  + background pulse) configurable vía data/config/postfx.yaml
- Fase 9: extracción de sistemas de GameScene (collision, continue,
  init_hud_animator) y descomposición de update en sub-pasos
- Plan A: frame loop al Director con interfaz Scene común
- Debug overlay (FPS + VSync) toggleable con F11; título de ventana estático
2026-05-20 09:36:22 +02:00
JailDesigner 0573022b7c Debug overlay (FPS + VSync) toggleable con F11
Crea core/system/DebugOverlay como sistema global propiedad del Director
que muestra FPS y estado de VSync en la esquina superior izquierda usando
VectorText. Visible por defecto en builds debug, oculto en release; F11
alterna.

Cambios:

- Nuevo DebugOverlay con su propio contador de FPS interno (cadencia 0.5s).
  El cálculo que vivía en SDLManager::updateFPS se mueve aquí.
- Director construye el overlay una vez y lo pasa a runFrameLoop. F11 se
  intercepta directamente en el event loop del Director (no en
  GlobalEvents para no acoplar la firma a la presencia del overlay).
- Limpieza de SDLManager: fuera updateFPS, updateColors (era no-op desde
  Fase 8c), setWindowTitle (no se usaba) y los campos fps_*.
- Título de ventana estático estilo CCAE:
    © 2026 Orni Attack — JailDesigner
  Ya no se reescribe cada 0.5s con FPS y VSync; ese estado vive en el
  overlay.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 09:34:46 +02:00
JailDesigner 5e82dc880f Plan A: frame loop al Director, interfaz Scene común
Cada escena ahora implementa una interfaz Scene { handleEvent, update,
draw, isFinished } y el Director es quien posee el bucle de frames.
Antes había tres bucles casi idénticos duplicados en logo/title/game
con ~30 LOC cada uno; ahora hay uno solo en Director::runFrameLoop.

Cambios:

- Nueva interfaz core/system/scene.hpp (pura virtual).
- Cada escena hereda final + override de handleEvent/update/draw/
  isFinished. Los métodos privados que ya existían (update, draw,
  processar_events) pasan a públicos como override; processar_events
  se renombra a handleEvent.
- Director::run gestiona la transición entre escenas vía
  buildScene(type) → runFrameLoop(scene), ambas estáticas.
- isFinished() = context_.nextScene() != mi_tipo, así que la única
  vía de transición es context_.setNextScene().
- TitleScene tenía un bug latente: llamaba a setNextScene(GAME)
  prematuramente al entrar en PLAYER_JOIN_PHASE, lo que con el nuevo
  modelo habría saltado las animaciones de salida. Movido el
  setNextScene al final de BLACK_SCREEN, que es donde la transición
  ocurría de verdad (vía la variable global SceneManager::actual).
- LogoScene::draw llamaba a clear() y present() dentro del draw, una
  anomalía. Sacados al Director para que la composición sea uniforme.
- Eliminadas todas las escrituras a SceneManager::actual desde las
  escenas. El Director es ahora la única fuente que actualiza la
  variable global (sigue ahí para lecturas externas, por compatibilidad).

Net: -60 LOC reales (las escenas pierden ~25 cada una de boilerplate),
y queda un único punto de inyección para los overlays globales que
vienen en el siguiente paso del roadmap.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 09:25:56 +02:00
JailDesigner a7aecbadd1 Fase 8c: postpro (bloom + flicker + background) en SDL_gpu
Renderiza la escena de líneas a una textura offscreen y aplica un pase
final de postpro que compone la imagen al swapchain. El shader del
postpro hace tres cosas:

- Bloom: kernel gaussiano 5×5 con high-pass por luminancia. Configurable
  vía intensity, threshold y radius_px.
- Flicker: multiplicador global de brillo modulado por sin(time*freq).
  Sustituye al antiguo ColorOscillator CPU; eliminados oscillator.{hpp,cpp}
  y Defaults::Color. SDLManager::updateColors queda como no-op para no
  tocar las escenas que lo invocaban.
- Background pulse: color de fondo aditivo entre color_min y color_max,
  pulsando en el tiempo.

Parámetros expuestos en data/config/postfx.yaml y cargados con fkYAML.
Si el archivo falta o falla, se usan defaults built-in. UV.y invertida
en el vertex shader del postpro para compensar la convención de
muestreo de SDL_gpu/Vulkan (el line shader sigue con su ndc.y flip).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 08:52:03 +02:00
JailDesigner 6d7060ceb5 Fase 8a+b: paleta semantica de color por entidad
Cada entity declara su color de linea via parametro opcional. Cuando
alpha==0 el pipeline cae al color global del oscilador (compatibilidad
con el comportamiento anterior).

Defaults::Palette (defaults.hpp):
- SHIP        = blanco neutro
- BULLET      = verde laser
- PENTAGON    = azul "esquivador"
- QUADRAT     = rojo "tank"
- MOLINILLO   = magenta agresivo

Pipeline:
- linea(): parametro SDL_Color color (default {0,0,0,0}). En .cpp,
  fuente del color = color.a>0 ? color : g_current_line_color.
- render_shape(): parametro SDL_Color color que propaga a cada linea
  del shape.
- Debris: campo color en la struct; explode() recibe SDL_Color color
  y lo guarda en cada fragment; draw() lo pasa a linea().

Aplicacion:
- Ship::draw -> Palette::SHIP.
- Bullet::draw -> Palette::BULLET.
- Enemy::draw -> Palette::{PENTAGON,QUADRAT,MOLINILLO} segun type_.
- CollisionSystem detectBulletEnemy: debris hereda color del enemy.
- GameScene::tocado: debris hereda Palette::SHIP.

Smoke test xvfb OK.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 08:04:56 +02:00
JailDesigner 5c9f6e6613 Actualizar MIGRATION_PLAN.md tras cerrar Fase 9
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 07:58:24 +02:00
JailDesigner 808abb28ea Fase 9d: descomponer GameScene::update en sub-pasos privados
update() pasa de 339 LOC monolitico (cognitive complexity ~137) a
18 LOC orquestadores. Cada seccion logica vive en su propio metodo
privado con responsabilidad unica:

- stepPhysics(dt): physics_world.update + postUpdate.
- stepShootingInput(): SHOOT de P1/P2.
- stepMidGameJoin(): START de jugador inactivo o muerto sin vidas.
- stepContinueScreen(dt): wrapping del Systems::ContinueScreen +
  update de fondo. Devuelve true si frame debe terminar.
- stepGameOver(dt): timer final + transicion a TITLE. Devuelve true
  si frame debe terminar.
- stepDeathSequence(dt): death timer/respawn/transicion a CONTINUE.
- stepStageStateMachine(dt): despacha a runStage{InitHud,LevelStart,
  Playing,LevelCompleted} segun el estado actual.
- runCollisionDetections(): construye el Systems::Collision::Context
  y llama detectAll.

GameScene.cpp acumulado tras Fase 9 (a+b+c+d): 1429 -> 1015 LOC.
update() solo: 339 -> 18 LOC. Smoke test xvfb OK.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 07:57:36 +02:00
JailDesigner a4942fcbae Fase 9c: extraer InitHudAnimator de GameScene
GameScene::dibuixar_marges_animat, dibuixar_marcador_animat,
calcular_posicio_nau_init_hud y calcular_progress_rango (4 funciones,
~135 LOC) salen a Systems::InitHud en
source/game/systems/init_hud_animator.{hpp,cpp}.

Las funciones son puras (sin estado interno propio). API libre en
namespace:
- computeRangeProgress(global, init, end): normalizacion de la
  ventana de progreso de un elemento dentro del global 0..1.
- computeShipPosition(progress, final_position): interpola Y desde
  fuera de pantalla con ease_out_quad.
- drawBordersAnimated(renderer, progress): efecto pincel en 3 fases.
- drawScoreboardAnimated(text, scoreboard_text, progress): texto
  subiendo desde abajo.

GameScene inyecta lo que cada funcion necesita por parametro
(spawn point desde obtenir_punt_spawn, scoreboard desde
buildScoreboard). Sin estado mutable compartido.

GameScene.cpp acumulado tras 9a/9b/9c: 1429 -> 1043 LOC.
Smoke test xvfb OK.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 07:54:02 +02:00
JailDesigner 816bc02d9d Fase 9b: extraer ContinueSystem de GameScene
GameScene::actualitzar_continue, processar_input_continue y el
helper check_and_apply_continue_timeout (3 funciones, ~140 LOC) salen
a Systems::ContinueScreen en source/game/systems/continue_system.{hpp,cpp}.

API:
- struct Systems::ContinueScreen::Context: agrupa el estado mutable
  (state, counter, tick_timer, continues_used, game_over_timer,
  lives/score/hit_timer arrays, ships, match_config) y un callback
  get_spawn_point inyectado por GameScene.
- update(ctx, dt): avanza countdown automatico y transiciona a
  GAME_OVER si timeout.
- processInput(ctx): START revive jugador(es), THRUST/SHOOT acelera
  countdown.

Helpers privados (revivePlayer, checkAndApplyTimeout) en anonymous
namespace del .cpp para evitar contaminar el header.

GameOverState ahora con underlying type explicito (uint8_t) para
permitir forward-declaration limpia en continue_system.hpp.

dibuixar_continue y unir_jugador se quedan en GameScene (render y
gameplay normal, no parte del state machine).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 07:50:43 +02:00
JailDesigner 896a899b0f Fase 9a: extraer CollisionSystem de GameScene a modulo aparte
GameScene::detectar_col*_* (3 funciones de deteccion de gameplay,
~170 LOC) salen a Systems::Collision en
source/game/systems/collision_system.{hpp,cpp}.

API:
- struct Systems::Collision::Context: agrupa todo lo que las
  detecciones leen/modifican (ships, enemies, bullets, hit_timer,
  score, lives, debris, floating_score, match_config) y un callback
  on_player_hit para delegar la muerte del jugador.
- Funciones libres: detectBulletEnemy, detectShipEnemy,
  detectBulletPlayer y detectAll.

GameScene::update construye el Context y llama detectAll. La
funcion GameScene::tocado se inyecta via lambda. El cuerpo de update
queda mas legible y separa fisica de gameplay (lo decide el solver)
de fisica rigida (lo decide PhysicsWorld).

GameScene.cpp: 1429 -> 1274 LOC. Smoke test xvfb OK.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 07:47:42 +02:00
JailDesigner e98b87243b Actualizar MIGRATION_PLAN.md: cerrar 7a/7b/7c, pendiente validacion visual
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 14:13:29 +02:00
JailDesigner fa7da4ca58 Fase 7b+c: swap atomico a SDL3 GPU (Vulkan/Metal, sin SDL_Renderer)
El runtime de rendering pasa a SDL3 GPU. SDL_Renderer eliminado por
completo del proyecto: SDLManager posee un GpuFrameRenderer y todo
el resto del codigo habla con un Rendering::Renderer* opaco (alias
del GpuFrameRenderer).

Cambios principales:

- core/rendering/render_context.hpp: alias central
  `using Rendering::Renderer = GPU::GpuFrameRenderer;` — punto unico
  de indireccion entre el juego y el backend de dibujo.

- core/rendering/sdl_manager.hpp/cpp: deja de tener SDL_Renderer*;
  contiene un Rendering::Renderer gpu_renderer_. iniciar() ahora hace
  GpuDevice::init + pipeline; clear() llama beginFrame; present()
  llama endFrame. Letterbox se aplica via setViewport tras cada
  begin del render pass. toggleVSync() usa
  SDL_SetGPUSwapchainParameters.

- core/rendering/line_renderer.hpp/cpp: la firma cambia a
  `linea(Renderer*, x1,y1,x2,y2, brightness, thickness)`. La
  implementacion deja de usar SDL_RenderLine: empuja la linea como
  quad extrudido al batch del GpuFrameRenderer. Se anade un grosor
  global configurable via setLineThickness (default 1.5 px). Ya no
  se aplica transform_x/y porque el shader hace logical->NDC y el
  viewport hace el letterbox.

- gpu_frame_renderer: anade setViewport (aplicable mid-frame),
  setVSync (PRESENTMODE_VSYNC/IMMEDIATE) y applyViewport interno
  que re-aplica el viewport tras reabrir el render pass en flushBatch.

- Sed sweep masivo en 19 archivos: SDL_Renderer* -> Rendering::Renderer*
  en headers y .cpp de entities, effects, graphics y title. Los
  archivos solo propagan el puntero — solo line_renderer consume sus
  metodos. SDL_Renderer queda eliminado del proyecto.

Smoke test xvfb: backend Vulkan detectado, binario arranca, carga
todos los shapes/audio/title, TitleScene inicializa, termina limpio
con "Adeu!". stderr vacio. Validacion visual pendiente en hardware
real (xvfb VMware sin 3D no muestra el swapchain Vulkan).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 14:12:34 +02:00
JailDesigner ba6fd00b54 Fase 7a: infraestructura SDL3 GPU (dormida, sin tocar runtime)
Preparacion del pipeline GPU. Codigo nuevo aislado en
core/rendering/gpu/; el runtime sigue usando SDL_Renderer hasta
Fase 7b. Tras 7a el juego sigue funcionando identico.

Shaders (shaders/):
- line.vert.glsl: vertex shader, transforma de pixeles logicos a NDC
  via uniform buffer LineUniforms{viewport_w, viewport_h}.
- line.frag.glsl: pinta el color RGBA interpolado.

Build:
- CMakeLists.txt: step nuevo que compila *.glsl a build/shaders/*.spv
  con glslc. ALL depende del target 'shaders' para incluirlo en cada
  build. Falla en cmake config si glslc no esta instalado.

Wrappers C++ (source/core/rendering/gpu/):
- gpu_device.hpp/cpp: GpuDevice, claim del window, loadShader desde
  .spv. Backends solicitados: Vulkan + Metal (sin DirectX).
- gpu_line_pipeline.hpp/cpp: GpuLinePipeline. Vertex layout
  (vec2 pos + vec4 color), primitive TRIANGLELIST (lineas como
  quads), alpha blending estandar, sin culling ni depth.
- gpu_frame_renderer.hpp/cpp: GpuFrameRenderer, API alto nivel:
  beginFrame / pushLine / endFrame. Extrusion perpendicular en CPU
  por linea (thickness libre por linea). Un draw call por frame
  con vertex+index buffers transitorios.

Plan: 7b swap del SDL_Renderer al GpuFrameRenderer en SDLManager.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 14:01:34 +02:00
JailDesigner 9993b2d98c Fase 6e: migrar Bullet al sistema de fisica vectorial
Las balas pasan a ser cinematicas dentro del PhysicsWorld:
- body_.setMass(0.5), radius=0 (no colisionan fisicamente)
- disparar() setea body_.position + body_.velocity cartesiana (140 px/s)
- update() detecta salida del PLAYAREA via body_.position y desactiva
- postUpdate() sincroniza center_ desde body_.position
- desactivar() detiene el body para evitar deriva mientras inactiva

GameScene registra los bodies en init() y llama postUpdate(). El gameplay
sigue gestionando colisiones bullet-enemy/bullet-ship con check_collision
(el radio gameplay es BULLET_RADIUS=3, expuesto via getCollisionRadius).

Renames a camelBack (clang-tidy): get_owner_id->getOwnerId,
get_grace_timer->getGraceTimer.

MIGRATION_PLAN.md actualizado: Fase 6e cerrada, Fase 7 (SDL3 GPU) siguiente.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 13:50:17 +02:00
JailDesigner c50ca23135 Anadir MIGRATION_PLAN.md en raiz como referencia maestra
Documento que resume el estado de la migracion (rama
rewrite/physics-gpu), las fases completadas con sus commits, lo que
queda inmediato y donde estan las decisiones persistentes (memoria
del proyecto). Para sobrevivir compactaciones de contexto y permitir
reanudar la migracion en sesiones futuras sin perder el hilo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 13:42:04 +02:00
JailDesigner 27242f54fe Fase 6d: migrar Enemy al sistema de fisica vectorial
Segunda entidad migrada. Los enemigos (Pentagon, Quadrat, Molinillo)
ahora viven en el PhysicsWorld con velocidad vectorial. Las colisiones
entre enemigos quedan habilitadas automaticamente (novedad: antes no
se chocaban).

Cambios en enemy.hpp:
- Eliminado: float velocity_ (escalar)
- Eliminado: void mou() (lo hace el world)
- Anadido: override postUpdate()
- Anadido: helper privado setVelocityFromAngle(angle, speed)
- Anadido: direction_change_timer_ para zigzag periodico del Pentagon

Cambios en enemy.cpp:
- Constructor configura body_ (mass=5 default, radius=0 inactivo,
  restitution=1.0 elastico, sin damping)
- init() ajusta masa por tipo:
  * Pentagon: 5.0 (esquivador ligero)
  * Quadrat: 8.0 (tanque pesado)
  * Molinillo: 4.0 (agil rapido)
- init() setea body_.radius = ENEMY_RADIUS al spawn
- behaviorPentagon: zigzag por probabilidad temporal (0.8/s) en lugar
  de detectar paredes; el rebote contra muros lo hace PhysicsWorld
- behaviorQuadrat: tracking discreto cada TRACKING_INTERVAL — mezcla
  velocity actual con direccion al ship (LERP por tracking_strength)
- behaviorMolinillo: solo boost de rotacion visual cerca del ship;
  movimiento puramente lineal integrado por el world
- destruir() pone velocity=0, angular=0, radius=0
- postUpdate() sincroniza center_ desde body_.position
- setVelocity(speed) mantiene la direccion, cambia solo la magnitud

Renames a camelBack (.clang-tidy del proyecto):
- get_drotacio -> getRotationDelta
- get_base_velocity -> getBaseVelocity, get_base_rotation -> getBaseRotation
- set_ship_position -> setShipPosition
- set_velocity -> setVelocity, set_rotation -> setRotation
- set_tracking_strength -> setTrackingStrength
- get_temps_invulnerabilitat -> getInvulnerabilityTime
- actualitzar_animacio -> updateAnimation
- actualitzar_palpitacio -> updatePalpitation
- actualitzar_rotacio_accelerada -> updateRotationAcceleration
- comportament_pentagon/quadrat/molinillo -> behaviorPentagon/Quadrat/Molinillo
- calcular_escala_actual -> computeCurrentScale
- intent_spawn_safe -> attemptSafeSpawn
(callsites actualizados en spawn_controller y game_scene)

Cambios en GameScene:
- En init(): physics_world_.addBody(&enemy.getBody()) por cada slot
  (los inactivos tienen radius=0, no estorban)
- En update(): postUpdate() de cada enemy tras physics_world_.update

Cambios de comportamiento visibles esperados:
- Enemigos rebotan elasticamente contra paredes (restitution=1.0)
- Enemigos se chocan entre si (impulsos elasticos con masas distintas
  por tipo: Quadrat empuja mas, Molinillo rebota mas)
- Pentagon zigzag periodico en lugar de solo al chocar pared
- Molinillo: comportamiento mas predecible (linea recta)

Aviso: Bullet sigue con su movimiento ad-hoc (Fase 6e pendiente).

Smoke test xvfb OK. Validacion gameplay del usuario pendiente.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 13:41:05 +02:00
JailDesigner 2fe22ff911 Fase 6c: migrar Ship al sistema de fisica vectorial
Primera entidad migrada. La nave del jugador ya NO mantiene su propio
estado cinemático ad-hoc — toda la física vive en Entity::body_ y el
movimiento lo realiza Physics::PhysicsWorld.

Cambios en ship.hpp:
- Eliminado: float velocity_ (escalar, polar)
- Eliminado: void applyPhysics() (lo hace el world)
- Añadido: override postUpdate() para sincronizar center_/angle_
- getVelocityVector() ahora devuelve body_.velocity (Vec2 cartesiano)
- Nuevo getter getSpeed() = body_.velocity.length()
- setCenter() actualiza tanto el mirror como body_.position
- markHit() detiene el body_ (velocity = 0)

Cambios en ship.cpp:
- Constructor configura el body_:
  * mass = 10.0 (referencia para impulsos en choques)
  * radius = SHIP_RADIUS (12.0)
  * restitution = 0.6 (rebote moderado en paredes)
  * linear_damping = 1.5 s⁻¹ (fricción exponencial)
  * angular_damping = 0.0 (la rotación es por input, no inercial)
- init() resetea body_ a la posición/orientación nueva, velocity = 0
- processInput() ahora:
  * Rotación: modifica body_.angle directamente (no física)
  * Thrust: applyForce(direction * mass * ACCELERATION)
- update() solo gestiona timer de invulnerabilidad y aplica el cap de
  MAX_VELOCITY (el thrust acumula fuerza sin tope; clampamos body_.velocity)
- postUpdate() copia body_.position -> center_ y body_.angle -> angle_
- draw() sin cambios funcionales (usa getSpeed() en lugar de velocity_)

Cambios en GameScene:
- En init(): physics_world_.addBody(&ship.getBody()) por cada nave activa
- En update(): physics_world_.update(dt) + ship.postUpdate(dt) al inicio
  del frame (las fuerzas del frame N-1 se integran en el frame N; 1
  frame de latencia ~16ms, imperceptible a 60fps)

Cambios de comportamiento visibles esperados:
- La nave ahora rebota contra las paredes del PLAYAREA con restitution=0.6
  (antes: clipping silencioso). PRIMERA muestra de la nueva física.
- Inercia: tras soltar THRUST, la nave conserva velocidad y se decelera
  exponencialmente con linear_damping. Sensación más espacial.
- Velocidad limitada en magnitud vectorial (antes: escalar). El cap
  preserva el feel arcade aproximado de MAX_VELOCITY = 120 px/s.

Edge case pendiente para tuning:
- Naves muertas siguen en el world como obstáculos físicos (radius=12).
  No es crítico mientras los enemies/bullets no estén migrados.

Smoke test xvfb: arranca correctamente. Validación de feeling requiere
test del usuario en vivo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 13:32:11 +02:00
JailDesigner 05740775c2 Fase 6a+b: Entity gana RigidBody body_, GameScene gana PhysicsWorld
Infraestructura mínima para la migración real de entidades a física
vectorial (Fase 6c-e). Sin cambios de comportamiento: las entidades
aún no usan body_ ni se registran al mundo.

Entity (core/entities/entity.hpp):
- Nuevo member protegido: Physics::RigidBody body_ (default-construido)
- Nuevo método virtual: postUpdate(dt) — no-op por default, override
  opcional para sincronizar mirror center_/angle_ desde body_ tras
  la integración física.
- Nuevos getters: getBody() (mutable y const)
- Include de core/physics/rigid_body.hpp

GameScene (game/scenes/game_scene.hpp/cpp):
- Nuevo member: Physics::PhysicsWorld physics_world_
- En init(): physics_world_.clear() + setBounds(PLAYAREA). Las
  entidades migradas se registrarán cada una en su propio init().

El loop de GameScene::update() no se modifica todavía. La invocación
de physics_world_.update(dt) + postUpdate() se añade en Fase 6c junto
con la primera entidad migrada (Ship), para validar el flujo tri-fase
con un caso real en lugar de cambios especulativos al control de flujo.

Smoke test xvfb OK. Compila y arranca sin cambios visibles.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 13:27:03 +02:00
JailDesigner 0fd9360029 Fase 5: infraestructura del sistema de fisica vectorial
Crea los componentes base del nuevo motor de fisica sin alterar
todavia el comportamiento del juego. La migracion de Ship/Enemy/
Bullet al nuevo sistema queda para Fase 6.

Nuevos archivos:
- core/physics/rigid_body.hpp - struct POD con:
  * Vec2 position, velocity (cartesianas, NO polares)
  * float angle, angular_velocity
  * mass, inverse_mass (cacheado; 0 = estatico)
  * restitution (elasticidad 0..1)
  * linear_damping, angular_damping (s-1, exponencial)
  * radius (circulo de colision)
  * applyForce / applyImpulse / clearAccumulators
  * setStatic() para paredes/obstaculos
- core/physics/physics_world.hpp/.cpp - mundo fisico:
  * Almacena RigidBody* (no-owning, ownership en entidades)
  * setBounds(SDL_FRect) para paredes implicitas (PLAYAREA)
  * update(dt) = integrate + resolveBoundsCollisions + resolveBodyCollisions
  * Integrador semi-implicito de Euler + damping exponencial
  * Resolucion circulo-circulo con correccion posicional e impulsos elasticos
  * Formula del impulso: j = -(1+e)*(v_rel . n) / (1/m_a + 1/m_b)
  * Broadphase trivial O(n^2): suficiente para ~25 cuerpos del juego

Decisiones de diseno:
- Velocidad en cartesianas (Vec2) en lugar de la representacion polar
  actual (escalar velocidad + cos/sin del angulo cada frame). Adios al
  acoplamiento entre orientacion y direccion de movimiento.
- Composicion sobre herencia: RigidBody es un struct independiente que
  las entidades incrustaran como member en Fase 6, no una clase base.
- El integrador semi-implicito es la version estandar para juegos
  arcade (mas estable que Euler explicito sin coste extra).
- Damping exponencial (exp(-damping*dt)) en lugar de lineal: mantiene
  el feeling consistente independientemente del framerate.
- Sin gravedad: el juego es top-down, no necesita campo de fuerzas
  global. Las entidades aplican sus propias fuerzas (thrust).

Pendiente Fase 6:
- Anadir RigidBody body_ a Entity (member, no pointer)
- Migrar Ship: thrust como applyForce, en lugar de velocity_ escalar
- Migrar Enemy: cambios de direccion via applyImpulse, rebotes los
  hace PhysicsWorld
- Migrar Bullet: lineal sin damping, restitution=0 (no rebotan)
- Anadir PhysicsWorld a GameScene, registrar bodies, llamar update()

Compila y enlaza. Smoke test xvfb OK: el juego arranca igual que antes
(la nueva infraestructura aun no se invoca).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 13:12:06 +02:00
JailDesigner ed98ef612e Fase 3: import del subsistema de audio desde AEEA
Reemplaza el audio antiguo de orni_attack (singleton con new/delete
raw, sin efectos, sin crossfade) por el subsistema moderno de AEEA
(unique_ptr, RAII, crossfade nativo, echo/reverb, pitch-shift,
callbacks de fin de pista, getMusicDurationMs para timelines
deterministas).

Eliminados:
- source/core/audio/audio_cache.{hpp,cpp} (1 cache por subsistema)
- source/core/audio/jail_audio.hpp viejo (motor inline globals)
- source/external/stb_vorbis.h (v1.20)

Añadidos (copiados de AEEA, traducidos comentarios al castellano):
- source/core/audio/audio.{hpp,cpp} — singleton con Audio::Config inyectada
- source/core/audio/audio_adapter.{hpp,cpp} — adapter para getMusic/getSound
- source/core/audio/audio_effects.{hpp,cpp} — Schroeder reverb + echo DSP
- source/core/audio/jail_audio.{hpp,cpp} — Ja::Engine class-based, streaming
- source/core/audio/sound_effects_config.{hpp,cpp} — presets YAML (opcional)
- source/external/stb_vorbis.c (v1.22) — OGG decoder, versión más reciente
- source/external/stb_vorbis_impl.cpp — TU aislada para evitar clang-tidy

Adaptaciones:
- audio_adapter.cpp implementado a medida para orni: usa
  Resource::Helper::loadFile (no Resource::Cache de AEEA que orni no
  tiene). Cache local con unique_ptr<Ja::Music> / unique_ptr<Ja::Sound>.
- Includes: utils/defaults.hpp -> core/defaults.hpp, utils/log.hpp
  reemplazado por iostream con std::cerr/std::cout.

API breaking changes (callsites migrados):
- Audio::init() -> Audio::init(Config); el Director construye la Config
  desde Defaults::Audio::* (ENABLED, VOLUME, MUSIC_*, SOUND_*).
- Audio::get()->getMusicState() -> Audio::getMusicState() (ahora static).
- AudioCache::getMusic/getSound -> AudioResource::getMusic/getSound.

Defaults::Audio consolidado: ahora aglutina las constantes que antes
estaban repartidas entre namespace Audio (VOLUME, ENABLED), namespace
Music (VOLUME, ENABLED), namespace Sound (VOLUME, ENABLED). Las pistas
y rutas de efectos siguen en Music::* / Sound::*. Añadidas FREQUENCY,
FORMAT, CHANNELS, CROSSFADE_MS, VOLUME_STEP para el motor.

Beneficios para fases siguientes:
- Crossfade en transiciones de escena (uso: playMusic(name, -1, 1500)).
- Pitch-shift para variaciones de SFX (Audio::playSound(name, group, 0.95)).
- Echo/reverb DSP via playSoundWithEcho/Reverb (sounds.yaml presets).
- Callbacks setOnMusicEnded para sincronizar eventos con el fin de pista.

Compila y enlaza. Pendiente: test runtime del usuario.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 12:43:01 +02:00
JailDesigner a4f6a5514f Fase 2: cambio de resolución lógica 640x480 a 1280x720 (16:9)
El juego pasa de 4:3 a 16:9. Solo se tocan las constantes raíz:
todo lo demás (PLAYAREA, SCOREBOARD, CENTER_X/Y, P1/P2_TARGET,
VANISHING_POINT, etc.) se deriva de Game::WIDTH/HEIGHT y se
recalcula automáticamente.

Decisión del usuario: priorizar la base técnica sobre el feeling
del juego. Las velocidades, masas, radios de colisión y tamaños
de shape se mantienen sin cambios — la nave se verá más pequeña
en relación al área de juego y habrá más espacio. El tuning
jugable se hará tras completar la migración (post-Fase 7 GPU).

Cambios:
- Defaults::Window::WIDTH/HEIGHT: 640/480 -> 1280/720
- Defaults::Window::MIN_WIDTH/MIN_HEIGHT: 320/240 -> 640/360 (16:9)
- Defaults::Game::WIDTH/HEIGHT: 640/480 -> 1280/720
- Options::Window defaults: width{640}/height{480} -> 1280/720
- logo_scene.cpp: PANTALLA_ANCHO/ALTO ya no hardcoded;
  deriva de Defaults::Game (era 640/480 magic numbers)
- Comentarios obsoletos limpiados en defaults.hpp
  (// w = 640.0, // 320.0f, etc.)
- Catalán residual traducido (marges->márgenes, percentatges->porcentajes,
  Àrea->Área, contenidor->contenedor, automàtic->automático)

Verificado: el ShipAnimator del título usa CENTER_X / CENTER_Y /
P1_TARGET_X/Y / VANISHING_POINT_X/Y, todos derivados de Game::WIDTH
y Game::HEIGHT. Se reposicionan automáticamente. CLOCK_RADIUS=150
se mantiene (escala relativa al centro).

PostFase: con 1280x720 el bug del HUD en ventana puede haber
cambiado de síntomas. Verificar visualmente cuando se haga la prueba.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 12:27:12 +02:00
JailDesigner 56533caff0 Fix: clave YAML 'quadrat' renombrada a 'cuadrado' tras Fase 1e
El sweep de comentarios de la Fase 1e cambió por error el string
literal yaml["quadrat"] a yaml["cuadrado"] dentro de
stage_loader.cpp:172 (sed sin distinción comentario vs string).

El archivo data/stages/stages.yaml seguía teniendo la clave
'quadrat:', lo que provocaba:
  [StageLoader] Error: enemy_distribution incompleta
  [GameScene] Error: no s'ha pogut load stages.yaml
  [StageManager] Error: config es null
  -> Violación de segmento al pasar de TITLE a GAME

Solución coherente con la política "código en inglés/castellano,
strings de UI en valenciano": el YAML es archivo de configuración,
no UI, así que se alinea con el código.

Cambios:
- data/stages/stages.yaml: quadrat -> cuadrado en las 10 stages
- build/resources.pack regenerado con `make pack`

Audit completo: verificado que ninguna otra clave YAML ni string
literal de filename (.shp, .wav) fue tocada por el sweep.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 12:19:24 +02:00
JailDesigner bf83f161b0 Fase 1e: cierre de naming sweep (#pragma once, locals, comentarios castellano)
Tres tareas de pulido para cerrar la Fase 1 por completo:

#pragma once uniforme:
- sdl_manager.hpp y game_scene.hpp pasan de #ifndef/#define guards
  a #pragma once. Los archivos externos (stb_vorbis.h, fkyaml_node.hpp)
  se mantienen intactos (codigo de terceros).

Variables locales y parametros restantes (catalan -> ingles):
- fitxer -> file, moviment -> movement, inici -> start
- comptador -> counter, escalada -> scaled
- missatges -> messages, llista -> list
- alçada -> height, amplada -> width, llargada -> length
- origen -> origin, distancia -> distance, valor -> value, desti -> target
- neteja -> clear, presenta -> present (SDLManager)
- total_enemics -> total_enemies, configurar -> configure, iniciar -> start

Comentarios catalan -> castellano:
- Cabeceras de fichero actualizadas con nombres nuevos
  (escena_joc.hpp -> game_scene.hpp, etc.)
- Palabras tecnicas: trasllacio->traslacion, col-lisio->colision,
  inicialitzacio->inicializacion, posicio->posicion, rotacio->rotacion,
  velocitat->velocidad, acceleracio->aceleracion, explosio->explosion,
  renderitzat->renderizado, calcul->calculo, transicio->transicion,
  comprovacio->comprobacion, substitucio->sustitucion,
  utilitzacio->utilizacion, opcio->opcion, configuracio->configuracion,
  funcio->funcion, distancia, animacio->animacion
- Determinantes y conectores: aquest->este, aquesta->esta,
  amb->con, sense->sin, pero->pero, mai->nunca, nomes->solo,
  tambe->tambien, sempre->siempre, ja->ya, mateix->mismo,
  vegada->vez, dintre->dentro, fora->fuera, dreta->derecha,
  esquerra->izquierda, sortir->salir, sortida->salida,
  petit->pequeno, gran->grande, nou->nuevo, vell->viejo,
  molt->mucho, els->los, les->las, totes les->todas las,
  d'->de, com->como, quan->cuando, mentre->mientras,
  despres->despues, abans->antes, durant->durante, fins->hasta,
  encara->aun, llavors->entonces, aixi->asi, perque->porque
- Sustantivos: classe->clase, metode->metodo, parametre->parametro,
  versio->version, entitat->entidad, joc->juego, nivell->nivel,
  enemic->enemigo, naus->naves, bales->balas, fitxer->archivo,
  pentagon->pentagono, pun- tuacio->puntuacion, flotant->flotante,
  titol->titulo, objectiu->objetivo, mostra->muestra, tipus->tipo

Strings literales preservados en valenciano segun decision del
usuario: el texto del HUD del juego (puntuaciones, mensajes en
pantalla, archivo de config) se mantiene en valenciano original.

70 fitxers tocats, +1117 / -1123. Compila i enllaca.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 12:12:30 +02:00
JailDesigner 7ee359b910 Fase 1d: rename del codi restant (effects, stage_system, locals)
Sweep final del naming a CamelCase/camelBack/lower_case:

Fitxers renombrats:
- effects/gestor_puntuacio_flotant.{hpp,cpp} -> floating_score_manager.{hpp,cpp}
- effects/puntuacio_flotant.hpp -> floating_score.hpp

Tipus (CamelCase):
- GestorPuntuacioFlotant -> FloatingScoreManager
- PuntuacioFlotant -> FloatingScore
- ConfigStage -> StageConfig
- ConfigSistemaStages -> StageSystemConfig
- NauTitol -> TitleShip
- EstatNau -> ShipState

Metodes publics (camelBack):
- obte_renderer -> getRenderer
- get_num_actius -> getActiveCount
- calcular_direccio_explosio -> computeExplosionDirection
- trobar_slot_lliure -> findFreeSlot
- explotar -> explode
- reiniciar -> reset
- es_valida -> isValid
- parsejar_fitxer -> parseFile
- carregar -> load
- crear_explosio -> createExplosion
- registrar_puntuacio -> registerScore
- construir_marcador -> buildScoreboard
- render_centered -> renderCentered

Camps struct publics (snake_case):
- actiu/actius -> active
- rotacio -> rotation, rotacio_visual -> visual_rotation
- acceleracio -> acceleration
- velocitat -> velocity
- escala/escala_inicial/objectiu/actual -> scale/initial_scale/...
- posicio/posicio_inicial/objectiu/actual -> position/initial_position/...
- fase_oscilacio -> oscillation_phase
- temps_estat -> state_time
- jugador_id -> player_id
- estat -> state
- brillantor -> brightness
- tipus -> type

Camps privats (sufix _):
- naus_ -> ships_, orni_ -> enemies_, bales_ -> bullets_
- gestor_puntuacio_ -> floating_score_manager_
- punt_mort_ -> death_position_, punt_spawn_ -> spawn_position_
- itocado_per_jugador_ -> hit_timer_per_player_
- vides_per_jugador_ -> lives_per_player_
- puntuacio_per_jugador_ -> score_per_player_
- estat_game_over_ -> game_over_state_
- continues_usados_ -> continues_used_

Constants:
- MARGE_ESQ/DRET/DALT/BAIX -> MARGIN_LEFT/RIGHT/TOP/BOTTOM

Variables locals i parametres comuns (snake_case):
- nau -> ship, enemic -> enemy, bala -> bullet
- forma -> shape, punt(s) -> point(s)
- jugador -> player, partida -> match
- temps -> time, missatge -> message

Diff: 59 fitxers, +1000/-1000 (simetric). Compila i enllaça.

Pendents per a futures fases (no bloquejants):
- Comentaris de capçalera en catala -> castella
- Variables locals/parametres minoritaris en catala
- Include guards (queden alguns #ifndef en lloc de #pragma once)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 11:44:45 +02:00
JailDesigner 5871d29d48 Fase 1c: rename d'escenes i sistema d'escenes
Tots els tipus, fitxers, namespace, enums i metodes relacionats amb
les escenes passen del catala a l'angles seguint el .clang-tidy:

Fitxers (renames git):
- source/game/escenes/escena_joc.{hpp,cpp} -> game/scenes/game_scene.{hpp,cpp}
- source/game/escenes/escena_titol.{hpp,cpp} -> game/scenes/title_scene.{hpp,cpp}
- source/game/escenes/escena_logo.{hpp,cpp} -> game/scenes/logo_scene.{hpp,cpp}
- source/core/system/context_escenes.hpp -> core/system/scene_context.hpp
- Carpeta game/escenes/ -> game/scenes/

Tipus (CamelCase):
- EscenaJoc -> GameScene
- EscenaTitol -> TitleScene
- EscenaLogo -> LogoScene
- ContextEscenes -> SceneContext
- Escena (enum class) -> SceneType
- Opcio -> Option
- EstatGameOver -> GameOverState
- EstatTitol -> TitleState
- EstatAnimacio -> AnimationState
- ConfigPartida -> MatchConfig

Namespace:
- GestorEscenes -> SceneManager

Valors d'enum SceneType:
- TITOL -> TITLE
- JOC -> GAME
- EIXIR -> EXIT
(LOGO mantingut)

Metodes (camelBack):
- executar -> run
- canviar_escena -> setNextScene
- escena_desti -> nextScene
- opcio (getter) -> option
- consumir_opcio -> consumeOption
- reset_opcio -> resetOption
- set_config_partida -> setMatchConfig
- get_config_partida -> getMatchConfig

Camps privats (lower_case_):
- escena_desti_ -> next_scene_
- opcio_ -> option_
- config_partida_ -> match_config_

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 11:41:11 +02:00
JailDesigner ae5cc1cfb4 Fase 1b: rename d'entitats i metodes virtuals a CamelCase/camelBack
Tots els tipus d'entitat passen del catala a l'angles seguint el
.clang-tidy del projecte (tipus en CamelCase, metodes en camelBack,
membres en lower_case amb sufix _).

Renames de tipus:
- Entitat -> Entity (core/entities/entity.hpp)
- Nau -> Ship (game/entities/ship.{hpp,cpp})
- Enemic -> Enemy (game/entities/enemy.{hpp,cpp})
- Bala -> Bullet (game/entities/bullet.{hpp,cpp})
- TipusEnemic -> EnemyType
- AnimacioEnemic -> EnemyAnimation

Metodes virtuals (s'aplica a tot el codi, no nomes a entitats):
- actualitzar -> update
- dibuixar -> draw
- inicialitzar -> init
- processar_input -> processInput
- esta_actiu -> isActive
- es_collidable -> isCollidable
- get_collision_radius -> getCollisionRadius

Getters comuns:
- get_centre -> getCenter
- get_angle -> getAngle
- get_brightness -> getBrightness
- get_forma -> getShape

Metodes especifics:
- esta_viva -> isAlive
- esta_tocada -> isHit
- es_invulnerable -> isInvulnerable
- get_velocitat_vector -> getVelocityVector
- set_centre -> setCenter
- marcar_tocada -> markHit
- aplicar_fisica -> applyPhysics
- get_tipus -> getType

Camps privats:
- centre_ -> center_
- velocitat_ -> velocity_
- forma_ -> shape_
- esta_tocada_ -> is_hit_
- tipus_ -> type_

L'import d'audio/input d'AEEA quedara coherent (mateix estil).
Diff net: 30 fitxers, +437/-437 (la majoria es renames simetrics).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 11:37:18 +02:00
JailDesigner cd38101f99 Fase 1a: Punt -> Vec2 amb operadors moderns
Primera sub-fase del naming sweep. Punt era un struct sense
operacions, conservat per compatibilitat amb el Pascal original.
Substituit per Vec2, un aggregate amb operadors aritmetics, dot,
length, normalized i length_squared (camelBack: lengthSquared)
seguint les regles del .clang-tidy del projecte.

Canvis:
- core/types.hpp reescrit: nou struct Vec2 amb +=,-=,*=,/=,
  unary -, ==, dot, length, lengthSquared, normalized
- Operadors fora de la classe: +, -, *, / (amb float per ambdues
  bandes), - unari, ==
- Vec2 segueix sent aggregate (sense constructors definits):
  els 'designated initializers' del codi existent funcionen igual:
  Vec2{.x = ..., .y = ...}
- Sed global sobre 35 fitxers: tots els 'Punt' -> 'Vec2'

Net: 35 fitxers tocats, +180 / -114. Compila i enllaça.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 11:33:27 +02:00
JailDesigner 6cf990bc1d Fase 0: eliminar tot el codi llegacy (polars + primitives + bool dibuixar)
Aplicada la directiva "res llegacy" abans d'arrencar la migracio a fisica
vectorial + SDL3 GPU. Cada bossa de cruft que arrossegava el port de Pascal
queda eliminada.

Borrats (huerfanos):
- source/core/rendering/primitives.hpp/.cpp (modul/diferencia/angle_punt/
  crear_poligon_regular)
- source/core/rendering/polygon_renderer.hpp/.cpp (rota_tri/rota_pol)
- core::types::Triangle, Poligon, IPunt
- Defaults::Entities::MAX_IPUNTS i alias a constants.hpp
- EscenaJoc::chatarra_cosmica_ (mai usat)
- Bresenham comentat dins de Rendering::linea()

Simplificat (parametre 'dibuixar' llegacy que sempre era true):
- Rendering::linea(...): treta la signatura bool dibuixar, retorn void
- Rendering::render_shape(...): treta la signatura bool dibuixar
- 11 callsites de linea() actualitzats (escena_joc, debris_manager)
- 12 callsites de render_shape() actualitzats

Modernitzats:
- 5 fitxers .shp netejats de comentaris polar->cartesia historics
- types.hpp queda nomes amb Punt (l'unica coordenada del joc)
- debris_manager.hpp afegit include explicit de defaults.hpp

Net: 452 linies eliminades, 56 afegides. Compila i enllaca correctament.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 11:10:42 +02:00
JailDesigner cb7b99cab3 deixar de versionar .claude/ 2026-05-19 08:54:51 +02:00
JailDesigner 21e0ae0c8c reorganitzat release/ alineat amb AEEA 2026-05-19 08:52:55 +02:00
JailDesigner 851e6d35a2 alineat amb AEEA: cmake, makefile, clang-* i hooks 2026-05-19 08:48:25 +02:00
JailDesigner 79d6e71fff afegit readme 2025-12-23 13:06:52 +01:00
JailDesigner fb394d23c9 corregit makefile de macos 2025-12-23 10:36:03 +01:00
JailDesigner 1951bcad11 corregit makefile de windows 2025-12-23 10:03:32 +01:00
JailDesigner 9a874fc83b corregit makefile de tools/pack_resources 2025-12-23 08:52:47 +01:00
JailDesigner 1acdd3f38d corregit make linux_release 2025-12-23 08:18:13 +01:00
JailDesigner a2b11371cf afegit include 2025-12-23 07:41:42 +01:00
JailDesigner b4b76ed6e8 afegit default per a fullscreen 2025-12-19 17:26:20 +01:00
JailDesigner 6f4eb9c1fc tidy: includes 2025-12-19 13:03:52 +01:00
JailDesigner 47f7ffb169 feat: implementar jerarquia d'entitats amb classe base Entitat 2025-12-19 13:01:58 +01:00
JailDesigner 70f2642e6d feat(linter): afegir checks llvm-include-order i misc-include-cleaner
- Check 11: llvm-include-order (0 errors - codi ja compleix)
- Check 12: misc-include-cleaner (detectar includes no usats i faltants)
  - Configurar IgnoreHeaders per SDL3 (genera falsos positius)
  - Fix: afegir <cstdint> a nau.hpp, enemic.hpp, bala.hpp
  - Fix: afegir <cmath> a nau.hpp, enemic.hpp (std::cos/sin)

Include order validat segons LLVM coding standards.
Headers més nets i compilació més ràpida.
2025-12-18 22:35:46 +01:00
JailDesigner 1a42f24a68 refactor(includes): convertir includes relativos a absolutos
- escena_joc.hpp: 7 includes cambiados de ../ a rutas absolutas
- pre-commit hook: añadir validación de includes relativos
- Bloquea commits con includes tipo #include "../foo.hpp"
- Coherencia con CMakeLists.txt (include_directories desde source/)
2025-12-18 22:24:17 +01:00
JailDesigner ac0f03c725 no compilava pack resources 2025-12-18 22:17:42 +01:00
JailDesigner 1804c8a171 feat(tools): afegit pre-commit hook versionat (clang-format + clang-tidy)
Sistema de git hooks per verificar qualitat de codi automàticament:

Hooks implementats:
- pre-commit: Executa clang-format + clang-tidy en arxius modificats
  - 🎨 clang-format: Formata automàticament el codi
  - 🔍 clang-tidy: Verifica errors i bloqueja commit si n'hi ha

Característiques:
-  Només revisa arxius modificats (ràpid)
-  Auto-formata amb clang-format i afegeix canvis al commit
-  Bloqueja commits amb errors de clang-tidy
-  Exclou directoris audio/ i legacy/ automàticament
-  Rutes dinàmiques (funciona en qualsevol màquina)

Instal·lació:
  ./tools/hooks/install.sh

O manual:
  cp tools/hooks/pre-commit .git/hooks/
  chmod +x .git/hooks/pre-commit

Documentació completa: tools/hooks/README.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 22:08:44 +01:00
JailDesigner d83056c614 test: verificar pre-commit hook (clang-format + clang-tidy) 2025-12-18 22:04:34 +01:00
JailDesigner ba2a6fe914 refactor(linter): completat check 10 - bugprone-* (0 fixes necessaris)
Check 10: bugprone-* - Detecció de bugs potencials
Resultat: 0 fixes aplicats - tots els warnings eren falsos positius acceptables

Warnings trobats i justificació d'exclusió:
- bugprone-branch-clone: Fall-through en switch és intencional (patró del codi)
- bugprone-switch-missing-default-case: No tots els switches necessiten default
- bugprone-implicit-widening-of-multiplication-result: Valors petits, sense risc d'overflow
- bugprone-exception-escape: Excepcions en main() terminen el programa (comportament acceptable)

Estat final:
 Check 1: readability-uppercase-literal-suffix (657 fixes)
 Check 2: readability-math-missing-parentheses (291 fixes)
 Check 3: readability-identifier-naming (DESHABILITADO - cascada de cambios)
 Check 4: readability-const-return-type (0 fixes)
 Check 5: readability-else-after-return (0 fixes)
 Check 6: readability-simplify-boolean-expr (0 fixes)
 Check 7: readability-* (225 fixes)
 Check 8: modernize-* (215 fixes)
 Check 9: performance-* (91 fixes)
 Check 10: bugprone-* (0 fixes - falsos positius)

Total: 1479 fixes aplicats correctament
Compilació:  OK
Test del joc:  OK

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 21:47:52 +01:00
JailDesigner 364cf36183 perf: aplicar checks performance-* (91 fixes)
Cambios aplicados:
- Reemplazar std::endl con '\n' (91 casos)
  * std::endl hace flush del buffer (más lento)
  * '\n' solo inserta newline (más rápido)
  * Mejora rendimiento de logging/debug

Check excluido:
- performance-enum-size: Tamaño de enum no es crítico para rendimiento
2025-12-18 21:24:07 +01:00
JailDesigner 7f6af6dd00 style: aplicar checks modernize-* (215 fixes)
Cambios aplicados:
- [[nodiscard]] añadido a funciones que retornan valores
- .starts_with() en lugar de .find() == 0
- Inicializadores designados {.x=0, .y=0}
- auto en castings obvios
- = default para constructores triviales
- Funciones deleted movidas a public
- std::numbers::pi_v<float> (C++20)

Checks excluidos:
- use-trailing-return-type: Estilo controversial
- avoid-c-arrays: Arrays C aceptables en ciertos contextos
2025-12-18 20:16:46 +01:00
JailDesigner fdfb84170f style: aplicar todos los checks readability-* (225 fixes)
Cambios aplicados:
- readability-braces-around-statements (añadir llaves en ifs/fors)
- readability-implicit-bool-conversion (puntero → bool explícito)
- readability-container-size-empty (.empty() en lugar de .size()==0)
- readability-container-contains (.contains() C++20)
- readability-make-member-function-const (métodos const)
- readability-else-after-return (5 casos adicionales)
- Añadido #include <cmath> en defaults.hpp

Checks excluidos (justificados):
- identifier-naming: Cascada de 300+ cambios
- identifier-length: Nombres cortos son OK en este proyecto
- magic-numbers: Demasiados falsos positivos
- convert-member-functions-to-static: Rompe encapsulación
- use-anyofallof: C++20 ranges no universal
- function-cognitive-complexity: Complejidad aceptable
- clang-analyzer-security.insecureAPI.rand: rand() suficiente para juegos
2025-12-18 19:51:43 +01:00
JailDesigner 2088ccdcc6 config(clang-tidy): check 6 completat + exclusió audio/legacy
- Check 6 (readability-simplify-boolean-expr): No cal canvis
- Deshabilitada temporalment check 3 (identifier-naming) per evitar
  cascada de 300+ canvis de nomenclatura
- Exclosa source/core/audio/ i source/legacy/ dels targets de tidy
  (per evitar "no checks enabled" error)
2025-12-18 13:55:26 +01:00
JailDesigner 7556c3fe8d style: habilitar readability-else-after-return
- Código ya cumple (no hay else innecesarios después de return)
- Check 5/N completado

🤖 Generated with Claude Code
2025-12-18 13:32:42 +01:00
JailDesigner decde1b7d5 style: habilitar readability-const-return-type
- Código ya cumple con el check (no hay const innecesarios en returns)
- Check 4/N completado

🤖 Generated with Claude Code
2025-12-18 13:32:00 +01:00
JailDesigner c8545c712d config(clang-tidy): excluir source/core/audio/ de análisis
- Crear .clang-tidy local en source/core/audio/ con Checks: '-*'
- Excluir jail_audio.hpp y archivos que dependen de él (código externo)
- Ajustar HeaderFilterRegex en .clang-tidy raíz
- Check 3 (readability-identifier-naming): código ya cumple convenciones

🤖 Generated with Claude Code
2025-12-18 13:26:27 +01:00
JailDesigner 76786203a0 style: aplicar readability-math-missing-parentheses
- Agregar paréntesis explícitos en operaciones matemáticas para claridad
- Ejemplos: '1.0F - a * b' → '1.0F - (a * b)'
- 291 correcciones aplicadas automáticamente con clang-tidy
- Check 2/N completado

🤖 Generated with Claude Code
2025-12-18 13:09:35 +01:00
JailDesigner bc94eff176 style: aplicar readability-uppercase-literal-suffix
- Cambiar todos los literales float de minúscula a mayúscula (1.0f → 1.0F)
- 657 correcciones aplicadas automáticamente con clang-tidy
- Check 1/N completado

🤖 Generated with Claude Code
2025-12-18 13:06:48 +01:00
JailDesigner 44cd0857e0 fix(shape_loader): corregir inconsistencias de naming y static
- Renombrar getCacheSize() → get_cache_size() (match con .hpp)
- Renombrar resolvePath() → resolve_path() (match con .hpp)
- Cambiar base_path → base_path_ (match con .hpp)
- Eliminar 'static' de definiciones fuera de clase (error de C++)
2025-12-18 13:04:15 +01:00
JailDesigner f8521d644c modificat cmake amb clang-tidy 2025-12-18 12:21:29 +01:00
JailDesigner eb2702eb19 afegit linter 2025-12-18 10:04:21 +01:00
JailDesigner bfb4903998 eliminat warning 2025-12-17 22:53:11 +01:00
JailDesigner f3abab7a13 augmentat numero de debris de 100 a 150 per necesitats del logo 2025-12-17 22:53:05 +01:00
JailDesigner 54031e3520 afegit friendly fire 2025-12-17 19:39:33 +01:00
JailDesigner 8b9d26a02c delay en naus en titol 2025-12-17 18:55:41 +01:00
JailDesigner 3d5277a395 fix: ratolí visible en fullscreen 2025-12-17 18:36:12 +01:00
JailDesigner 2555157bd7 fix: en alguns casos no podies tornar a unirte a la partida 2025-12-17 18:16:46 +01:00
JailDesigner 461eaedecf retocs en nave2 2025-12-17 17:55:14 +01:00
JailDesigner 1891c9e49e eliminades shapes sobrants 2025-12-17 17:44:23 +01:00
JailDesigner 829a895464 continue counter ara arriba fins a 0 2025-12-17 17:21:03 +01:00
JailDesigner 8bc259b25a nous sons 2025-12-17 17:05:42 +01:00
JailDesigner ec333efe66 afegida logica de continues
fix: el text no centrava correctament en horitzontal
2025-12-17 13:31:32 +01:00
JailDesigner 3b432e6580 layout de TITOL 2025-12-17 11:32:37 +01:00
JailDesigner 886ec8ab1d amagat el cursor d'inici en mode finestra 2025-12-16 22:47:12 +01:00
JailDesigner bc5982b286 treballant en les naus de title 2025-12-16 22:14:55 +01:00
JailDesigner 75a4a1b3b9 millorada la JOIN_PHASE i fase final de TITOL 2025-12-16 12:34:19 +01:00
JailDesigner f3f0bfcd9a afegit so a init_hud 2025-12-16 10:05:18 +01:00
JailDesigner c959e0e3a0 animacions de INIT_HUD amb control d'inici i final 2025-12-16 09:39:53 +01:00
JailDesigner 8b896912b2 centralitzada la gestio d'SKIP per a les escenes 2025-12-16 08:33:29 +01:00
JailDesigner 3d0057220d afegides tecles d'START. ja comença el joc amb el numero correcte de jugadors 2025-12-12 16:40:46 +01:00
JailDesigner 0c75f56cb5 treballant en context per a jugador 1, jugador 2 o els dos 2025-12-12 10:43:17 +01:00
JailDesigner 0ceaa75862 integrada classe Input 2025-12-11 12:41:03 +01:00
JailDesigner 087b8d346d afegit segon jugador 2025-12-10 17:18:34 +01:00
JailDesigner aca1f5200b els enemics poden morir mentre fan spawn 2025-12-10 11:58:26 +01:00
JailDesigner 3b638f4715 respawn de nau i invulnerabilitat 2025-12-10 11:35:45 +01:00
JailDesigner 9a5adcbcc5 revisat el marcador
modificada la shape 03
2025-12-10 11:05:15 +01:00
JailDesigner d0be5ea2d1 millorades les definicions de zones 2025-12-10 08:20:43 +01:00
JailDesigner 07e00fff09 eliminada ship2.shp i substituida ship.shp 2025-12-10 07:51:02 +01:00
JailDesigner b4e0ca7eca INIT_HUD amb temps de les animacions per percentatge
ordenats en subcarpetes els fitxers d'audio
corregit typo LIFES a LIVES
2025-12-09 22:57:01 +01:00
JailDesigner b8173b205b acabat INIT_HUD 2025-12-09 22:17:35 +01:00
JailDesigner 57d623d6bc treballant en INIT_HUD 2025-12-09 22:09:24 +01:00
JailDesigner 64ab08973c efecte maquina d'escriure per als textos d'entrada de fase 2025-12-09 19:38:29 +01:00
JailDesigner 94a7a38cdd afegit sistema de punts 2025-12-09 16:56:07 +01:00
JailDesigner 76165e4345 limitada la velocitat angular dels debris i transformada en velocitat lineal tangencial 2025-12-09 13:38:18 +01:00
JailDesigner 767a1f6af8 incrementada velocitat base angular dels enemics 2025-12-09 13:18:24 +01:00
JailDesigner 20ca024100 les bales ara son redones 2025-12-09 12:58:44 +01:00
JailDesigner 3c3857c1b2 debris hereten velocitat angular 2025-12-09 12:30:03 +01:00
JailDesigner 523342fed9 canvis en el inici i final de fase 2025-12-09 11:45:28 +01:00
JailDesigner 217ca58b1a millorat el spawn d'enemics: perimetre de seguretat i animació amb invulnerabilitat 2025-12-09 10:21:42 +01:00
JailDesigner ec6565bf71 debris hereta brillantor i velocitat 2025-12-09 09:25:46 +01:00
JailDesigner cd7f06f3a1 corregit el comptador de FPS 2025-12-08 22:13:26 +01:00
JailDesigner 8886873ed5 corregida la posició dels fitxers en el .dmg 2025-12-08 21:55:49 +01:00
JailDesigner a41e696b69 afegit resources.pack y prefixe a les rutes de recursos 2025-12-08 21:48:52 +01:00
JailDesigner 4b7cbd88bb nou icon per a la release sorpresa 2025-12-04 18:38:30 +01:00
JailDesigner 789cbbc593 afegida veu: good job commander
calibrats els volumnes de musica i efectes
afegida forma: ship2.shp
canviat tamany de textos de canvi de pantalla
2025-12-04 18:27:39 +01:00
JailDesigner 1dd87c0707 corregit: al pulsar per a jugar, el titol deixava d'animar-se 2025-12-04 12:00:08 +01:00
JailDesigner 330044e10f millorada la gestio d'escenes i opcions 2025-12-04 11:51:41 +01:00
JailDesigner f8c5207d5c corregida la posicio del titol al inici 2025-12-04 08:52:07 +01:00
JailDesigner 2caaa29124 afegit fade in al starfield de TITOL 2025-12-04 08:24:08 +01:00
JailDesigner cdc4d07394 animacio del titol als 10 segons 2025-12-04 08:00:13 +01:00
JailDesigner 1023cde1be afegida progresió 2025-12-03 22:19:44 +01:00
JailDesigner a3aeed4b7c afegides musiques
afegit control de brillo al starfield
2025-12-03 19:27:36 +01:00
JailDesigner 3b0354da54 afegit titol al TITOL 2025-12-03 17:40:27 +01:00
JailDesigner 622ccd22bc afegits diferents enemics 2025-12-03 13:47:31 +01:00
JailDesigner 1441134aea afegida colisió nau-enemics i game over 2025-12-03 12:04:44 +01:00
JailDesigner 0500dce7aa includes amb ruta absoluta 2025-12-03 11:19:23 +01:00
JailDesigner 9f0dfc4e24 gitignore no ha deixat versionar cap fitxer de core
afegida gestió de ratolí
2025-12-03 09:42:45 +01:00
JailDesigner aa66dd41c1 ja renderitza a la resolució de la finestra 2025-12-03 08:23:42 +01:00
JailDesigner 69fb5f3cc1 Migrate to CMake-based build with packaging
Major build system refactoring:

**CMake (build authority)**:
- Auto-discovers .cpp files (GLOB_RECURSE in source/core/ and source/game/)
- No manual file list maintenance needed
- Excludes source/legacy/ automatically
- Generates build/project.h from template

**Makefile (simplified wrapper)**:
- Delegates compilation to CMake (make → cmake --build build)
- Contains 5 release packaging targets:
  * macos_release: .app bundle + .dmg (Apple Silicon)
  * linux_release: .tar.gz
  * windows_release: .zip with .exe + DLLs
  * windows_cross: cross-compile from Linux/macOS
  * rpi_release: ARM64 cross-compile
- Complex packaging logic preserved (code signing, symlinks, DMG creation)

**Benefits**:
- Add new .cpp file → automatically compiled (no manual updates)
- Single source of truth in CMakeLists.txt (no duplication)
- IDE-friendly (VSCode, CLion, etc.)
- Complete packaging support (5 platforms)

**Files changed**:
- CMakeLists.txt: GLOB_RECURSE replaces 23-file hardcoded list
- Makefile: Simplified compilation + added 5 release targets (~220 lines)
- CLAUDE.md: Updated build system documentation
- escena_titol.cpp: Fixed include path (build/project.h → project.h)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 07:36:53 +01:00
JailDesigner d6b2e97777 afegit nivell de brillo per shape 2025-12-02 22:11:17 +01:00
JailDesigner 98c90e6075 treballant en el starfield 2025-12-02 21:19:43 +01:00
JailDesigner f795c86a38 afegida escena TITOL 2025-12-02 21:03:21 +01:00
JailDesigner c1c5774406 retocs disseny en LOGO 2025-12-02 17:27:18 +01:00
JailDesigner 0139da4764 corregit el escalat de finestra i mode fullscreen 2025-12-02 17:10:53 +01:00
JailDesigner ec911979fb afegit so al LOGO 2025-12-02 14:01:53 +01:00
JailDesigner e51749dbc6 afegit sistema de audio 2025-12-02 13:51:54 +01:00
JailDesigner 9ceb21c04f colisions bala-enemic 2025-12-02 13:22:26 +01:00
JailDesigner 76a91b4736 restaurada funcionalitat de disparar 2025-12-02 13:09:34 +01:00
JailDesigner df744338f1 enemics ja no ixen del area de joc 2025-12-02 10:01:31 +01:00
JailDesigner 8803fc3806 afegit vsync toggle 2025-12-02 09:44:58 +01:00
JailDesigner c26a4774a1 afegit comptador de frames per segon 2025-12-02 09:09:22 +01:00
JailDesigner 20538af4c6 LOGO explota 2025-12-02 08:50:38 +01:00
JailDesigner 73f222fcb7 afegit debris_manager 2025-12-02 08:30:32 +01:00
JailDesigner 67681e0f37 el marcador fake ja es pinta correctament 2025-12-01 23:47:42 +01:00
JailDesigner 5210448ac9 versió preliminar de text en pantalla 2025-12-01 22:29:34 +01:00
JailDesigner 983f42814f afegides shapes per a fonts 2025-11-29 10:06:33 +01:00
JailDesigner 89302a2ee3 afegides zones 2025-11-29 09:04:18 +01:00
JailDesigner 832f77de80 Makefile regenera project.h automàticament 2025-11-29 08:50:38 +01:00
JailDesigner 656144d182 afegits estats al LOGO 2025-11-28 23:06:25 +01:00
JailDesigner 4f926ddebf el zoom del LOGO ja es correcte 2025-11-28 22:43:36 +01:00
JailDesigner 624039e00d treballant en el LOGO 2025-11-28 21:07:36 +01:00
JailDesigner 430fcbe026 afegides escenes 2025-11-28 20:22:15 +01:00
JailDesigner 8e25d388fa afegida clase text 2025-11-28 17:08:42 +01:00
JailDesigner 3c7df0e989 afegides formes per als numeros i simbols 2025-11-28 12:49:51 +01:00
JailDesigner 4d0a5ca5bd migrat a sistema de shapes 2025-11-28 12:29:56 +01:00
JailDesigner 06e9a10c98 afegit pulso de color 2025-11-28 09:00:41 +01:00
JailDesigner 836debdc0b separació per entitats 2025-11-28 08:17:12 +01:00
JailDesigner 1e8829ba22 ja guarda la configuracio 2025-11-27 22:19:00 +01:00
JailDesigner 2b1311042f creat project.h 2025-11-27 21:47:08 +01:00
JailDesigner 0d69af667d migrant a SDL3 2025-11-27 17:32:01 +01:00
JailDesigner 93fed0b984 migrant a SDL3 2025-11-27 12:25:39 +01:00
JailDesigner c8838aa450 Convirtiendo el código a cpp 2022-08-13 15:11:25 +02:00
JailDesigner 896a61ed0d Convirtiendo el código a cpp 2022-08-13 15:00:01 +02:00
JailDoctor c7a7e604f1 BETA 2.2 2022-08-13 10:43:09 +02:00
JailDoctor cdfb966fc3 BETA 2.01 2022-08-13 10:41:21 +02:00
JailDoctor 18e45526b8 BETA 1.0 2022-08-13 10:38:00 +02:00
404 changed files with 135857 additions and 440 deletions
+22
View File
@@ -0,0 +1,22 @@
BasedOnStyle: Google
IndentWidth: 4
NamespaceIndentation: All
IndentAccessModifiers: false
ColumnLimit: 0 # Sin límite de longitud de línea
BreakBeforeBraces: Attach # Llaves en la misma línea
AllowShortIfStatementsOnASingleLine: true
AllowShortBlocksOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AlignOperands: DontAlign
AlignAfterOpenBracket: DontAlign
BinPackArguments: false
BinPackParameters: false
ContinuationIndentWidth: 4
ConstructorInitializerIndentWidth: 4
IndentWrappedFunctionNames: false
Cpp11BracedListStyle: true
BreakConstructorInitializers: BeforeColon
AllowAllConstructorInitializersOnNextLine: false
PackConstructorInitializers: Never
AllowAllArgumentsOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
+112
View File
@@ -0,0 +1,112 @@
Checks:
- readability-*
- modernize-*
- performance-*
- bugprone-*
- -readability-identifier-length
- -readability-magic-numbers
- -bugprone-integer-division
- -bugprone-easily-swappable-parameters
- -bugprone-narrowing-conversions
- -modernize-avoid-c-arrays
# performance-noexcept-move-constructor crashea clang-tidy (LLVM 19.1)
# con recursión infinita en ExceptionSpecAnalyzer::analyzeRecord cuando
# analiza ciertas instanciaciones de std::set. No es un falso positivo
# sobre nuestro código: el check ni siquiera llega a evaluar el patrón.
- -performance-noexcept-move-constructor
WarningsAsErrors: '*'
# Headers nostres (excloem source/external/ que conté dependències de tercers no editables)
HeaderFilterRegex: 'source/(core|game|utils)/'
FormatStyle: file
CheckOptions:
# bugprone-empty-catch: aceptar catches vacíos marcados con @INTENTIONAL en un comentario
- { key: bugprone-empty-catch.IgnoreCatchWithKeywords, value: '@INTENTIONAL' }
# =====================================================================
# CONSTANTES → UPPER_CASE (compile-time y runtime, en cualquier scope)
# =====================================================================
# Todo lo que sea const o constexpr se identifica visualmente en UPPER_CASE,
# sin importar si es global, local, miembro o static.
# constexpr en cualquier scope (globales y locales)
- { key: readability-identifier-naming.ConstexprVariableCase, value: UPPER_CASE }
# Constantes globales (const no-constexpr)
- { key: readability-identifier-naming.GlobalConstantCase, value: UPPER_CASE }
# Constantes locales (const en función)
- { key: readability-identifier-naming.LocalConstantCase, value: UPPER_CASE }
# Static const a nivel de archivo/namespace
- { key: readability-identifier-naming.StaticConstantCase, value: UPPER_CASE }
# Miembros static const/constexpr de clase (p.ej. static constexpr int MAX = 100;)
- { key: readability-identifier-naming.ClassConstantCase, value: UPPER_CASE }
# Miembros const no-static de clase (p.ej. const int limit;)
- { key: readability-identifier-naming.ConstantMemberCase, value: UPPER_CASE }
# Valores de enums
- { key: readability-identifier-naming.EnumConstantCase, value: UPPER_CASE }
# NOTA: Los parámetros const NO se tratan como constantes aquí.
# Un parámetro sigue siendo un parámetro aunque sea const → hereda ParameterCase.
# =====================================================================
# VARIABLES NO-CONST
# =====================================================================
# Variables locales
- { key: readability-identifier-naming.VariableCase, value: lower_case }
- { key: readability-identifier-naming.LocalVariableCase, value: lower_case }
# Parámetros de función
- { key: readability-identifier-naming.ParameterCase, value: lower_case }
# Variables estáticas no-const (static locales, static file-scope,
# y static members no-const de clase como el instance_ de un Singleton).
# Sufijo _ para marcar que tienen storage estático.
- { key: readability-identifier-naming.StaticVariableCase, value: lower_case }
- { key: readability-identifier-naming.StaticVariableSuffix, value: _ }
# =====================================================================
# MIEMBROS DE CLASE NO-CONST
# =====================================================================
# Privados: snake_case con sufijo _
- { key: readability-identifier-naming.PrivateMemberCase, value: lower_case }
- { key: readability-identifier-naming.PrivateMemberSuffix, value: _ }
# Protegidos: snake_case con sufijo _
- { key: readability-identifier-naming.ProtectedMemberCase, value: lower_case }
- { key: readability-identifier-naming.ProtectedMemberSuffix, value: _ }
# Públicos: snake_case sin sufijo
- { key: readability-identifier-naming.PublicMemberCase, value: lower_case }
# =====================================================================
# TIPOS
# =====================================================================
- { key: readability-identifier-naming.ClassCase, value: CamelCase }
- { key: readability-identifier-naming.StructCase, value: CamelCase }
- { key: readability-identifier-naming.EnumCase, value: CamelCase }
- { key: readability-identifier-naming.UnionCase, value: CamelCase }
- { key: readability-identifier-naming.TypeAliasCase, value: CamelCase }
- { key: readability-identifier-naming.TypedefCase, value: CamelCase }
- { key: readability-identifier-naming.TemplateParameterCase, value: CamelCase }
# Namespaces
- { key: readability-identifier-naming.NamespaceCase, value: CamelCase }
# =====================================================================
# FUNCIONES Y MÉTODOS (incluyendo constexpr)
# =====================================================================
# Un método/función constexpr es un invocable, no una constante → camelBack.
- { key: readability-identifier-naming.FunctionCase, value: camelBack }
- { key: readability-identifier-naming.ConstexprFunctionCase, value: camelBack }
- { key: readability-identifier-naming.MethodCase, value: camelBack }
- { key: readability-identifier-naming.PrivateMethodCase, value: camelBack }
- { key: readability-identifier-naming.ProtectedMethodCase, value: camelBack }
- { key: readability-identifier-naming.PublicMethodCase, value: camelBack }
- { key: readability-identifier-naming.ConstexprMethodCase, value: camelBack }
+97
View File
@@ -0,0 +1,97 @@
#!/usr/bin/env bash
# Pre-commit hook: aplica clang-format als fitxers C++ staged abans del commit.
# - Només toca fitxers staged dins source/ (exclou source/external/ i source/legacy/).
# - Avorta el commit si hi ha canvis NO staged en aquests fitxers (per no incloure'ls sense voler).
set -euo pipefail
if ! command -v clang-format >/dev/null 2>&1; then
echo "pre-commit: clang-format no trobat — saltant format check" >&2
exit 0
fi
mapfile -t STAGED < <(git diff --cached --name-only --diff-filter=ACMR \
| grep -E '^source/.*\.(cpp|hpp|h)$' \
| grep -vE '^source/(external|legacy)/' || true)
if [ ${#STAGED[@]} -eq 0 ]; then
exit 0
fi
UNSTAGED_DIRTY=()
for f in "${STAGED[@]}"; do
if ! git diff --quiet -- "$f"; then
UNSTAGED_DIRTY+=("$f")
fi
done
if [ ${#UNSTAGED_DIRTY[@]} -gt 0 ]; then
echo "pre-commit: aquests fitxers tenen canvis NO staged i estan al commit." >&2
echo " Fes 'git add' o 'git stash' abans de continuar:" >&2
printf ' %s\n' "${UNSTAGED_DIRTY[@]}" >&2
exit 1
fi
clang-format -i "${STAGED[@]}"
git add -- "${STAGED[@]}"
# --- clang-tidy només sobre els fitxers staged ---
if ! command -v clang-tidy >/dev/null 2>&1; then
echo "pre-commit: clang-tidy no trobat — saltant tidy" >&2
exit 0
fi
REPO_ROOT="$(git rev-parse --show-toplevel)"
BUILD_DIR="$REPO_ROOT/build"
if [ ! -f "$BUILD_DIR/compile_commands.json" ]; then
echo "pre-commit: generant compile_commands.json (build dir buit)..." >&2
cmake -S "$REPO_ROOT" -B "$BUILD_DIR" >/dev/null
fi
echo "pre-commit: clang-tidy sobre ${#STAGED[@]} fitxer(s)..." >&2
if ! clang-tidy -p "$BUILD_DIR" --quiet "${STAGED[@]}"; then
echo "pre-commit: clang-tidy ha trobat errors — commit avortat" >&2
exit 1
fi
# --- cppcheck només sobre els .cpp staged ---
if ! command -v cppcheck >/dev/null 2>&1; then
echo "pre-commit: cppcheck no trobat — saltant cppcheck" >&2
exit 0
fi
CPP_STAGED=()
for f in "${STAGED[@]}"; do
[[ "$f" == *.cpp ]] && CPP_STAGED+=("$f")
done
if [ ${#CPP_STAGED[@]} -eq 0 ]; then
exit 0
fi
echo "pre-commit: cppcheck sobre ${#CPP_STAGED[@]} fitxer(s)..." >&2
# Nota: el path d'inclusió ha d'anar en relatiu. Amb path absolut, cppcheck
# falla a parsejar "enum class X : std::uint8_t" (no resol <cstdint> bé) i
# emet un syntaxError fals. Els hooks de git s'executen sempre des de la
# rel del repo, així que "source" relatiu és prou.
if ! cppcheck \
--enable=warning,style,performance,portability \
--std=c++20 \
--language=c++ \
--inline-suppr \
--suppress=missingIncludeSystem \
--suppress=toomanyconfigs \
--suppress='*:*source/external/*' \
--suppress='*:*source/legacy/*' \
--suppress=normalCheckLevelMaxBranches \
--suppress=useStlAlgorithm \
-D_DEBUG \
-DLINUX_BUILD \
--quiet \
--error-exitcode=1 \
-I source \
"${CPP_STAGED[@]}"; then
echo "pre-commit: cppcheck ha trobat errors — commit avortat" >&2
exit 1
fi
+108
View File
@@ -0,0 +1,108 @@
# IDEs and Editors
.vscode/*
.idea/
*.swp
*.swo
*~
# Build directories
build/
bin/
out/
cmake-build-*/
# Executables
orni
asteroids
*.exe
*.out
*.app
tools/pack_resources/pack_resources
tools/pack_resources/pack_resources.exe
# Releases
*.zip
*.tar.gz
*.dmg
dist/
# Generated resources
resources.pack
release/windows/*.res
# Compiled Object files
*.o
*.obj
*.ko
*.elf
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.so.*
*.dylib
*.dll
# Compiled Static libraries
*.a
*.lib
*.la
*.lo
# CMake
CMakeCache.txt
CMakeFiles/
CMakeScripts/
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps/
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
*.ilk
# Core dumps
# core
# core.*
# *.core
# macOS
.DS_Store
.AppleDouble
.LSOverride
._*
# Windows
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
*.stackdump
[Dd]esktop.ini
# Linux
*~
.directory
.fuse_hidden*
.Trash-*
.nfs*
# Temporary files
*.tmp
*.temp
*.log
*.bak
*.swp
*.swo
.cache/
.claude/lint-reports/
lint-reports/
-151
View File
@@ -1,151 +0,0 @@
uses crt,keyboard;
const
marge_dalt=10;
marge_baix=192;
marge_esq=7;
marge_dret=312;
type
ipunt=RECORD r,angle:real; END;
punt=RECORD x,y:integer; END;
triangle=RECORD p1,p2,p3:ipunt;
centre:punt;
angle:real;
velocitat:real;
END;
procedure MCGA;
begin
asm
mov ax,0013h
int 10h
end;
directvideo:= false;
end;
procedure Text;
begin
asm
mov ax,0003h
int 10h
end;
end;
procedure WaitRetrace; assembler;
label
l1,l2;
asm
mov dx,3DAh
l1:
in al,dx
and al,08h
jnz l1
l2:
in al,dx
and al,08h
jz l2
end;
procedure posa(x,y:word;color:byte);
begin
mem[$A000:y*320+x]:=color;
end;
procedure linea(x1,y1,x2,y2,color:word);
function sign(x:integer):integer; {like sgn(x) in basic}
begin if x<0 then sign:=-1 else if x>0 then sign:=1 else sign:=0 end;
var
x,y,count,xs,ys,xm,ym:integer;
begin
x:=x1;y:=y1;
xs:=x2-x1; ys:=y2-y1;
xm:=sign(xs); ym:=sign(ys);
xs:=abs(xs); ys:=abs(ys);
posa(x,y,color);
if xs > ys
then begin {flat line <45 deg}
count:=-(xs div 2);
while (x <> x2 ) do begin
count:=count+ys;
x:=x+xm;
if count>0 then begin
y:=y+ym;
count:=count-xs;
end;
posa(x,y,color);
end;
end
else begin {steep line >=45 deg}
count:=-(ys div 2);
while (y <> y2 ) do begin
count:=count+xs;
y:=y+ym;
if count>0 then begin
x:=x+xm;
count:=count-ys;
end;
posa(x,y,color);
end;
end;
end;
procedure rota_tri(tri:triangle;angul,velocitat:real;color:byte);
var x1,x2,x3,y1,y2,y3:word;
begin
x1:=round((tri.p1.r+velocitat/2)*cos(tri.p1.angle+angul))+tri.centre.x;
x2:=round((tri.p2.r+velocitat/2)*cos(tri.p2.angle+angul+velocitat/5))+tri.centre.x;
x3:=round((tri.p3.r+velocitat/2)*cos(tri.p3.angle+angul-velocitat/5))+tri.centre.x;
y1:=round((tri.p1.r+velocitat/2)*sin(tri.p1.angle+angul))+tri.centre.y;
y2:=round((tri.p2.r+velocitat/2)*sin(tri.p2.angle+angul+velocitat/5))+tri.centre.y;
y3:=round((tri.p3.r+velocitat/2)*sin(tri.p3.angle+angul-velocitat/5))+tri.centre.y;
linea(x1,y1,x2,y2,color);
linea(x1,y1,x3,y3,color);
linea(x3,y3,x2,y2,color);
end;
var nau:triangle;
ang:real;
ch:char;
Dx,Dy:word;
begin
nau.p1.r:=6;nau.p1.angle:=3*pi/2;
nau.p2.r:=6;nau.p2.angle:=pi/4;
nau.p3.r:=6;nau.p3.angle:=(3*pi)/4;
nau.angle:=0;
nau.centre.x:=160;nau.centre.y:=100;
instalarkb;
mcga;
repeat
waitretrace;
rota_tri(nau,nau.angle,nau.velocitat,0);
if teclapuls(KEYarrowright) then nau.angle:=nau.angle+0.157079632;
if teclapuls(KEYarrowleft) then nau.angle:=nau.angle-0.157079632;
if teclapuls(KEYarrowup) then begin
if nau.velocitat<3 then nau.velocitat:=nau.velocitat+0.1;
end;
Dy:=round(nau.velocitat*sin(nau.angle-pi/2))+nau.centre.y;
Dx:=round(nau.velocitat*cos(nau.angle-pi/2))+nau.centre.x;
if (dy>marge_dalt) and (dy<marge_baix) then
nau.centre.y:=Dy;
if (dx>marge_esq) and (dx<marge_dret) then
nau.centre.x:=Dx;
if (nau.velocitat>0.05) then nau.velocitat:=nau.velocitat-0.05;
rota_tri(nau,nau.angle,nau.velocitat,2);
until teclapuls(keyesc);
desinstalarkb;
text;
end.
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

+287
View File
@@ -0,0 +1,287 @@
cmake_minimum_required(VERSION 3.16)
project(orni VERSION 0.8.0 LANGUAGES CXX)
# Info del projecte (font de veritat per a project.h)
set(PROJECT_LONG_NAME "Orni Attack")
set(PROJECT_COPYRIGHT "© 2026 JailDesigner")
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
endif()
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# --- GENERACIÓ DEL project.h AMB GIT HASH ---
# Si GIT_HASH ve passat des de fora (Makefile), l'usem; si no, el resolem amb git.
if(NOT DEFINED GIT_HASH OR GIT_HASH STREQUAL "")
find_package(Git QUIET)
if(GIT_FOUND)
execute_process(
COMMAND ${GIT_EXECUTABLE} rev-parse --short=7 HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
endif()
if(NOT DEFINED GIT_HASH OR GIT_HASH STREQUAL "")
set(GIT_HASH "unknown")
endif()
endif()
configure_file(${CMAKE_SOURCE_DIR}/source/project.h.in ${CMAKE_BINARY_DIR}/project.h @ONLY)
# --- LLISTA DE FONTS (AUTO-DESCOBRIMENT) ---
# Cerquem tots els .cpp dins core/ i game/, més main.cpp. Exclou legacy/.
file(GLOB_RECURSE CORE_SOURCES CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/source/core/*.cpp")
file(GLOB_RECURSE GAME_SOURCES CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/source/game/*.cpp")
file(GLOB_RECURSE EXTERNAL_SOURCES CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/source/external/*.cpp")
set(APP_SOURCES
${CORE_SOURCES}
${GAME_SOURCES}
${EXTERNAL_SOURCES}
source/main.cpp
)
list(FILTER APP_SOURCES EXCLUDE REGEX ".*/legacy/.*")
list(LENGTH APP_SOURCES APP_SOURCES_COUNT)
message(STATUS "Fonts .cpp trobades: ${APP_SOURCES_COUNT}")
# --- SDL3 ---
find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3)
add_executable(${PROJECT_NAME} ${APP_SOURCES})
target_include_directories(${PROJECT_NAME} PRIVATE
"${CMAKE_SOURCE_DIR}/source"
"${CMAKE_BINARY_DIR}"
)
target_link_libraries(${PROJECT_NAME} PRIVATE SDL3::SDL3)
# Silencia warnings de codi de tercers (mateixa filosofia que el
# .clang-tidy a source/external/). Només afecta aquests TUs concrets;
# la resta del codi continua compilant amb -Wall -Wextra -Wpedantic.
if(EXTERNAL_SOURCES)
set_source_files_properties(
${EXTERNAL_SOURCES}
PROPERTIES COMPILE_OPTIONS "-Wno-missing-field-initializers;-Wno-deprecated-declarations"
)
endif()
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Wpedantic)
target_compile_options(${PROJECT_NAME} PRIVATE
$<$<CONFIG:Release>:-O2 -ffunction-sections -fdata-sections>
)
target_compile_definitions(${PROJECT_NAME} PRIVATE
$<$<CONFIG:Debug>:_DEBUG>
$<$<CONFIG:Release>:RELEASE_BUILD>
)
if(APPLE AND MACOSX_BUNDLE)
target_compile_definitions(${PROJECT_NAME} PRIVATE MACOS_BUNDLE)
endif()
if(WIN32)
target_compile_definitions(${PROJECT_NAME} PRIVATE WINDOWS_BUILD)
target_link_libraries(${PROJECT_NAME} PRIVATE mingw32)
target_link_options(${PROJECT_NAME} PRIVATE
-static-libgcc
-static-libstdc++
-static
)
elseif(APPLE)
target_compile_definitions(${PROJECT_NAME} PRIVATE MACOS_BUILD)
target_compile_options(${PROJECT_NAME} PRIVATE -Wno-deprecated)
elseif(UNIX AND NOT APPLE)
target_compile_definitions(${PROJECT_NAME} PRIVATE LINUX_BUILD)
endif()
# --- EINA STANDALONE: pack_resources ---
# Executable auxiliar que empaqueta `data/` a `build/resources.pack`.
# EXCLUDE_FROM_ALL: només es compila quan algun target en depèn (ho fa
# `resource_pack`). Build manual: `cmake --build build --target pack_resources`.
add_executable(pack_resources EXCLUDE_FROM_ALL
tools/pack_resources/pack_resources.cpp
source/core/resources/resource_pack.cpp
)
target_include_directories(pack_resources PRIVATE
"${CMAKE_SOURCE_DIR}/source"
"${CMAKE_BINARY_DIR}"
)
target_compile_options(pack_resources PRIVATE -Wall -Wextra -Wpedantic)
# --- REGENERACIÓ AUTOMÀTICA DE build/resources.pack ---
# A cada build re-empaquetem data/ si algun fitxer dins ha canviat. Evita
# debugar amb un pack obsolet. CONFIGURE_DEPENDS força CMake a re-globbar
# a la pròxima invocació (recull fitxers nous afegits a data/).
file(GLOB_RECURSE DATA_FILES CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/data/*")
set(RESOURCE_PACK "${CMAKE_BINARY_DIR}/resources.pack")
add_custom_command(
OUTPUT ${RESOURCE_PACK}
COMMAND $<TARGET_FILE:pack_resources>
"${CMAKE_SOURCE_DIR}/data"
"${RESOURCE_PACK}"
DEPENDS pack_resources ${DATA_FILES}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Empaquetant data/ → build/resources.pack"
VERBATIM
)
add_custom_target(resource_pack ALL DEPENDS ${RESOURCE_PACK})
add_dependencies(${PROJECT_NAME} resource_pack)
# --- COMPILACIÓ DE SHADERS GLSL → SPIR-V (headers C++ embedits) ---
# Compila els shaders .glsl a SPIR-V i els converteix en headers C++ embedits
# (source/core/rendering/gpu/spv/*.h). Aquests headers es commiteen al repo,
# així que glslc només és necessari quan canvien els .glsl o falten headers.
#
# Per a macOS hi ha a més els headers MSL escrits a mà a source/core/rendering/gpu/msl/.
set(SHADERS_DIR "${CMAKE_SOURCE_DIR}/shaders")
set(HEADERS_DIR "${CMAKE_SOURCE_DIR}/source/core/rendering/gpu/spv")
set(ALL_SHADER_HEADERS
"${HEADERS_DIR}/line_vert_spv.h"
"${HEADERS_DIR}/line_frag_spv.h"
"${HEADERS_DIR}/postfx_vert_spv.h"
"${HEADERS_DIR}/postfx_frag_spv.h"
"${HEADERS_DIR}/bloom_frag_spv.h"
)
set(ALL_SHADER_SOURCES
"${SHADERS_DIR}/line.vert.glsl"
"${SHADERS_DIR}/line.frag.glsl"
"${SHADERS_DIR}/postfx.vert.glsl"
"${SHADERS_DIR}/postfx.frag.glsl"
"${SHADERS_DIR}/bloom.frag.glsl"
)
set(ALL_SHADER_HEADERS_PRESENT TRUE)
foreach(_spv_header IN LISTS ALL_SHADER_HEADERS)
if(NOT EXISTS "${_spv_header}")
set(ALL_SHADER_HEADERS_PRESENT FALSE)
break()
endif()
endforeach()
find_program(GLSLC_EXE NAMES glslc HINTS ${Vulkan_GLSLC_EXECUTABLE})
if(GLSLC_EXE)
add_custom_command(
OUTPUT ${ALL_SHADER_HEADERS}
COMMAND ${CMAKE_COMMAND}
-D GLSLC=${GLSLC_EXE}
-D SHADERS_DIR=${SHADERS_DIR}
-D HEADERS_DIR=${HEADERS_DIR}
-P ${CMAKE_SOURCE_DIR}/tools/shaders/compile_spirv.cmake
DEPENDS ${ALL_SHADER_SOURCES} ${CMAKE_SOURCE_DIR}/tools/shaders/compile_spirv.cmake
COMMENT "Compilant shaders GLSL → headers SPIR-V embedits"
VERBATIM
)
add_custom_target(shaders DEPENDS ${ALL_SHADER_HEADERS})
add_dependencies(${PROJECT_NAME} shaders)
message(STATUS "Shaders: glslc trobat (${GLSLC_EXE}); headers SPV es regeneraran si canvia el GLSL")
elseif(ALL_SHADER_HEADERS_PRESENT)
message(STATUS "Shaders: glslc no trobat — s'usaran els headers SPV ja commiteats al repo")
else()
message(FATAL_ERROR "glslc no trobat i falten headers SPV: instal·la 'shaderc' o 'vulkan-sdk' per generar-los")
endif()
# --- STATIC ANALYSIS / FORMAT TARGETS ---
find_program(CLANG_TIDY_EXE NAMES clang-tidy)
find_program(CLANG_FORMAT_EXE NAMES clang-format)
find_program(CPPCHECK_EXE NAMES cppcheck)
file(GLOB_RECURSE ALL_SOURCE_FILES
"${CMAKE_SOURCE_DIR}/source/*.cpp"
"${CMAKE_SOURCE_DIR}/source/*.hpp"
"${CMAKE_SOURCE_DIR}/source/*.h"
)
list(FILTER ALL_SOURCE_FILES EXCLUDE REGEX ".*/external/.*")
list(FILTER ALL_SOURCE_FILES EXCLUDE REGEX ".*/legacy/.*")
set(CPPCHECK_SOURCES ${ALL_SOURCE_FILES})
list(FILTER CPPCHECK_SOURCES INCLUDE REGEX ".*\\.cpp$")
if(CLANG_TIDY_EXE)
# En macOS, obtenir la ruta del SDK perquè clang-tidy trobe els headers del sistema.
set(CLANG_TIDY_EXTRA_ARGS "")
if(APPLE)
execute_process(
COMMAND xcrun --show-sdk-path
OUTPUT_VARIABLE MACOS_SDK_PATH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(MACOS_SDK_PATH)
set(CLANG_TIDY_EXTRA_ARGS "--extra-arg=-isysroot${MACOS_SDK_PATH}")
message(STATUS "clang-tidy usarà SDK de macOS: ${MACOS_SDK_PATH}")
endif()
endif()
add_custom_target(tidy
COMMAND ${CLANG_TIDY_EXE}
-p ${CMAKE_BINARY_DIR}
${CLANG_TIDY_EXTRA_ARGS}
${ALL_SOURCE_FILES}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Running clang-tidy..."
)
add_custom_target(tidy-fix
COMMAND ${CLANG_TIDY_EXE}
-p ${CMAKE_BINARY_DIR}
${CLANG_TIDY_EXTRA_ARGS}
--fix
${ALL_SOURCE_FILES}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Running clang-tidy with fixes..."
)
else()
message(STATUS "clang-tidy no trobat - targets 'tidy' i 'tidy-fix' no disponibles")
endif()
if(CLANG_FORMAT_EXE)
add_custom_target(format
COMMAND ${CLANG_FORMAT_EXE}
-i
${ALL_SOURCE_FILES}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Running clang-format..."
)
add_custom_target(format-check
COMMAND ${CLANG_FORMAT_EXE}
--dry-run
--Werror
${ALL_SOURCE_FILES}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Checking clang-format..."
)
else()
message(STATUS "clang-format no trobat - targets 'format' i 'format-check' no disponibles")
endif()
if(CPPCHECK_EXE)
add_custom_target(cppcheck
COMMAND ${CPPCHECK_EXE}
--enable=warning,style,performance,portability
--std=c++20
--language=c++
--inline-suppr
--suppress=missingIncludeSystem
--suppress=toomanyconfigs
--suppress=*:*source/external/*
--suppress=*:*source/legacy/*
--suppress=normalCheckLevelMaxBranches
--suppress=useStlAlgorithm
-D_DEBUG
-DLINUX_BUILD
--quiet
-I ${CMAKE_SOURCE_DIR}/source
${CPPCHECK_SOURCES}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Running cppcheck..."
)
else()
message(STATUS "cppcheck no trobat - target 'cppcheck' no disponible")
endif()
-275
View File
@@ -1,275 +0,0 @@
{
-----------------------------------------------------
File: Keyboard.Pas
By: Ronny Wester, ronny@rat.se
Unit to check up/down status of individual key flags.
Written from code I got off rec.games.programmer.
Sorry, I lost the name of the poster.
As most of this code is scancode-dependent some keys
may not be where they "should" on your keyboard.
-----------------------------------------------------
}
unit Keyboard;
interface
uses Dos;
const
keySysReq = $54;
keyCapsLock = $3A;
keyNumLock = $45;
keyScrollLock = $46;
keyLeftCtrl = $1D;
keyLeftAlt = $38;
keyLeftShift = $2A;
keyRightCtrl = $9D;
keyAltGr = $B8;
keyRightShift = $36;
keyEsc = $01;
keyBackspace = $0E;
keyEnter = $1C;
keySpace = $39;
keyTab = $0F;
keyF1 = $3B;
keyF2 = $3C;
keyF3 = $3D;
keyF4 = $3E;
keyF5 = $3F;
keyF6 = $40;
keyF7 = $41;
keyF8 = $42;
keyF9 = $43;
keyF10 = $44;
keyF11 = $57;
keyF12 = $58;
keyA = $1E;
keyB = $30;
keyC = $2E;
keyD = $20;
keyE = $12;
keyF = $21;
keyG = $22;
keyH = $23;
keyI = $17;
keyJ = $24;
keyK = $25;
keyL = $26;
keyM = $32;
keyN = $31;
keyO = $18;
keyP = $19;
keyQ = $10;
keyR = $13;
keyS = $1F;
keyT = $14;
keyU = $16;
keyV = $2F;
keyW = $11;
keyX = $2D;
keyY = $15;
keyZ = $2C;
key1 = $02;
key2 = $03;
key3 = $04;
key4 = $05;
key5 = $06;
key6 = $07;
key7 = $08;
key8 = $09;
key9 = $0A;
key0 = $0B;
keyMinus = $0C;
keyEqual = $0D;
keyLBracket = $1A;
keyRBracket = $1B;
keySemicolon = $27;
keyTick = $28;
keyApostrophe = $29;
keyBackslash = $2B;
keyComma = $33;
keyPeriod = $34;
keySlash = $35;
keyInsert = $D2;
keyDelete = $D3;
keyHome = $C7;
keyEnd = $CF;
keyPageUp = $C9;
keyArrowLeft = $CB;
keyArrowRight = $CD;
keyArrowUp = $C8;
keyArrowDown = $D0;
keyKeypad0 = $52;
keyKeypad1 = $4F;
keyKeypad2 = $50;
keyKeypad3 = $51;
keyKeypad4 = $4B;
keyKeypad5 = $4C;
keyKeypad6 = $4D;
keyKeypad7 = $47;
keyKeypad8 = $48;
keyKeypad9 = $49;
keyKeypadComma = $53;
keyKeypadStar = $37;
keyKeypadMinus = $4A;
keyKeypadPlus = $4E;
keyKeypadEnter = $9C;
keyCtrlPrtScr = $B7;
keyShiftPrtScr = $B7;
keyKeypadSlash = $B5;
keyNames : array [0..255] of PChar =
( { $00 } nil, 'Esc', '1', '2', '3', '4', '5', '6',
{ $08 } '7', '8', '9', '0', '+', 'Apostrophe', 'Backspace', 'Tab',
{ $10 } 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
{ $18 } 'O', 'P', '', '?', 'Enter', 'Left Ctrl', 'A', 'S',
{ $20 } 'D', 'F', 'G', 'H', 'J', 'K', 'L', '™',
{ $28 } 'Ž', '''', 'Left shift', '<', 'Z', 'X', 'C', 'V',
{ $30 } 'B', 'N', 'M', ',', '.', '-', 'Right shift', '* (pad)',
{ $38 } 'Alt', 'Space', 'Caps Lock', 'F1', 'F2', 'F3', 'F4', 'F5',
{ $40 } 'F6', 'F7', 'F8', 'F9', 'F10', 'Num Lock', 'Scroll Lock', '7 (pad)',
{ $48 } '8 (pad)', '9 (pad)', '- (pad)', '4 (pad)', '5 (pad)', '6 (pad)', '+ (pad)', '1 (pad)',
{ $50 } '2 (pad)', '3 (pad)', '0 (pad)', ', (pad)', 'SysRq', nil, nil, 'F11', 'F12',
{ $59 } nil, nil, nil, nil, nil, nil, nil,
{ $60 } nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
{ $70 } nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
{ $80 } nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
{ $90 } nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 'Enter (pad)', 'Right Ctrl', nil, nil,
{ $A0 } nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
{ $B0 } nil, nil, nil, nil, nil, '/ (pad)', nil, 'PrtScr', 'Alt Gr', nil, nil, nil, nil, nil, nil, nil,
{ $C0 } nil, nil, nil, nil, nil, nil, nil, 'Home',
{ $C8 } 'Up arrow', 'Page Up', nil, 'Left arrow', nil, 'Right arrow', nil, 'End',
{ $D0 } 'Down arrow', nil, 'Insert', 'Delete', nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
{ $E0 } nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
{ $F0 } nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil
);
procedure InstalarKb;
procedure DesinstalarKb;
function TeclaPuls( b : byte ) : Boolean;
function QTeclaPuls : Boolean;
function AgarrarTecla : Byte;
procedure BorrarKb;
procedure EscriuKb;
implementation
var
uOldInt9 : Pointer; { saves location of old OldInt9 vector }
uKeys : array [0..255] of Boolean; { array that holds key values }
e0Flag : Byte;
uExitProc : Pointer;
{$F+}
procedure NewInt9; interrupt; assembler;
asm
cli
in al, $60 { get scan code from keyboard port }
cmp al, $E0 { al = $E0 key ? }
jne @@SetScanCode
mov [e0Flag], 128
mov al, 20h { Send 'generic' EOI to PIC }
out 20h, al
jmp @@exit
@@SetScanCode:
mov bl, al { Save scancode in BL }
and bl, 01111111b
add bl, [e0Flag]
xor bh, bh
and al, 10000000b { keep break bit, if set }
xor al, 10000000b { flip bit, 1 means pressed, 0 no }
rol al, 1 { move breakbit to bit 0 }
mov [offset uKeys + bx], al
mov [e0Flag], 0
mov al, 20h { send EOI to PIC }
out 20h, al
@@exit:
sti
end;
{$F-}
procedure InstalarKb;
begin
GetIntVec( $09, uOldInt9); { save old location of INT 09 handler }
SetIntVec( $09, Addr( NewInt9)); { point to new routine }
FillChar( uKeys, SizeOf( uKeys), 0); { clear the keys array }
end;
procedure DesinstalarKb;
begin
SetIntVec( $09, uOldInt9); { point back to original routine }
uOldInt9 := nil;
end;
function TeclaPuls( b : byte ) : Boolean;
begin
TeclaPuls := uKeys[b];
end;
function QTeclaPuls : Boolean;
var b : Integer;
begin
QTeclaPuls := True;
for b := 0 to 255 do
if uKeys[b] and (keyNames[b] <> nil) then
Exit;
QTeclaPuls := False;
end;
function AgarrarTecla : Byte;
var b : Integer;
begin
AgarrarTecla := 0;
for b := 1 to 255 do
if uKeys[b] and (keyNames[b] <> nil) then
begin
AgarrarTecla := b;
Exit;
end;
end;
procedure BorrarKb;
begin
FillChar( uKeys, SizeOf( uKeys), 0); { clear the keys array }
end;
{$F+}
procedure CleanUp;
begin
ExitProc := uExitProc;
if uOldInt9 <> nil then
DesinstalarKb;
end;
procedure EscriuKb;
var b:byte;
begin
for b := 0 to 255 do
if uKeys[b] and (keyNames[b] <> nil) then
write(keyNames[b],' | ');
writeln;
end;
{$F-}
begin
uExitProc := ExitProc;
ExitProc := @CleanUp;
uOldInt9 := nil;
end.
+340
View File
@@ -0,0 +1,340 @@
PROJECT := orni
BUILDDIR := build
# Detecció de plataforma. En Windows CMake defaulteja a "NMake Makefiles"
# (que requereix Visual Studio); forcem MinGW Makefiles per usar el g++ de
# MinGW. nproc tampoc existeix en cmd.exe → fem servir NUMBER_OF_PROCESSORS.
ifeq ($(OS),Windows_NT)
ifneq ($(MSYSTEM),)
NULDEV := /dev/null
else
NULDEV := NUL
endif
JOBS ?= $(NUMBER_OF_PROCESSORS)
HAS_NINJA := $(shell ninja --version 2>$(NULDEV))
ifneq ($(HAS_NINJA),)
CMAKE_GEN := -G "Ninja"
else
CMAKE_GEN := -G "MinGW Makefiles"
endif
else
NULDEV := /dev/null
JOBS ?= $(shell nproc 2>/dev/null || echo 4)
HAS_NINJA := $(shell ninja --version 2>/dev/null)
ifneq ($(HAS_NINJA),)
CMAKE_GEN := -G "Ninja"
else
CMAKE_GEN :=
endif
endif
# VERSION (única font de veritat: CMakeLists.txt project(...) VERSION ...).
# Lazy (=): només es calcula quan s'invoca un target que la usa.
ifeq ($(OS),Windows_NT)
VERSION = v$(shell powershell -Command "(Select-String -Path 'CMakeLists.txt' -Pattern 'project.*VERSION\s+([0-9.]+)').Matches.Groups[1].Value")
else
VERSION = v$(shell grep '^project' CMakeLists.txt | sed -E 's/.*VERSION[[:space:]]+([0-9.]+).*/\1/')
endif
# GIT_HASH calculat al host i passat a CMake (evita problemes si CMake corre en
# entorns sense accés a git).
GIT_HASH := $(shell git rev-parse --short=7 HEAD 2>$(NULDEV))
ifeq ($(GIT_HASH),)
GIT_HASH := unknown
endif
CMAKE_DEFS := -DGIT_HASH=$(GIT_HASH)
# ==============================================================================
# RELEASE — variables d'empaquetat per distribució
# ==============================================================================
APP_NAME := Orni Attack
DIST_DIR := dist
RELEASE_FOLDER := $(DIST_DIR)/_tmp
TARGET_FILE := $(BUILDDIR)/$(PROJECT)
RELEASE_FILE := $(RELEASE_FOLDER)/$(PROJECT)
# Noms dels artefactes finals (amb VERSION i PROJECT)
WINDOWS_RELEASE := $(DIST_DIR)/$(PROJECT)-$(VERSION)-win32-x64.zip
MACOS_APPLE_SILICON_RELEASE := $(DIST_DIR)/$(PROJECT)-$(VERSION)-macos-apple-silicon.dmg
LINUX_RELEASE := $(DIST_DIR)/$(PROJECT)-$(VERSION)-linux.tar.gz
# Variables específiques de Windows (PowerShell). El subst escapa apòstrofs.
ifeq ($(OS),Windows_NT)
WIN_TARGET_FILE := $(BUILDDIR)/$(APP_NAME)
WIN_RELEASE_FILE := $(RELEASE_FOLDER)/$(APP_NAME)
WIN_RELEASE_FILE_PS := $(subst ','',$(WIN_RELEASE_FILE))
UNAME_S :=
else
WIN_TARGET_FILE := $(TARGET_FILE)
WIN_RELEASE_FILE := $(RELEASE_FILE)
WIN_RELEASE_FILE_PS := $(WIN_RELEASE_FILE)
UNAME_S := $(shell uname -s)
endif
# Helpers cross-platform.
ifeq ($(OS),Windows_NT)
RMFILE := del /Q
RMDIR := rmdir /S /Q
MKDIR := mkdir
else
RMFILE := rm -f
RMDIR := rm -rdf
MKDIR := mkdir -p
endif
.PHONY: all debug release _windows-release _macos-release _linux-release \
run run-debug clean rebuild show-version pack \
format format-check tidy tidy-fix cppcheck hooks-install help
# ==============================================================================
# COMPILACIÓ
# ==============================================================================
# make → Release (binari d'ús normal)
# make debug → Debug
# make release → Release + empaquetat per a distribució (zip/dmg/tar.gz segons SO)
# ==============================================================================
all:
@cmake -S . -B $(BUILDDIR) $(CMAKE_GEN) -DCMAKE_BUILD_TYPE=Release $(CMAKE_DEFS)
@cmake --build $(BUILDDIR) -j$(JOBS)
debug:
@cmake -S . -B $(BUILDDIR) $(CMAKE_GEN) -DCMAKE_BUILD_TYPE=Debug $(CMAKE_DEFS)
@cmake --build $(BUILDDIR) -j$(JOBS)
run: all
@./$(BUILDDIR)/$(PROJECT)
run-debug: debug
@./$(BUILDDIR)/$(PROJECT)
# Release + empaquetat: detecta el SO i delega al sub-target corresponent.
release:
ifeq ($(OS),Windows_NT)
@"$(MAKE)" _windows-release
else
ifeq ($(UNAME_S),Darwin)
@$(MAKE) _macos-release
else
@$(MAKE) _linux-release
endif
endif
# ==============================================================================
# RELEASE — Linux (.tar.gz)
# ==============================================================================
_linux-release:
@echo "Creando release para Linux - Version: $(VERSION)"
# Compila Release (genera resources.pack i binari)
@cmake -S . -B $(BUILDDIR) $(CMAKE_GEN) -DCMAKE_BUILD_TYPE=Release $(CMAKE_DEFS)
@cmake --build $(BUILDDIR) -j$(JOBS)
# Recrea la carpeta temporal
@$(MKDIR) "$(DIST_DIR)" 2>/dev/null || true
@$(RMDIR) "$(RELEASE_FOLDER)" 2>/dev/null || true
$(MKDIR) "$(RELEASE_FOLDER)"
# Còpia de fitxers
cp $(BUILDDIR)/resources.pack "$(RELEASE_FOLDER)"
cp README.md "$(RELEASE_FOLDER)"
@[ -f LICENSE ] && cp LICENSE "$(RELEASE_FOLDER)" || true
cp "$(TARGET_FILE)" "$(RELEASE_FILE)"
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE)" --strip-unneeded
# Empaqueta a .tar.gz
$(RMFILE) "$(LINUX_RELEASE)"
tar -czvf "$(LINUX_RELEASE)" -C "$(RELEASE_FOLDER)" .
@echo "Release creado: $(LINUX_RELEASE)"
# Neteja la carpeta temporal
$(RMDIR) "$(RELEASE_FOLDER)"
# ==============================================================================
# RELEASE — Windows (.zip)
# ==============================================================================
_windows-release:
@echo off
@echo Creando release para Windows - Version: $(VERSION)
@cmake -S . -B $(BUILDDIR) $(CMAKE_GEN) -DCMAKE_BUILD_TYPE=Release $(CMAKE_DEFS)
@cmake --build $(BUILDDIR) -j$(JOBS)
@powershell -Command "if (-not (Test-Path '$(DIST_DIR)')) {New-Item '$(DIST_DIR)' -ItemType Directory}"
@powershell -Command "if (Test-Path '$(RELEASE_FOLDER)') {Remove-Item '$(RELEASE_FOLDER)' -Recurse -Force}"
@powershell -Command "if (-not (Test-Path '$(RELEASE_FOLDER)')) {New-Item '$(RELEASE_FOLDER)' -ItemType Directory}"
@powershell -Command "Copy-Item -Path '$(BUILDDIR)/resources.pack' -Destination '$(RELEASE_FOLDER)'"
@powershell -Command "if (Test-Path 'LICENSE') { Copy-Item 'LICENSE' -Destination '$(RELEASE_FOLDER)' }"
@powershell -Command "Copy-Item 'README.md' -Destination '$(RELEASE_FOLDER)'"
@powershell -Command "if (Test-Path 'release\windows\dll') { Copy-Item 'release\windows\dll\*.dll' -Destination '$(RELEASE_FOLDER)' }"
@powershell -Command "Copy-Item -Path '$(TARGET_FILE).exe' -Destination '$(WIN_RELEASE_FILE_PS).exe'"
strip -s -R .comment -R .gnu.version "$(WIN_RELEASE_FILE).exe" --strip-unneeded
@powershell -Command "if (Test-Path '$(WINDOWS_RELEASE)') {Remove-Item '$(WINDOWS_RELEASE)'}"
@powershell -Command "Compress-Archive -Path '$(RELEASE_FOLDER)/*' -DestinationPath '$(WINDOWS_RELEASE)'"
@echo Release creado: $(WINDOWS_RELEASE)
@powershell -Command "if (Test-Path '$(RELEASE_FOLDER)') {Remove-Item '$(RELEASE_FOLDER)' -Recurse -Force}"
# ==============================================================================
# RELEASE — macOS (.dmg per Apple Silicon)
# ==============================================================================
_macos-release:
@echo "Creando release para macOS - Version: $(VERSION)"
# Verificar/instal·lar create-dmg si cal
@which create-dmg > /dev/null || (echo "Instalando create-dmg..." && brew install create-dmg)
# Compila la versió Apple Silicon
@cmake -S . -B $(BUILDDIR)/arm $(CMAKE_GEN) -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 \
-DMACOS_BUNDLE=ON $(CMAKE_DEFS)
@cmake --build $(BUILDDIR)/arm -j$(JOBS)
# Neteja artefactes anteriors
@$(MKDIR) "$(DIST_DIR)" 2>/dev/null || true
$(RMDIR) "$(RELEASE_FOLDER)" 2>/dev/null || true
$(RMFILE) "$(DIST_DIR)"/rw.* 2>/dev/null || true
$(RMFILE) "$(MACOS_APPLE_SILICON_RELEASE)"
# Crea l'estructura del bundle .app
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks"
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS"
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
# Còpia de recursos i metadades del bundle
cp $(BUILDDIR)/arm/resources.pack "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
cp -R release/macos/frameworks/SDL3.xcframework/macos-arm64_x86_64/SDL3.framework "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks"
cp release/icons/icon.icns "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
cp release/macos/Info.plist "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents"
@[ -f LICENSE ] && cp LICENSE "$(RELEASE_FOLDER)" || true
cp README.md "$(RELEASE_FOLDER)"
# Recreate framework symlinks (Versions/Current i top-level)
@cd "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks/SDL3.framework" && \
rm -f SDL3 Headers Resources && \
ln -s Versions/Current/SDL3 SDL3 && \
ln -s Versions/Current/Headers Headers && \
ln -s Versions/Current/Resources Resources
@cd "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks/SDL3.framework/Versions" && \
rm -f Current && ln -s A Current
# Actualitza Info.plist amb VERSION i metadades
@echo "Actualizando Info.plist con versión $(VERSION)..."
@RAW_VERSION=$$(echo "$(VERSION)" | sed 's/^v//'); \
sed -i '' '/<key>CFBundleShortVersionString<\/key>/{n;s|<string>.*</string>|<string>'"$$RAW_VERSION"'</string>|;}' "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Info.plist"; \
sed -i '' '/<key>CFBundleVersion<\/key>/{n;s|<string>.*</string>|<string>'"$$RAW_VERSION"'</string>|;}' "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Info.plist"; \
sed -i '' '/<key>CFBundleExecutable<\/key>/{n;s|<string>.*</string>|<string>$(PROJECT)</string>|;}' "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Info.plist"; \
sed -i '' '/<key>CFBundleName<\/key>/{n;s|<string>.*</string>|<string>$(APP_NAME)</string>|;}' "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Info.plist"; \
sed -i '' '/<key>CFBundleDisplayName<\/key>/{n;s|<string>.*</string>|<string>$(APP_NAME)</string>|;}' "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Info.plist"
# Còpia del binari al bundle
cp "$(BUILDDIR)/arm/$(PROJECT)" "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(PROJECT)"
# Firma ad-hoc del bundle
codesign --deep --force --sign - --timestamp=none "$(RELEASE_FOLDER)/$(APP_NAME).app"
# Empaqueta el .dmg
@echo "Creando DMG Apple Silicon con iconos de 96x96..."
create-dmg \
--volname "$(APP_NAME)" \
--window-pos 200 120 \
--window-size 720 300 \
--icon-size 96 \
--text-size 12 \
--icon "$(APP_NAME).app" 278 102 \
--icon "LICENSE" 441 102 \
--icon "README.md" 604 102 \
--app-drop-link 115 102 \
--hide-extension "$(APP_NAME).app" \
"$(MACOS_APPLE_SILICON_RELEASE)" \
"$(RELEASE_FOLDER)" || true
@echo "Release Apple Silicon creado: $(MACOS_APPLE_SILICON_RELEASE)"
# Neteja temporals
$(RMDIR) "$(RELEASE_FOLDER)"
$(RMDIR) $(BUILDDIR)/arm
$(RMFILE) "$(DIST_DIR)"/rw.* 2>/dev/null || true
show-version:
@echo "$(PROJECT) $(VERSION) ($(GIT_HASH))"
clean:
@rm -rf $(BUILDDIR) $(DIST_DIR)
rebuild: clean all
# Empaqueta data/ a $(BUILDDIR)/resources.pack. Força un rebuild del pack encara
# que res no hagi canviat dins data/. L'empaquetat també es fa automàticament a
# cada `make`/`make debug` via el target CMake `resource_pack`.
pack:
@cmake -S . -B $(BUILDDIR) $(CMAKE_GEN) $(CMAKE_DEFS)
@cmake --build $(BUILDDIR) --target pack_resources
@./$(BUILDDIR)/pack_resources data $(BUILDDIR)/resources.pack
# ==============================================================================
# CODE QUALITY (delegats a cmake)
# ==============================================================================
format:
@cmake -S . -B $(BUILDDIR) $(CMAKE_GEN) -DCMAKE_BUILD_TYPE=Release $(CMAKE_DEFS)
@cmake --build $(BUILDDIR) --target format
format-check:
@cmake -S . -B $(BUILDDIR) $(CMAKE_GEN) -DCMAKE_BUILD_TYPE=Release $(CMAKE_DEFS)
@cmake --build $(BUILDDIR) --target format-check
tidy:
@cmake -S . -B $(BUILDDIR) $(CMAKE_GEN) -DCMAKE_BUILD_TYPE=Release $(CMAKE_DEFS)
@cmake --build $(BUILDDIR) --target tidy
tidy-fix:
@cmake -S . -B $(BUILDDIR) $(CMAKE_GEN) -DCMAKE_BUILD_TYPE=Release $(CMAKE_DEFS)
@cmake --build $(BUILDDIR) --target tidy-fix
cppcheck:
@cmake -S . -B $(BUILDDIR) $(CMAKE_GEN) -DCMAKE_BUILD_TYPE=Release $(CMAKE_DEFS)
@cmake --build $(BUILDDIR) --target cppcheck
# ==============================================================================
# GIT HOOKS
# ==============================================================================
hooks-install:
@git config core.hooksPath .githooks
@echo "Git hooks activats: $(shell pwd)/.githooks"
# ==============================================================================
# AJUDA
# ==============================================================================
help:
@echo "Makefile per a $(PROJECT)"
@echo ""
@echo " Compilació:"
@echo " make - Compilar amb cmake (Release)"
@echo " make debug - Compilar amb cmake (Debug)"
@echo ""
@echo " Execució:"
@echo " make run - Compilar (Release) i executar"
@echo " make run-debug - Compilar (Debug) i executar"
@echo ""
@echo " Release:"
@echo " make release - Release + empaquetat (zip/dmg/tar.gz segons SO)"
@echo ""
@echo " Recursos:"
@echo " make pack - Empaquetar data/ a $(BUILDDIR)/resources.pack"
@echo ""
@echo " Qualitat de codi:"
@echo " make format - Formatar codi amb clang-format"
@echo " make format-check - Verificar format sense modificar"
@echo " make tidy - Anàlisi estàtic amb clang-tidy"
@echo " make tidy-fix - Anàlisi estàtic amb auto-fix"
@echo " make cppcheck - Anàlisi estàtic amb cppcheck"
@echo ""
@echo " Altres:"
@echo " make clean - Esborrar $(BUILDDIR)/ i $(DIST_DIR)/"
@echo " make rebuild - clean + all"
@echo " make show-version - Mostrar versió"
@echo " make hooks-install - Activar git hooks del projecte"
@echo ""
@echo " Versió actual: $(VERSION) ($(GIT_HASH))"
+65 -14
View File
@@ -1,20 +1,71 @@
# Asteroids
<div align="center">
<img src="https://php.sustancia.synology.me/images/orni_attack/orni_attack_1.png" width="600" alt="Orni Attack">
</div>
# Orni Attack
Destrueix als cosinus mesisinus que ens ataquen montats en ORNIs!
<img width="752" src="https://user-images.githubusercontent.com/110221325/184473983-a07c8594-f87c-4e6a-b723-b0a0f8d08e85.png">
---
## Controls
* `cursor amunt` accelerar
* `cursor avall` frenar
* `cursor dreta` rotar en el sentit de les agulles del rellotge
* `cursor esquerra`rotar en l'altre sentit
* `espai` disparar
* `esc` eixir
Nomes tens una bala a l'hora. Crec que els teus dispars encara no fan pupa als ORNIs. Pero si ells te toquen sí que rebentes.
## Com jugar hui en dia
El joc permet l'ús del teclat per a controlar la nau i la finestra. Les tecles són les següents:
Amb DosBox. Augmenta cicles, uns 30000 en el meu macbook.
| Tecla | Acció |
|-------|-------|
| **↑** | Accelerar la nau |
| **↓** | Frenar |
| **←** | Rotar a l'esquerra |
| **→** | Rotar a la dreta |
| **Espai** | Disparar |
| **ESC** | Eixir del joc |
| **F1** | Disminuir la mida de la finestra |
| **F2** | Augmentar la mida de la finestra |
| **F3** | Alternar pantalla completa |
## Com compilar hui en dia
---
Turbo Pascal 7 desde DosBox. No m'ha fet falta activar res.
## Compilació i execució
### Compilar el joc
```bash
make # Compilar
make debug # Compilació en mode debug
make clean # Netejar fitxers compilats
./orni # Executar
```
### Crear versions release
```bash
make macos_release # macOS .app bundle + .dmg (Apple Silicon)
make linux_release # Linux .tar.gz
make windows_release # Windows .zip (requereix MinGW a Windows)
make windows_cross # Cross-compilació Windows des de Linux/macOS
make rpi_release # Raspberry Pi ARM64 cross-compilació
```
---
## Requisits
- **C++20** compatible compiler
- **SDL3** library
- **CMake** 3.15 o superior
### Plataformes suportades
- macOS (Apple Silicon i Intel)
- Linux (x86_64)
- Windows (MinGW)
- Raspberry Pi (ARM64)
---
## Història
Joc original creat en **Turbo Pascal 7 per a DOS** (1999), ara migrat a **C++20 amb SDL3**. Aquest port modern preserva la jugabilitat i l'estètica de l'original mentre aprofita les capacitats dels sistemes actuals.
**Versió actual**: BETA 3.0
+40
View File
@@ -0,0 +1,40 @@
# postfx.yaml - Parámetros del shader de postprocesado
#
# Este archivo configura el pase final del renderer (bloom + flicker +
# background pulse). Se carga al iniciar el juego desde resources.pack.
# Si falta o tiene errores, se usan los valores por defecto de
# Defaults::PostFx (defaults.hpp).
#
# Tip de tuning:
# - Para más "neón vector", sube bloom.intensity y bloom.radius_px.
# - Para más "CRT viejo", sube flicker.amplitude (riesgo de mareo si >0.3).
# - Background es muy sutil; pasa los componentes G a 0.15-0.20 para
# un fondo verde-tenue más marcado.
# Bloom / glow: separable gaussian blur de dues passes (H + V).
# Equivalent matemàtic d'un kernel 15×15 dens (225 mostres) però només cosTa
# 30 mostres per píxel. Sense moiré: sigma_px controla l'amplada del halo.
bloom:
enabled: true
intensity: 1.8 # 0..2 — cuanto del bloom se suma a la imagen
threshold: 0.20 # 0..1 — luminància mínima que aporta al bloom
sigma_px: 5.0 # sigma de la gaussiana en texels (~1.5..6 raonable;
# halo ≈ 3·sigma a cada banda. 3.5 → halo de ~10 px)
# Flicker: modulación global de brillo (efecto fósforo CRT).
# Sustituye a la antigua oscilación CPU del ColorOscillator.
# Solo afecta a `(lines + bloom)` en el shader; NO toca el fondo, así que
# los píxeles negros siguen siendo negros (no pulsan).
flicker:
enabled: true
amplitude: 0.18 # 0..1 — profundidad del flicker
frequency_hz: 6.0 # Hz — velocidad de la pulsación
# Background pulse: color de fondo oscilante (suma aditiva).
# Desactivado: fondo negro puro. Se mantienen los valores por si queremos
# reactivar más adelante un tinte verdoso muy tenue al estilo CRT.
background:
enabled: false
color_min: [0, 0, 0] # negro puro
color_max: [0, 0, 0] # negro puro
pulse_frequency_hz: 6.0 # Hz — sincronizado con flicker por defecto
+22
View File
@@ -0,0 +1,22 @@
name: bullet
# Shape de la bala. El bounding_radius del .shp dóna el hitbox base (~3 px);
# scale el modula visualment i pel hitbox.
shape:
path: bullet.shp
scale: 1.0
collision_factor: 1.0
# Cinemàtica pura: la bala no col·lisiona físicament al PhysicsWorld
# (body_.radius = 0 al spawn), però sí participa al gameplay via
# checkCollisionSwept. La mass i l'impact_momentum_factor es fan servir
# només per calcular l'impuls que rep l'enemic en impactar.
physics:
mass: 0.5
restitution: 0.0 # irrelevant (no rebota)
linear_damping: 0.0 # movement rectilini uniforme
angular_damping: 0.0
impact_momentum_factor: 3.0 # factor de transferència de moment bala→enemic
colors:
normal: [155, 255, 175] # verd laser
+68
View File
@@ -0,0 +1,68 @@
name: pentagon
ai_type: pentagon # Validat contra el directori; mapeja a EnemyType::PENTAGON.
shape:
path: enemy_pentagon.shp
scale: 1.0 # multiplicador visual + hitbox sobre la mida nativa del .shp
collision_factor: 1.0 # ajust opcional del hitbox (default 1.0)
physics:
mass: 5.0
speed: 35.0 # px/s (esquivador lent)
rotation_delta_min: 0.75 # rad/s — rotació visual mínima
rotation_delta_max: 3.75 # rad/s — rotació visual màxima
restitution: 1.0 # rebot elàstic perfecte contra parets
linear_damping: 0.0 # manté velocitat (sense fricció)
angular_damping: 0.0
behavior:
# Pentagon: zigzag esquivador (canvi de direcció probabilístic per segon).
angle_change_max: 1.0 # rad — magnitud del canvi de direcció
zigzag_prob_per_second: 0.8
animation:
pulse: # respiració d'escala aleatòria
trigger_prob_per_second: 0.01
duration_min: 1.0
duration_max: 3.0
amplitude_min: 0.08
amplitude_max: 0.20
frequency_min: 1.5
frequency_max: 3.0
rotation_accel: # acceleració/desacceleració de rotació visual
trigger_prob_per_second: 0.02
duration_min: 3.0
duration_max: 8.0
multiplier_min: 0.3
multiplier_max: 4.0
wounded:
duration: 1.0 # segons en estat ferit abans d'explotar
blink_hz: 10.0 # parpelleig color normal ↔ wounded
spawn:
invulnerability_duration: 3.0
invulnerability_brightness_start: 0.3
invulnerability_brightness_end: 0.7
invulnerability_scale_start: 0.0
invulnerability_scale_end: 1.0
safety_distance: 36.0 # px mínim respecte al player al spawn
colors:
normal: [0, 255, 255] # Cyan pur "esquivador"
wounded: [255, 220, 60] # Daurat (parpelleig al rebre impacte)
score: 100
events:
# Comportament clàssic: dos impactes per matar (set_hurt entra wounded;
# el segon hit detecta wounded i destrueix automàticament).
on_hit:
- action: apply_impulse
- action: set_hurt
on_hurt_end:
- action: destroy
on_destroy:
- action: add_score
- action: create_debris
- action: create_fireworks
+66
View File
@@ -0,0 +1,66 @@
name: pinwheel
ai_type: pinwheel # Validat contra el directori; mapeja a EnemyType::PINWHEEL.
shape:
path: enemy_pinwheel.shp
scale: 1.0 # multiplicador visual + hitbox sobre la mida nativa del .shp
collision_factor: 1.0 # ajust opcional del hitbox (default 1.0)
physics:
mass: 4.0 # Més lleuger — àgil
speed: 50.0 # px/s (el més ràpid)
rotation_delta_min: 3.0 # rad/s — rotació base elevada
rotation_delta_max: 6.0
restitution: 1.0
linear_damping: 0.0
angular_damping: 0.0
behavior:
# Pinwheel: movement rectilíniauniforme + boost de rotació visual prop de la nau.
rotation_proximity_multiplier: 3.0 # Multiplicador de rotació quan és prop de la nau
proximity_distance: 100.0 # Llindar de distància (px)
animation:
pulse:
trigger_prob_per_second: 0.01
duration_min: 1.0
duration_max: 3.0
amplitude_min: 0.08
amplitude_max: 0.20
frequency_min: 1.5
frequency_max: 3.0
rotation_accel:
trigger_prob_per_second: 0.02
duration_min: 3.0
duration_max: 8.0
multiplier_min: 0.3
multiplier_max: 4.0
wounded:
duration: 1.0
blink_hz: 10.0
spawn:
invulnerability_duration: 3.0
invulnerability_brightness_start: 0.3
invulnerability_brightness_end: 0.7
invulnerability_scale_start: 0.0
invulnerability_scale_end: 1.0
safety_distance: 36.0
colors:
normal: [255, 0, 255] # Magenta pur "agressiu"
wounded: [255, 220, 60]
score: 200
events:
on_hit:
- action: apply_impulse
- action: set_hurt
on_hurt_end:
- action: destroy
on_destroy:
- action: add_score
- action: create_debris
- action: create_fireworks
+49
View File
@@ -0,0 +1,49 @@
name: player_ship
# Shape de la nau. Resolt per ShapeLoader (busca a "shapes/<path>").
# Nota: el segon jugador rep un override del shape ("ship2.shp") al ctor.
# Quan s'introdueixin variants reals de nau, es crearà un YAML separat
# per cada model.
#
# scale: multiplicador visual i de hitbox sobre la mida nativa del .shp (1.0 = mida del fitxer).
# collision_factor: ajust opcional del hitbox respecte el cercle circumscrit
# automàtic de la shape; tocar només si el feel del hitbox
# no quadra amb la silueta visual (default 1.0).
shape:
path: ship.shp
scale: 1.0
collision_factor: 1.0
physics:
mass: 10.0
restitution: 0.6
linear_damping: 1.5
angular_damping: 0.0
rotation_speed: 3.14 # rad/s (~180 deg/s, input-driven sense inercia)
acceleration: 400.0 # px/s^2 multiplicat per la massa quan THRUST
max_velocity: 180.0 # px/s (clamp post-integració per preservar feel arcade)
# Factor de transferència del moment lineal de la nau a l'enemic en el
# frame exacte que mor per col·lisió (afegit per damunt del rebot natural).
death_impact_factor: 0.3
invulnerability:
duration: 3.0 # segons d'invulnerabilitat post-respawn
blink_visible: 0.1 # segons visible per cicle de parpelleig
blink_invisible: 0.1 # segons invisible per cicle de parpelleig
hurt:
duration: 15.0 # segons en estat "ferit" abans de tornar a normal
blink_hz: 10.0 # freqüència parpelleig color normal <-> color hurt
# Empenta visual: la nau s'escala lleugerament amb la velocitat.
# Manté la sensació del Pascal original (0..MAX_VEL → 1.0..~1.5).
visual_thrust:
push_divisor: 33.33
scale_divisor: 12.0
colors:
normal: [255, 255, 255] # blanc neutre
hurt: [255, 220, 60] # daurat (estat ferit)
weapon:
bullet_speed: 700.0 # velocitat escalar de la bullet (px/s)
+66
View File
@@ -0,0 +1,66 @@
name: square
ai_type: square # Validat contra el directori; mapeja a EnemyType::SQUARE.
shape:
path: enemy_square.shp
scale: 1.0 # multiplicador visual + hitbox sobre la mida nativa del .shp
collision_factor: 1.0 # ajust opcional del hitbox (default 1.0)
physics:
mass: 8.0 # Més pesat — "tanc"
speed: 40.0 # px/s (velocitat mitjana)
rotation_delta_min: 0.3 # rad/s — rotació lenta
rotation_delta_max: 1.5
restitution: 1.0
linear_damping: 0.0
angular_damping: 0.0
behavior:
# Square: tracking discret cap a la nau cada N segons.
tracking_strength: 0.5 # Interpolació LERP cap a la direcció desitjada (0..1)
tracking_interval: 1.0 # segons entre updates d'angle
animation:
pulse:
trigger_prob_per_second: 0.01
duration_min: 1.0
duration_max: 3.0
amplitude_min: 0.08
amplitude_max: 0.20
frequency_min: 1.5
frequency_max: 3.0
rotation_accel:
trigger_prob_per_second: 0.02
duration_min: 3.0
duration_max: 8.0
multiplier_min: 0.3
multiplier_max: 4.0
wounded:
duration: 1.0
blink_hz: 10.0
spawn:
invulnerability_duration: 3.0
invulnerability_brightness_start: 0.3
invulnerability_brightness_end: 0.7
invulnerability_scale_start: 0.0
invulnerability_scale_end: 1.0
safety_distance: 36.0
colors:
normal: [255, 0, 0] # Roig pur "tanc"
wounded: [255, 220, 60]
score: 150
events:
on_hit:
- action: apply_impulse
- action: set_hurt
on_hurt_end:
- action: destroy
on_destroy:
- action: add_score
- action: create_debris
- action: create_fireworks
+65
View File
@@ -0,0 +1,65 @@
name: star
ai_type: star # Validat contra el directori; mapeja a EnemyType::STAR.
shape:
path: star_5.shp
scale: 0.7 # Lleugerament més petit que els altres enemics per diferenciar visualment.
collision_factor: 1.0
physics:
mass: 5.0
speed: 35.0 # Mateixos paràmetres que pentagon (esquivador lent).
rotation_delta_min: 0.75
rotation_delta_max: 3.75
restitution: 1.0
linear_damping: 0.0
angular_damping: 0.0
behavior:
# Hereta el comportament de Pentagon (zigzag esquivador).
angle_change_max: 1.0
zigzag_prob_per_second: 0.8
animation:
pulse:
trigger_prob_per_second: 0.01
duration_min: 1.0
duration_max: 3.0
amplitude_min: 0.08
amplitude_max: 0.20
frequency_min: 1.5
frequency_max: 3.0
rotation_accel:
trigger_prob_per_second: 0.02
duration_min: 3.0
duration_max: 8.0
multiplier_min: 0.3
multiplier_max: 4.0
wounded:
duration: 1.0
blink_hz: 10.0
spawn:
invulnerability_duration: 3.0
invulnerability_brightness_start: 0.3
invulnerability_brightness_end: 0.7
invulnerability_scale_start: 0.0
invulnerability_scale_end: 1.0
safety_distance: 36.0
colors:
normal: [255, 255, 0] # Groc estrella
wounded: [255, 220, 60]
score: 100
events:
# STAR: mor al primer impacte, sense passar per wounded.
on_hit:
- action: apply_impulse
- action: destroy
on_destroy:
- action: add_score
- action: create_debris
- action: create_fireworks
File diff suppressed because it is too large Load Diff
+112
View File
@@ -0,0 +1,112 @@
# Orni Attack - locale: Catala (valencia)
# Interficie traduida; pool in-game identic a en.yaml (es queda en angles).
# Tots els textos en ASCII: VectorText no suporta caracters accentuats.
notification:
press_again_exit: "PREMEU ESC UN ALTRE COP PER EIXIR"
zoom: "ZOOM: {z}X"
fullscreen_on: "PANTALLA COMPLETA"
fullscreen_off: "MODE FINESTRA"
vsync_on: "VSYNC ACTIU"
vsync_off: "VSYNC INACTIU"
antialias_on: "AA ACTIU"
antialias_off: "AA INACTIU"
postfx_on: "POSTPROCESSAT ACTIU"
postfx_off: "POSTPROCESSAT INACTIU"
locale_switched: "IDIOMA: {lang}"
gamepad_connected: "{name} CONNECTAT"
gamepad_disconnected: "{name} DESCONNECTAT"
language:
ca: "CATALA"
en: "ANGLES"
hud:
level: "NIVELL "
title:
press_start: "PREMEU START PER JUGAR"
game_screen:
game_over: "FI DEL JOC"
continue: "CONTINUAR"
continues_left: "CONTINUACIONS: {n}"
stage:
start:
- "ORNI ALERT!"
- "INCOMING ORNIS!"
- "ROLLING THREAT!"
- "ENEMY WAVE!"
- "WAVE OF ORNIS DETECTED!"
- "NEXT SWARM APPROACHING!"
- "BRACE FOR THE NEXT WAVE!"
- "ANOTHER ATTACK INCOMING!"
- "SENSORS DETECT HOSTILE ORNIS..."
- "UNIDENTIFIED ROLLING OBJECTS INBOUND!"
- "ENEMY FORCES MOBILIZING!"
- "PREPARE FOR IMPACT!"
completed: "GOOD JOB COMMANDER!"
service_menu:
title: "MENU DE SERVEI"
video: "VIDEO"
audio: "AUDIO"
options: "OPCIONS"
system: "SISTEMA"
controls: "CONTROLS"
back: "ENRERE"
exit: "EIXIR DEL JOC"
# Items del submenu VIDEO
video_zoom: "ZOOM"
video_fullscreen: "PANTALLA COMPLETA"
video_vsync: "VSYNC"
video_aa: "ANTIALIAS"
video_postfx: "POSTPROCESSAT"
video_resolution: "RESOLUCIO"
# Items del submenu OPCIONS
options_language: "IDIOMA"
options_show_info: "MOSTRAR INFO"
# Items del submenu AUDIO
audio_master: "AUDIO"
audio_master_volume: "VOLUM GENERAL"
audio_music: "MUSICA"
audio_music_volume: "VOLUM MUSICA"
audio_sound: "EFECTES"
audio_sound_volume: "VOLUM EFECTES"
# Items del submenu SISTEMA
system_restart: "REINICIAR"
# Pagines de confirmacio (estructura: titol + NO/SI)
confirm_restart: "ESTAS SEGUR DE REINICIAR?"
confirm_exit: "ESTAS SEGUR DE EIXIR?"
confirm_no: "NO"
confirm_yes: "SI"
# Valors comuns
value_on: "ACTIU"
value_off: "INACTIU"
# Items del submenu CONTROLS
controls_pad_p1: "MANDO JUGADOR 1"
controls_pad_p2: "MANDO JUGADOR 2"
controls_no_pad: "SENSE MANDO"
controls_define_keyboard_p1: "REDEFINIR TECLES P1"
controls_define_keyboard_p2: "REDEFINIR TECLES P2"
controls_define_gamepad_p1: "REDEFINIR BOTONS P1"
controls_define_gamepad_p2: "REDEFINIR BOTONS P2"
# Overlay modal de redefinicio (DefineInputs)
define:
title_keyboard_p1: "REDEFINIR TECLES P1"
title_keyboard_p2: "REDEFINIR TECLES P2"
title_gamepad_p1: "REDEFINIR BOTONS P1"
title_gamepad_p2: "REDEFINIR BOTONS P2"
press_key: "PREMEU UNA TECLA"
press_button: "PREMEU UN BOTO"
complete: "CONFIGURACIO COMPLETA"
no_gamepad: "CAP MANDO ASSIGNAT AL JUGADOR"
action:
left: "ESQUERRA"
right: "DRETA"
fire: "DISPARAR"
accelerate: "ACCELERAR"
start: "START"
menu: "MENU"
+111
View File
@@ -0,0 +1,111 @@
# Orni Attack - locale: English
# In-game pool kept English in both locales per design.
notification:
press_again_exit: "PRESS ESC AGAIN TO EXIT"
zoom: "ZOOM: {z}X"
fullscreen_on: "FULLSCREEN"
fullscreen_off: "WINDOWED"
vsync_on: "VSYNC ON"
vsync_off: "VSYNC OFF"
antialias_on: "AA ON"
antialias_off: "AA OFF"
postfx_on: "POSTPROCESS ON"
postfx_off: "POSTPROCESS OFF"
locale_switched: "LANGUAGE: {lang}"
gamepad_connected: "{name} CONNECTED"
gamepad_disconnected: "{name} DISCONNECTED"
language:
ca: "CATALAN"
en: "ENGLISH"
hud:
level: "LEVEL "
title:
press_start: "PRESS START TO PLAY"
game_screen:
game_over: "GAME OVER"
continue: "CONTINUE"
continues_left: "CONTINUES LEFT: {n}"
stage:
start:
- "ORNI ALERT!"
- "INCOMING ORNIS!"
- "ROLLING THREAT!"
- "ENEMY WAVE!"
- "WAVE OF ORNIS DETECTED!"
- "NEXT SWARM APPROACHING!"
- "BRACE FOR THE NEXT WAVE!"
- "ANOTHER ATTACK INCOMING!"
- "SENSORS DETECT HOSTILE ORNIS..."
- "UNIDENTIFIED ROLLING OBJECTS INBOUND!"
- "ENEMY FORCES MOBILIZING!"
- "PREPARE FOR IMPACT!"
completed: "GOOD JOB COMMANDER!"
service_menu:
title: "SERVICE MENU"
video: "VIDEO"
audio: "AUDIO"
options: "OPTIONS"
system: "SYSTEM"
controls: "CONTROLS"
back: "BACK"
exit: "EXIT GAME"
# Items of VIDEO submenu
video_zoom: "ZOOM"
video_fullscreen: "FULLSCREEN"
video_vsync: "VSYNC"
video_aa: "ANTIALIAS"
video_postfx: "POSTPROCESS"
video_resolution: "RESOLUTION"
# Items of OPTIONS submenu
options_language: "LANGUAGE"
options_show_info: "SHOW INFO"
# Items of AUDIO submenu
audio_master: "AUDIO"
audio_master_volume: "MASTER VOLUME"
audio_music: "MUSIC"
audio_music_volume: "MUSIC VOLUME"
audio_sound: "SOUNDS"
audio_sound_volume: "SOUND VOLUME"
# Items of SYSTEM submenu
system_restart: "RESTART"
# Confirmation pages (structure: title + NO/YES)
confirm_restart: "REALLY RESTART?"
confirm_exit: "REALLY EXIT?"
confirm_no: "NO"
confirm_yes: "YES"
# Common values
value_on: "ON"
value_off: "OFF"
# Items of CONTROLS submenu
controls_pad_p1: "PLAYER 1 GAMEPAD"
controls_pad_p2: "PLAYER 2 GAMEPAD"
controls_no_pad: "NO GAMEPAD"
controls_define_keyboard_p1: "REDEFINE KEYS P1"
controls_define_keyboard_p2: "REDEFINE KEYS P2"
controls_define_gamepad_p1: "REDEFINE BUTTONS P1"
controls_define_gamepad_p2: "REDEFINE BUTTONS P2"
# Modal overlay for input redefinition (DefineInputs)
define:
title_keyboard_p1: "REDEFINE KEYS P1"
title_keyboard_p2: "REDEFINE KEYS P2"
title_gamepad_p1: "REDEFINE BUTTONS P1"
title_gamepad_p2: "REDEFINE BUTTONS P2"
press_key: "PRESS A KEY"
press_button: "PRESS A BUTTON"
complete: "CONFIGURATION COMPLETE"
no_gamepad: "NO GAMEPAD ASSIGNED TO PLAYER"
action:
left: "LEFT"
right: "RIGHT"
fire: "FIRE"
accelerate: "ACCELERATE"
start: "START"
menu: "MENU"
Binary file not shown.
Binary file not shown.
+7
View File
@@ -0,0 +1,7 @@
# bullet.shp - Projectil (octàgon, radi=3)
name: bullet
scale: 1.0
center: 0, 0
polyline: 0,-3 2.12,-2.12 3,0 2.12,2.12 0,3 -2.12,2.12 -3,0 -2.12,-2.12 0,-3
+17
View File
@@ -0,0 +1,17 @@
# bullet_double.shp - Bala anular (dos cercles concèntrics)
# © 2026 JailDesigner
#
# Dos octàgons concèntrics al centre (0,0):
# - Exterior: radi 4 (lleugerament més gran que la bala estàndard, radi 3)
# - Interior: radi 2 (lleugerament més petit que la bala estàndard)
# Aspecte d'anell / aura de plasma. Bounding radius natiu = 4.
name: bullet_double
scale: 1.0
center: 0, 0
# Cercle exterior (octàgon, radi 4)
polyline: 0,-4 2.83,-2.83 4,0 2.83,2.83 0,4 -2.83,2.83 -4,0 -2.83,-2.83 0,-4
# Cercle interior (octàgon, radi 2)
polyline: 0,-2 1.41,-1.41 2,0 1.41,1.41 0,2 -1.41,1.41 -2,0 -1.41,-1.41 0,-2
+28
View File
@@ -0,0 +1,28 @@
# bullet_long.shp - Bala allargada (dos octàgons tangents + tapes superior i inferior)
# © 2026 JailDesigner
#
# Dos cercles (octàgons radi 3) tangents externament al punt (0,0), units
# per una línia horitzontal superior i una d'inferior. La silueta resultant
# és una càpsula amb la separació visible dels dos cercles al centre.
#
# Geometria:
# Centre octàgon esquerre: (-3, 0)
# Centre octàgon dret: ( 3, 0)
# Punt de tangència: ( 0, 0)
# Bounding radius natiu ≈ 6 (extrem horitzontal a x=±6).
name: bullet_long
scale: 1.0
center: 0, 0
# Octàgon esquerre (centre x=-3, radi 3)
polyline: -3,-3 -0.88,-2.12 0,0 -0.88,2.12 -3,3 -5.12,2.12 -6,0 -5.12,-2.12 -3,-3
# Octàgon dret (centre x=3, radi 3)
polyline: 3,-3 5.12,-2.12 6,0 5.12,2.12 3,3 0.88,2.12 0,0 0.88,-2.12 3,-3
# Tapa superior: uneix el cim de l'octàgon esquerre amb el del dret
polyline: -3,-3 3,-3
# Tapa inferior: uneix la base de l'octàgon esquerre amb la del dret
polyline: -3,3 3,3
+11
View File
@@ -0,0 +1,11 @@
# enemy_pentagon.shp - ORNI enemic (pentàgon doble concentric, radi exterior=20)
name: enemy_pentagon
scale: 1.0
center: 0, 0
# Pentàgon exterior (vèrtex apuntant amunt, radi 20)
polyline: 0,-20 19.02,-6.18 11.76,16.18 -11.76,16.18 -19.02,-6.18 0,-20
# Pentàgon interior (radi 10, rotat 36° → vèrtex apuntant a les arestes exteriors)
polyline: 5.88,-8.09 9.51,3.09 0,10 -9.51,3.09 -5.88,-8.09 5.88,-8.09
+30
View File
@@ -0,0 +1,30 @@
# enemy_pinwheel.shp - ORNI enemic (molinillo de 4 triangles)
# © 2026 JailDesigner
name: enemy_pinwheel
scale: 1.0
center: 0, 0
# Molinillo: 4 triangles, un en cada quadrant
# Cada triangle comparteix el centre (0,0) i té:
# - Un vèrtex en un eix (±20, 0) o (0, ±20)
# - Un vèrtex en la diagonal del quadrant (±14.14, ±14.14)
# - El tercer vèrtex al centre (0,0)
#
# Geometria:
# Triangle 1 (quadrant superior-dret): centre → eix dret → diagonal
# Triangle 2 (quadrant superior-esq): centre → eix superior → diagonal
# Triangle 3 (quadrant inferior-esq): centre → eix esquerre → diagonal
# Triangle 4 (quadrant inferior-dret): centre → eix inferior → diagonal
# Triangle 1: quadrant superior-dret
polyline: 0,0 20,0 14.14,-14.14 0,0
# Triangle 2: quadrant superior-esquerre
polyline: 0,0 0,-20 -14.14,-14.14 0,0
# Triangle 3: quadrant inferior-esquerre
polyline: 0,0 -20,0 -14.14,14.14 0,0
# Triangle 4: quadrant inferior-dret
polyline: 0,0 0,20 14.14,14.14 0,0
+14
View File
@@ -0,0 +1,14 @@
# enemy_square.shp - ORNI enemic (rombe, radi=20) + ull amb pupil·la al centre
name: enemy_square
scale: 1.0
center: 0, 0
# Rombe exterior
polyline: 0,-20 20,0 0,20 -20,0 0,-20
# Ull (dos arcs units, forma d'almetlla). Amplada 20px, altura 8px.
polyline: -10,0 -5,-3 0,-4 5,-3 10,0 5,3 0,4 -5,3 -10,0
# Pupil·la (octàgon, radi 2) al centre
polyline: 0,-2 1.41,-1.41 2,0 1.41,1.41 0,2 -1.41,1.41 -2,0 -1.41,-1.41 0,-2
+10
View File
@@ -0,0 +1,10 @@
# char_0.shp - Dígito 0
# Dimensiones: 20×40 (blocky display)
# Rectángulo cerrado (polyline continua, NO 6 líneas separadas)
name: char_0
scale: 1.0
center: 10, 20
# Rectángulo cerrado
polyline: 2,10 18,10 18,30 2,30 2,10
+10
View File
@@ -0,0 +1,10 @@
# char_1.shp - Dígito 1
# Dimensiones: 20×40 (blocky display)
# Línea vertical simple centrada
name: char_1
scale: 1.0
center: 10, 20
# Línea vertical central
line: 10,10 10,30
+10
View File
@@ -0,0 +1,10 @@
# char_2.shp - Dígito 2
# Dimensiones: 20×40 (blocky display)
# Forma de "2" con curva simulada (polyline continua)
name: char_2
scale: 1.0
center: 10, 20
# Trazo continuo en forma de S achatada
polyline: 2,10 18,10 18,20 2,20 2,30 18,30
+11
View File
@@ -0,0 +1,11 @@
# char_3.shp - Dígito 3
# Dimensiones: 20×40 (blocky display)
# Forma de "3" con dos curvas (polylines)
name: char_3
scale: 1.0
center: 10, 20
# Trazo continuo (barra superior + lateral derecho + barra media + lateral derecho + barra inferior)
polyline: 2,10 18,10 18,20 8,20
polyline: 8,20 18,20 18,30 2,30
+12
View File
@@ -0,0 +1,12 @@
# char_4.shp - Dígito 4
# Dimensiones: 20×40 (blocky display)
# Forma de "4" con líneas continuas
name: char_4
scale: 1.0
center: 10, 20
# Trazo principal (vertical izquierda + horizontal + vertical derecha superior)
polyline: 2,10 2,20 18,20
# Vertical derecha completa (cruza la horizontal)
line: 18,10 18,30
+10
View File
@@ -0,0 +1,10 @@
# char_5.shp - Dígito 5
# Dimensiones: 20×40 (blocky display)
# Forma de "5" con curva (polyline continua)
name: char_5
scale: 1.0
center: 10, 20
# Trazo continuo en forma de S invertida
polyline: 18,10 2,10 2,20 18,20 18,30 2,30
+10
View File
@@ -0,0 +1,10 @@
# char_6.shp - Dígito 6
# Dimensiones: 20×40 (blocky display)
# Forma de "6" con espiral (polyline continua)
name: char_6
scale: 1.0
center: 10, 20
# Trazo continuo: barra superior + lateral izquierdo + barra media + lateral derecho inferior + barra inferior + cierre
polyline: 18,10 2,10 2,30 18,30 18,20 2,20
+10
View File
@@ -0,0 +1,10 @@
# char_7.shp - Dígito 7
# Dimensiones: 20×40 (blocky display)
# Línea horizontal superior + diagonal hacia abajo-derecha
name: char_7
scale: 1.0
center: 10, 20
# Barra superior + diagonal
polyline: 2,10 18,10 18,30
+12
View File
@@ -0,0 +1,12 @@
# char_8.shp - Dígito 8
# Dimensiones: 20×40 (blocky display)
# Dos rectángulos apilados (polylines continuas)
name: char_8
scale: 1.0
center: 10, 20
# Rectángulo superior
polyline: 2,10 18,10 18,20 2,20 2,10
# Rectángulo inferior (comparte borde con el superior)
polyline: 2,20 18,20 18,30 2,30 2,20
+10
View File
@@ -0,0 +1,10 @@
# char_9.shp - Dígito 9
# Dimensiones: 20×40 (blocky display)
# Forma de "9" con espiral (polyline continua)
name: char_9
scale: 1.0
center: 10, 20
# Trazo continuo: lateral derecho completo + barra superior + lateral izquierdo superior + barra media
polyline: 18,30 18,10 2,10 2,20 18,20
+11
View File
@@ -0,0 +1,11 @@
# char_A.shp - Letra A
# Dimensiones: 20×40 (blocky display)
name: char_A
scale: 1.0
center: 10, 20
# Forma triangular (dos diagonales hacia arriba)
polyline: 2,30 10,10 18,30
# Barra horizontal media
line: 5,22 15,22
+11
View File
@@ -0,0 +1,11 @@
# char_B.shp - Letra B
# Dimensiones: 20×40 (blocky display)
name: char_B
scale: 1.0
center: 10, 20
# Rectángulo superior
polyline: 2,10 14,10 14,20 2,20 2,10
# Rectángulo inferior (más ancho)
polyline: 2,20 16,20 16,30 2,30 2,20
+9
View File
@@ -0,0 +1,9 @@
# char_C.shp - Letra C
# Dimensiones: 20×40 (blocky display)
name: char_C
scale: 1.0
center: 10, 20
# Curva simulada (semicírculo abierto a la derecha)
polyline: 18,12 14,10 6,10 2,14 2,26 6,30 14,30 18,28
+9
View File
@@ -0,0 +1,9 @@
# char_D.shp - Letra D
# Dimensiones: 20×40 (blocky display)
name: char_D
scale: 1.0
center: 10, 20
# Vertical izquierda + curva derecha simulada
polyline: 2,10 14,10 18,14 18,26 14,30 2,30 2,10
+10
View File
@@ -0,0 +1,10 @@
# char_E.shp - Letra E
# Dimensiones: 20×40 (blocky display)
name: char_E
scale: 1.0
center: 10, 20
# Forma de E (vertical izquierda + 3 horizontales)
polyline: 18,10 2,10 2,30 18,30
line: 2,20 14,20
+10
View File
@@ -0,0 +1,10 @@
# char_F.shp - Letra F
# Dimensiones: 20×40 (blocky display)
name: char_F
scale: 1.0
center: 10, 20
# Vertical izquierda + barra superior + barra media
polyline: 2,30 2,10 18,10
line: 2,20 14,20
+9
View File
@@ -0,0 +1,9 @@
# char_G.shp - Letra G
# Dimensiones: 20×40 (blocky display)
name: char_G
scale: 1.0
center: 10, 20
# Como C pero con barra horizontal hacia adentro
polyline: 18,12 14,10 6,10 2,14 2,26 6,30 14,30 18,28 18,20 12,20
+13
View File
@@ -0,0 +1,13 @@
# char_H.shp - Letra H
# Dimensiones: 20×40 (blocky display)
name: char_H
scale: 1.0
center: 10, 20
# Vertical izquierda
line: 2,10 2,30
# Vertical derecha
line: 18,10 18,30
# Barra media
line: 2,20 18,20
+9
View File
@@ -0,0 +1,9 @@
# char_I.shp - Letra I
# Dimensiones: 20×40 (blocky display)
name: char_I
scale: 1.0
center: 10, 20
# Línea vertical central
line: 10,10 10,30
+9
View File
@@ -0,0 +1,9 @@
# char_J.shp - Letra J
# Dimensiones: 20×40 (blocky display)
name: char_J
scale: 1.0
center: 10, 20
# Vertical derecha con curva abajo-izquierda
polyline: 18,10 18,26 14,30 6,30 2,26
+13
View File
@@ -0,0 +1,13 @@
# char_K.shp - Letra K
# Dimensiones: 20×40 (blocky display)
name: char_K
scale: 1.0
center: 10, 20
# Vertical izquierda
line: 2,10 2,30
# Diagonal superior
line: 18,10 2,20
# Diagonal inferior
line: 2,20 18,30
+9
View File
@@ -0,0 +1,9 @@
# char_L.shp - Letra L
# Dimensiones: 20×40 (blocky display)
name: char_L
scale: 1.0
center: 10, 20
# Forma de L (vertical izquierda + horizontal abajo)
polyline: 2,10 2,30 18,30
+9
View File
@@ -0,0 +1,9 @@
# char_M.shp - Letra M
# Dimensiones: 20×40 (blocky display)
name: char_M
scale: 1.0
center: 10, 20
# Forma de M con pico en el medio
polyline: 2,30 2,10 10,20 18,10 18,30
+9
View File
@@ -0,0 +1,9 @@
# char_N.shp - Letra N
# Dimensiones: 20×40 (blocky display)
name: char_N
scale: 1.0
center: 10, 20
# Vertical izquierda + diagonal + vertical derecha
polyline: 2,30 2,10 18,30 18,10
+9
View File
@@ -0,0 +1,9 @@
# char_O.shp - Letra O
# Dimensiones: 20×40 (blocky display)
name: char_O
scale: 1.0
center: 10, 20
# Rectángulo cerrado
polyline: 2,10 18,10 18,30 2,30 2,10
+11
View File
@@ -0,0 +1,11 @@
# char_P.shp - Letra P
# Dimensiones: 20×40 (blocky display)
name: char_P
scale: 1.0
center: 10, 20
# Vertical izquierda completa
line: 2,10 2,30
# Rectángulo superior cerrado
polyline: 2,10 14,10 14,20 2,20
+11
View File
@@ -0,0 +1,11 @@
# char_Q.shp - Letra Q
# Dimensiones: 20×40 (blocky display)
name: char_Q
scale: 1.0
center: 10, 20
# Rectángulo cerrado (como O)
polyline: 2,10 18,10 18,30 2,30 2,10
# Diagonal inferior derecha (cola de la Q)
line: 12,24 18,30
+13
View File
@@ -0,0 +1,13 @@
# char_R.shp - Letra R
# Dimensiones: 20×40 (blocky display)
name: char_R
scale: 1.0
center: 10, 20
# Vertical izquierda completa
line: 2,10 2,30
# Rectángulo superior cerrado
polyline: 2,10 14,10 14,20 2,20
# Diagonal inferior derecha
line: 8,20 18,30
+9
View File
@@ -0,0 +1,9 @@
# char_S.shp - Letra S
# Dimensiones: 20×40 (blocky display)
name: char_S
scale: 1.0
center: 10, 20
# Forma de S con curvas simuladas
polyline: 18,12 14,10 6,10 2,14 2,18 6,20 14,20 18,22 18,26 14,30 6,30 2,28
+11
View File
@@ -0,0 +1,11 @@
# char_T.shp - Letra T
# Dimensiones: 20×40 (blocky display)
name: char_T
scale: 1.0
center: 10, 20
# Barra horizontal superior
line: 2,10 18,10
# Línea vertical central
line: 10,10 10,30
+9
View File
@@ -0,0 +1,9 @@
# char_U.shp - Letra U
# Dimensiones: 20×40 (blocky display)
name: char_U
scale: 1.0
center: 10, 20
# Forma de U (dos verticales + curva abajo)
polyline: 2,10 2,26 6,30 14,30 18,26 18,10
+9
View File
@@ -0,0 +1,9 @@
# char_V.shp - Letra V
# Dimensiones: 20×40 (blocky display)
name: char_V
scale: 1.0
center: 10, 20
# Forma de V (dos diagonales hacia abajo)
polyline: 2,10 10,30 18,10
+9
View File
@@ -0,0 +1,9 @@
# char_W.shp - Letra W
# Dimensiones: 20×40 (blocky display)
name: char_W
scale: 1.0
center: 10, 20
# Forma de W (doble V)
polyline: 2,10 5,30 10,20 15,30 18,10
+11
View File
@@ -0,0 +1,11 @@
# char_X.shp - Letra X
# Dimensiones: 20×40 (blocky display)
name: char_X
scale: 1.0
center: 10, 20
# Diagonal \
line: 2,10 18,30
# Diagonal /
line: 18,10 2,30
+12
View File
@@ -0,0 +1,12 @@
# char_Y.shp - Letra Y
# Dimensiones: 20×40 (blocky display)
name: char_Y
scale: 1.0
center: 10, 20
# Dos diagonales superiores que se juntan
polyline: 2,10 10,20
polyline: 18,10 10,20
# Línea vertical inferior
line: 10,20 10,30
+9
View File
@@ -0,0 +1,9 @@
# char_Z.shp - Letra Z
# Dimensiones: 20×40 (blocky display)
name: char_Z
scale: 1.0
center: 10, 20
# Barra superior + diagonal + barra inferior
polyline: 2,10 18,10 2,30 18,30
+11
View File
@@ -0,0 +1,11 @@
# char_colon.shp - Símbolo : (dos puntos)
# Dimensiones: 20×40 (blocky display)
name: char_colon
scale: 1.0
center: 10, 20
# Punto superior
polyline: 8,14 12,14 12,17 8,17 8,14
# Punto inferior
polyline: 8,23 12,23 12,26 8,26 8,23
+9
View File
@@ -0,0 +1,9 @@
# char_comma.shp - Símbolo , (coma)
# Dimensiones: 20×40 (blocky display)
name: char_comma
scale: 1.0
center: 10, 20
# Dot + tail hacia abajo-izquierda
polyline: 10,28 10,32 8,34
+12
View File
@@ -0,0 +1,12 @@
# char_copyright.shp - Símbolo © (copyright)
# Dimensiones: 20×40 (blocky display)
name: char_copyright
scale: 1.0
center: 10, 20
# Círculo exterior (aproximado con 12 puntos)
polyline: 10,8 13,9 15,11 17,14 18,17 18,23 17,26 15,29 13,31 10,32 7,31 5,29 3,26 2,23 2,17 3,14 5,11 7,9 10,8
# Letra C interior
polyline: 13,16 9,14 7,16 6,20 7,24 9,26 13,24
+9
View File
@@ -0,0 +1,9 @@
# char_dot.shp - Símbolo . (punto)
# Dimensiones: 20×40 (blocky display)
name: char_dot
scale: 1.0
center: 10, 20
# Cuadrado pequeño centrado abajo
polyline: 8,28 12,28 12,32 8,32 8,28
+11
View File
@@ -0,0 +1,11 @@
# char_exclamation.shp - Símbolo ! (exclamación)
# Dimensiones: 20×40 (blocky display)
name: char_exclamation
scale: 1.0
center: 10, 20
# Línea vertical superior
line: 10,10 10,24
# Dot inferior
polyline: 8,28 12,28 12,32 8,32 8,28
+9
View File
@@ -0,0 +1,9 @@
# char_lparen.shp - Símbol ( (parèntesi esquerre)
# Dimensions: 20×40 (blocky display)
name: char_lparen
scale: 1.0
center: 10, 20
# Arc cap a l'esquerra aproximat amb 4 trams rectes
polyline: 14,4 8,12 6,20 8,28 14,36
+9
View File
@@ -0,0 +1,9 @@
# char_minus.shp - Símbolo - (menos/guión)
# Dimensiones: 20×40 (blocky display)
name: char_minus
scale: 1.0
center: 10, 20
# Línea horizontal en el centro
line: 4,20 16,20
+11
View File
@@ -0,0 +1,11 @@
# char_question.shp - Símbolo ? (interrogación)
# Dimensiones: 20×40 (blocky display)
name: char_question
scale: 1.0
center: 10, 20
# Curva superior + trazo hacia abajo
polyline: 2,12 10,10 18,12 18,18 10,20 10,24
# Dot inferior
polyline: 8,28 12,28 12,32 8,32 8,28
+9
View File
@@ -0,0 +1,9 @@
# char_rparen.shp - Símbol ) (parèntesi dret)
# Dimensions: 20×40 (blocky display)
name: char_rparen
scale: 1.0
center: 10, 20
# Arc cap a la dreta aproximat amb 4 trams rectes
polyline: 6,4 12,12 14,20 12,28 6,36
+9
View File
@@ -0,0 +1,9 @@
# char_slash.shp - Símbol / (barra)
# Dimensions: 20×40 (blocky display)
name: char_slash
scale: 1.0
center: 10, 20
# Línia diagonal de baix-esquerra a dalt-dreta
line: 4,36 16,4
+9
View File
@@ -0,0 +1,9 @@
# char_space.shp - Espacio (vacío)
# Dimensiones: 20×40 (blocky display)
# Sin geometría (espacio vacío intencional)
name: char_space
scale: 1.0
center: 10, 20
# No hay polylines ni lines (vacío intencionado)
+10
View File
@@ -0,0 +1,10 @@
# letra_a.shp
# Generado automáticamente desde jailgames.svg
# Dimensiones: 71.43 x 100.00 px
name: letra_a
scale: 1.0
center: 35.71, 50.00
polyline: 28.57,71.43 28.57,100.00 0.00,100.00 0.00,14.29 14.29,14.29 14.29,0.00 57.14,0.00 57.14,14.29 71.43,14.29 71.43,100.00 42.86,100.00 42.86,71.43 28.57,71.43
polyline: 28.57,14.29 28.57,57.14 42.86,57.14 42.86,14.29 28.57,14.29
+9
View File
@@ -0,0 +1,9 @@
# letra_e.shp
# Generado automáticamente desde jailgames.svg
# Dimensiones: 71.43 x 100.00 px
name: letra_e
scale: 1.0
center: 35.71, 50.00
polyline: 57.14,28.57 57.14,42.86 28.57,42.86 28.57,85.71 71.43,85.71 71.43,100.00 0.00,100.00 0.00,0.00 71.43,0.00 71.43,14.29 28.57,14.29 28.57,28.57 57.14,28.57
+9
View File
@@ -0,0 +1,9 @@
# letra_g.shp
# Generado automáticamente desde jailgames.svg
# Dimensiones: 71.43 x 100.00 px
name: letra_g
scale: 1.0
center: 35.71, 50.00
polyline: 14.29,0.00 57.14,0.00 57.14,14.29 28.57,14.29 28.57,85.71 42.86,85.71 42.86,42.86 71.43,42.86 71.43,100.00 14.29,100.00 14.29,85.71 0.00,85.71 0.00,14.29 14.29,14.29 14.29,0.00
+9
View File
@@ -0,0 +1,9 @@
# letra_i.shp
# Generado automáticamente desde jailgames.svg
# Dimensiones: 28.57 x 100.00 px
name: letra_i
scale: 1.0
center: 14.29, 50.00
polyline: 0.00,0.00 28.57,0.00 28.57,100.00 0.00,100.00 0.00,0.00
+9
View File
@@ -0,0 +1,9 @@
# letra_j.shp
# Generado automáticamente desde jailgames.svg
# Dimensiones: 57.14 x 100.00 px
name: letra_j
scale: 1.0
center: 28.57, 50.00
polyline: 0.00,100.00 0.00,85.71 28.57,85.71 28.57,0.00 57.14,0.00 57.14,85.71 42.86,85.71 42.86,100.00 0.00,100.00
+9
View File
@@ -0,0 +1,9 @@
# letra_l.shp
# Generado automáticamente desde jailgames.svg
# Dimensiones: 57.14 x 100.00 px
name: letra_l
scale: 1.0
center: 28.57, 50.00
polyline: 0.00,0.00 28.57,0.00 28.57,85.71 57.14,85.71 57.14,100.00 0.00,100.00 0.00,0.00
+9
View File
@@ -0,0 +1,9 @@
# letra_m.shp
# Generado automáticamente desde jailgames.svg
# Dimensiones: 100.00 x 100.00 px
name: letra_m
scale: 1.0
center: 50.00, 50.00
polyline: 71.43,57.14 57.14,57.14 57.14,71.43 42.86,71.43 42.86,57.14 28.57,57.14 28.57,100.00 0.00,100.00 0.00,0.00 14.29,0.00 14.29,14.29 28.57,14.29 28.57,28.57 42.86,28.57 42.86,42.86 57.14,42.86 57.14,28.57 71.43,28.57 71.43,14.29 85.71,14.29 85.71,0.00 100.00,0.00 100.00,100.00 71.43,100.00 71.43,57.14
+9
View File
@@ -0,0 +1,9 @@
# letra_s.shp
# Generado automáticamente desde jailgames.svg
# Dimensiones: 57.14 x 100.00 px
name: letra_s
scale: 1.0
center: 28.57, 50.00
polyline: 0.00,85.71 28.57,85.71 28.57,57.14 14.29,57.14 14.29,42.86 0.00,42.86 0.00,14.29 14.29,14.29 14.29,0.00 57.14,0.00 57.14,14.29 28.57,14.29 28.57,42.86 42.86,42.86 42.86,57.14 57.14,57.14 57.14,85.71 42.86,85.71 42.86,100.00 0.00,100.00 0.00,85.71
+8
View File
@@ -0,0 +1,8 @@
# ship.shp - Nau del jugador 1
# Triangle amb base còncava (punta de fletxa)
name: ship
scale: 1.0
center: 0, 0
polyline: 0,-12 8.49,8.49 0,4 -8.49,8.49 0,-12
+11
View File
@@ -0,0 +1,11 @@
# ship2.shp - Nau del jugador 2
# Triangle amb cercle central (distintiu visual)
name: ship2
scale: 1.0
center: 0, 0
polyline: 0,-12 8.49,8.49 -8.49,8.49 0,-12
# Octàgon central (radi=2.5)
polyline: 0,-2.5 1.77,-1.77 2.5,0 1.77,1.77 0,2.5 -1.77,1.77 -2.5,0 -1.77,-1.77 0,-2.5
+27
View File
@@ -0,0 +1,27 @@
# ship2.shp - Nau del jugador 2 (interceptor amb ales)
# © 2026 JailDesigner
name: ship2
scale: 1.0
center: 0, 0
# Interceptor amb ales laterals
# Disseny més ample i agressiu que P1
#
# Geometria:
# - Punta més curta i ampla
# - Ales laterals pronunciades
# - Base més ampla per estabilitat visual
#
# Punts (cartesianes, Y negatiu = amunt):
# p1: (0, -10) → punta (més curta que P1)
# p2: (4, -6) → transició ala dreta
# p3: (10, 2) → punta ala dreta (més ampla)
# p4: (6, 8) → base ala dreta
# p5: (0, 6) → base centre (menys còncava)
# p6: (-6, 8) → base ala esquerra
# p7: (-10, 2) → punta ala esquerra
# p8: (-4, -6) → transició ala esquerra
# p1: (0, -10) → tanca
polyline: 0,-10 4,-6 10,2 6,8 0,6 -6,8 -10,2 -4,-6 0,-10
+19
View File
@@ -0,0 +1,19 @@
# star.shp - Estrella per a starfield
# © 2026 JailDesigner
name: star
scale: 1.0
center: 0, 0
# Estrella de 4 puntes (diamant/creu)
# Petita i simple per a l'efecte starfield
#
# Punts:
# angle=0°: (0, -3) Dalt
# angle=90°: (3, 0) Dreta
# angle=180°: (0, 3) Baix
# angle=270°: (-3, 0) Esquerra
#
# Forma de diamant amb línies de centre a puntes
polyline: 0,-3 3,0 0,3 -3,0 0,-3
+15
View File
@@ -0,0 +1,15 @@
# star_5.shp - ORNI enemic (estrella de 5 puntes, només perímetre)
# © 2026 JailDesigner
#
# Pentagrama clàssic: 5 vèrtexs exteriors (radi 20) alternant amb 5 vèrtexs
# interiors (radi 7.64 = 20/φ² ≈ proporció àuria) per donar puntes esveltes.
# Vèrtex apuntant amunt (igual que enemy_pentagon).
#
# Sense línies interiors: una única polyline que recorre el perímetre.
# Bounding radius natiu ≈ 20 (alineat amb pentagon/square/pinwheel).
name: star_5
scale: 1.0
center: 0, 0
polyline: 0,-20 4.49,-6.18 19.02,-6.18 7.27,2.36 11.76,16.18 0,7.64 -11.76,16.18 -7.27,2.36 -19.02,-6.18 -4.49,-6.18 0,-20
+10
View File
@@ -0,0 +1,10 @@
# letra_a.shp
# Generado automáticamente desde jailgames.svg
# Dimensiones: 137.50 x 100.00 px
name: letra_a
scale: 1.0
center: 68.75, 50.00
polyline: 0.00,100.00 0.00,75.00 37.50,0.00 100.00,0.00 137.50,75.00 137.50,100.00 100.00,100.00 100.00,87.50 37.50,87.50 37.50,100.00 0.00,100.00
polyline: 62.50,25.00 50.00,50.00 50.00,62.50 87.50,62.50 87.50,50.00 75.00,25.00 62.50,25.00
+9
View File
@@ -0,0 +1,9 @@
# letra_c.shp
# Generado automáticamente desde jailgames.svg
# Dimensiones: 137.50 x 100.00 px
name: letra_c
scale: 1.0
center: 68.75, 50.00
polyline: 12.50,100.00 0.00,87.50 0.00,12.50 12.50,0.00 125.00,0.00 137.50,12.50 137.50,37.50 100.00,37.50 100.00,25.00 37.50,25.00 37.50,75.00 100.00,75.00 100.00,62.50 137.50,62.50 137.50,87.50 125.00,100.00 12.50,100.00
+10
View File
@@ -0,0 +1,10 @@
# letra_exclamacion.shp
# Generado automáticamente desde jailgames.svg
# Dimensiones: 37.51 x 100.00 px
name: letra_exclamacion
scale: 1.0
center: 18.75, 50.00
polyline: 0.00,62.50 0.00,0.00 37.51,0.00 37.51,62.50 0.00,62.50
polyline: 0.00,100.00 0.00,75.00 37.51,75.00 37.51,100.00 0.00,100.00
+9
View File
@@ -0,0 +1,9 @@
# letra_i.shp
# Generado automáticamente desde jailgames.svg
# Dimensiones: 37.50 x 100.00 px
name: letra_i
scale: 1.0
center: 18.75, 50.00
polyline: 0.00,0.00 37.50,0.00 37.50,100.00 0.00,100.00 0.00,0.00
+9
View File
@@ -0,0 +1,9 @@
# letra_k.shp
# Generado automáticamente desde jailgames.svg
# Dimensiones: 137.50 x 100.00 px
name: letra_k
scale: 1.0
center: 68.75, 50.00
polyline: 0.00,100.00 0.00,0.00 37.50,0.00 37.50,37.50 50.00,37.50 100.00,0.00 137.50,0.00 137.50,25.00 87.06,50.00 137.50,75.00 137.50,100.00 100.00,100.00 50.00,62.50 37.50,62.50 37.50,100.00 0.00,100.00
+9
View File
@@ -0,0 +1,9 @@
# letra_n.shp
# Generado automáticamente desde jailgames.svg
# Dimensiones: 137.50 x 100.00 px
name: letra_n
scale: 1.0
center: 68.75, 50.00
polyline: 0.00,100.00 0.00,0.00 50.00,0.00 100.00,50.00 100.00,0.00 137.50,0.00 137.50,100.00 87.50,100.00 37.50,50.00 37.50,100.00 0.00,100.00
+10
View File
@@ -0,0 +1,10 @@
# letra_o.shp
# Generado automáticamente desde jailgames.svg
# Dimensiones: 137.50 x 100.00 px
name: letra_o
scale: 1.0
center: 68.75, 50.00
polyline: 12.50,100.00 0.00,87.50 0.00,12.50 12.50,0.00 125.00,0.00 137.50,12.50 137.50,87.50 125.00,100.00 12.50,100.00
polyline: 100.00,25.00 37.50,25.00 37.50,75.00 100.00,75.00 100.00,25.00
+10
View File
@@ -0,0 +1,10 @@
# letra_r.shp
# Generado automáticamente desde jailgames.svg
# Dimensiones: 137.50 x 100.00 px
name: letra_r
scale: 1.0
center: 68.75, 50.00
polyline: 0.00,100.00 0.00,0.00 125.00,0.00 137.50,12.50 137.50,62.50 125.00,62.50 137.50,75.00 137.50,100.00 100.00,100.00 100.00,75.00 37.50,75.00 37.50,100.00 0.00,100.00
polyline: 37.50,50.00 100.00,50.00 100.00,25.00 37.50,25.00 37.50,50.00
+9
View File
@@ -0,0 +1,9 @@
# letra_t.shp
# Generado automáticamente desde jailgames.svg
# Dimensiones: 137.50 x 100.00 px
name: letra_t
scale: 1.0
center: 68.75, 50.00
polyline: 0.00,25.00 0.00,0.00 137.50,0.00 137.50,25.00 87.50,25.00 87.50,100.00 50.00,100.00 50.00,25.00 0.00,25.00
+9
View File
@@ -0,0 +1,9 @@
# title_flash.shp - Sparkle 4-puntes amb costats còncaus (Atari-style)
# 4 puntes als cardinals (radi 30) i valls còncaus als 45° (corba Bezier
# quadràtica amb control point ±8). 5 punts per arc subdividint la corba.
name: title_flash
scale: 1.0
center: 0, 0
polyline: 0,-30 3.76,-21.76 8.64,-14.64 14.64,-8.64 21.76,-3.76 30,0 21.76,3.76 14.64,8.64 8.64,14.64 3.76,21.76 0,30 -3.76,21.76 -8.64,14.64 -14.64,8.64 -21.76,3.76 -30,0 -21.76,-3.76 -14.64,-8.64 -8.64,-14.64 -3.76,-21.76 0,-30
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More