From 39eda56c9dcd339945557977206f59528828935b Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Tue, 28 Apr 2026 20:27:09 +0200 Subject: [PATCH] docs(player): neteja comentaris dels YAMLs (sense documentar el motor) --- data/player/morcus.gif | Bin 2133 -> 3289 bytes data/player/morcus.yaml | 107 +++++++++--------------------------- data/player/sam.gif | Bin 3307 -> 3289 bytes data/player/sam.yaml | 116 ++++++++++------------------------------ 4 files changed, 52 insertions(+), 171 deletions(-) diff --git a/data/player/morcus.gif b/data/player/morcus.gif index 97b32b8ef5ffd39f543d2ce9028e0dc5d8502ca2..d8d2dece9a7f3050aa727c45f3beea7ba904264a 100644 GIT binary patch delta 3268 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 diff --git a/data/player/morcus.yaml b/data/player/morcus.yaml index 2f8bca4..ece6005 100644 --- a/data/player/morcus.yaml +++ b/data/player/morcus.yaml @@ -1,38 +1,16 @@ -# player animation sprite: path: morcus.gif size: [16, 32] -# Geometria de col·lisió del jugador (independent de l'animació): -# size → costat del quadrat de col·lisió (16×16) -# base_size → costat del quadrat visual inferior del sprite (els "peus"); -# s'usa per centrar la caixa de col·lisió sobre ell. +# Geometria de col·lisió. `size` és la caixa contra murs/sarcs; +# `hit_size`, la caixa contra altres actors (més petita); `height`, +# l'alçada que un salt ha de superar per passar per damunt. collision: size: 16 base_size: 16 - # Caixa de contacte actor-actor (jugador↔jugador, jugador↔momia/trampa). - # Més petita que `size` perquè els contactes d'acció siguin precisos; - # `size` es reserva per a la col·lisió amb murs/sarcòfags i per enfilar - # els passadissos. Centrada en el mateix punt que la caixa base. hit_size: 8 - # Alçada del cos en píxels. Funció DOBLE segons amb què col·lisione: - # · Contra entitats (mummy, rolling_rock, sarc): si `jump_z > height` - # d'aquella entitat, no hi ha col·lisió. Igual que als YAMLs - # d'entitats. - # · Contra altres jugadors: la col·lisió és binària per estat aeri. - # Si un està en l'aire i l'altre no → cap col·lisió. Si tots dos - # estan en l'aire, llavors `body_height` decideix si els rangs - # verticals solapen i s'aplica el rebot mid-aire. `0` = sense cos - # (ni rebot quan tots dos volen). height: 12 -# Animacions en mapa (clau = nom). Camps per animació: -# frames → llista d'índexs dins de l'spritesheet. -# frame_ms → durada de cada frame en ms. Escalar = uniforme; llista = -# per-frame (mateixa mida que `frames`). -# loop → true per defecte. `loop: false` = un sol tret (es queda al -# darrer frame i `animationIsCompleted()` passa a true). -# loop_from → rebota a aquest índex en passar del final (implica loop). animations: stand_down: { frames: [0] } stand_up: { frames: [4] } @@ -68,76 +46,46 @@ animations: frames: [8, 9, 10, 11] frame_ms: 100 - # Placeholder mentre no arribe l'art real (el GIF de morcus encara no té - # frames d'atac específics — reaprofitem `walk_*`). El bloc està declarat - # perquè `Player::animationName` el busque sense fallback i la mecànica - # de l'atac estiga lligada amb morcus tan bon punt s'afegisquen els - # frames; ara mateix visualment el sprite caminarà mentre llança el - # látigo (acceptat per al placeholder). attack_down: - frames: [0, 1, 2, 3] + frames: [20, 21, 22, 23] frame_ms: 50 attack_up: - frames: [4, 5, 6, 7] + frames: [24, 25, 26, 27] frame_ms: 50 attack: - frames: [8, 9, 10, 11] + frames: [28, 29, 30, 31] frame_ms: 50 - # Cooldown post-swing (recovery): igual que a sam.yaml, placeholder als - # frames de `stand_*`. Quan arriben els frames reals només cal canviar - # els índexs ací. recover_down: - frames: [0] + frames: [23] recover_up: - frames: [4] + frames: [27] recover: - frames: [8] + frames: [31] -# Inèrcia només de frenada. L'acceleració és sempre instantània (soltar -# el teclat + prémer una direcció = velocitat plena); en canvi, quan es -# solta la direcció el jugador decau linealment a 0 en `brake_time_ms`. -# El `threshold_ms` filtra els tocs curts: si el temps acumulat de -# moviment continu no ha arribat al llindar, la parada és instantània -# (permet "passets" d'un tile sense rellisquera). L'acumulador es -# reseteja només quan no hi ha ni input ni velocitat residual, així -# els canvis de direcció enmig del coast no rearmen el llindar. -# `brake_time_ms: 0` o absència del bloc = inèrcia desactivada. +# Inèrcia de frenada en soltar la direcció. `threshold_ms` filtra +# tocs curts (passets d'un tile sense rellisquera). inertia: brake_time_ms: 150 threshold_ms: 300 -# Gir de 180°: mentre dura, el facing queda fixat a la direcció -# intermèdia (efecte purament visual; el moviment continua sense -# alterar-se). Els girs de 90° no passen per cap intermedi. +# Gir de 180°: durant `duration_ms` el facing es fixa a la direcció +# intermèdia indicada (purament visual). turn: duration_ms: 80 - # Direcció intermèdia per a cada gir de 180° (sentit horari). transitions: - west_to_east: down # passa per baix (stand_down) - east_to_west: up # passa per dalt (stand_up) - north_to_south: east # passa per la dreta (stand, sense flip) - south_to_north: west # passa per l'esquerra (stand, amb flip) + west_to_east: down + east_to_west: up + north_to_south: east + south_to_north: west -# Salt vertical (px verticals "visuals", no afecta la posició al món). -# impulse → velocitat vertical inicial (px/s) en deixar el sòl. -# gravity → acceleració descendent constant (px/s²). -# landing_stun_ms → temps en què el jugador queda paralitzat en aterrar -# (no es pot moure ni tornar a saltar). -# shadow_y_offset → desplaçament vertical de la sombra (px, positiu = -# puja). Compensa la franja transparent que els -# sprites del jugador tenen sota els peus reals -# perquè camine "pel mig del passadís" (3 px aquí). -# sound → fitxer .wav reproduït al despegue (relatiu a -# data/sounds/). Buit o absent = sense so. -# land_sound → fitxer .wav reproduït en aterrar. -# L'alçada del cos viu al bloc `collision:` (`height`), igual que la resta -# d'entitats: és una propietat de col·lisió, no de la física del salt. -# Amb impulse=240 i gravity=600: pic ≈ 48 px, temps total en l'aire ≈ 0.8 s. +# Salt vertical (px de z, no toca la posició al món). +# `shadow_y_offset`: puja la sombra per compensar la franja +# transparent sota els peus del sprite. jump: impulse: 200 gravity: 600 @@ -146,21 +94,16 @@ jump: sound: jump.wav land_sound: land.wav -# Estat HURT: el jugador queda projectat sense control per un impacte -# (algú que cau al damunt; en el futur també fuetada de l'altre jugador). -# `enterHurt` tria automàticament la direcció amb més recorregut lliure -# entre els 4 cardinals, posa la velocitat inicial a `speed` i la fa -# decaure linealment fins a 0 en `brake_time_ms`. Si pel camí xoca amb -# un mur, para en sec. En tornar a velocitat 0, recupera l'estat -# GROUNDED i el control. Mentre dura, no col·lisiona amb altres jugadors. -# Amb speed=120 i brake_time=500ms ⇒ recorregut ≈ 30 px (≈2 tiles). +# Projecció post-impacte: surt cap a la direcció amb més recorregut +# lliure i frena fins a 0 en `brake_time_ms`. hurt: speed: 120 brake_time_ms: 500 sound: hurt.wav -# Configuració del látigo. Mateixos valors que Sam de moment; -# diferenciar quan equilibrem cada personatge. +# Atac amb làtigo. `range_tiles` és la longitud abans de retallar +# contra murs/sarcs; `cooldown_ms` allarga ATTACKING amb una +# recuperació en què la hitbox ja no fa dany. whip: range_tiles: 3 swing_ms: 200 diff --git a/data/player/sam.gif b/data/player/sam.gif index 943e29241eb7e06b311d8302b6f0cc94214ee7c0..0f15c83e4ca377d3b2c59bba333d92ba53174cbe 100644 GIT binary patch delta 3195 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 delta 3214 zcmV;93~}?>8S5E6M@dFFH(@{k00FZA000005D*Z02@GI46Lm}^Q%6B_V^@?44zK_i z?HnYGVmY{2K-hRtnTB=vpm4~@*pWRzK8ivR!w{hLo$r@G52xeVh(L=F=SxuO zb5fwvr_dHfYJ1(^m+LEDw^XqtRm&ZbF}A{egYV?@@(MqZyBYxmk=87K4*?7e0S^nn z#>L0U%frsd%FM*Z)X`514+X~s)k@sn4B*;V|`OE;j%?FSI>71@2aNZs)!O{D*AXL1d@sjpFzu9rQ9cSdRS692J{Upw5h0J7ZT0c30Y- zT}ul$;ypo+l3vIkU1zFT60cZQYAEZYgs&W+NiSSnN~gy17a>B z@=`0UxR?ZzMk2NH(XLrJPn{k1N>BC+IAD!>jV z6GdAEbW}tM?{HO92%ojU!d{m3AGVQMoPth??Q3rw9Mi>C$XAqxTWeQz#+qoIuHhMO z<*lJIXe^Iv8)mb0cLr}K>sDlG)1g+IbUhRIglIW`=crr&%mo3oZ%R+cbahYUfZ1=} zS*EiRzZIYc*Wbk)>myN^p#_dh&}WGbqBM%O4V8Mr#j#uF2iK6h zUWl?VY2Mv})A!-xj5qH10^{%s@Ul2cqi_9?E=c)q$H}m?n>;ZuTiFguMgjQah$s;Jnt?dFQx9SzruPj zMnYe=^nq6&e0|SP-xLhcQ{R1&=e7`jOc{^DIyMaC@G1G}kGX!S?pw}&{e+iV46L!x zKfwE>I>!E1CBS6`K_1=UpUeuVK(CCWffIRu;O8RPDt<`t1^vLFJtl~d&pEJyA_8Fu z8wd&qK;#7~5Mh!`sJT=OfGi16+ekDLLsXgYW6YT0P;#`4i5bOaYjBKIg7g=u*yV+= zN=j4!f)9mp#4*Fr0aaWTF^?p%eg8NJiU#tYAphV589WJwvnz9bh1^f^mDh&Dae$C zt0m=j$;)2)@|VC2Cgjv;%NAk?4PLN+QH(qY#}Qzm3Mlfy_Oy^X4{|^bX)xRFq)DV& zByXA@;DaA@X(cdqX>iqJ{23GfgY75>L?db{2LtzE%T4q}y{eetd;i$W#@HpWpsMR7uaU`Ftl3bO zNM(p(5m#iA#jA}uWfDc43R77y61Aj6C(#%fRvHF?aCvK2Tg9Ni0>c2t{G}tr(U{T1 zn8h8Q06U`D4l_(nhvM2VHp z!Oho{fCewrgm1Joe(lNo1|sR z;G!OQrZ$tr%^W?4J-OWl81(R?9vSX>a{qGX7V=;R#klUAuuErh*T7DHNw||u{M?T` z`x(wx%*lLh>r-Xm3C?iVlTw9J??BD8-TK@XP<{jILhI|0X+R@~5)ETaD*C@>&NQRu zh|Wb+g(?Qt_YC<+$gNIf(gZ%ZAPsp4-CA1Jms%vI7oG@4P-4Zjd~2uYfPo7ASw3eC z^$taK@w$?FL%;@CEKd!83trwx)nLs_cv-c}PrHhduV!lj1S6|i1%}okuk{#ig<>i^ zwuhvS(XKz$ns2_t48scT34aCdH5*H2rw!JxiluC25!Z(xLDFl(?dfnNbe|lF;t?`9 zZR2kH1Wmk_!nF;wpa)IpLK_;k2KI&jH4|MQ8B`O6kM3mXj2mfxZ{AMQmoD8my?5Lz z;SPA~`<-^J3+hjgdU=B&UMt2MyiTtte6CitrLi~bOVkLu%8Q<@=bP(TY0r1So921w zs~B&@ub=u=U&@XxY=x@tG0X5D00Y>*0$)tp_QQ5+{Pj^1vTuN{a&UvMaYY>0dNCq`{j{|Oy-Xg?m##ZbLeh0(fEm(0=YV0L1E_KRRAoyJSr*MSh z!h~8yqF>YJjd#pT1r>kI0D=qy$Hr_*vAB^Nam01--eg$5YQFJeqNydJ3 zjK8Mr$}f)&qh&SWi32)0YA$ThpZ~B}CFpVJ1t}zAaiMg7<2F5WPq$Gd)j5f&^T_Hb z!n&m2{S9sl}kE%W7Do^N4#iOinvwW;eHEW+vmcE&b!|C&i4@T znL~eX5sf&Q=)fE4?LR8+jGn|J-`Ys=&E=-yga`S=56R7vr&~JDxy>V)(n;O4E|;=& z3OI!~uGb}hJ?cj-JqR;fb2LF%ge9XKUj{Zovve+_gibgfP?#ftgoLqB zg;cnIG*qVWbkzWQvZs)g-u~Vd~MKw2a&LRXt0WS(~9F%WwiK;6%z@mrU=vJ zih2MDz~^0}&|SMI3eWI-ctVVhupsZnC#2Af=e03OVGErDjj*>lvoMF**cL~@bJ(~F zxa5ucHzG)N4bQMq<9I3Nm<`t8UmJxj>7Y^k(+m$akMWpb;(%c9$Py8j9`}fj_0SK0 z3MPV7p5hd0?3lNbul|IRVc_@^0S?QryZMIijc9>v8 zn2mxZsl^7QgiDTzhm%Q;Tz4s#St$ height` - # d'aquella entitat, no hi ha col·lisió. Igual que als YAMLs - # d'entitats. - # · Contra altres jugadors: la col·lisió és binària per estat aeri. - # Si un està en l'aire i l'altre no → cap col·lisió. Si tots dos - # estan en l'aire, llavors `body_height` decideix si els rangs - # verticals solapen i s'aplica el rebot mid-aire. `0` = sense cos - # (ni rebot quan tots dos volen). height: 12 -# Animacions en mapa (clau = nom). Camps per animació: -# frames → llista d'índexs dins de l'spritesheet. -# frame_ms → durada de cada frame en ms. Escalar = uniforme; llista = -# per-frame (mateixa mida que `frames`). -# loop → true per defecte. `loop: false` = un sol tret (es queda al -# darrer frame i `animationIsCompleted()` passa a true). -# loop_from → rebota a aquest índex en passar del final (implica loop). animations: - stand_down: { frames: [1] } - stand_up: { frames: [5] } - stand: { frames: [9] } + stand_down: { frames: [0] } + stand_up: { frames: [4] } + stand: { frames: [8] } jump_down: { frames: [12] } jump_up: { frames: [13] } jump: { frames: [14] } @@ -68,12 +46,8 @@ animations: frames: [8, 9, 10, 11] frame_ms: 100 - # Animacions del braç llançant el látigo. Placeholder: reaprofiten els - # frames de `walk_*` perquè els sprites reals encara no existeixen - # (TODO: dibuixar-ne d'específics quan arribe l'art). El sprite del - # látigo viu al `WhipAttack` i es renderitza superposat per z-order. attack_down: - frames: [28, 29, 30, 31] + frames: [20, 21, 22, 23] frame_ms: 50 attack_up: @@ -81,63 +55,37 @@ animations: frame_ms: 50 attack: - frames: [20, 21, 22, 23] + frames: [28, 29, 30, 31] frame_ms: 50 - # Animacions de cooldown post-swing (recovery): mentre dura - # `whip_cooldown_ms` el jugador continua bloquejat però l'animació ja - # no és la d'atac. Placeholder: reaprofiten els frames de `stand_*` - # (la silueta no canvia respecte d'ells); quan arriben els frames - # reals només cal canviar els índexs ací, sense tocar el codi. recover_down: - frames: [1] + frames: [23] recover_up: - frames: [5] + frames: [27] recover: - frames: [9] + frames: [31] -# Inèrcia només de frenada. L'acceleració és sempre instantània (soltar -# el teclat + prémer una direcció = velocitat plena); en canvi, quan es -# solta la direcció el jugador decau linealment a 0 en `brake_time_ms`. -# El `threshold_ms` filtra els tocs curts: si el temps acumulat de -# moviment continu no ha arribat al llindar, la parada és instantània -# (permet "passets" d'un tile sense rellisquera). L'acumulador es -# reseteja només quan no hi ha ni input ni velocitat residual, així -# els canvis de direcció enmig del coast no rearmen el llindar. -# `brake_time_ms: 0` o absència del bloc = inèrcia desactivada. +# Inèrcia de frenada en soltar la direcció. `threshold_ms` filtra +# tocs curts (passets d'un tile sense rellisquera). inertia: brake_time_ms: 150 threshold_ms: 300 -# Gir de 180°: mentre dura, el facing queda fixat a la direcció -# intermèdia (efecte purament visual; el moviment continua sense -# alterar-se). Els girs de 90° no passen per cap intermedi. +# Gir de 180°: durant `duration_ms` el facing es fixa a la direcció +# intermèdia indicada (purament visual). turn: duration_ms: 80 - # Direcció intermèdia per a cada gir de 180° (sentit horari). transitions: - west_to_east: down # passa per baix (stand_down) - east_to_west: up # passa per dalt (stand_up) - north_to_south: east # passa per la dreta (stand, sense flip) - south_to_north: west # passa per l'esquerra (stand, amb flip) + west_to_east: down + east_to_west: up + north_to_south: east + south_to_north: west -# Salt vertical (px verticals "visuals", no afecta la posició al món). -# impulse → velocitat vertical inicial (px/s) en deixar el sòl. -# gravity → acceleració descendent constant (px/s²). -# landing_stun_ms → temps en què el jugador queda paralitzat en aterrar -# (no es pot moure ni tornar a saltar). -# shadow_y_offset → desplaçament vertical de la sombra (px, positiu = -# puja). Compensa la franja transparent que els -# sprites del jugador tenen sota els peus reals -# perquè camine "pel mig del passadís" (3 px aquí). -# sound → fitxer .wav reproduït al despegue (relatiu a -# data/sounds/). Buit o absent = sense so. -# land_sound → fitxer .wav reproduït en aterrar. -# L'alçada del cos viu al bloc `collision:` (`height`), igual que la resta -# d'entitats: és una propietat de col·lisió, no de la física del salt. -# Amb impulse=240 i gravity=600: pic ≈ 48 px, temps total en l'aire ≈ 0.8 s. +# Salt vertical (px de z, no toca la posició al món). +# `shadow_y_offset`: puja la sombra per compensar la franja +# transparent sota els peus del sprite. jump: impulse: 200 gravity: 600 @@ -146,26 +94,16 @@ jump: sound: jump.wav land_sound: land.wav -# Estat HURT: el jugador queda projectat sense control per un impacte -# (algú que cau al damunt; en el futur també fuetada de l'altre jugador). -# `enterHurt` tria automàticament la direcció amb més recorregut lliure -# entre els 4 cardinals, posa la velocitat inicial a `speed` i la fa -# decaure linealment fins a 0 en `brake_time_ms`. Si pel camí xoca amb -# un mur, para en sec. En tornar a velocitat 0, recupera l'estat -# GROUNDED i el control. Mentre dura, no col·lisiona amb altres jugadors. -# Amb speed=120 i brake_time=500ms ⇒ recorregut ≈ 30 px (≈2 tiles). +# Projecció post-impacte: surt cap a la direcció amb més recorregut +# lliure i frena fins a 0 en `brake_time_ms`. hurt: speed: 120 brake_time_ms: 500 sound: hurt.wav -# Configuració del látigo. `range_tiles` és la longitud de la hitbox -# abans de retallar contra murs/sarcs (3 tiles ≈ 48 px). `swing_ms` és -# la durada de l'animació de l'atac, durant la qual la hitbox del whip -# està viva. `cooldown_ms` allarga ATTACKING amb una recuperació en què -# el jugador segueix bloquejat però la hitbox ja ha desaparegut: castiga -# l'ús abusiu del látigo. `damage` queda llegit per a futur (els -# objectius reben `enterHurt` directament; cap entitat té HP encara). +# Atac amb làtigo. `range_tiles` és la longitud abans de retallar +# contra murs/sarcs; `cooldown_ms` allarga ATTACKING amb una +# recuperació en què la hitbox ja no fa dany. whip: range_tiles: 3 swing_ms: 200