From 70143d995bd58739a3a02760d32bd3818991b239 Mon Sep 17 00:00:00 2001 From: JVeg199X <97848253+JVeg199X@users.noreply.github.com> Date: Sun, 27 Oct 2024 12:52:30 -0400 Subject: [PATCH] Pango - 2nd PR (#306) Lots of Pango improvements --- assets/fonts/tiny_numbers.font.png | Bin 0 -> 191 bytes assets/pango/sounds/bgmGameOver.mid | Bin 209 -> 209 bytes assets/pango/sounds/snd1up.mid | Bin 152 -> 192 bytes assets/pango/sounds/sndBlockCombo.mid | Bin 0 -> 736 bytes assets/pango/sounds/sndTally.mid | Bin 0 -> 136 bytes assets/pango/sprites/kr-007.png | Bin 1080 -> 1085 bytes assets/pango/sprites/kr-008.png | Bin 1085 -> 1080 bytes assets/pango/sprites/kr-009.png | Bin 1065 -> 1079 bytes assets/pango/sprites/kr-010.png | Bin 1079 -> 1065 bytes assets/pango/sprites/kr-011.png | Bin 1065 -> 1066 bytes assets/pango/sprites/kr-012.png | Bin 1066 -> 1065 bytes assets/pango/sprites/pa-115.png | Bin 0 -> 1050 bytes assets/pango/sprites/po-015.png | Bin 0 -> 1059 bytes assets/pango/sprites/px-015.png | Bin 0 -> 1042 bytes assets/pango/tiles/pa-tile-010.png | Bin 1021 -> 1023 bytes assets/pango/tiles/pa-tile-011.png | Bin 1022 -> 1021 bytes assets/pango/tiles/pa-tile-012.png | Bin 1023 -> 1022 bytes assets/pango/tiles/pa-tile-013.png | Bin 1030 -> 1022 bytes assets/pango/tiles/pa-tile-014.png | Bin 1031 -> 1022 bytes assets/pango/tiles/pa-tile-015.png | Bin 1031 -> 999 bytes main/modes/games/pango/paEntity.c | 383 +++++++----- main/modes/games/pango/paEntity.h | 22 +- main/modes/games/pango/paEntityManager.c | 78 ++- main/modes/games/pango/paEntityManager.h | 1 + main/modes/games/pango/paGameData.c | 156 ++--- main/modes/games/pango/paGameData.h | 26 +- main/modes/games/pango/paLeveldef.h | 19 - main/modes/games/pango/paSoundManager.c | 68 +-- main/modes/games/pango/paTables.h | 100 ++- main/modes/games/pango/paTilemap.c | 32 +- main/modes/games/pango/paTilemap.h | 27 - main/modes/games/pango/paWsgManager.c | 57 +- main/modes/games/pango/paWsgManager.h | 103 +--- main/modes/games/pango/pango.c | 735 ++++++++--------------- main/modes/games/pango/pango.h | 1 + main/modes/games/pango/pango_typedef.h | 128 ++++ 36 files changed, 895 insertions(+), 1041 deletions(-) create mode 100644 assets/fonts/tiny_numbers.font.png create mode 100644 assets/pango/sounds/sndBlockCombo.mid create mode 100644 assets/pango/sounds/sndTally.mid create mode 100644 assets/pango/sprites/pa-115.png create mode 100644 assets/pango/sprites/po-015.png create mode 100644 assets/pango/sprites/px-015.png delete mode 100644 main/modes/games/pango/paLeveldef.h diff --git a/assets/fonts/tiny_numbers.font.png b/assets/fonts/tiny_numbers.font.png new file mode 100644 index 0000000000000000000000000000000000000000..975ec1cc86a6e7ea84e26a37f076e51829db9303 GIT binary patch literal 191 zcmeAS@N?(olHy`uVBq!ia0vp^mw}j_gBeIJE$g@hq!^2X+?^QKos)S99L{(D{a@Uzvqqro>PeG@ zrzzMBZF)P6w+&>qr>mdKI;Vst0At@o#sB~S literal 0 HcmV?d00001 diff --git a/assets/pango/sounds/bgmGameOver.mid b/assets/pango/sounds/bgmGameOver.mid index ed84b35d312d7ef84f900946cda7df89e1228d93..a862aa0ecc21b0fc3201f38f23c9fa82cd06e218 100644 GIT binary patch delta 25 gcmcb}c#&~JH6z2s8V}xz2_f~31q~q#4FB~R0C|fD;Q#;t delta 25 gcmcb}c#&~JHDkcU8V_EE2_f~31q~q#4FB~R0C^J#xc~qF diff --git a/assets/pango/sounds/snd1up.mid b/assets/pango/sounds/snd1up.mid index e3b994f42be5c019266ecf462df7579665d21247..9757fa2963947b600cf9f6e0559979b168cacc06 100644 GIT binary patch delta 95 zcmbQicz|(&8b7D{0fztj489>n*$fN}-4jjSTp1W9nAO`fm;q@mAgzVOcLMUAfP6n7 U?FXczfOHg)P6N_u2tLq202p8!o&W#< delta 55 zcmX@WID>J58bA9&1&06n489>n*$fN}$rDZ8WCIu`WYpUi5QR_Dk`^uAg^P+HD2M@z1nDARKZ?<34BxOS6A z@KO3E@h};sWbrZgo(XejPNtZ>E&)Uc5C*Ga_Ws7(5OoKrZ@b-ar;obq^uG2{Cuq{) zH>wY&`AM~Lfok&;)eFzd5LLvxo`dFmL|yNU(Euwj9{@jq6wm)uy@m4y@Q0+#H8`JA zH>6y^aK5B&NJhQE`HZ?DbLtJw{Kf!Q5rf$gO5oJ-~2&#GE11dl=47 zsT-2q!EipIZb*Iu!}*-LA>$bg=f~6yDN1^!w0ydzPfE+DEBd6ge9GyQ((>t&J}E7q zChCt&&eaPUo$1^%O?6I5#yXeer#gp>Pqc3-j`IL+wMd1ASNKd-{&VyHR)4JjG93z9`vpOOEXEBgy><*b(g literal 0 HcmV?d00001 diff --git a/assets/pango/sounds/sndTally.mid b/assets/pango/sounds/sndTally.mid new file mode 100644 index 0000000000000000000000000000000000000000..943d55c60bd5cf7ad8cb206292fc635200e650fa GIT binary patch literal 136 zcmeYb$w*;fU|?flWME=^;2Tnu4djV4{AXrh_#eT-!X&}L@IR25eW3!we|-k1bTGq) zN}x1Q$p$V5h7If~3>&!X88)N>`6)~c8`ywiU^XL!tp*ea^MN!Q55ofnpgbc3!vO|{ O2?_Q54GBP_^cetm5)lFN2l+nW8x0Ui^F=uxkqKH&p{QECx47D=H|00000NkvXX Hu0mjfSL#0u delta 148 zcmV;F0Birf2)GEatpk5{Nkl=-cKr%CV^~NAe%RcwChmqZ#jl&#Pgk2 zfoPM4V=WOfHKLZ+6Pv%|?T=W?mJ17jBRIBBAU=H?UR7>Y1=9=w0000=-cKr%CV^~NAe%RcwChmqZ#jl&#Pgk2 zfoPM4V=WOfHKLZ+6Pv%|?T=W?mJ17jBRIBBAU=H?UR7>Y1=9=w00005)lFN2l+nW8x0Ui^F=uxkqKH&p{QECx47D=H|00000NkvXX Hu0mjfSL#0u diff --git a/assets/pango/sprites/kr-009.png b/assets/pango/sprites/kr-009.png index 6aaf31c3535573779cc3a45e6e3bd4925bb4030f..377c86f745ba34ff0a81ddc7f3d8b87a40b93782 100644 GIT binary patch delta 147 zcmV;E0BrxM2)78Ztpk5`Nkl$^t$0AQkPq?QL8QUD78002ovPDHLkV1kua BJZAs^ delta 132 zcmV-~0DJ$p2&o9Ltpj{#Nkl?*2m|?0AIi`AtQDN7EL&C+L(irpnn_4m z2{;MR$Orflc>%oxXe0;M*&`HSb?A+uN=z^#;RB5-dCzxbLdLKFM+CNkEV)Ony^k-; m=EEm&x1DGmSvFeZiunTSrBjw#J^u;-0000?*2m|?0AIi`AtQDN7EL&C+L(irpnn_4m z2{;MR$Orflc>%oxXe0;M*&`HSb?A+uN=z^#;RB5-dCzxbLdLKFM+CNkEV)Ony^k-; m=EEm&x1DGmSvFeZiunTSrBjw#J^u;-0000$^t$0AQkPq?QL8QUD78002ovPDHLkV1kua BJZAs^ diff --git a/assets/pango/sprites/kr-011.png b/assets/pango/sprites/kr-011.png index dba09167cad638e82e3617fa2705c3c3424480c5..858714176ac3775aa3e31280eed98b9cb1aeb285 100644 GIT binary patch delta 133 zcmV;00DAwa2&xFMtpj~%Nkl?*2m|>L5ADx*)+`RJB$Bw;8?;2TSNW6-oY delta 132 zcmV-~0DJ$c2&o9Ltpj{#NklUrc0~qpw8(0000Urc0~qpw8(0000?*2m|>L5ADx*)+`RJB$Bw;8?;2TSNW6-oY diff --git a/assets/pango/sprites/pa-115.png b/assets/pango/sprites/pa-115.png new file mode 100644 index 0000000000000000000000000000000000000000..461857e17b19ce29702be97fd08317cc29093083 GIT binary patch literal 1050 zcmds#ziZTC48~)1C5*t4qaNoQM#25+Cd?s zI0zl8f+%#-+0daPs7oDn(80kqewshS7uqlHo8-y!#i!M;wqt%RaO%-ag#8~>Q)zX zahGt(8rBdC@sJ3~!qOB=@svo(f>r^EQF-n7f&}X_#j5plq)08m?Ki z=(bP~jnFKX3|p$FMrsymM8F!F@PY`NSp_y=Ow&%C2acPCS(ZW;b9c9J%MuI^${rSB zS^A+xx2Hu~mL0f-J@|nEC`KZh5CLmw!V4m71{!R@n5LaN51eq%vJ!O63=GQ&y~vY2~T zgyc`)Buu1aNNA))EaZUkIE}S1Z$QKUd9MC_@EnoXy6yARV^3~AT58In(Ot8*m*2F$eHl5{dEEIues8!q za(MTNP5Jcw!q~<48?!4jum1R{XN|4l*^{q7Ki!&JIl3CB-~O5#9=X2%?)uA_7k5_o d&0jt@lr#4~Ol+=yeE5zX(w*$J*IKt0{{dH-R;T~~ literal 0 HcmV?d00001 diff --git a/assets/pango/sprites/po-015.png b/assets/pango/sprites/po-015.png new file mode 100644 index 0000000000000000000000000000000000000000..bbee456c5ace0e68d7a63f0f06006842e2f4ea8d GIT binary patch literal 1059 zcmds$ziZQB5XLWlq1I}uOF^Vy5fm2@ywSlLQes3xOj;FjuvBhvt%DAA(5dJk_ybM^ z2Nx@tO>k7`;BZ=SD_C$-p$;yBR=9rh{u#cIyxeTs*fEQ6OnrROtZ(m zZ}=Il_&$1UZ=b8S*lRUp@M-dg$c}s6bF(u%s)&iWNQh*KRmD_XB~-Gc)x=EPBuuhY ztBbj~OSoid)({KvkO;|wr74!;DUp%|S_LFpsU=A?Jf`ZZp_*kdv6;GQm}cQY+Fac= zT(i)k+Cn`vLbI@>*-||yRzu!Ok zsB!Ae^r062-Gv8}Mm+s21YURq)gCD9V qn}0u^-}-#`_QmHfcmCTPS(3N4t%;;(;PIe-q{A6_FDP? literal 0 HcmV?d00001 diff --git a/assets/pango/sprites/px-015.png b/assets/pango/sprites/px-015.png new file mode 100644 index 0000000000000000000000000000000000000000..e95caef5b68d4a79abbd2e54587febe2d7c4ac86 GIT binary patch literal 1042 zcmds#J8P6t5QfLtEWyPz;spsdij5GQLaZdq7m@{8mfe^_L97M~(IN_7NF!Q=s3d~L z5F4=)Ax%UC8w(4CAsDR$D+|#^Y_u|rPv&QMAo)0FX5M)(yV&ndw?_|*ib%UV(+v2I zZU41)^8e_u-9tV*<_FUqS=%`HLu6#Be|mO`M-?#<7YUK9yQ-LqtAt8cSxwBuO~NFr zTV2e>UBV@6SVJttLn0&#OH(YxQz9h`S_LFV>7~eR`4z5Go)&3YcHkEF;0Fev7>Q^?1gxP6FNm-iXs`iens(|uaKb&yN))n~dxU2> zi(q(Aj`S>}iG>_69;dMuFEJ0dum?Xd0L4gzG+3~PCcGfRW}v|ajA`1b^T5f<3@cH{ zV(wWHl0SiyFp-iWp^*}?kORi!G}huJcEFNh{J;PdBN5VI!5W(If(V;|1{*M@X{XKu zhu__i;o0weK3^U5hBW-2XYSASr-Us}2Ic93_!rV69GUXK>qdX*O5e+cOtkjft_dq wJ83Jxj3&U0Dgg8eL<_24m{C0o^)3n@0C$gco4%6j?*IS*07*qoM6N<$f>D1W_5c6? delta 88 zcmV-e0H^=|2mJ@ItpiXyNklqsI7*$6I7ARA2} vo3;W5XaWYP0zjWYw4nOM0M)Zl@1pPlv87b*u2X9700000NkvXXu0mjf<2E9s diff --git a/assets/pango/tiles/pa-tile-012.png b/assets/pango/tiles/pa-tile-012.png index 727d2b831d646098bf1b6c0ecbb6d9d7b9e792bd..a901f31c4e52aaf6c583746af30652b8b739913b 100644 GIT binary patch delta 89 zcmV-f0H*){2mS}Jtpia!NklqsJe;s`EGKpag# voVEgdXaanw0zjWYw4nNh57o0!@1pPlJi-@n)UFw{00000NkvXXu0mjfMV=$C delta 90 zcmV-g0Hy!_2mc4Ktpid$Nklc93_!rV69GUXK>qdX*O5e+cOtkjft_dq wJ83Jxj3&U0Dgg8eL<_24m{C0o^)3n@0C$gco4%6j?*IS*07*qoM6N<$f>GHb_W%F@ diff --git a/assets/pango/tiles/pa-tile-013.png b/assets/pango/tiles/pa-tile-013.png index c0627e07e8912b302694ce7f600c353b18c46fc0..b06a00e8695f2107ad02d6a8d62e4ee82cb763ce 100644 GIT binary patch delta 89 zcmV-f0H*(j2>u7Ktpia!NklqsI7*$6I7ARA2} vo3;W5XaWYP0zjWYw4nOM0M)Zl@1pPlv87b*u2X9700000NkvXXu0mjfx-TLw delta 97 zcmV-n0G|K;2Zji+tpiy^Nklu7Ktpia!NklqsJ@X$US%APr3* vjkW@zXab?A0zjWYw4nMW6xFj(@1pPlbyQwDlEb5X00000NkvXXu0mjftzIEp delta 98 zcmV-o0Gbz)FtD#3BU~Eqq9iD2kP3#txuz zi3>P7QwSL-2YQ%2z-msJK#u68!&-fq!u?zT{4M;l0kXqF1>dfWCIA2c07*qoM6N<$ Ef@$t1>;M1& diff --git a/assets/pango/tiles/pa-tile-015.png b/assets/pango/tiles/pa-tile-015.png index bfa1ea4ab2046d5c74593fc55bac60d69f8c618b..7bfa1c753e01dec1a6d83b38a920d9d293a92ae0 100644 GIT binary patch delta 66 zcmZqYc+S3IEwh!Xr;B5V#MI=3gbz+kJPr(M3m8P7QwSL-2YQ%2z-msJK#u68!&-fq!u?zT{4M;l0Tn+-rMWIEkN^Mx07*qoM6N<$ Ef>kgj+5i9m diff --git a/main/modes/games/pango/paEntity.c b/main/modes/games/pango/paEntity.c index a33ca8a9c..dfd9da01c 100644 --- a/main/modes/games/pango/paEntity.c +++ b/main/modes/games/pango/paEntity.c @@ -14,6 +14,7 @@ #include "trigonometry.h" #include #include "soundFuncs.h" +#include "paTables.h" //============================================================================== // Constants @@ -45,7 +46,6 @@ void pa_initializeEntity(paEntity_t* self, paEntityManager_t* entityManager, paT self->gravity = false; self->falling = false; self->entityManager = entityManager; - self->fallOffTileHandler = &defaultFallOffTileHandler; self->spriteFlipHorizontal = false; self->spriteFlipVertical = false; self->facingDirection = PA_DIRECTION_SOUTH; @@ -93,8 +93,15 @@ void pa_updatePlayer(paEntity_t* self) { self->xspeed = -16; } + + // Make the player face in the most recent direction pressed + if (!(self->gameData->prevBtnState & PB_LEFT)) + { + self->facingDirection = PA_DIRECTION_WEST; + } } - else if (self->gameData->btnState & PB_RIGHT) + + if (self->gameData->btnState & PB_RIGHT) { self->xspeed += 4; @@ -102,6 +109,12 @@ void pa_updatePlayer(paEntity_t* self) { self->xspeed = 16; } + + // Make the player face in the most recent direction pressed + if (!(self->gameData->prevBtnState & PB_RIGHT)) + { + self->facingDirection = PA_DIRECTION_EAST; + } } if (self->gameData->btnState & PB_UP) @@ -112,8 +125,15 @@ void pa_updatePlayer(paEntity_t* self) { self->yspeed = -16; } + + // Make the player face in the most recent direction pressed + if (!(self->gameData->prevBtnState & PB_UP)) + { + self->facingDirection = PA_DIRECTION_NORTH; + } } - else if (self->gameData->btnState & PB_DOWN) + + if (self->gameData->btnState & PB_DOWN) { self->yspeed += 4; @@ -121,8 +141,19 @@ void pa_updatePlayer(paEntity_t* self) { self->yspeed = 16; } + + // Make the player face in the most recent direction pressed + if (!(self->gameData->prevBtnState & PB_DOWN)) + { + self->facingDirection = PA_DIRECTION_SOUTH; + } } + // Fix the player's facing direction if: + //- the player has let go of the most recent direction held + //- the player is pressing opposite directions + self->facingDirection = pa_correctPlayerFacingDirection(self->gameData->btnState, self->facingDirection); + if (self->animationTimer > 0) { self->animationTimer--; @@ -133,24 +164,6 @@ void pa_updatePlayer(paEntity_t* self) self->gameData->changeState = PA_ST_PAUSE; } - /* - if(self->xspeed){ - self->targetTileX = PA_TO_TILECOORDS(self->x >> SUBPIXEL_RESOLUTION) + SIGNOF(self->xspeed); - - if(!self->yspeed){ - self->targetTileY = PA_TO_TILECOORDS(self->y >> SUBPIXEL_RESOLUTION); - } - } - - if(self->yspeed){ - self->targetTileY = PA_TO_TILECOORDS(self->y >> SUBPIXEL_RESOLUTION) + SIGNOF(self->yspeed); - - if(!self->xspeed){ - self->targetTileX = PA_TO_TILECOORDS(self->x >> SUBPIXEL_RESOLUTION); - } - } - */ - switch (self->facingDirection) { case PA_DIRECTION_WEST: @@ -184,7 +197,7 @@ void pa_updatePlayer(paEntity_t* self) if (newHitBlock != NULL) { pa_setTile(self->tilemap, self->targetTileX, self->targetTileY, PA_TILE_EMPTY); - newHitBlock->jumpPower = t; + newHitBlock->state = t; switch (self->facingDirection) { case PA_DIRECTION_WEST: @@ -254,6 +267,25 @@ void pa_updatePlayer(paEntity_t* self) pa_detectEntityCollisions(self); } +uint16_t pa_correctPlayerFacingDirection(int16_t btnState, uint16_t currentFacingDirection) +{ + // Mask out button bits that do not correspond to directional buttons + int16_t directionBtnState = btnState & 0b1111; + + switch (directionBtnState) + { + case PA_DIRECTION_NORTH: + case PA_DIRECTION_SOUTH: + case PA_DIRECTION_WEST: + case PA_DIRECTION_EAST: + return directionBtnState; + break; + default: + return currentFacingDirection; + break; + } +} + void updateCrabdozer(paEntity_t* self) { switch (self->state) @@ -271,7 +303,7 @@ void updateCrabdozer(paEntity_t* self) } else*/ { self->state = PA_EN_ST_NORMAL; - self->stateTimer = (300 + esp_random() % 600); // Min 5 seconds, max 15 seconds + self->stateTimer = pa_enemySetAggroStateTimer(self); } } else @@ -303,14 +335,14 @@ void updateCrabdozer(paEntity_t* self) self->state = PA_EN_ST_AGGRESSIVE; self->entityManager->aggroEnemies++; self->baseSpeed += 2; - self->stateTimer = (300 + esp_random() % 300); // Min 5 seconds, max 10 seconds + self->stateTimer = pa_enemySetAggroStateTimer(self); } else if (self->state == PA_EN_ST_AGGRESSIVE) { self->state = PA_EN_ST_NORMAL; self->entityManager->aggroEnemies--; self->baseSpeed -= 2; - self->stateTimer = (300 + esp_random() % 300); // Min 5 seconds, max 10 seconds + self->stateTimer = pa_enemySetAggroStateTimer(self); } } @@ -721,6 +753,12 @@ void updateCrabdozer(paEntity_t* self) } } +int16_t pa_enemySetAggroStateTimer(paEntity_t* self) +{ + return (self->gameData->minAggroTime + + esp_random() % (self->gameData->maxAggroTime - self->gameData->minAggroTime)); +} + void pa_enemyChangeDirection(paEntity_t* self, uint16_t newDirection, int16_t speed) { switch (newDirection) @@ -805,26 +843,20 @@ void pa_animateEnemy(paEntity_t* self) } else if (self->yspeed > 0) { - if (self->yspeed > 0) + if (self->gameData->frameCount % 5 == 0) { - if (self->gameData->frameCount % 5 == 0) - { - self->spriteIndex = PA_SP_ENEMY_SOUTH + ((self->state != PA_EN_ST_NORMAL) ? 4 : 0); - self->spriteFlipHorizontal = (self->gameData->frameCount >> 1) % 2; - self->facingDirection = PA_DIRECTION_SOUTH; - } + self->spriteIndex = PA_SP_ENEMY_SOUTH + ((self->state != PA_EN_ST_NORMAL) ? 4 : 0); + self->spriteFlipHorizontal = (self->gameData->frameCount >> 1) % 2; + self->facingDirection = PA_DIRECTION_SOUTH; } } else if (self->yspeed < 0) { - if (self->yspeed < 0) + if (self->gameData->frameCount % 5 == 0) { - if (self->gameData->frameCount % 5 == 0) - { - self->spriteIndex = PA_SP_ENEMY_NORTH + ((self->state != PA_EN_ST_NORMAL) ? 4 : 0); - self->spriteFlipHorizontal = (self->gameData->frameCount >> 1) % 2; - self->facingDirection = PA_DIRECTION_NORTH; - } + self->spriteIndex = PA_SP_ENEMY_NORTH + ((self->state != PA_EN_ST_NORMAL) ? 4 : 0); + self->spriteFlipHorizontal = (self->gameData->frameCount >> 1) % 2; + self->facingDirection = PA_DIRECTION_NORTH; } } else @@ -938,18 +970,6 @@ void pa_moveEntityWithTileCollisions(paEntity_t* self) << SUBPIXEL_RESOLUTION; } } - - if (!self->falling) - { - uint8_t newBelowTile = pa_getTile(self->tilemap, tx, ty + 1); - - if ((self->gravityEnabled - && !pa_isSolid( - newBelowTile)) /*(|| (!self->gravityEnabled && newBelowTile != PA_TILE_LADDER)*/) - { - self->fallOffTileHandler(self); - } - } } } } @@ -1054,55 +1074,50 @@ void pa_destroyEntity(paEntity_t* self, bool respawn) void animatePlayer(paEntity_t* self) { - if (abs(self->xspeed) > abs(self->yspeed)) + switch (self->facingDirection) { - if (((self->gameData->btnState & PB_LEFT) && self->xspeed < 0) - || ((self->gameData->btnState & PB_RIGHT) && self->xspeed > 0)) - { - // Running - self->spriteFlipHorizontal = (self->xspeed > 0) ? 0 : 1; - self->facingDirection = self->spriteFlipHorizontal ? PA_DIRECTION_WEST : PA_DIRECTION_EAST; - - if (self->gameData->frameCount % 7 == 0) + case PA_DIRECTION_NORTH: + if ((self->gameData->btnState & PB_UP) && self->yspeed < 0) { - self->spriteIndex = PA_SP_PLAYER_SIDE + ((self->spriteIndex + 1) % 3); + if (self->gameData->frameCount % 7 == 0) + { + self->spriteIndex = PA_SP_PLAYER_NORTH + ((self->spriteIndex + 1) % 2); + self->spriteFlipHorizontal = (self->gameData->frameCount >> 1) % 2; + } } - } - else - { - // self->spriteIndex = SP_PLAYER_SLIDE; - } - } - else if (self->yspeed > 0) - { - if ((self->gameData->btnState & PB_DOWN) && self->yspeed > 0) - { - self->facingDirection = PA_DIRECTION_SOUTH; - - if (self->gameData->frameCount % 7 == 0) + break; + case PA_DIRECTION_SOUTH: + if ((self->gameData->btnState & PB_DOWN) && self->yspeed > 0) { - self->spriteIndex = PA_SP_PLAYER_SOUTH + ((self->spriteIndex + 1) % 2); - self->spriteFlipHorizontal = (self->gameData->frameCount >> 1) % 2; + if (self->gameData->frameCount % 7 == 0) + { + self->spriteIndex = PA_SP_PLAYER_SOUTH + ((self->spriteIndex + 1) % 2); + self->spriteFlipHorizontal = (self->gameData->frameCount >> 1) % 2; + } } - } - } - else if (self->yspeed < 0) - { - if ((self->gameData->btnState & PB_UP) && self->yspeed < 0) - { - self->facingDirection = PA_DIRECTION_NORTH; - - if (self->gameData->frameCount % 7 == 0) + break; + case PA_DIRECTION_WEST: + if ((self->gameData->btnState & PB_LEFT) && self->xspeed < 0) { - self->spriteIndex = PA_SP_PLAYER_NORTH + ((self->spriteIndex + 1) % 2); - self->spriteFlipHorizontal = (self->gameData->frameCount >> 1) % 2; + self->spriteFlipHorizontal = 1; + if (self->gameData->frameCount % 7 == 0) + { + self->spriteIndex = PA_SP_PLAYER_SIDE + ((self->spriteIndex + 1) % 3); + } } - } - } - else - { - // Standing - // self->spriteIndex = PA_SP_PLAYER_SOUTH; + break; + case PA_DIRECTION_EAST: + if ((self->gameData->btnState & PB_RIGHT) && self->xspeed > 0) + { + self->spriteFlipHorizontal = 0; + if (self->gameData->frameCount % 7 == 0) + { + self->spriteIndex = PA_SP_PLAYER_SIDE + ((self->spriteIndex + 1) % 3); + } + } + break; + default: + break; } } @@ -1131,25 +1146,9 @@ void pa_playerCollisionHandler(paEntity_t* self, paEntity_t* other) { other->xspeed = -other->xspeed; - /*if (self->y < other->y || self->yspeed > 0) - { - pa_scorePoints(self->gameData, other->scoreValue); - - killEnemy(other); - soundPlaySfx(&(self->soundManager->sndSquish), BZR_LEFT); - - self->yspeed = -180; - self->jumpPower = 64 + ((abs(self->xspeed) + 16) >> 3); - self->falling = true; - } - else*/ - if (self->invincibilityFrames <= 0 && other->state != PA_EN_ST_STUN) + if (other->state != PA_EN_ST_STUN) { - self->hp--; - pa_updateLedsHpMeter(self->entityManager, self->gameData); - self->gameData->comboTimer = 0; - - if (!self->gameData->debugMode && self->hp == 0) + if (!self->gameData->debugMode) { self->updateFunction = &updateEntityDead; self->type = ENTITY_DEAD; @@ -1162,10 +1161,8 @@ void pa_playerCollisionHandler(paEntity_t* self, paEntity_t* other) } else { - self->xspeed = 0; - self->yspeed = 0; - self->jumpPower = 0; - self->invincibilityFrames = 120; + self->xspeed = 0; + self->yspeed = 0; soundPlaySfx(&(self->soundManager->sndHurt), BZR_LEFT); } } @@ -1208,6 +1205,7 @@ void pa_enemyCollisionHandler(paEntity_t* self, paEntity_t* other) switch (other->type) { case PA_ENTITY_CRABDOZER: + { if ((self->xspeed > 0 && self->x < other->x) || (self->xspeed < 0 && self->x > other->x)) { self->xspeed = -self->xspeed; @@ -1220,13 +1218,27 @@ void pa_enemyCollisionHandler(paEntity_t* self, paEntity_t* other) // self->spriteFlipHorizontal = -self->spriteFlipHorizontal; } break; + } case ENTITY_HIT_BLOCK: + { self->xspeed = other->xspeed * 2; self->yspeed = other->yspeed * 2; - pa_scorePoints(self->gameData, self->scoreValue); + + uint16_t pointsScored = hitBlockComboScores[other->scoreValue]; + pa_scorePoints(self->gameData, pointsScored); + other->scoreValue++; + + paEntity_t* createdEntity = pa_createScoreDisplay(self->entityManager, (self->x >> SUBPIXEL_RESOLUTION) - 4, + (self->y >> SUBPIXEL_RESOLUTION) - 4); + if (createdEntity != NULL) + { + createdEntity->scoreValue = pointsScored; + } + soundPlaySfx(&(self->soundManager->sndHurt), 2); killEnemy(self); break; + } default: { break; @@ -1375,37 +1387,67 @@ bool pa_hitBlockTileCollisionHandler(paEntity_t* self, uint8_t tileId, uint8_t t if (pa_isSolid(tileId)) { soundPlaySfx(&(self->soundManager->sndHit), 1); - pa_destroyEntity(self, false); + + self->tilemap->map[PA_TO_TILECOORDS(self->y >> SUBPIXEL_RESOLUTION) * self->tilemap->mapWidth + + PA_TO_TILECOORDS(self->x >> SUBPIXEL_RESOLUTION)] + = self->state; if (PA_TO_TILECOORDS(self->x >> SUBPIXEL_RESOLUTION) == self->homeTileX && PA_TO_TILECOORDS(self->y >> SUBPIXEL_RESOLUTION) == self->homeTileY) { - pa_createBreakBlock(self->entityManager, self->x >> SUBPIXEL_RESOLUTION, self->y >> SUBPIXEL_RESOLUTION); - if (self->jumpPower == PA_TILE_SPAWN_BLOCK_0) + if (self->state == PA_TILE_SPAWN_BLOCK_0) { - self->entityManager->gameData->remainingEnemies--; + pa_executeSpawnBlockCombo(self, self->homeTileX, self->homeTileY, 0); + } + else + { + pa_createBreakBlock(self->entityManager, self->x >> SUBPIXEL_RESOLUTION, + self->y >> SUBPIXEL_RESOLUTION); + pa_scorePoints(self->gameData, 10); } - } - else - { - self->tilemap->map[PA_TO_TILECOORDS(self->y >> SUBPIXEL_RESOLUTION) * self->tilemap->mapWidth - + PA_TO_TILECOORDS(self->x >> SUBPIXEL_RESOLUTION)] - = self->jumpPower; } + pa_destroyEntity(self, false); + return true; } return false; } +void pa_executeSpawnBlockCombo(paEntity_t* self, uint8_t tx, uint8_t ty, uint16_t scoreIndex) +{ + uint8_t t = pa_getTile(self->tilemap, tx, ty); + paEntity_t* newEntity; + + switch (t) + { + case PA_TILE_SPAWN_BLOCK_0: + newEntity + = pa_createBreakBlock(self->entityManager, (tx << PA_TILE_SIZE_IN_POWERS_OF_2) + PA_HALF_TILE_SIZE, + (ty << PA_TILE_SIZE_IN_POWERS_OF_2) + PA_HALF_TILE_SIZE); + if (newEntity == NULL) + { + pa_setTile(self->tilemap, tx, ty, PA_TILE_EMPTY); + pa_scorePoints(self->gameData, spawnBlockComboScores[self->scoreValue]); + self->entityManager->gameData->remainingEnemies--; + } + else + { + newEntity->state = PA_TILE_SPAWN_BLOCK_0; + newEntity->scoreValue = scoreIndex; + } + break; + default: + break; + } +} + void dieWhenFallingOffScreen(paEntity_t* self) { uint16_t deathBoundary = (self->tilemap->mapOffsetY + PA_TILE_MAP_DISPLAY_HEIGHT_PIXELS + DESPAWN_THRESHOLD); if (((self->y >> SUBPIXEL_RESOLUTION) > deathBoundary) && ((self->y >> SUBPIXEL_RESOLUTION) < deathBoundary + DESPAWN_THRESHOLD)) { - self->hp = 0; - pa_updateLedsHpMeter(self->entityManager, self->gameData); self->gameData->changeState = PA_ST_DEAD; pa_destroyEntity(self, true); } @@ -1424,13 +1466,59 @@ void pa_updateBreakBlock(paEntity_t* self) if (self->spriteIndex > PA_SP_BREAK_BLOCK_3) { - pa_createBlockFragment(self->entityManager, self->x >> SUBPIXEL_RESOLUTION, self->y >> SUBPIXEL_RESOLUTION); - pa_createBlockFragment(self->entityManager, self->x >> SUBPIXEL_RESOLUTION, self->y >> SUBPIXEL_RESOLUTION); - pa_createBlockFragment(self->entityManager, self->x >> SUBPIXEL_RESOLUTION, self->y >> SUBPIXEL_RESOLUTION); - pa_createBlockFragment(self->entityManager, self->x >> SUBPIXEL_RESOLUTION, self->y >> SUBPIXEL_RESOLUTION); + uint8_t tx = (self->x >> SUBPIXEL_RESOLUTION >> PA_TILE_SIZE_IN_POWERS_OF_2); + uint8_t ty = (self->y >> SUBPIXEL_RESOLUTION >> PA_TILE_SIZE_IN_POWERS_OF_2); + uint16_t pointsScored; + + switch (self->state) + { + case PA_TILE_SPAWN_BLOCK_0: + { + pointsScored = spawnBlockComboScores[self->scoreValue]; + + pa_scorePoints(self->gameData, pointsScored); + soundPlaySfx(&(self->soundManager->sndCoin), BZR_STEREO); + self->entityManager->gameData->remainingEnemies--; + + pa_executeSpawnBlockCombo(self, tx + 1, ty, self->scoreValue + 1); + pa_executeSpawnBlockCombo(self, tx - 1, ty, self->scoreValue + 1); + pa_executeSpawnBlockCombo(self, tx, ty + 1, self->scoreValue + 1); + pa_executeSpawnBlockCombo(self, tx, ty - 1, self->scoreValue + 1); + + paEntity_t* createdEntity + = pa_createScoreDisplay(self->entityManager, (self->x >> SUBPIXEL_RESOLUTION) - 4, + (self->y >> SUBPIXEL_RESOLUTION) - 4); + if (createdEntity != NULL) + { + createdEntity->scoreValue = pointsScored; + } + + break; + } + default: + { + pa_createBlockFragment(self->entityManager, self->x >> SUBPIXEL_RESOLUTION, + self->y >> SUBPIXEL_RESOLUTION); + pa_createBlockFragment(self->entityManager, self->x >> SUBPIXEL_RESOLUTION, + self->y >> SUBPIXEL_RESOLUTION); + pa_createBlockFragment(self->entityManager, self->x >> SUBPIXEL_RESOLUTION, + self->y >> SUBPIXEL_RESOLUTION); + pa_createBlockFragment(self->entityManager, self->x >> SUBPIXEL_RESOLUTION, + self->y >> SUBPIXEL_RESOLUTION); + break; + } + } + pa_destroyEntity(self, false); } } + + /*if(self->scoreValue > 0){ + char scoreStr[32]; + snprintf(scoreStr, sizeof(scoreStr) - 1, "+%" PRIu32, self->scoreValue); + drawText(&(self->gameData->scoreFont), c050, scoreStr, self->x >> SUBPIXEL_RESOLUTION, self->y >> + SUBPIXEL_RESOLUTION); + }*/ } void updateEntityDead(paEntity_t* self) @@ -1442,6 +1530,16 @@ void updateEntityDead(paEntity_t* self) despawnWhenOffscreen(self); } +void pa_updateScoreDisplay(paEntity_t* self) +{ + self->stateTimer++; + + if (self->stateTimer > 120) + { + pa_destroyEntity(self, false); + } +} + void pa_updateBlockFragment(paEntity_t* self) { self->animationTimer++; @@ -1526,9 +1624,6 @@ void pa_defaultOverlapTileHandler(paEntity_t* self, uint8_t tileId, uint8_t tx, void killPlayer(paEntity_t* self) { - self->hp = 0; - pa_updateLedsHpMeter(self->entityManager, self->gameData); - self->updateFunction = &updateEntityDead; self->type = ENTITY_DEAD; self->xspeed = 0; @@ -1545,3 +1640,21 @@ void drawEntityTargetTile(paEntity_t* self) (self->targetTileX << PA_TILE_SIZE_IN_POWERS_OF_2) + PA_TILE_SIZE - self->tilemap->mapOffsetX, (self->targetTileY << PA_TILE_SIZE_IN_POWERS_OF_2) + PA_TILE_SIZE, esp_random() % 216); } + +void pa_defaultEntityDrawHandler(paEntity_t* self) +{ + drawWsg(self->entityManager->wsgManager->sprites[self->spriteIndex].wsg, + (self->x >> SUBPIXEL_RESOLUTION) - self->entityManager->wsgManager->sprites[self->spriteIndex].originX + - self->entityManager->tilemap->mapOffsetX, + (self->y >> SUBPIXEL_RESOLUTION) - self->entityManager->tilemap->mapOffsetY + - self->entityManager->wsgManager->sprites[self->spriteIndex].originY, + self->spriteFlipHorizontal, self->spriteFlipVertical, 0); +} + +void pa_scoreDisplayDrawHandler(paEntity_t* self) +{ + char scoreStr[32]; + snprintf(scoreStr, sizeof(scoreStr) - 1, "+%" PRIu16, self->scoreValue); + drawText(&(self->gameData->scoreFont), greenColors[(self->stateTimer >> 3) % 4], scoreStr, + self->x >> SUBPIXEL_RESOLUTION, self->y >> SUBPIXEL_RESOLUTION); +} \ No newline at end of file diff --git a/main/modes/games/pango/paEntity.h b/main/modes/games/pango/paEntity.h index dc89f4587..f797886bf 100644 --- a/main/modes/games/pango/paEntity.h +++ b/main/modes/games/pango/paEntity.h @@ -24,7 +24,8 @@ typedef enum PA_ENTITY_BREAK_BLOCK, PA_ENTITY_BLOCK_FRAGMENT, ENTITY_HIT_BLOCK, - ENTITY_DEAD + ENTITY_DEAD, + PA_ENTITY_SCORE_DISPLAY } paEntityIndex_t; typedef enum @@ -64,10 +65,11 @@ typedef enum typedef void (*pa_updateFunction_t)(struct paEntity_t* self); typedef void (*pa_collisionHandler_t)(struct paEntity_t* self, struct paEntity_t* other); -typedef bool (*PA_TILE_CollisionHandler_t)(struct paEntity_t* self, uint8_t tileId, uint8_t tx, uint8_t ty, - uint8_t direction); +typedef bool (*pa_tileCollisionHandler_t)(struct paEntity_t* self, uint8_t tileId, uint8_t tx, uint8_t ty, + uint8_t direction); typedef void (*pa_fallOffTileHandler_t)(struct paEntity_t* self); typedef void (*pa_overlapTileHandler_t)(struct paEntity_t* self, uint8_t tileId, uint8_t tx, uint8_t ty); +typedef void (*pa_drawHandler_t)(struct paEntity_t* self); struct paEntity_t { @@ -107,11 +109,7 @@ struct paEntity_t uint8_t homeTileX; uint8_t homeTileY; - int16_t jumpPower; - bool visible; - uint8_t hp; - int8_t invincibilityFrames; uint16_t scoreValue; uint8_t targetTileX; @@ -126,9 +124,9 @@ struct paEntity_t paEntityManager_t* entityManager; pa_collisionHandler_t collisionHandler; - PA_TILE_CollisionHandler_t tileCollisionHandler; - pa_fallOffTileHandler_t fallOffTileHandler; + pa_tileCollisionHandler_t tileCollisionHandler; pa_overlapTileHandler_t overlapTileHandler; + pa_drawHandler_t drawHandler; }; //============================================================================== @@ -185,7 +183,13 @@ void killPlayer(paEntity_t* self); void drawEntityTargetTile(paEntity_t* self); bool pa_hitBlockTileCollisionHandler(paEntity_t* self, uint8_t tileId, uint8_t tx, uint8_t ty, uint8_t direction); +void pa_executeSpawnBlockCombo(paEntity_t* self, uint8_t tx, uint8_t ty, uint16_t scoreIndex); void pa_updateBreakBlock(paEntity_t* self); void pa_updateBlockFragment(paEntity_t* self); +void pa_updateScoreDisplay(paEntity_t* self); +void pa_defaultEntityDrawHandler(paEntity_t* self); +void pa_scoreDisplayDrawHandler(paEntity_t* self); +int16_t pa_enemySetAggroStateTimer(paEntity_t* self); +uint16_t pa_correctPlayerFacingDirection(int16_t btnState, uint16_t currentFacingDirection); #endif diff --git a/main/modes/games/pango/paEntityManager.c b/main/modes/games/pango/paEntityManager.c index de3c819bf..924013946 100644 --- a/main/modes/games/pango/paEntityManager.c +++ b/main/modes/games/pango/paEntityManager.c @@ -68,22 +68,17 @@ void pa_deactivateAllEntities(paEntityManager_t* entityManager, bool excludePlay for (uint8_t i = 0; i < MAX_ENTITIES; i++) { paEntity_t* currentEntity = &(entityManager->entities[i]); - currentEntity->active = false; - // clear out invisible block tiles that are placed for every Break Block object - // if(currentEntity->type == PA_ENTITY_BREAK_BLOCK){ - // pa_setTile(currentEntity->tilemap, PA_TO_TILECOORDS(currentEntity->x >> SUBPIXEL_RESOLUTION), - // PA_TO_TILECOORDS(currentEntity->y >> SUBPIXEL_RESOLUTION), PA_TILE_EMPTY); - // } - - if (currentEntity->type == ENTITY_HIT_BLOCK && currentEntity->jumpPower == PA_TILE_SPAWN_BLOCK_0) + if (currentEntity->active == false || (excludePlayer && currentEntity == entityManager->playerEntity)) { - entityManager->gameData->remainingEnemies--; + continue; } - if (excludePlayer && currentEntity == entityManager->playerEntity) + currentEntity->active = false; + + if (currentEntity->type == ENTITY_HIT_BLOCK && currentEntity->state == PA_TILE_SPAWN_BLOCK_0) { - currentEntity->active = true; + entityManager->gameData->remainingEnemies--; } } @@ -99,13 +94,7 @@ void pa_drawEntities(paEntityManager_t* entityManager) if (currentEntity.active && currentEntity.visible) { - drawWsg(entityManager->wsgManager->sprites[currentEntity.spriteIndex].wsg, - (currentEntity.x >> SUBPIXEL_RESOLUTION) - - entityManager->wsgManager->sprites[currentEntity.spriteIndex].originX - - entityManager->tilemap->mapOffsetX, - (currentEntity.y >> SUBPIXEL_RESOLUTION) - entityManager->tilemap->mapOffsetY - - entityManager->wsgManager->sprites[currentEntity.spriteIndex].originY, - currentEntity.spriteFlipHorizontal, currentEntity.spriteFlipVertical, 0); + currentEntity.drawHandler(¤tEntity); } } } @@ -207,9 +196,7 @@ paEntity_t* pa_createPlayer(paEntityManager_t* entityManager, uint16_t x, uint16 entity->gravityEnabled = false; entity->gravity = 4; entity->falling = false; - entity->jumpPower = 0; entity->spriteFlipVertical = false; - entity->hp = 1; entity->animationTimer = 0; // Used as a cooldown for shooting square wave balls entity->state = PA_PL_ST_NORMAL; entity->stateTimer = -1; @@ -219,8 +206,8 @@ paEntity_t* pa_createPlayer(paEntityManager_t* entityManager, uint16_t x, uint16 entity->updateFunction = &pa_updatePlayer; entity->collisionHandler = &pa_playerCollisionHandler; entity->tileCollisionHandler = &pa_playerTileCollisionHandler; - entity->fallOffTileHandler = &defaultFallOffTileHandler; entity->overlapTileHandler = &pa_playerOverlapTileHandler; + entity->drawHandler = &pa_defaultEntityDrawHandler; return entity; } @@ -260,8 +247,8 @@ paEntity_t* createCrabdozer(paEntityManager_t* entityManager, uint16_t x, uint16 entity->updateFunction = &updateCrabdozer; entity->collisionHandler = &pa_enemyCollisionHandler; entity->tileCollisionHandler = &pa_enemyTileCollisionHandler; - entity->fallOffTileHandler = &defaultFallOffTileHandler; entity->overlapTileHandler = &pa_defaultOverlapTileHandler; + entity->drawHandler = &pa_defaultEntityDrawHandler; return entity; } @@ -288,7 +275,7 @@ paEntity_t* pa_createBreakBlock(paEntityManager_t* entityManager, uint16_t x, ui entity->gravity = 0; entity->spriteFlipHorizontal = false; entity->spriteFlipVertical = false; - entity->scoreValue = 100; + entity->scoreValue = 0; entity->animationTimer = 0; entity->type = PA_ENTITY_BREAK_BLOCK; entity->spriteIndex = PA_SP_BREAK_BLOCK; @@ -296,8 +283,9 @@ paEntity_t* pa_createBreakBlock(paEntityManager_t* entityManager, uint16_t x, ui entity->updateFunction = &pa_updateBreakBlock; entity->collisionHandler = &pa_dummyCollisionHandler; entity->tileCollisionHandler = &pa_dummyTileCollisionHandler; - entity->fallOffTileHandler = &defaultFallOffTileHandler; entity->overlapTileHandler = &pa_defaultOverlapTileHandler; + entity->drawHandler = &pa_defaultEntityDrawHandler; + entity->state = 0; pa_setTile(entityManager->tilemap, PA_TO_TILECOORDS(x), PA_TO_TILECOORDS(y), PA_TILE_EMPTY); @@ -323,7 +311,7 @@ paEntity_t* pa_createBlockFragment(paEntityManager_t* entityManager, uint16_t x, entity->xMaxSpeed = 132; entity->yMaxSpeed = 132; entity->gravityEnabled = true; - entity->gravity = 0; + entity->gravity = 4; entity->spriteFlipHorizontal = false; entity->spriteFlipVertical = false; entity->scoreValue = 100; @@ -334,8 +322,8 @@ paEntity_t* pa_createBlockFragment(paEntityManager_t* entityManager, uint16_t x, entity->updateFunction = &pa_updateBlockFragment; entity->collisionHandler = &pa_dummyCollisionHandler; entity->tileCollisionHandler = &pa_dummyTileCollisionHandler; - entity->fallOffTileHandler = &defaultFallOffTileHandler; entity->overlapTileHandler = &pa_defaultOverlapTileHandler; + entity->drawHandler = &pa_defaultEntityDrawHandler; return entity; } @@ -370,10 +358,48 @@ paEntity_t* createHitBlock(paEntityManager_t* entityManager, uint16_t x, uint16_ entity->type = ENTITY_HIT_BLOCK; entity->spriteIndex = PA_SP_BLOCK; entity->animationTimer = 0; + entity->scoreValue = 0; entity->updateFunction = &updateHitBlock; entity->collisionHandler = &pa_dummyCollisionHandler; entity->tileCollisionHandler = &pa_hitBlockTileCollisionHandler; entity->overlapTileHandler = &pa_defaultOverlapTileHandler; + entity->drawHandler = &pa_defaultEntityDrawHandler; + + return entity; +} + +paEntity_t* pa_createScoreDisplay(paEntityManager_t* entityManager, uint16_t x, uint16_t y) +{ + paEntity_t* entity = pa_findInactiveEntity(entityManager); + + if (entity == NULL) + { + return NULL; + } + + entity->active = true; + entity->visible = true; + entity->x = x << SUBPIXEL_RESOLUTION; + entity->y = y << SUBPIXEL_RESOLUTION; + + entity->xspeed = 0; + entity->yspeed = 0; + entity->gravityEnabled = false; + entity->gravity = 0; + + entity->spriteFlipHorizontal = false; + entity->spriteFlipVertical = false; + + entity->type = PA_ENTITY_SCORE_DISPLAY; + entity->spriteIndex = 0; + entity->animationTimer = 0; + entity->scoreValue = 0; + entity->stateTimer = 0; + entity->updateFunction = &pa_updateScoreDisplay; + entity->collisionHandler = &pa_dummyCollisionHandler; + entity->tileCollisionHandler = &pa_hitBlockTileCollisionHandler; + entity->overlapTileHandler = &pa_defaultOverlapTileHandler; + entity->drawHandler = &pa_scoreDisplayDrawHandler; return entity; } diff --git a/main/modes/games/pango/paEntityManager.h b/main/modes/games/pango/paEntityManager.h index 48412900f..d1f66e171 100644 --- a/main/modes/games/pango/paEntityManager.h +++ b/main/modes/games/pango/paEntityManager.h @@ -64,5 +64,6 @@ void pa_freeEntityManager(paEntityManager_t* entityManager); paEntity_t* pa_spawnEnemyFromSpawnBlock(paEntityManager_t* entityManager); paEntity_t* pa_createBreakBlock(paEntityManager_t* entityManager, uint16_t x, uint16_t y); paEntity_t* pa_createBlockFragment(paEntityManager_t* entityManager, uint16_t x, uint16_t y); +paEntity_t* pa_createScoreDisplay(paEntityManager_t* entityManager, uint16_t x, uint16_t y); #endif diff --git a/main/modes/games/pango/paGameData.c b/main/modes/games/pango/paGameData.c index cf394f013..2ceef223a 100644 --- a/main/modes/games/pango/paGameData.c +++ b/main/modes/games/pango/paGameData.c @@ -15,129 +15,53 @@ //============================================================================== void pa_initializeGameData(paGameData_t* gameData, paSoundManager_t* soundManager) { - gameData->gameState = 0; - gameData->btnState = 0; - gameData->score = 0; - gameData->lives = 3; - gameData->countdown = 000; - gameData->world = 1; - gameData->level = 1; - gameData->frameCount = 0; - gameData->coins = 0; - gameData->combo = 0; - gameData->comboTimer = 0; - gameData->bgColor = c000; - gameData->initials[0] = 'A'; - gameData->initials[1] = 'A'; - gameData->initials[2] = 'A'; - gameData->rank = 5; - gameData->extraLifeCollected = false; - gameData->checkpoint = 0; - gameData->levelDeaths = 0; - gameData->initialHp = 1; - gameData->debugMode = false; - gameData->continuesUsed = false; - gameData->inGameTimer = 0; - gameData->soundManager = soundManager; + gameData->gameState = 0; + gameData->btnState = 0; + gameData->score = 0; + gameData->extraLifeScore = 10000; + gameData->lives = 3; + gameData->levelTime = 000; + gameData->level = 1; + gameData->frameCount = 0; + gameData->bgColor = c000; + gameData->initials[0] = 'A'; + gameData->initials[1] = 'A'; + gameData->initials[2] = 'A'; + gameData->rank = 5; + gameData->debugMode = false; + gameData->continuesUsed = false; + gameData->inGameTimer = 0; + gameData->soundManager = soundManager; + gameData->playerCharacter = PA_PLAYER_CHARACTER_PANGO; } void pa_initializeGameDataFromTitleScreen(paGameData_t* gameData, uint16_t levelIndex) { - gameData->gameState = 0; - gameData->btnState = 0; - gameData->score = 0; - gameData->lives = 3; - gameData->countdown = 000; - gameData->frameCount = 0; - gameData->coins = 0; - gameData->combo = 0; - gameData->comboTimer = 0; - gameData->bgColor = c000; - gameData->extraLifeCollected = false; - gameData->checkpoint = 0; - gameData->levelDeaths = 0; - gameData->currentBgm = 0; - gameData->changeBgm = 0; - gameData->initialHp = 1; - gameData->continuesUsed = (gameData->world == 1 && gameData->level == 1) ? false : true; - gameData->inGameTimer = 0; - - pa_setDifficultyLevel(gameData, levelIndex); + gameData->gameState = 0; + gameData->btnState = 0; + gameData->score = 0; + gameData->extraLifeScore = 10000; + gameData->lives = 3; + gameData->levelTime = 000; + gameData->frameCount = 0; + gameData->bgColor = c000; + gameData->currentBgm = 0; + gameData->changeBgm = 0; + gameData->continuesUsed = (gameData->level == 1) ? false : true; + gameData->inGameTimer = 0; pa_resetGameDataLeds(gameData); } -void pa_updateLedsHpMeter(paEntityManager_t* entityManager, paGameData_t* gameData) -{ - if (entityManager->playerEntity == NULL) - { - return; - } - - uint8_t hp = entityManager->playerEntity->hp; - if (hp > 3) - { - hp = 3; - } - - // HP meter led pairs: - // 3 4 - // 2 5 - // 1 6 - for (int32_t i = 1; i < 7; i++) - { - gameData->leds[i].r = 0x80; - gameData->leds[i].g = 0x00; - gameData->leds[i].b = 0x00; - } - - for (int32_t i = 1; i < 1 + hp; i++) - { - gameData->leds[i].r = 0x00; - gameData->leds[i].g = 0x80; - - gameData->leds[7 - i].r = 0x00; - gameData->leds[7 - i].g = 0x80; - } - - setLeds(gameData->leds, CONFIG_NUM_LEDS); -} - void pa_scorePoints(paGameData_t* gameData, uint16_t points) { - gameData->combo++; - - uint32_t comboPoints = points * gameData->combo; - - gameData->score += comboPoints; - gameData->comboScore = comboPoints; - - gameData->comboTimer = (gameData->levelDeaths < 3) ? 240 : 1; -} + gameData->score += points; -void addCoins(paGameData_t* gameData, uint8_t coins) -{ - gameData->coins += coins; - if (gameData->coins > 99) + if (gameData->score >= gameData->extraLifeScore) { gameData->lives++; - soundPlaySfx(&(gameData->soundManager->snd1up), BZR_LEFT); - gameData->coins = 0; - } - else - { - soundPlaySfx(&(gameData->soundManager->sndCoin), BZR_LEFT); - } -} - -void updateComboTimer(paGameData_t* gameData) -{ - gameData->comboTimer--; - - if (gameData->comboTimer < 0) - { - gameData->comboTimer = 0; - gameData->combo = 0; + gameData->extraLifeScore += 10000; //(gameData->extraLifeScore + 2000); + soundPlaySfx(&(gameData->soundManager->snd1up), MIDI_SFX); } } @@ -268,15 +192,3 @@ void pa_updateLedsGameClear(paGameData_t* gameData) } setLeds(gameData->leds, CONFIG_NUM_LEDS); } - -void pa_setDifficultyLevel(paGameData_t* gameData, uint16_t levelIndex) -{ - gameData->remainingEnemies - = masterDifficulty[(levelIndex * MASTER_DIFFICULTY_TABLE_ROW_LENGTH) + TOTAL_ENEMIES_LOOKUP_OFFSET]; - gameData->maxActiveEnemies - = masterDifficulty[(levelIndex * MASTER_DIFFICULTY_TABLE_ROW_LENGTH) + MAX_ACTIVE_ENEMIES_LOOKUP_OFFSET]; - gameData->enemyInitialSpeed - = masterDifficulty[(levelIndex * MASTER_DIFFICULTY_TABLE_ROW_LENGTH) + ENEMY_INITIAL_SPEED_LOOKUP_OFFSET]; - gameData->minAggroEnemies = 1; - gameData->maxAggroEnemies = 1; -} \ No newline at end of file diff --git a/main/modes/games/pango/paGameData.h b/main/modes/games/pango/paGameData.h index 2a93f4547..2e2a26d18 100644 --- a/main/modes/games/pango/paGameData.h +++ b/main/modes/games/pango/paGameData.h @@ -10,6 +10,7 @@ #include "pango_typedef.h" #include "palette.h" #include "paSoundManager.h" +#include "font.h" //============================================================================== // Constants @@ -27,23 +28,14 @@ typedef struct uint8_t changeState; uint32_t score; + uint32_t bonusScore; + uint32_t extraLifeScore; uint8_t lives; - uint8_t coins; - int16_t countdown; + int16_t levelTime; uint16_t frameCount; - uint8_t world; uint8_t level; - uint16_t combo; - int16_t comboTimer; - uint32_t comboScore; - - bool extraLifeCollected; - uint8_t checkpoint; - uint8_t levelDeaths; - uint8_t initialHp; - led_t leds[CONFIG_NUM_LEDS]; paletteColor_t bgColor; @@ -58,13 +50,19 @@ typedef struct bool continuesUsed; uint32_t inGameTimer; + uint8_t playerCharacter; + int16_t maxActiveEnemies; int16_t remainingEnemies; int16_t enemyInitialSpeed; int16_t minAggroEnemies; int16_t maxAggroEnemies; + int16_t minAggroTime; + int16_t maxAggroTime; paSoundManager_t* soundManager; + + font_t scoreFont; } paGameData_t; //============================================================================== @@ -72,15 +70,11 @@ typedef struct //============================================================================== void pa_initializeGameData(paGameData_t* gameData, paSoundManager_t* soundManager); void pa_initializeGameDataFromTitleScreen(paGameData_t* gameData, uint16_t levelIndex); -void pa_updateLedsHpMeter(paEntityManager_t* entityManager, paGameData_t* gameData); void pa_scorePoints(paGameData_t* gameData, uint16_t points); -void addCoins(paGameData_t* gameData, uint8_t coins); -void updateComboTimer(paGameData_t* gameData); void pa_resetGameDataLeds(paGameData_t* gameData); void pa_updateLedsShowHighScores(paGameData_t* gameData); void pa_updateLedsLevelClear(paGameData_t* gameData); void pa_updateLedsGameClear(paGameData_t* gameData); void pa_updateLedsGameOver(paGameData_t* gameData); -void pa_setDifficultyLevel(paGameData_t* gameData, uint16_t levelIndex); #endif \ No newline at end of file diff --git a/main/modes/games/pango/paLeveldef.h b/main/modes/games/pango/paLeveldef.h deleted file mode 100644 index b75733b85..000000000 --- a/main/modes/games/pango/paLeveldef.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _LEVELDEF_H_ -#define _LEVELDEF_H_ - -//============================================================================== -// Includes -//============================================================================== -#include - -//============================================================================== -// Structs -//============================================================================== -typedef struct -{ - char filename[16]; - uint16_t timeLimit; - uint16_t checkpointTimeLimit; -} paLeveldef_t; - -#endif diff --git a/main/modes/games/pango/paSoundManager.c b/main/modes/games/pango/paSoundManager.c index 9344b388c..d4b3d6c2d 100644 --- a/main/modes/games/pango/paSoundManager.c +++ b/main/modes/games/pango/paSoundManager.c @@ -10,51 +10,51 @@ //============================================================================== void pa_initializeSoundManager(paSoundManager_t* self) { - loadMidiFile("bgmCastle.mid", &self->bgmCastle, false); + loadMidiFile("bgmCastle.mid", &self->bgmCastle, true); // self->bgmCastle.shouldLoop = true; - loadMidiFile("bgmDeMAGio.mid", &self->bgmDemagio, false); + loadMidiFile("bgmDeMAGio.mid", &self->bgmDemagio, true); // self->bgmDemagio.shouldLoop = true; - loadMidiFile("bgmGameStart.mid", &self->bgmGameStart, false); - loadMidiFile("bgmIntro.mid", &self->bgmIntro, false); - loadMidiFile("bgmNameEntry.mid", &self->bgmNameEntry, false); + loadMidiFile("bgmGameStart.mid", &self->bgmGameStart, true); + loadMidiFile("bgmIntro.mid", &self->bgmIntro, true); + loadMidiFile("bgmNameEntry.mid", &self->bgmNameEntry, true); // self->bgmNameEntry.shouldLoop = true; - loadMidiFile("bgmSmooth.mid", &self->bgmSmooth, false); + loadMidiFile("bgmSmooth.mid", &self->bgmSmooth, true); // self->bgmSmooth.shouldLoop = true; - loadMidiFile("bgmUnderground.mid", &self->bgmUnderground, false); + loadMidiFile("bgmUnderground.mid", &self->bgmUnderground, true); // self->bgmUnderground.shouldLoop = true; - loadMidiFile("snd1up.mid", &self->snd1up, false); - // loadMidiFile("sndBreak.mid", &self->sndBreak, false); - loadMidiFile("sndCheckpoint.mid", &self->sndCheckpoint, false); - loadMidiFile("sndCoin.mid", &self->sndCoin, false); - loadMidiFile("sndDie.mid", &self->sndDie, false); - loadMidiFile("bgmGameOver.mid", &self->bgmGameOver, false); - loadMidiFile("sndBlockStop.mid", &self->sndHit, false); - loadMidiFile("sndSquish.mid", &self->sndHurt, false); - loadMidiFile("sndJump1.mid", &self->sndJump1, false); - loadMidiFile("sndJump2.mid", &self->sndJump2, false); - loadMidiFile("sndJump3.mid", &self->sndJump3, false); - loadMidiFile("sndLevelClearA.mid", &self->sndLevelClearA, false); - loadMidiFile("sndLevelClearB.mid", &self->sndLevelClearB, false); - loadMidiFile("sndLevelClearC.mid", &self->sndLevelClearC, false); - loadMidiFile("sndLevelClearD.mid", &self->sndLevelClearD, false); - loadMidiFile("sndLevelClearS.mid", &self->sndLevelClearS, false); - loadMidiFile("sndMenuConfirm.mid", &self->sndMenuConfirm, false); - loadMidiFile("sndMenuDeny.mid", &self->sndMenuDeny, false); - loadMidiFile("sndMenuSelect.mid", &self->sndMenuSelect, false); - loadMidiFile("sndOutOfTime.mid", &self->sndOuttaTime, false); - loadMidiFile("sndPause.mid", &self->sndPause, false); - loadMidiFile("sndPowerUp.mid", &self->sndPowerUp, false); - loadMidiFile("sndSlide.mid", &self->sndSquish, false); - // loadMidiFile("sndTally.mid", &self->sndTally, false); - loadMidiFile("sndWarp.mid", &self->sndWarp, false); - loadMidiFile("sndWaveBall.mid", &self->sndWaveBall, false); + loadMidiFile("snd1up.mid", &self->snd1up, true); + // loadMidiFile("sndBreak.mid", &self->sndBreak, true); + loadMidiFile("sndCheckpoint.mid", &self->sndCheckpoint, true); + loadMidiFile("sndBlockCombo.mid", &self->sndCoin, true); + loadMidiFile("sndDie.mid", &self->sndDie, true); + loadMidiFile("bgmGameOver.mid", &self->bgmGameOver, true); + loadMidiFile("sndBlockStop.mid", &self->sndHit, true); + loadMidiFile("sndSquish.mid", &self->sndHurt, true); + loadMidiFile("sndJump1.mid", &self->sndJump1, true); + loadMidiFile("sndJump2.mid", &self->sndJump2, true); + loadMidiFile("sndJump3.mid", &self->sndJump3, true); + loadMidiFile("sndLevelClearA.mid", &self->sndLevelClearA, true); + loadMidiFile("sndLevelClearB.mid", &self->sndLevelClearB, true); + loadMidiFile("sndLevelClearC.mid", &self->sndLevelClearC, true); + loadMidiFile("sndLevelClearD.mid", &self->sndLevelClearD, true); + loadMidiFile("sndLevelClearS.mid", &self->sndLevelClearS, true); + loadMidiFile("sndMenuConfirm.mid", &self->sndMenuConfirm, true); + loadMidiFile("sndMenuDeny.mid", &self->sndMenuDeny, true); + loadMidiFile("sndMenuSelect.mid", &self->sndMenuSelect, true); + loadMidiFile("sndOutOfTime.mid", &self->sndOuttaTime, true); + loadMidiFile("sndPause.mid", &self->sndPause, true); + loadMidiFile("sndPowerUp.mid", &self->sndPowerUp, true); + loadMidiFile("sndSlide.mid", &self->sndSquish, true); + loadMidiFile("sndTally.mid", &self->sndTally, true); + loadMidiFile("sndWarp.mid", &self->sndWarp, true); + loadMidiFile("sndWaveBall.mid", &self->sndWaveBall, true); - loadMidiFile("sndSpawn.mid", &self->sndSpawn, false); + loadMidiFile("sndSpawn.mid", &self->sndSpawn, true); } void pa_freeSoundManager(paSoundManager_t* self) diff --git a/main/modes/games/pango/paTables.h b/main/modes/games/pango/paTables.h index ebdd6c82c..d39ca9ea7 100644 --- a/main/modes/games/pango/paTables.h +++ b/main/modes/games/pango/paTables.h @@ -5,6 +5,7 @@ // Includes //============================================================================== #include +#include "pango_typedef.h" //============================================================================== // Look Up Tables @@ -21,9 +22,19 @@ static const uint8_t = { // tx,ty - 1, 1, 15, 1, 1, 13, 15, 13, 8, 1, 15, 7, 8, 13, 1, 7, 4, 1, 12, 1, + 1, 1, 15, 1, 1, 13, 15, 13, 8, 1, 15, 7, 8, 13, 1, 7, 4, 1, 12, 1, // 15, 4, 15, 10, 12, 13, 4, 13, 1, 10, 1, 4, 6, 1, 10, 1, 6, 13, 10, 13}; +#define SPAWN_BLOCK_COMBO_SCORE_TABLE_LENGTH 10 + +static const uint32_t spawnBlockComboScores[SPAWN_BLOCK_COMBO_SCORE_TABLE_LENGTH] + = {100, 500, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000}; + +#define HIT_BLOCK_COMBO_SCORE_TABLE_LENGTH 10 + +static const uint32_t hitBlockComboScores[HIT_BLOCK_COMBO_SCORE_TABLE_LENGTH] + = {200, 400, 800, 1600, 3200, 3200, 6400, 6400, 6400, 6400}; + /*#define MASTER_DIFFICULTY2_TABLE_LENGTH 6 #define TOTAL_ENEMIES_LOOKUP_OFFSET 0 @@ -38,7 +49,7 @@ static const uint8_t static const int16_t masterDifficulty2[MASTER_DIFFICULTY2_TABLE_LENGTH * MASTER_DIFFICULTY2_TABLE_ROW_LENGTH] = { //In-level difficulty curve: -//Starting at 15 seconds, the leftmost parameter will increment every 10 seconds until it reaches the max, +//Starting at 15 seconds, the leftmost parameter will increment every 10 seconds until it reaches the max, // //Then the same will happen with the next parameter in the table until all reach the end-state for the current level. // Total initial max initial max initial max @@ -51,19 +62,86 @@ static const int16_t masterDifficulty2[MASTER_DIFFICULTY2_TABLE_LENGTH * MASTER_ 7, 4, 4, 0, 1, 8, 10, };*/ -#define MASTER_DIFFICULTY_TABLE_LENGTH 16 +#define MASTER_DIFFICULTY_TABLE_LENGTH 50 -#define TOTAL_ENEMIES_LOOKUP_OFFSET 0 -#define MAX_ACTIVE_ENEMIES_LOOKUP_OFFSET 1 -#define ENEMY_INITIAL_SPEED_LOOKUP_OFFSET 2 -#define MASTER_DIFFICULTY_TABLE_ROW_LENGTH 3 +#define BLOCK_WSG_LOOKUP_OFFSET 0 +#define TOTAL_ENEMIES_LOOKUP_OFFSET 1 +#define MAX_ACTIVE_ENEMIES_LOOKUP_OFFSET 2 +#define ENEMY_INITIAL_SPEED_LOOKUP_OFFSET 3 +#define ENEMY_MINIMUM_AGGRESSIVE_TIME_LOOKUP_OFFSET 4 +#define ENEMY_MAXIMUM_AGGRESSIVE_TIME_LOOKUP_OFFSET 5 +#define ENEMY_MINIMUM_AGGRESSIVE_COUNT_LOOKUP_OFFSET 6 +#define ENEMY_MAXIMUM_AGGRESSIVE_COUNT_LOOKUP_OFFSET 7 +#define MASTER_DIFFICULTY_TABLE_ROW_LENGTH 8 static const int16_t masterDifficulty[MASTER_DIFFICULTY_TABLE_LENGTH * MASTER_DIFFICULTY_TABLE_ROW_LENGTH] = { - // Total max min max - // enemies, active, speed aggro, aggro, - 5, 2, 12, 5, 3, 12, 6, 3, 13, 7, 4, 10, 8, 3, 13, 8, 3, 14, 8, 3, 15, 7, 2, 16, - 8, 3, 15, 8, 3, 16, 9, 3, 16, 8, 4, 12, 9, 3, 16, 8, 3, 17, 10, 4, 14, 12, 1, 18, + // Block Total max min max min max + // wsg, enemies, active, speed, aggro time, aggro time, aggro count, aggro count + PA_WSG_BLOCK_BLUE, 5, 2, 12, 300, 900, 0, 0, // + PA_WSG_BLOCK_BLUE, 5, 2, 12, 300, 900, 1, 1, // + // Placeholder: bonus stage + PA_WSG_BLOCK_BLUE, 6, 3, 12, 300, 900, 1, 1, // + PA_WSG_BLOCK_BLUE, 7, 3, 13, 300, 900, 1, 1, // + PA_WSG_BLOCK_BLUE, 7, 4, 10, 300, 900, 1, 1, // + // Placeholder: bonus stage + PA_WSG_BLOCK_GREEN, 8, 3, 13, 300, 600, 1, 1, // + PA_WSG_BLOCK_GREEN, 9, 3, 13, 300, 600, 1, 1, // + PA_WSG_BLOCK_GREEN, 10, 4, 11, 300, 600, 1, 1, // + PA_WSG_BLOCK_GREEN, 7, 2, 14, 200, 600, 1, 1, // + // Placeholder: bonus stage + PA_WSG_BLOCK_YELLOW, 10, 3, 13, 200, 600, 1, 1, // + PA_WSG_BLOCK_YELLOW, 11, 3, 14, 200, 600, 1, 1, // + PA_WSG_BLOCK_YELLOW, 12, 4, 12, 200, 600, 1, 1, // + PA_WSG_BLOCK_YELLOW, 9, 2, 14, 100, 600, 1, 1, // + // Placeholder: bonus stage + PA_WSG_BLOCK_ORANGE, 12, 3, 14, 100, 600, 1, 1, // + PA_WSG_BLOCK_ORANGE, 13, 4, 13, 100, 600, 1, 1, // + PA_WSG_BLOCK_ORANGE, 10, 2, 15, 100, 600, 1, 1, // + PA_WSG_BLOCK_ORANGE, 24, 8, 12, 100, 500, 1, 1, // + // Placeholder: bonus stage + PA_WSG_BLOCK_RED, 13, 3, 15, 100, 500, 1, 1, // + PA_WSG_BLOCK_RED, 14, 4, 14, 100, 500, 1, 1, // + PA_WSG_BLOCK_RED, 11, 2, 16, 100, 400, 1, 1, // + PA_WSG_BLOCK_RED, 28, 8, 13, 100, 500, 1, 1, // + // Placeholder: bonus stage + PA_WSG_BLOCK_MAGENTA, 14, 3, 16, 100, 400, 1, 1, // + PA_WSG_BLOCK_MAGENTA, 15, 4, 15, 100, 400, 1, 1, // + PA_WSG_BLOCK_MAGENTA, 12, 2, 17, 100, 300, 1, 1, // + PA_WSG_BLOCK_MAGENTA, 30, 10, 13, 100, 400, 1, 1, // + + // Placeholder: bonus stage + PA_WSG_BLOCK_BLUE, 12, 1, 18, 100, 300, 1, 1, // + PA_WSG_BLOCK_GREEN, 16, 3, 12, 300, 900, 1, 2, // + PA_WSG_BLOCK_YELLOW, 17, 3, 13, 300, 900, 1, 2, // + PA_WSG_BLOCK_ORANGE, 17, 4, 10, 300, 900, 1, 2, // + // Placeholder: bonus stage + PA_WSG_BLOCK_RED, 18, 3, 13, 300, 600, 1, 2, // + PA_WSG_BLOCK_MAGENTA, 19, 3, 13, 300, 600, 1, 2, // + PA_WSG_BLOCK_BLUE, 20, 4, 11, 300, 600, 1, 2, // + PA_WSG_BLOCK_GREEN, 17, 2, 14, 200, 600, 1, 2, // + // Placeholder: bonus stage + PA_WSG_BLOCK_YELLOW, 20, 3, 13, 200, 600, 1, 2, // + PA_WSG_BLOCK_ORANGE, 21, 3, 14, 200, 600, 1, 2, // + PA_WSG_BLOCK_RED, 22, 4, 12, 200, 600, 1, 2, // + PA_WSG_BLOCK_MAGENTA, 19, 2, 14, 100, 600, 1, 2, // + // Placeholder: bonus stage + PA_WSG_BLOCK_BLUE, 22, 3, 14, 100, 600, 1, 2, // + PA_WSG_BLOCK_GREEN, 23, 4, 13, 100, 600, 1, 2, // + PA_WSG_BLOCK_YELLOW, 20, 2, 15, 100, 600, 1, 2, // + PA_WSG_BLOCK_ORANGE, 34, 8, 12, 100, 500, 1, 2, // + // Placeholder: bonus stage + PA_WSG_BLOCK_RED, 23, 3, 15, 100, 500, 1, 2, // + PA_WSG_BLOCK_MAGENTA, 24, 4, 14, 100, 500, 1, 2, // + PA_WSG_BLOCK_BLUE, 21, 2, 16, 100, 400, 1, 2, // + PA_WSG_BLOCK_GREEN, 38, 8, 13, 100, 500, 1, 2, // + // Placeholder: bonus stage + PA_WSG_BLOCK_YELLOW, 24, 3, 16, 100, 400, 1, 2, // + PA_WSG_BLOCK_ORANGE, 25, 4, 15, 100, 400, 1, 2, // + PA_WSG_BLOCK_RED, 22, 2, 17, 100, 300, 1, 2, // + PA_WSG_BLOCK_MAGENTA, 42, 10, 13, 100, 400, 1, 2, // }; +static const paletteColor_t greenColors[4] = {c555, c051, c030, c051}; + #endif \ No newline at end of file diff --git a/main/modes/games/pango/paTilemap.c b/main/modes/games/pango/paTilemap.c index 92808b766..7667c22d6 100644 --- a/main/modes/games/pango/paTilemap.c +++ b/main/modes/games/pango/paTilemap.c @@ -9,7 +9,6 @@ #include "fs_wsg.h" #include "paTilemap.h" -#include "paLeveldef.h" #include "esp_random.h" #include "cnfs.h" @@ -33,21 +32,11 @@ void pa_initializeTileMap(paTilemap_t* tilemap, paWsgManager_t* wsgManager) tilemap->executeTileSpawnColumn = -1; tilemap->executeTileSpawnRow = -1; - tilemap->animationFrame = 0; - tilemap->animationTimer = 23; - tilemap->wsgManager = wsgManager; } void pa_drawTileMap(paTilemap_t* tilemap) { - tilemap->animationTimer--; - if (tilemap->animationTimer < 0) - { - tilemap->animationFrame = ((tilemap->animationFrame + 1) % 3); - tilemap->animationTimer = 23; - } - for (int32_t y = (tilemap->mapOffsetY >> PA_TILE_SIZE_IN_POWERS_OF_2); y < (tilemap->mapOffsetY >> PA_TILE_SIZE_IN_POWERS_OF_2) + PA_TILE_MAP_DISPLAY_HEIGHT_TILES; y++) { @@ -75,12 +64,6 @@ void pa_drawTileMap(paTilemap_t* tilemap) continue; } - // Test animated tiles - if (tile == PA_TILE_SPAWN_BLOCK_0 || tile == PA_TILE_BONUS_BLOCK_0) - { - tile += tilemap->animationFrame; - } - // Draw only non-garbage tiles if (tile > 0 && tile < 13) { @@ -183,12 +166,6 @@ bool pa_loadMapFromFile(paTilemap_t* tilemap, const char* name) tilemap->minMapOffsetY = 0; tilemap->maxMapOffsetY = height * PA_TILE_SIZE - PA_TILE_MAP_DISPLAY_HEIGHT_PIXELS; - /*for (uint16_t i = 0; i < 16; i++) - { - tilemap->warps[i].x = buf[2 + width * height + i * 2]; - tilemap->warps[i].y = buf[2 + width * height + i * 2 + 1]; - }*/ - free(buf); return true; @@ -250,11 +227,6 @@ bool pa_isSolid(uint8_t tileId) } } -// bool isInteractive(uint8_t tileId) -// { -// return tileId > PA_TILE_INVISIBLE_BLOCK && tileId < PA_TILE_BG_GOAL_ZONE; -// } - void pa_unlockScrolling(paTilemap_t* tilemap) { tilemap->minMapOffsetX = 0; @@ -266,6 +238,10 @@ void pa_unlockScrolling(paTilemap_t* tilemap) bool pa_needsTransparency(uint8_t tileId) { + // TODO + // Currently, all tiles need transparency. + // So get rid of this then? + switch (tileId) { /*case PA_TILE_BOUNCE_BLOCK: diff --git a/main/modes/games/pango/paTilemap.h b/main/modes/games/pango/paTilemap.h index 66ea92770..32dcdc45d 100644 --- a/main/modes/games/pango/paTilemap.h +++ b/main/modes/games/pango/paTilemap.h @@ -27,30 +27,6 @@ #define PA_TILE_SET_SIZE 15 -//============================================================================== -// Enums -//============================================================================== -typedef enum -{ - PA_TILE_EMPTY, - PA_TILE_WALL_0, - PA_TILE_WALL_1, - PA_TILE_WALL_2, - PA_TILE_WALL_3, - PA_TILE_WALL_4, - PA_TILE_WALL_5, - PA_TILE_WALL_6, - PA_TILE_WALL_7, - PA_TILE_BLOCK, - PA_TILE_SPAWN_BLOCK_0, - PA_TILE_SPAWN_BLOCK_1, - PA_TILE_SPAWN_BLOCK_2, - PA_TILE_BONUS_BLOCK_0, - PA_TILE_BONUS_BLOCK_1, - PA_TILE_BONUS_BLOCK_2, - PA_TILE_INVISIBLE_BLOCK -} PA_TILE_Index_t; - //============================================================================== // Structs //============================================================================== @@ -83,9 +59,6 @@ struct paTilemap_t bool executeTileSpawnAll; paEntityManager_t* entityManager; - - uint8_t animationFrame; - int16_t animationTimer; }; //============================================================================== diff --git a/main/modes/games/pango/paWsgManager.c b/main/modes/games/pango/paWsgManager.c index 6ba690e25..f6a98fa5a 100644 --- a/main/modes/games/pango/paWsgManager.c +++ b/main/modes/games/pango/paWsgManager.c @@ -6,6 +6,7 @@ #include #include "fs_wsg.h" #include "paWsgManager.h" +#include "pango_typedef.h" //============================================================================== // Functions @@ -43,7 +44,7 @@ void pa_loadWsgs(paWsgManager_t* self) loadWsg("pa-112.wsg", &self->wsgs[PA_WSG_PANGO_PUSH_SIDE_2], false); loadWsg("pa-113.wsg", &self->wsgs[PA_WSG_PANGO_HURT], false); loadWsg("pa-114.wsg", &self->wsgs[PA_WSG_PANGO_WIN], false); - loadWsg("pa-015.wsg", &self->wsgs[PA_WSG_PANGO_ICON], false); + loadWsg("pa-115.wsg", &self->wsgs[PA_WSG_PANGO_ICON], false); loadWsg("po-000.wsg", &self->wsgs[PA_WSG_PO_SOUTH], false); loadWsg("po-001.wsg", &self->wsgs[PA_WSG_PO_WALK_SOUTH], false); loadWsg("po-002.wsg", &self->wsgs[PA_WSG_PO_NORTH], false); @@ -59,7 +60,7 @@ void pa_loadWsgs(paWsgManager_t* self) loadWsg("po-012.wsg", &self->wsgs[PA_WSG_PO_PUSH_SIDE_2], false); loadWsg("po-013.wsg", &self->wsgs[PA_WSG_PO_HURT], false); loadWsg("po-014.wsg", &self->wsgs[PA_WSG_PO_WIN], false); - loadWsg("pa-015.wsg", &self->wsgs[PA_WSG_PO_ICON], false); + loadWsg("po-015.wsg", &self->wsgs[PA_WSG_PO_ICON], false); loadWsg("px-000.wsg", &self->wsgs[PA_WSG_PIXEL_SOUTH], false); loadWsg("px-001.wsg", &self->wsgs[PA_WSG_PIXEL_WALK_SOUTH], false); loadWsg("px-002.wsg", &self->wsgs[PA_WSG_PIXEL_NORTH], false); @@ -117,13 +118,13 @@ void pa_loadWsgs(paWsgManager_t* self) loadWsg("pa-tile-006.wsg", &self->wsgs[PA_WSG_WALL_5], false); loadWsg("pa-tile-007.wsg", &self->wsgs[PA_WSG_WALL_6], false); loadWsg("pa-tile-008.wsg", &self->wsgs[PA_WSG_WALL_7], false); - loadWsg("pa-tile-009.wsg", &self->wsgs[PA_WSG_BLOCK], false); - loadWsg("pa-tile-010.wsg", &self->wsgs[PA_WSG_SPAWN_BLOCK_0], false); - loadWsg("pa-tile-011.wsg", &self->wsgs[PA_WSG_SPAWN_BLOCK_1], false); - loadWsg("pa-tile-012.wsg", &self->wsgs[PA_WSG_SPAWN_BLOCK_2], false); - loadWsg("pa-tile-013.wsg", &self->wsgs[PA_WSG_BONUS_BLOCK_0], false); - loadWsg("pa-tile-014.wsg", &self->wsgs[PA_WSG_BONUS_BLOCK_1], false); - loadWsg("pa-tile-015.wsg", &self->wsgs[PA_WSG_BONUS_BLOCK_2], false); + loadWsg("pa-tile-009.wsg", &self->wsgs[PA_WSG_BLOCK_BLUE], false); + loadWsg("pa-tile-010.wsg", &self->wsgs[PA_WSG_BLOCK_MAGENTA], false); + loadWsg("pa-tile-011.wsg", &self->wsgs[PA_WSG_BLOCK_RED], false); + loadWsg("pa-tile-012.wsg", &self->wsgs[PA_WSG_BLOCK_ORANGE], false); + loadWsg("pa-tile-013.wsg", &self->wsgs[PA_WSG_BLOCK_YELLOW], false); + loadWsg("pa-tile-014.wsg", &self->wsgs[PA_WSG_BLOCK_GREEN], false); + loadWsg("pa-tile-015.wsg", &self->wsgs[PA_WSG_BLOCK_TITLESCREEN], false); } void pa_initializeSprites(paWsgManager_t* self) @@ -192,11 +193,11 @@ void pa_initializeSprites(paWsgManager_t* self) self->sprites[PA_SP_PLAYER_ICON].originX = 8; self->sprites[PA_SP_PLAYER_ICON].originY = 16; - self->sprites[PA_SP_BLOCK].wsg = &self->wsgs[PA_WSG_BLOCK]; + self->sprites[PA_SP_BLOCK].wsg = &self->wsgs[PA_WSG_BLOCK_BLUE]; self->sprites[PA_SP_BLOCK].originX = 8; self->sprites[PA_SP_BLOCK].originY = 8; - self->sprites[PA_SP_BONUS_BLOCK].wsg = &self->wsgs[PA_WSG_BONUS_BLOCK_0]; + self->sprites[PA_SP_BONUS_BLOCK].wsg = &self->wsgs[PA_WSG_BLOCK_RED]; self->sprites[PA_SP_BONUS_BLOCK].originX = 8; self->sprites[PA_SP_BONUS_BLOCK].originY = 8; @@ -267,13 +268,13 @@ void pa_initializeTiles(paWsgManager_t* self) self->tiles[5] = &self->wsgs[PA_WSG_WALL_5]; self->tiles[6] = &self->wsgs[PA_WSG_WALL_6]; self->tiles[7] = &self->wsgs[PA_WSG_WALL_7]; - self->tiles[8] = &self->wsgs[PA_WSG_BLOCK]; - self->tiles[9] = &self->wsgs[PA_WSG_SPAWN_BLOCK_0]; - self->tiles[10] = &self->wsgs[PA_WSG_SPAWN_BLOCK_1]; - self->tiles[11] = &self->wsgs[PA_WSG_SPAWN_BLOCK_2]; - self->tiles[12] = &self->wsgs[PA_WSG_BONUS_BLOCK_0]; - self->tiles[13] = &self->wsgs[PA_WSG_BONUS_BLOCK_1]; - self->tiles[14] = &self->wsgs[PA_WSG_BONUS_BLOCK_2]; + self->tiles[8] = &self->wsgs[PA_WSG_BLOCK_BLUE]; + self->tiles[9] = &self->wsgs[PA_WSG_BLOCK_RED]; + self->tiles[10] = &self->wsgs[PA_WSG_BLOCK_ORANGE]; + self->tiles[11] = &self->wsgs[PA_WSG_BLOCK_YELLOW]; + self->tiles[12] = &self->wsgs[PA_WSG_BLOCK_GREEN]; + self->tiles[13] = &self->wsgs[PA_WSG_BLOCK_MAGENTA]; + self->tiles[14] = &self->wsgs[PA_WSG_BLOCK_TITLESCREEN]; } void pa_remapWsgToSprite(paWsgManager_t* self, uint16_t spriteIndex, uint16_t wsgIndex) @@ -293,3 +294,23 @@ void pa_remapPlayerCharacter(paWsgManager_t* self, uint16_t newBaseIndex) pa_remapWsgToSprite(self, i, newBaseIndex + i); } } + +void pa_animateTiles(paWsgManager_t* self) +{ + self->globalTileAnimationTimer--; + if (self->globalTileAnimationTimer < 0) + { + // Assumption: all animated tiles have 6 frames of animation + self->globalTileAnimationFrame = ((self->globalTileAnimationFrame + 1) % 6); + + pa_remapWsgToTile(self, 9, PA_WSG_BLOCK_BLUE + self->globalTileAnimationFrame); + + self->globalTileAnimationTimer = 6; + } +} + +void pa_remapBlockTile(paWsgManager_t* self, uint16_t newBlockWsgIndex) +{ + pa_remapWsgToTile(self, 8, newBlockWsgIndex); + pa_remapWsgToSprite(self, PA_SP_BLOCK, newBlockWsgIndex); +} \ No newline at end of file diff --git a/main/modes/games/pango/paWsgManager.h b/main/modes/games/pango/paWsgManager.h index a6bbe9f4a..45d3fc638 100644 --- a/main/modes/games/pango/paWsgManager.h +++ b/main/modes/games/pango/paWsgManager.h @@ -20,104 +20,6 @@ //============================================================================== // Enums //============================================================================== -typedef enum -{ - PA_WSG_PANGO_SOUTH, - PA_WSG_PANGO_WALK_SOUTH, - PA_WSG_PANGO_NORTH, - PA_WSG_PANGO_WALK_NORTH, - PA_WSG_PANGO_SIDE, - PA_WSG_PANGO_WALK_SIDE_1, - PA_WSG_PANGO_WALK_SIDE_2, - PA_WSG_PANGO_PUSH_SOUTH_1, - PA_WSG_PANGO_PUSH_SOUTH_2, - PA_WSG_PANGO_PUSH_NORTH_1, - PA_WSG_PANGO_PUSH_NORTH_2, - PA_WSG_PANGO_PUSH_SIDE_1, - PA_WSG_PANGO_PUSH_SIDE_2, - PA_WSG_PANGO_HURT, - PA_WSG_PANGO_WIN, - PA_WSG_PANGO_ICON, - PA_WSG_PO_SOUTH, - PA_WSG_PO_WALK_SOUTH, - PA_WSG_PO_NORTH, - PA_WSG_PO_WALK_NORTH, - PA_WSG_PO_SIDE, - PA_WSG_PO_WALK_SIDE_1, - PA_WSG_PO_WALK_SIDE_2, - PA_WSG_PO_PUSH_SOUTH_1, - PA_WSG_PO_PUSH_SOUTH_2, - PA_WSG_PO_PUSH_NORTH_1, - PA_WSG_PO_PUSH_NORTH_2, - PA_WSG_PO_PUSH_SIDE_1, - PA_WSG_PO_PUSH_SIDE_2, - PA_WSG_PO_HURT, - PA_WSG_PO_WIN, - PA_WSG_PO_ICON, - PA_WSG_PIXEL_SOUTH, - PA_WSG_PIXEL_WALK_SOUTH, - PA_WSG_PIXEL_NORTH, - PA_WSG_PIXEL_WALK_NORTH, - PA_WSG_PIXEL_SIDE, - PA_WSG_PIXEL_WALK_SIDE_1, - PA_WSG_PIXEL_WALK_SIDE_2, - PA_WSG_PIXEL_PUSH_SOUTH_1, - PA_WSG_PIXEL_PUSH_SOUTH_2, - PA_WSG_PIXEL_PUSH_NORTH_1, - PA_WSG_PIXEL_PUSH_NORTH_2, - PA_WSG_PIXEL_PUSH_SIDE_1, - PA_WSG_PIXEL_PUSH_SIDE_2, - PA_WSG_PIXEL_HURT, - PA_WSG_PIXEL_WIN, - PA_WSG_PIXEL_ICON, - PA_WSG_GIRL_SOUTH, - PA_WSG_GIRL_WALK_SOUTH, - PA_WSG_GIRL_NORTH, - PA_WSG_GIRL_WALK_NORTH, - PA_WSG_GIRL_SIDE, - PA_WSG_GIRL_WALK_SIDE_1, - PA_WSG_GIRL_WALK_SIDE_2, - PA_WSG_GIRL_PUSH_SOUTH_1, - PA_WSG_GIRL_PUSH_SOUTH_2, - PA_WSG_GIRL_PUSH_NORTH_1, - PA_WSG_GIRL_PUSH_NORTH_2, - PA_WSG_GIRL_PUSH_SIDE_1, - PA_WSG_GIRL_PUSH_SIDE_2, - PA_WSG_GIRL_HURT, - PA_WSG_GIRL_WIN, - PA_WSG_GIRL_ICON, - // PA_WSG_BLOCK, - // PA_WSG_BONUS_BLOCK, - PA_WSG_ENEMY_SOUTH, - PA_WSG_ENEMY_NORTH, - PA_WSG_ENEMY_SIDE_1, - PA_WSG_ENEMY_SIDE_2, - PA_WSG_ENEMY_DRILL_SOUTH, - PA_WSG_ENEMY_DRILL_NORTH, - PA_WSG_ENEMY_DRILL_SIDE_1, - PA_WSG_ENEMY_DRILL_SIDE_2, - PA_WSG_ENEMY_STUN, - PA_WSG_BREAK_BLOCK, - PA_WSG_BREAK_BLOCK_1, - PA_WSG_BREAK_BLOCK_2, - PA_WSG_BREAK_BLOCK_3, - PA_WSG_BLOCK_FRAGMENT, - PA_WSG_WALL_0, - PA_WSG_WALL_1, - PA_WSG_WALL_2, - PA_WSG_WALL_3, - PA_WSG_WALL_4, - PA_WSG_WALL_5, - PA_WSG_WALL_6, - PA_WSG_WALL_7, - PA_WSG_BLOCK, - PA_WSG_SPAWN_BLOCK_0, - PA_WSG_SPAWN_BLOCK_1, - PA_WSG_SPAWN_BLOCK_2, - PA_WSG_BONUS_BLOCK_0, - PA_WSG_BONUS_BLOCK_1, - PA_WSG_BONUS_BLOCK_2 -} paWsgIndex_t; //============================================================================== // Structs @@ -127,6 +29,9 @@ typedef struct wsg_t wsgs[PA_WSGS_SIZE]; paSprite_t sprites[PA_SPRITESET_SIZE]; wsg_t* tiles[PA_TILE_SET_SIZE]; + + uint8_t globalTileAnimationFrame; + int16_t globalTileAnimationTimer; } paWsgManager_t; //============================================================================== @@ -143,5 +48,7 @@ void pa_remapWsgToSprite(paWsgManager_t* self, uint16_t spriteIndex, uint16_t ws void pa_remapWsgToTile(paWsgManager_t* self, uint16_t tileIndex, uint16_t wsgIndex); void pa_remapPlayerCharacter(paWsgManager_t* self, uint16_t newBaseIndex); +void pa_animateTiles(paWsgManager_t* self); +void pa_remapBlockTile(paWsgManager_t* self, uint16_t newBlockWsgIndex); #endif \ No newline at end of file diff --git a/main/modes/games/pango/pango.c b/main/modes/games/pango/pango.c index b50a2cbd9..9593780da 100644 --- a/main/modes/games/pango/pango.c +++ b/main/modes/games/pango/pango.c @@ -24,7 +24,6 @@ #include "paTilemap.h" #include "paGameData.h" #include "paEntityManager.h" -#include "paLeveldef.h" #include "hdw-led.h" #include "palette.h" @@ -34,6 +33,7 @@ #include "mainMenu.h" #include "fill.h" #include "paTables.h" +#include "shapes.h" //============================================================================== // Constants @@ -47,15 +47,21 @@ const char pangoName[] = "Pango"; static const paletteColor_t highScoreNewEntryColors[4] = {c050, c055, c005, c055}; static const paletteColor_t redColors[4] = {c501, c540, c550, c540}; +static const paletteColor_t tsRedColors[4] = {c535, c534, c514, c534}; static const paletteColor_t yellowColors[4] = {c550, c331, c550, c555}; -static const paletteColor_t greenColors[4] = {c555, c051, c030, c051}; + static const paletteColor_t cyanColors[4] = {c055, c455, c055, c033}; static const paletteColor_t purpleColors[4] = {c213, c535, c555, c535}; -static const paletteColor_t rgbColors[4] = {c500, c050, c005, c050}; +// static const paletteColor_t rgbColors[4] = {c500, c050, c005, c050}; static const int16_t cheatCode[11] = {PB_UP, PB_UP, PB_DOWN, PB_DOWN, PB_LEFT, PB_RIGHT, PB_LEFT, PB_RIGHT, PB_B, PB_A, PB_START}; +const char* characterSelectOptions[] = {"Pango", "Po", "Pixel", "Polly"}; +const int32_t characterSelectOptionValues[] + = {PA_PLAYER_CHARACTER_PANGO, PA_PLAYER_CHARACTER_PO, PA_PLAYER_CHARACTER_PIXEL, PA_PLAYER_CHARACTER_GIRL}; +#define NUM_CHARACTERS 4 + //============================================================================== // Functions Prototypes //============================================================================== @@ -71,7 +77,7 @@ void pangoMainLoop(int64_t elapsedUs); typedef void (*pa_gameUpdateFuncton_t)(pango_t* self, int64_t elapsedUs); struct pango_t { - font_t radiostars; + font_t font; paWsgManager_t wsgManager; paTilemap_t tilemap; @@ -133,7 +139,8 @@ void loadPangoUnlockables(pango_t* self); void pangoSaveUnlockables(pango_t* self); void drawPangoHighScores(font_t* font, pangoHighScores_t* highScores, paGameData_t* gameData); uint8_t getHighScoreRank(pangoHighScores_t* highScores, uint32_t newScore); -void insertScoreIntoHighScores(pangoHighScores_t* highScores, uint32_t newScore, char newInitials[], uint8_t rank); +void insertScoreIntoHighScores(pangoHighScores_t* highScores, uint32_t newScore, char newInitials[], + uint8_t newCharacter, uint8_t rank); void changeStateNameEntry(pango_t* self); void updateNameEntry(pango_t* self, int64_t elapsedUs); void drawNameEntry(font_t* font, paGameData_t* gameData, uint8_t currentInitial); @@ -143,8 +150,11 @@ void drawShowHighScores(font_t* font, uint8_t menuState); void changeStatePause(pango_t* self); void updatePause(pango_t* self, int64_t elapsedUs); void drawPause(font_t* font); -uint16_t getLevelIndex(uint8_t world, uint8_t level); void pangoChangeStateMainMenu(pango_t* self); +static void pa_backgroundDrawCallback(int16_t x, int16_t y, int16_t w, int16_t h, int16_t up, int16_t upNum); +void drawPangoLogo(font_t* font, int16_t x, int16_t y); +uint16_t pa_getLevelClearBonus(int16_t elapsedTime); +void pa_setDifficultyLevel(paWsgManager_t* wsgManager, paGameData_t* gameData, uint16_t levelIndex); //============================================================================== // Variables @@ -161,56 +171,37 @@ swadgeMode_t pangoMode = {.modeName = pangoName, .fnExitMode = pangoExitMode, .fnMainLoop = pangoMainLoop, .fnAudioCallback = NULL, - .fnBackgroundDrawCallback = NULL, + .fnBackgroundDrawCallback = pa_backgroundDrawCallback, .fnEspNowRecvCb = NULL, .fnEspNowSendCb = NULL}; -#define NUM_LEVELS 16 - -static const paLeveldef_t leveldef[17] = {{.filename = "level1-1.bin", .timeLimit = 180, .checkpointTimeLimit = 90}, - {.filename = "dac01.bin", .timeLimit = 180, .checkpointTimeLimit = 90}, - {.filename = "level1-3.bin", .timeLimit = 180, .checkpointTimeLimit = 90}, - {.filename = "level1-4.bin", .timeLimit = 180, .checkpointTimeLimit = 90}, - {.filename = "level2-1.bin", .timeLimit = 180, .checkpointTimeLimit = 90}, - {.filename = "dac03.bin", .timeLimit = 220, .checkpointTimeLimit = 90}, - {.filename = "level2-3.bin", .timeLimit = 200, .checkpointTimeLimit = 90}, - {.filename = "level2-4.bin", .timeLimit = 180, .checkpointTimeLimit = 90}, - {.filename = "level3-1.bin", .timeLimit = 180, .checkpointTimeLimit = 90}, - {.filename = "dac02.bin", .timeLimit = 180, .checkpointTimeLimit = 90}, - {.filename = "level3-3.bin", .timeLimit = 180, .checkpointTimeLimit = 90}, - {.filename = "level3-4.bin", .timeLimit = 220, .checkpointTimeLimit = 110}, - {.filename = "level4-1.bin", .timeLimit = 270, .checkpointTimeLimit = 90}, - {.filename = "level4-2.bin", .timeLimit = 240, .checkpointTimeLimit = 90}, - {.filename = "level4-3.bin", .timeLimit = 240, .checkpointTimeLimit = 90}, - {.filename = "level4-4.bin", .timeLimit = 240, .checkpointTimeLimit = 90}, - {.filename = "debug.bin", .timeLimit = 180, .checkpointTimeLimit = 90}}; - -led_t platLeds[CONFIG_NUM_LEDS]; +// #define NUM_LEVELS 16 + +led_t paLeds[CONFIG_NUM_LEDS]; static const char str_ready[] = "Ready?"; static const char str_set[] = "Set..."; static const char str_pango[] = "PANGO!"; -static const char str_time_up[] = "-Time Up!-"; static const char str_game_over[] = "Game Over"; static const char str_well_done[] = "Nice Clear!"; static const char str_congrats[] = "Congratulations!"; static const char str_initials[] = "Enter your initials!"; static const char str_hbd[] = "Happy Birthday, Evelyn!"; static const char str_registrated[] = "Your name registrated."; -static const char str_do_your_best[] = "Do your best!"; +static const char str_do_your_best[] = "Hotdog Heroes"; static const char str_pause[] = "-Pause-"; static const char pangoMenuNewGame[] = "New Game"; -static const char pangoMenuContinue[] = "Continue - Lv"; -static const char pangoMenuCharacter[] = "Character"; +static const char pangoMenuContinue[] = "Continue - Rd"; +static const char pangoMenuCharacter[] = "Character: "; static const char pangoMenuHighScores[] = "High Scores"; static const char pangoMenuResetScores[] = "Reset Scores"; static const char pangoMenuResetProgress[] = "Reset Progress"; static const char pangoMenuExit[] = "Exit"; static const char pangoMenuSaveAndExit[] = "Save & Exit"; -static const char KEY_SCORES[] = "pf_scores"; -static const char KEY_UNLOCKS[] = "pf_unlocks"; +static const char KEY_SCORES[] = "pa_scores"; +static const char KEY_UNLOCKS[] = "pa_unlocks"; //============================================================================== // Functions @@ -239,8 +230,17 @@ void pangoEnterMode(void) pango->easterEgg = true; } - loadFont("pango-fw.font", &pango->radiostars, false); - pango->menuRenderer = initMenuManiaRenderer(&pango->radiostars, &pango->radiostars, &pango->radiostars); + loadFont("pango-fw.font", &pango->font, false); + pango->menuRenderer = initMenuManiaRenderer(&pango->font, &pango->font, &pango->font); + + led_t ledColor = {.r = 0xf0, .g = 0xf0, .b = 0x00}; + recolorMenuManiaRenderer(pango->menuRenderer, // + c200, c555, c555, // Title colors (bg, text, outline) + c000, // Background + c110, c100, // Rings + c003, c555, // Rows + highScoreNewEntryColors, ARRAY_SIZE(highScoreNewEntryColors), ledColor); + setManiaLedsOn(pango->menuRenderer, true); pa_initializeWsgManager(&(pango->wsgManager)); @@ -252,6 +252,7 @@ void pangoEnterMode(void) pa_initializeSoundManager(&(pango->soundManager)); pa_initializeGameData(&(pango->gameData), &(pango->soundManager)); + loadFont("tiny_numbers.font", &(pango->gameData.scoreFont), false); pa_initializeEntityManager(&(pango->entityManager), &(pango->wsgManager), &(pango->tilemap), &(pango->gameData), &(pango->soundManager)); @@ -280,7 +281,7 @@ void pangoExitMode(void) } deinitMenuManiaRenderer(pango->menuRenderer); - freeFont(&pango->radiostars); + freeFont(&pango->font); pa_freeWsgManager(&(pango->wsgManager)); pa_freeTilemap(&(pango->tilemap)); pa_freeSoundManager(&(pango->soundManager)); @@ -301,10 +302,10 @@ static void pangoMenuCb(const char* label, bool selected, uint32_t settingVal) { if (label == pangoMenuNewGame) { - pango->gameData.world = 1; pango->gameData.level = 1; pango->entityManager.activeEnemies = 0; pa_initializeGameDataFromTitleScreen(&(pango->gameData), 0); + pa_setDifficultyLevel(&(pango->wsgManager), &(pango->gameData), 1); pa_loadMapFromFile(&(pango->tilemap), "preset.bin"); pa_generateMaze(&(pango->tilemap)); pa_placeEnemySpawns(&(pango->tilemap)); @@ -314,9 +315,9 @@ static void pangoMenuCb(const char* label, bool selected, uint32_t settingVal) } else if (label == pangoMenuContinue) { - pango->gameData.world = 1; pango->gameData.level = settingVal; pa_initializeGameDataFromTitleScreen(&(pango->gameData), settingVal); + pa_setDifficultyLevel(&(pango->wsgManager), &(pango->gameData), settingVal); pango->entityManager.activeEnemies = 0; pa_loadMapFromFile(&(pango->tilemap), "preset.bin"); pa_generateMaze(&(pango->tilemap)); @@ -327,6 +328,7 @@ static void pangoMenuCb(const char* label, bool selected, uint32_t settingVal) } else if (label == pangoMenuCharacter) { + pango->gameData.playerCharacter = settingVal; pa_remapPlayerCharacter(&(pango->wsgManager), 16 * settingVal); soundPlaySfx(&(pango->soundManager.sndMenuConfirm), BZR_STEREO); } @@ -359,7 +361,13 @@ static void pangoMenuCb(const char* label, bool selected, uint32_t settingVal) } else { - // soundPlaySfx(&(pango->soundManager.hit3), BZR_STEREO); + if (label == pangoMenuCharacter) + { + pango->gameData.playerCharacter = settingVal; + pa_remapPlayerCharacter(&(pango->wsgManager), 16 * settingVal); + } + + soundPlaySfx(&(pango->soundManager.sndMenuConfirm), BZR_STEREO); } } @@ -414,7 +422,7 @@ void pangoBuildMainMenu(pango_t* self) pango->levelSelectMenuItem->label = pangoMenuContinue; pango->levelSelectMenuItem->minSetting = 1; pango->levelSelectMenuItem->maxSetting - = (pango->gameData.debugMode) ? NUM_LEVELS - 1 : pango->unlockables.maxLevelIndexUnlocked; + = (pango->gameData.debugMode) ? MASTER_DIFFICULTY_TABLE_LENGTH : pango->unlockables.maxLevelIndexUnlocked; pango->levelSelectMenuItem->currentSetting = (pango->gameData.level == 1) ? pango->levelSelectMenuItem->maxSetting : pango->gameData.level; pango->levelSelectMenuItem->options = NULL; @@ -429,7 +437,8 @@ void pangoBuildMainMenu(pango_t* self) .max = 3, .key = NULL, }; - addSettingsItemToMenu(pango->menu, pangoMenuCharacter, &characterSettingBounds, 0); + addSettingsOptionsItemToMenu(pango->menu, pangoMenuCharacter, characterSelectOptions, characterSelectOptionValues, + NUM_CHARACTERS, &characterSettingBounds, pango->gameData.playerCharacter); addSingleItemToMenu(pango->menu, pangoMenuHighScores); @@ -449,15 +458,14 @@ static void pangoUpdateMainMenu(pango_t* self, int64_t elapsedUs) { // Draw the menu drawMenuMania(pango->menu, pango->menuRenderer, elapsedUs); + drawWsgSimple(pango->wsgManager.sprites[PA_SP_PLAYER_ICON].wsg, 224, 136); } void updateGame(pango_t* self, int64_t elapsedUs) { - // Clear the display - fillDisplayArea(0, 0, TFT_WIDTH, TFT_HEIGHT, self->gameData.bgColor); - pa_updateEntities(&(self->entityManager)); + pa_animateTiles(&(self->wsgManager)); pa_drawTileMap(&(self->tilemap)); pa_drawEntities(&(self->entityManager)); @@ -467,17 +475,17 @@ void updateGame(pango_t* self, int64_t elapsedUs) detectBgmChange(self); // self->gameData.coins = self->gameData.remainingEnemies; - self->gameData.coins = self->entityManager.aggroEnemies; - drawPangoHud(&(self->radiostars), &(self->gameData)); + // self->gameData.coins = self->entityManager.aggroEnemies; + drawPangoHud(&(self->font), &(self->gameData)); self->gameData.frameCount++; if (self->gameData.frameCount > 59) { self->gameData.frameCount = 0; - self->gameData.countdown--; + self->gameData.levelTime++; self->gameData.inGameTimer++; - if (self->gameData.countdown < 10) + /*if (self->gameData.countdown < 10) { soundPlayBgm(&(self->soundManager.sndOuttaTime), BZR_STEREO); } @@ -485,57 +493,46 @@ void updateGame(pango_t* self, int64_t elapsedUs) if (self->gameData.countdown < 0) { killPlayer(self->entityManager.playerEntity); - } + }*/ pa_spawnEnemyFromSpawnBlock(&(self->entityManager)); } - - updateComboTimer(&(self->gameData)); } void drawPangoHud(font_t* font, paGameData_t* gameData) { - char coinStr[8]; - snprintf(coinStr, sizeof(coinStr) - 1, "C:%02d", gameData->coins); - char scoreStr[32]; - snprintf(scoreStr, sizeof(scoreStr) - 1, "%06" PRIu32, gameData->score); + snprintf(scoreStr, sizeof(scoreStr) - 1, "%7.6" PRIu32, gameData->score); char levelStr[15]; - snprintf(levelStr, sizeof(levelStr) - 1, "Level %d-%d", gameData->world, gameData->level); + snprintf(levelStr, sizeof(levelStr) - 1, "R:%02d", gameData->level); char livesStr[8]; snprintf(livesStr, sizeof(livesStr) - 1, "x%d", gameData->lives); char timeStr[10]; - snprintf(timeStr, sizeof(timeStr) - 1, "T:%03d", gameData->countdown); + snprintf(timeStr, sizeof(timeStr) - 1, "T:%02d", gameData->levelTime); if (gameData->frameCount > 29) { drawText(font, c500, "1UP", 24, 2); } - drawText(font, c553, livesStr, 56, 2); - // drawText(font, c553, coinStr, 160, 224); - drawText(font, c553, scoreStr, 112, 2); - drawText(font, c553, levelStr, 32, 226); - drawText(font, (gameData->countdown > 30) ? c553 : redColors[(gameData->frameCount >> 3) % 4], timeStr, 200, 226); + drawText(font, c553, scoreStr, 57, 2); + snprintf(scoreStr, sizeof(scoreStr) - 1, "HI%7.6" PRIu32, pango->highScores.scores[0]); + drawText(font, c553, scoreStr, 157, 2); - if (gameData->comboTimer == 0) + for (uint8_t i = 0; i < gameData->lives; i++) { - return; + drawWsgSimple(pango->wsgManager.sprites[PA_SP_PLAYER_ICON].wsg, 32 + i * 16, 224); } - snprintf(scoreStr, sizeof(scoreStr) - 1, "+%" PRIu32 /*" (x%d)"*/, gameData->comboScore /*, gameData->combo*/); - drawText(font, (gameData->comboTimer < 60) ? c030 : greenColors[(pango->gameData.frameCount >> 3) % 4], scoreStr, - 190, 2); + drawText(font, c553, levelStr, 145, 226); + drawText(font, c553, timeStr, 200, 226); } void updateTitleScreen(pango_t* self, int64_t elapsedUs) { - // Clear the display - fillDisplayArea(0, 0, TFT_WIDTH, TFT_HEIGHT, self->gameData.bgColor); - self->gameData.frameCount++; if (self->gameData.frameCount > 600) @@ -580,367 +577,87 @@ void updateTitleScreen(pango_t* self, int64_t elapsedUs) return; } - // Handle inputs - /*switch (pango->menuState) - { - case 0: - { - if (self->gameData.frameCount > 600) - { - pa_resetGameDataLeds(&(self->gameData)); - changeStateShowHighScores(self); - } + drawPangoTitleScreen(&(self->font), &(self->gameData)); - if ((self->gameData.btnState & cheatCode[pango->cheatCodeIdx]) - && !(self->gameData.prevBtnState & cheatCode[pango->cheatCodeIdx])) - { - pango->cheatCodeIdx++; - - if (pango->cheatCodeIdx > 10) - { - pango->cheatCodeIdx = 0; - pango->menuState = 1; - pango->gameData.debugMode = true; - soundPlaySfx(&(pango->soundManager.sndLevelClearS), BZR_STEREO); - break; - } - else - { - soundPlaySfx(&(pango->soundManager.sndMenuSelect), BZR_STEREO); - break; - } - } - else - { - if (!(self->gameData.frameCount % 150)) - { - pango->cheatCodeIdx = 0; - } - } - - if (((self->gameData.btnState & PB_START) && !(self->gameData.prevBtnState & PB_START)) - || ((self->gameData.btnState & PB_A) && !(self->gameData.prevBtnState & PB_A))) - { - soundPlaySfx(&(self->soundManager.sndMenuConfirm), BZR_STEREO); - pango->menuState = 1; - pango->menuSelection = 0; - } - - break; - } - case 1: + if (((self->gameData.frameCount) % 10) == 0) + { + for (int32_t i = 0; i < CONFIG_NUM_LEDS; i++) { - if (((self->gameData.btnState & PB_START) && !(self->gameData.prevBtnState & PB_START)) - || ((self->gameData.btnState & PB_A) && !(self->gameData.prevBtnState & PB_A))) + if (!(esp_random() % 8)) { - switch (self->menuSelection) + switch (esp_random() % 3) { - case 0 ... 1: - { - uint16_t levelIndex = getLevelIndex(self->gameData.world, self->gameData.level); - if ((levelIndex >= NUM_LEVELS) - || (!self->gameData.debugMode && levelIndex > self->unlockables.maxLevelIndexUnlocked)) - { - soundPlaySfx(&(self->soundManager.sndMenuDeny), BZR_STEREO); - break; - } - - //if(self->menuSelection == 0){ - // self->gameData.world = 1; - // self->gameData.level = 1; - // } - - pa_initializeGameDataFromTitleScreen(&(self->gameData), levelIndex); - self->entityManager.activeEnemies = 0; - pa_loadMapFromFile(&(pango->tilemap), "preset.bin"); - pa_generateMaze(&(pango->tilemap)); - pa_placeEnemySpawns(&(pango->tilemap)); - - changeStateReadyScreen(self); - break; - } - case 2: - { - if (self->gameData.debugMode) - { - // Reset Progress - pangoInitializeUnlockables(self); - soundPlaySfx(&(self->soundManager.sndBreak), BZR_STEREO); - } - else - { - // Show High Scores - self->menuSelection = 0; - self->menuState = 0; - - changeStateShowHighScores(self); - soundPlaySfx(&(self->soundManager.sndMenuConfirm), BZR_STEREO); - } + case 0: + default: + paLeds[i].r = 255; + paLeds[i].g = 0; + paLeds[i].b = 0; break; - } - case 3: - { - if (self->gameData.debugMode) - { - // Reset High Scores - pangoInitializeHighScores(self); - soundPlaySfx(&(self->soundManager.sndBreak), BZR_STEREO); - } - else - { - // Show Achievements - self->menuSelection = 0; - self->menuState = 2; - soundPlaySfx(&(self->soundManager.sndMenuConfirm), BZR_STEREO); - } + case 1: + paLeds[i].r = 255; + paLeds[i].g = 255; + paLeds[i].b = 0; break; - } - case 4: - { - if (self->gameData.debugMode) - { - // Save & Quit - pangoSaveHighScores(self); - pangoSaveUnlockables(self); - soundPlaySfx(&(self->soundManager.sndMenuConfirm), BZR_STEREO); - switchToSwadgeMode(&mainMenuMode); - } - else - { - soundPlaySfx(&(self->soundManager.sndMenuConfirm), BZR_STEREO); - switchToSwadgeMode(&mainMenuMode); - } + case 2: + paLeds[i].r = 0; + paLeds[i].g = 0; + paLeds[i].b = 255; break; - } - default: - { - soundPlaySfx(&(self->soundManager.sndMenuDeny), BZR_STEREO); - self->menuSelection = 0; - } - } - } - else if ((self->gameData.btnState & PB_UP && !(self->gameData.prevBtnState & PB_UP))) - { - if (pango->menuSelection > 0) - { - pango->menuSelection--; - - if (!self->gameData.debugMode && pango->menuSelection == 1 - && self->unlockables.maxLevelIndexUnlocked == 0) - { - pango->menuSelection--; - } - - soundPlaySfx(&(self->soundManager.sndMenuSelect), BZR_STEREO); } } - else if ((self->gameData.btnState & PB_DOWN && !(self->gameData.prevBtnState & PB_DOWN))) - { - if (pango->menuSelection < 4) - { - pango->menuSelection++; - if (!self->gameData.debugMode && pango->menuSelection == 1 - && self->unlockables.maxLevelIndexUnlocked == 0) - { - pango->menuSelection++; - } - - soundPlaySfx(&(self->soundManager.sndMenuSelect), BZR_STEREO); - } - else - { - soundPlaySfx(&(self->soundManager.sndMenuDeny), BZR_STEREO); - } - } - else if ((self->gameData.btnState & PB_LEFT && !(self->gameData.prevBtnState & PB_LEFT))) + if (paLeds[i].r >= 16) { - if (pango->menuSelection == 1) - { - if (pango->gameData.level == 1 && pango->gameData.world == 1) - { - soundPlaySfx(&(self->soundManager.sndMenuDeny), BZR_STEREO); - } - else - { - pango->gameData.level--; - if (pango->gameData.level < 1) - { - pango->gameData.level = 4; - if (pango->gameData.world > 1) - { - pango->gameData.world--; - } - } - soundPlaySfx(&(self->soundManager.sndMenuSelect), BZR_STEREO); - } - } - } - else if ((self->gameData.btnState & PB_RIGHT && !(self->gameData.prevBtnState & PB_RIGHT))) - { - if (pango->menuSelection == 1) - { - if ((pango->gameData.level == 4 && pango->gameData.world == 4) - || (!pango->gameData.debugMode - && getLevelIndex(pango->gameData.world, pango->gameData.level + 1) - > pango->unlockables.maxLevelIndexUnlocked)) - { - soundPlaySfx(&(self->soundManager.sndMenuDeny), BZR_STEREO); - } - else - { - pango->gameData.level++; - if (pango->gameData.level > 4) - { - pango->gameData.level = 1; - if (pango->gameData.world < 8) - { - pango->gameData.world++; - } - } - soundPlaySfx(&(self->soundManager.sndMenuSelect), BZR_STEREO); - } - } + paLeds[i].r -= 16; } - else if ((self->gameData.btnState & PB_B && !(self->gameData.prevBtnState & PB_B))) + if (paLeds[i].g >= 16) { - self->gameData.frameCount = 0; - pango->menuState = 0; - soundPlaySfx(&(self->soundManager.sndMenuConfirm), BZR_STEREO); + paLeds[i].g -= 16; } - break; - } - case 2: - { - if ((self->gameData.btnState & PB_B && !(self->gameData.prevBtnState & PB_B))) + if (paLeds[i].b >= 16) { - self->gameData.frameCount = 0; - pango->menuState = 1; - soundPlaySfx(&(self->soundManager.sndMenuConfirm), BZR_STEREO); + paLeds[i].b -= 16; } - break; - } - default: - pango->menuState = 0; - soundPlaySfx(&(pango->soundManager.sndMenuDeny), BZR_STEREO); - break; - }*/ - - // pa_scrollTileMap(&(pango->tilemap), 1, 0); - // if (self->tilemap.mapOffsetX >= self->tilemap.maxMapOffsetX && self->gameData.frameCount > 58) - //{ - // self->tilemap.mapOffsetX = 0; - // } - - drawPangoTitleScreen(&(self->radiostars), &(self->gameData)); - - if (((self->gameData.frameCount) % 10) == 0) - { - for (int32_t i = 0; i < CONFIG_NUM_LEDS; i++) - { - // self->gameData.leds[i].r = (( (self->gameData.frameCount >> 4) % NUM_LEDS) == i) ? 0xFF : 0x00; - - platLeds[i].r += (esp_random() % 1); - platLeds[i].g += (esp_random() % 8); - platLeds[i].b += (esp_random() % 8); } } - setLeds(platLeds, CONFIG_NUM_LEDS); + setLeds(paLeds, CONFIG_NUM_LEDS); } void drawPangoTitleScreen(font_t* font, paGameData_t* gameData) { - // pa_drawTileMap(&(pango->tilemap)); + pa_drawTileMap(&(pango->tilemap)); - drawText(font, c555, "P A N G O", 96, 32); + drawPangoLogo(font, 100, 32); if (pango->gameData.debugMode) { drawText(font, c555, "Debug Mode", 80, 48); } - switch (pango->menuState) - { - case 0: - { - if ((gameData->frameCount % 60) < 30) - { - drawText(font, c555, "- Press START button -", 20, 128); - } - break; - } - - case 1: - { - drawText(font, c555, "Start Game", 48, 128); + drawWsgSimple(&(pango->wsgManager.wsgs[PA_WSG_GIRL_WIN]), 128, 116); + drawWsgSimple(&(pango->wsgManager.wsgs[PA_WSG_PO_PUSH_SIDE_1]), 144, 122); + drawWsgSimple(&(pango->wsgManager.wsgs[PA_WSG_PIXEL_WIN]), 120, 126); + drawWsgSimple(&(pango->wsgManager.wsgs[PA_WSG_PANGO_PUSH_SOUTH_2]), 136, 132); + drawWsgSimple(&(pango->wsgManager.wsgs[PA_WSG_ENEMY_SIDE_2]), 64, 120); + drawWsgSimple(&(pango->wsgManager.wsgs[PA_WSG_ENEMY_DRILL_SIDE_1]), 52, 128); + drawWsg(&(pango->wsgManager.wsgs[PA_WSG_ENEMY_DRILL_SIDE_2]), 200, 120, true, false, 0); + drawWsg(&(pango->wsgManager.wsgs[PA_WSG_ENEMY_SIDE_1]), 212, 128, true, false, 0); - if (pango->gameData.debugMode || pango->unlockables.maxLevelIndexUnlocked > 0) - { - char levelStr[24]; - snprintf(levelStr, sizeof(levelStr) - 1, "Level Select: %d-%d", gameData->world, gameData->level); - drawText(font, c555, levelStr, 48, 144); - } - - if (pango->gameData.debugMode) - { - drawText(font, c555, "Reset Progress", 48, 160); - drawText(font, c555, "Reset High Scores", 48, 176); - drawText(font, c555, "Save & Exit to Menu", 48, 192); - } - else - { - drawText(font, c555, "High Scores", 48, 160); - drawText(font, c555, "Achievements", 48, 176); - drawText(font, c555, "Exit to Menu", 48, 192); - } - - drawText(font, c555, "->", 24, 128 + pango->menuSelection * 16); - - break; - } - - case 2: - { - if (pango->unlockables.gameCleared) - { - drawText(font, redColors[(gameData->frameCount >> 3) % 4], "Beat the game!", 48, 80); - } - - if (pango->unlockables.oneCreditCleared) - { - drawText(font, yellowColors[(gameData->frameCount >> 3) % 4], "1 Credit Clear!", 48, 96); - } - - if (pango->unlockables.bigScore) - { - drawText(font, greenColors[(gameData->frameCount >> 3) % 4], "Got 4 million points!", 48, 112); - } - - if (pango->unlockables.biggerScore) - { - drawText(font, cyanColors[(gameData->frameCount >> 3) % 4], "Got 10 million points!", 48, 128); - } - - if (pango->unlockables.fastTime) - { - drawText(font, purpleColors[(gameData->frameCount >> 3) % 4], "Beat within 25 min!", 48, 144); - } - - if (pango->unlockables.gameCleared && pango->unlockables.oneCreditCleared && pango->unlockables.bigScore - && pango->unlockables.biggerScore && pango->unlockables.fastTime) - { - drawText(font, rgbColors[(gameData->frameCount >> 3) % 4], "100% 100% 100%", 48, 160); - } - - drawText(font, c555, "Press B to Return", 48, 192); - break; - } - - default: - break; + if ((gameData->frameCount % 60) < 30) + { + drawText(font, c555, "- Press START button -", 20, 208); } } +void drawPangoLogo(font_t* font, int16_t x, int16_t y) +{ + drawTriangleOutlined(x, y + 23, x + 63, y, x + 71, y + 47, c003, cyanColors[(pango->gameData.frameCount >> 2) % 4]); + drawTriangleOutlined(x, y, x + 79, y + 15, x + 23, y + 47, c220, + yellowColors[(pango->gameData.frameCount >> 3) % 4]); + drawText(font, c500, "PANGO", x + 12, y + 16); + drawText(font, tsRedColors[(pango->gameData.frameCount >> 4) % 4], "PANGO", x + 11, y + 15); +} + void changeStateReadyScreen(pango_t* self) { self->gameData.frameCount = 0; @@ -954,9 +671,6 @@ void changeStateReadyScreen(pango_t* self) void updateReadyScreen(pango_t* self, int64_t elapsedUs) { - // Clear the display - fillDisplayArea(0, 0, TFT_WIDTH, TFT_HEIGHT, c000); - self->gameData.frameCount++; if (self->gameData.frameCount > 179) { @@ -964,7 +678,7 @@ void updateReadyScreen(pango_t* self, int64_t elapsedUs) changeStateGame(self); } - drawReadyScreen(&(self->radiostars), &(self->gameData)); + drawReadyScreen(&(self->font), &(self->gameData)); } void drawReadyScreen(font_t* font, paGameData_t* gameData) @@ -998,18 +712,10 @@ void changeStateGame(pango_t* self) pa_deactivateAllEntities(&(self->entityManager), false); - uint16_t levelIndex = getLevelIndex(self->gameData.world, self->gameData.level); - // pa_loadMapFromFile(&(pango->tilemap), "preset.bin"); - // pa_generateMaze(&(pango->tilemap)); - // pa_placeEnemySpawns(&(pango->tilemap)); - - self->gameData.countdown = leveldef[levelIndex].timeLimit; - paEntityManager_t* entityManager = &(self->entityManager); entityManager->viewEntity = pa_createPlayer(entityManager, (9 << PA_TILE_SIZE_IN_POWERS_OF_2) + PA_HALF_TILE_SIZE, (7 << PA_TILE_SIZE_IN_POWERS_OF_2) + PA_HALF_TILE_SIZE); entityManager->playerEntity = entityManager->viewEntity; - entityManager->playerEntity->hp = self->gameData.initialHp; if (entityManager->activeEnemies == 0) { @@ -1065,15 +771,16 @@ void changeStateGame(pango_t* self) entityManager->activeEnemies -= skippedEnemyRespawnCount; } - // pa_viewFollowEntity(&(self->tilemap), entityManager->playerEntity); - - pa_updateLedsHpMeter(&(self->entityManager), &(self->gameData)); - self->tilemap.executeTileSpawnAll = true; self->update = &updateGame; } +static void pa_backgroundDrawCallback(int16_t x, int16_t y, int16_t w, int16_t h, int16_t up, int16_t upNum) +{ + fillDisplayArea(x, y, x + w, y + h, c000); +} + void detectGameStateChange(pango_t* self) { if (!self->gameData.changeState) @@ -1162,10 +869,6 @@ void changeStateDead(pango_t* self) { self->gameData.frameCount = 0; self->gameData.lives--; - self->gameData.levelDeaths++; - self->gameData.combo = 0; - self->gameData.comboTimer = 0; - self->gameData.initialHp = 1; soundStop(true); soundPlayBgm(&(self->soundManager.sndDie), BZR_STEREO); @@ -1175,9 +878,6 @@ void changeStateDead(pango_t* self) void updateDead(pango_t* self, int64_t elapsedUs) { - // Clear the display - fillDisplayArea(0, 0, TFT_WIDTH, TFT_HEIGHT, self->gameData.bgColor); - self->gameData.frameCount++; if (self->gameData.frameCount > 179) { @@ -1194,20 +894,11 @@ void updateDead(pango_t* self, int64_t elapsedUs) pa_updateEntities(&(self->entityManager)); pa_drawTileMap(&(self->tilemap)); pa_drawEntities(&(self->entityManager)); - drawPangoHud(&(self->radiostars), &(self->gameData)); - - if (self->gameData.countdown < 0) - { - drawText(&(self->radiostars), c555, str_time_up, (TFT_WIDTH - textWidth(&(self->radiostars), str_time_up)) / 2, - 128); - } + drawPangoHud(&(self->font), &(self->gameData)); } void updateGameOver(pango_t* self, int64_t elapsedUs) { - // Clear the display - fillDisplayArea(0, 0, TFT_WIDTH, TFT_HEIGHT, c000); - self->gameData.frameCount++; if (self->gameData.frameCount > 179) { @@ -1231,7 +922,7 @@ void updateGameOver(pango_t* self, int64_t elapsedUs) changeStateNameEntry(self); } - drawGameOver(&(self->radiostars), &(self->gameData)); + drawGameOver(&(self->font), &(self->gameData)); pa_updateLedsGameOver(&(self->gameData)); } @@ -1253,55 +944,38 @@ void changeStateTitleScreen(pango_t* self) { self->gameData.frameCount = 0; self->gameData.gameState = PA_ST_TITLE_SCREEN; - self->update = &updateTitleScreen; + pa_remapBlockTile(&(pango->wsgManager), PA_WSG_BLOCK_TITLESCREEN); + self->update = &updateTitleScreen; } void changeStateLevelClear(pango_t* self) { - self->gameData.frameCount = 0; - self->gameData.checkpoint = 0; - self->gameData.levelDeaths = 0; - self->gameData.initialHp = self->entityManager.playerEntity->hp; - self->gameData.extraLifeCollected = false; + self->gameData.frameCount = 0; pa_resetGameDataLeds(&(self->gameData)); + + self->gameData.bonusScore = pa_getLevelClearBonus(self->gameData.levelTime); + self->update = &updateLevelClear; } void updateLevelClear(pango_t* self, int64_t elapsedUs) { - // Clear the display - fillDisplayArea(0, 0, TFT_WIDTH, TFT_HEIGHT, self->gameData.bgColor); - self->gameData.frameCount++; - if (self->gameData.frameCount > 60) + if (self->gameData.frameCount > 100) { - if (self->gameData.countdown > 0) + if (self->gameData.bonusScore > 0) { - self->gameData.countdown--; - - if (self->gameData.countdown % 2) - { - soundPlayBgm(&(self->soundManager.sndTally), BZR_STEREO); - } - - uint16_t comboPoints = 50 * self->gameData.combo; - - self->gameData.score += comboPoints; - self->gameData.comboScore = comboPoints; - - if (self->gameData.combo > 1) - { - self->gameData.combo--; - } + pa_scorePoints(&(pango->gameData), 100); + self->gameData.bonusScore -= 100; + soundPlaySfx(&(self->soundManager.sndTally), 0); } - else if (self->gameData.frameCount % 60 == 0) + else if (self->gameData.frameCount % 120 == 0) { // Hey look, it's a frame rule! + self->gameData.levelTime = 0; - uint16_t levelIndex = getLevelIndex(self->gameData.world, self->gameData.level); - - if (levelIndex >= NUM_LEVELS - 1) + if (self->gameData.level >= MASTER_DIFFICULTY_TABLE_LENGTH) { // Game Cleared! @@ -1337,20 +1011,14 @@ void updateLevelClear(pango_t* self, int64_t elapsedUs) { // Advance to the next level self->gameData.level++; - if (self->gameData.level > 4) - { - self->gameData.world++; - self->gameData.level = 1; - } // Unlock the next level - levelIndex++; - if (levelIndex > self->unlockables.maxLevelIndexUnlocked) + if (self->gameData.level > self->unlockables.maxLevelIndexUnlocked) { - self->unlockables.maxLevelIndexUnlocked = levelIndex; + self->unlockables.maxLevelIndexUnlocked = self->gameData.level; } - pa_setDifficultyLevel(&(pango->gameData), getLevelIndex(self->gameData.world, self->gameData.level)); + pa_setDifficultyLevel(&(pango->wsgManager), &(pango->gameData), self->gameData.level); pa_loadMapFromFile(&(pango->tilemap), "preset.bin"); pa_generateMaze(&(pango->tilemap)); pa_placeEnemySpawns(&(pango->tilemap)); @@ -1368,20 +1036,52 @@ void updateLevelClear(pango_t* self, int64_t elapsedUs) return; } } + else if (self->gameData.frameCount < 30 || !(self->gameData.frameCount % 2)) + { + pa_drawTileMap(&(self->tilemap)); + } pa_updateEntities(&(self->entityManager)); - pa_drawTileMap(&(self->tilemap)); + // pa_drawTileMap(&(self->tilemap)); pa_drawEntities(&(self->entityManager)); - drawPangoHud(&(self->radiostars), &(self->gameData)); - drawLevelClear(&(self->radiostars), &(self->gameData)); + drawPangoHud(&(self->font), &(self->gameData)); + drawLevelClear(&(self->font), &(self->gameData)); pa_updateLedsLevelClear(&(self->gameData)); } void drawLevelClear(font_t* font, paGameData_t* gameData) { drawPangoHud(font, gameData); - drawText(font, c000, str_well_done, (TFT_WIDTH - textWidth(font, str_well_done) + 1) >> 1, 129); - drawText(font, c553, str_well_done, (TFT_WIDTH - textWidth(font, str_well_done)) >> 1, 128); + drawText(font, c000, str_well_done, (TFT_WIDTH - textWidth(font, str_well_done) + 1) >> 1, 48); + drawText(font, c553, str_well_done, (TFT_WIDTH - textWidth(font, str_well_done)) >> 1, 48); + + if (gameData->frameCount > 30) + { + drawText(font, c555, "Time Bonus", 80, 80); + drawText(font, (gameData->levelTime < 20) ? yellowColors[(pango->gameData.frameCount >> 3) % 4] : c555, + "00 - 19s ... 5000", 44, 100); + drawText(font, + (gameData->levelTime >= 20 && gameData->levelTime < 30) + ? greenColors[(pango->gameData.frameCount >> 3) % 4] + : c555, + "20 - 29s ... 2000", 44, 112); + drawText(font, + (gameData->levelTime >= 30 && gameData->levelTime < 40) + ? cyanColors[(pango->gameData.frameCount >> 3) % 4] + : c555, + "30 - 39s ... 1000", 44, 124); + drawText(font, + (gameData->levelTime >= 40 && gameData->levelTime < 50) + ? purpleColors[(pango->gameData.frameCount >> 3) % 4] + : c555, + "40 - 49s ... 500", 44, 136); + drawText(font, + (gameData->levelTime >= 50 && gameData->levelTime < 60) + ? redColors[(pango->gameData.frameCount >> 3) % 4] + : c555, + "50 - 59s ... 100", 44, 148); + drawText(font, (gameData->levelTime > 59) ? c500 : c555, ">59s ....... None", 44, 160); + } } void changeStateGameClear(pango_t* self) @@ -1394,9 +1094,6 @@ void changeStateGameClear(pango_t* self) void updateGameClear(pango_t* self, int64_t elapsedUs) { - // Clear the display - fillDisplayArea(0, 0, TFT_WIDTH, TFT_HEIGHT, c000); - self->gameData.frameCount++; if (self->gameData.frameCount > 450) @@ -1416,8 +1113,8 @@ void updateGameClear(pango_t* self, int64_t elapsedUs) } } - drawPangoHud(&(self->radiostars), &(self->gameData)); - drawGameClear(&(self->radiostars), &(self->gameData)); + drawPangoHud(&(self->font), &(self->gameData)); + drawGameClear(&(self->font), &(self->gameData)); pa_updateLedsGameClear(&(self->gameData)); } @@ -1433,8 +1130,8 @@ void drawGameClear(font_t* font, paGameData_t* gameData) if (gameData->frameCount > 120) { - drawText(font, c555, "You've completed your", 8, 80); - drawText(font, c555, "trip across Swadge Land", 8, 96); + drawText(font, c555, "Many more battle scenes", 8, 80); + drawText(font, c555, "will soon be available", 8, 96); } if (gameData->frameCount > 180) @@ -1471,6 +1168,12 @@ void pangoInitializeHighScores(pango_t* self) self->highScores.scores[3] = 20000; self->highScores.scores[4] = 10000; + self->highScores.character[0] = 0; + self->highScores.character[1] = 1; + self->highScores.character[2] = 2; + self->highScores.character[3] = 3; + self->highScores.character[4] = 0; + for (uint8_t i = 0; i < NUM_PLATFORMER_HIGH_SCORES; i++) { self->highScores.initials[i][0] = 'J' + i; @@ -1533,6 +1236,7 @@ void drawPangoHighScores(font_t* font, pangoHighScores_t* highScores, paGameData highScores->initials[i][0], highScores->initials[i][1], highScores->initials[i][2]); drawText(font, (gameData->rank == i) ? highScoreNewEntryColors[(gameData->frameCount >> 3) % 4] : c555, rowStr, 60, 128 + i * 16); + drawWsgSimple(&(pango->wsgManager.wsgs[PA_WSG_PANGO_ICON + 16 * highScores->character[i]]), 75, 126 + i * 16); } } @@ -1550,7 +1254,8 @@ uint8_t getHighScoreRank(pangoHighScores_t* highScores, uint32_t newScore) return i; } -void insertScoreIntoHighScores(pangoHighScores_t* highScores, uint32_t newScore, char newInitials[], uint8_t rank) +void insertScoreIntoHighScores(pangoHighScores_t* highScores, uint32_t newScore, char newInitials[], + uint8_t newCharacter, uint8_t rank) { if (rank >= NUM_PLATFORMER_HIGH_SCORES) { @@ -1563,12 +1268,14 @@ void insertScoreIntoHighScores(pangoHighScores_t* highScores, uint32_t newScore, highScores->initials[i][0] = highScores->initials[i - 1][0]; highScores->initials[i][1] = highScores->initials[i - 1][1]; highScores->initials[i][2] = highScores->initials[i - 1][2]; + highScores->character[i] = highScores->character[i - 1]; } highScores->scores[rank] = newScore; highScores->initials[rank][0] = newInitials[0]; highScores->initials[rank][1] = newInitials[1]; highScores->initials[rank][2] = newInitials[2]; + highScores->character[rank] = newCharacter; } void changeStateNameEntry(pango_t* self) @@ -1595,8 +1302,6 @@ void changeStateNameEntry(pango_t* self) void updateNameEntry(pango_t* self, int64_t elapsedUs) { - fillDisplayArea(0, 0, TFT_WIDTH, TFT_HEIGHT, c000); - self->gameData.frameCount++; if (self->gameData.btnState & PB_LEFT && !(self->gameData.prevBtnState & PB_LEFT)) @@ -1643,7 +1348,7 @@ void updateNameEntry(pango_t* self, int64_t elapsedUs) if (self->menuState > 2) { insertScoreIntoHighScores(&(self->highScores), self->gameData.score, self->gameData.initials, - self->gameData.rank); + self->gameData.playerCharacter, self->gameData.rank); pangoSaveHighScores(self); pangoChangeStateShowHighScores(self); soundPlaySfx(&(self->soundManager.sndPowerUp), BZR_STEREO); @@ -1655,7 +1360,7 @@ void updateNameEntry(pango_t* self, int64_t elapsedUs) } } - drawNameEntry(&(self->radiostars), &(self->gameData), self->menuState); + drawNameEntry(&(self->font), &(self->gameData), self->menuState); pa_updateLedsShowHighScores(&(self->gameData)); } @@ -1684,8 +1389,6 @@ void pangoChangeStateShowHighScores(pango_t* self) void updateShowHighScores(pango_t* self, int64_t elapsedUs) { - fillDisplayArea(0, 0, TFT_WIDTH, TFT_HEIGHT, c000); - self->gameData.frameCount++; if ((self->gameData.frameCount > 300) @@ -1698,8 +1401,8 @@ void updateShowHighScores(pango_t* self, int64_t elapsedUs) changeStateTitleScreen(self); } - drawShowHighScores(&(self->radiostars), self->menuState); - drawPangoHighScores(&(self->radiostars), &(self->highScores), &(self->gameData)); + drawShowHighScores(&(self->font), self->menuState); + drawPangoHighScores(&(self->font), &(self->highScores), &(self->gameData)); pa_updateLedsShowHighScores(&(self->gameData)); } @@ -1741,8 +1444,8 @@ void updatePause(pango_t* self, int64_t elapsedUs) pa_drawTileMap(&(self->tilemap)); pa_drawEntities(&(self->entityManager)); - drawPangoHud(&(self->radiostars), &(self->gameData)); - drawPause(&(self->radiostars)); + drawPangoHud(&(self->font), &(self->gameData)); + drawPause(&(self->font)); } void drawPause(font_t* font) @@ -1751,7 +1454,43 @@ void drawPause(font_t* font) drawText(font, c553, str_pause, (TFT_WIDTH - textWidth(font, str_pause)) >> 1, 128); } -uint16_t getLevelIndex(uint8_t world, uint8_t level) +uint16_t pa_getLevelClearBonus(int16_t elapsedTime) +{ + switch (elapsedTime) + { + case 0 ... 19: + return 5000; + case 20 ... 29: + return 2000; + case 30 ... 39: + return 1000; + case 40 ... 49: + return 500; + case 50 ... 59: + return 100; + default: + return 0; + } +} + +void pa_setDifficultyLevel(paWsgManager_t* wsgManager, paGameData_t* gameData, uint16_t levelIndex) { - return (world - 1) * 4 + (level - 1); + gameData->remainingEnemies + = masterDifficulty[((levelIndex - 1) * MASTER_DIFFICULTY_TABLE_ROW_LENGTH) + TOTAL_ENEMIES_LOOKUP_OFFSET]; + gameData->maxActiveEnemies + = masterDifficulty[((levelIndex - 1) * MASTER_DIFFICULTY_TABLE_ROW_LENGTH) + MAX_ACTIVE_ENEMIES_LOOKUP_OFFSET]; + gameData->enemyInitialSpeed + = masterDifficulty[((levelIndex - 1) * MASTER_DIFFICULTY_TABLE_ROW_LENGTH) + ENEMY_INITIAL_SPEED_LOOKUP_OFFSET]; + gameData->minAggroTime = masterDifficulty[((levelIndex - 1) * MASTER_DIFFICULTY_TABLE_ROW_LENGTH) + + ENEMY_MINIMUM_AGGRESSIVE_TIME_LOOKUP_OFFSET]; + gameData->maxAggroTime = masterDifficulty[((levelIndex - 1) * MASTER_DIFFICULTY_TABLE_ROW_LENGTH) + + ENEMY_MAXIMUM_AGGRESSIVE_TIME_LOOKUP_OFFSET]; + gameData->minAggroEnemies = masterDifficulty[((levelIndex - 1) * MASTER_DIFFICULTY_TABLE_ROW_LENGTH) + + ENEMY_MINIMUM_AGGRESSIVE_COUNT_LOOKUP_OFFSET]; + gameData->maxAggroEnemies = masterDifficulty[((levelIndex - 1) * MASTER_DIFFICULTY_TABLE_ROW_LENGTH) + + ENEMY_MAXIMUM_AGGRESSIVE_COUNT_LOOKUP_OFFSET]; + + pa_remapBlockTile( + wsgManager, + masterDifficulty[((levelIndex - 1) * MASTER_DIFFICULTY_TABLE_ROW_LENGTH) + BLOCK_WSG_LOOKUP_OFFSET]); } \ No newline at end of file diff --git a/main/modes/games/pango/pango.h b/main/modes/games/pango/pango.h index 74d86ca46..746411498 100644 --- a/main/modes/games/pango/pango.h +++ b/main/modes/games/pango/pango.h @@ -23,6 +23,7 @@ typedef struct { uint32_t scores[NUM_PLATFORMER_HIGH_SCORES]; char initials[NUM_PLATFORMER_HIGH_SCORES][3]; + uint8_t character[NUM_PLATFORMER_HIGH_SCORES]; } pangoHighScores_t; typedef struct diff --git a/main/modes/games/pango/pango_typedef.h b/main/modes/games/pango/pango_typedef.h index 151211633..77f307e88 100644 --- a/main/modes/games/pango/pango_typedef.h +++ b/main/modes/games/pango/pango_typedef.h @@ -68,4 +68,132 @@ typedef enum PA_SP_BLOCK_FRAGMENT } pa_spriteDef_t; +typedef enum +{ + PA_TILE_EMPTY, + PA_TILE_WALL_0, + PA_TILE_WALL_1, + PA_TILE_WALL_2, + PA_TILE_WALL_3, + PA_TILE_WALL_4, + PA_TILE_WALL_5, + PA_TILE_WALL_6, + PA_TILE_WALL_7, + PA_TILE_BLOCK, + PA_TILE_SPAWN_BLOCK_0, + PA_TILE_SPAWN_BLOCK_1, + PA_TILE_SPAWN_BLOCK_2, + PA_TILE_BONUS_BLOCK_0, + PA_TILE_BONUS_BLOCK_1, + PA_TILE_BONUS_BLOCK_2, + PA_TILE_INVISIBLE_BLOCK +} pa_tileDef_t; + +typedef enum +{ + PA_PLAYER_CHARACTER_PANGO, + PA_PLAYER_CHARACTER_PO, + PA_PLAYER_CHARACTER_PIXEL, + PA_PLAYER_CHARACTER_GIRL +} pa_playerCharacterDef_t; + +typedef enum +{ + PA_WSG_PANGO_SOUTH, + PA_WSG_PANGO_WALK_SOUTH, + PA_WSG_PANGO_NORTH, + PA_WSG_PANGO_WALK_NORTH, + PA_WSG_PANGO_SIDE, + PA_WSG_PANGO_WALK_SIDE_1, + PA_WSG_PANGO_WALK_SIDE_2, + PA_WSG_PANGO_PUSH_SOUTH_1, + PA_WSG_PANGO_PUSH_SOUTH_2, + PA_WSG_PANGO_PUSH_NORTH_1, + PA_WSG_PANGO_PUSH_NORTH_2, + PA_WSG_PANGO_PUSH_SIDE_1, + PA_WSG_PANGO_PUSH_SIDE_2, + PA_WSG_PANGO_HURT, + PA_WSG_PANGO_WIN, + PA_WSG_PANGO_ICON, + PA_WSG_PO_SOUTH, + PA_WSG_PO_WALK_SOUTH, + PA_WSG_PO_NORTH, + PA_WSG_PO_WALK_NORTH, + PA_WSG_PO_SIDE, + PA_WSG_PO_WALK_SIDE_1, + PA_WSG_PO_WALK_SIDE_2, + PA_WSG_PO_PUSH_SOUTH_1, + PA_WSG_PO_PUSH_SOUTH_2, + PA_WSG_PO_PUSH_NORTH_1, + PA_WSG_PO_PUSH_NORTH_2, + PA_WSG_PO_PUSH_SIDE_1, + PA_WSG_PO_PUSH_SIDE_2, + PA_WSG_PO_HURT, + PA_WSG_PO_WIN, + PA_WSG_PO_ICON, + PA_WSG_PIXEL_SOUTH, + PA_WSG_PIXEL_WALK_SOUTH, + PA_WSG_PIXEL_NORTH, + PA_WSG_PIXEL_WALK_NORTH, + PA_WSG_PIXEL_SIDE, + PA_WSG_PIXEL_WALK_SIDE_1, + PA_WSG_PIXEL_WALK_SIDE_2, + PA_WSG_PIXEL_PUSH_SOUTH_1, + PA_WSG_PIXEL_PUSH_SOUTH_2, + PA_WSG_PIXEL_PUSH_NORTH_1, + PA_WSG_PIXEL_PUSH_NORTH_2, + PA_WSG_PIXEL_PUSH_SIDE_1, + PA_WSG_PIXEL_PUSH_SIDE_2, + PA_WSG_PIXEL_HURT, + PA_WSG_PIXEL_WIN, + PA_WSG_PIXEL_ICON, + PA_WSG_GIRL_SOUTH, + PA_WSG_GIRL_WALK_SOUTH, + PA_WSG_GIRL_NORTH, + PA_WSG_GIRL_WALK_NORTH, + PA_WSG_GIRL_SIDE, + PA_WSG_GIRL_WALK_SIDE_1, + PA_WSG_GIRL_WALK_SIDE_2, + PA_WSG_GIRL_PUSH_SOUTH_1, + PA_WSG_GIRL_PUSH_SOUTH_2, + PA_WSG_GIRL_PUSH_NORTH_1, + PA_WSG_GIRL_PUSH_NORTH_2, + PA_WSG_GIRL_PUSH_SIDE_1, + PA_WSG_GIRL_PUSH_SIDE_2, + PA_WSG_GIRL_HURT, + PA_WSG_GIRL_WIN, + PA_WSG_GIRL_ICON, + // PA_WSG_BLOCK, + // PA_WSG_BONUS_BLOCK, + PA_WSG_ENEMY_SOUTH, + PA_WSG_ENEMY_NORTH, + PA_WSG_ENEMY_SIDE_1, + PA_WSG_ENEMY_SIDE_2, + PA_WSG_ENEMY_DRILL_SOUTH, + PA_WSG_ENEMY_DRILL_NORTH, + PA_WSG_ENEMY_DRILL_SIDE_1, + PA_WSG_ENEMY_DRILL_SIDE_2, + PA_WSG_ENEMY_STUN, + PA_WSG_BREAK_BLOCK, + PA_WSG_BREAK_BLOCK_1, + PA_WSG_BREAK_BLOCK_2, + PA_WSG_BREAK_BLOCK_3, + PA_WSG_BLOCK_FRAGMENT, + PA_WSG_WALL_0, + PA_WSG_WALL_1, + PA_WSG_WALL_2, + PA_WSG_WALL_3, + PA_WSG_WALL_4, + PA_WSG_WALL_5, + PA_WSG_WALL_6, + PA_WSG_WALL_7, + PA_WSG_BLOCK_BLUE, + PA_WSG_BLOCK_MAGENTA, + PA_WSG_BLOCK_RED, + PA_WSG_BLOCK_ORANGE, + PA_WSG_BLOCK_YELLOW, + PA_WSG_BLOCK_GREEN, + PA_WSG_BLOCK_TITLESCREEN +} paWsgIndex_t; + #endif \ No newline at end of file