- 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).
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.
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>