From e35b38019f91b99117a31737f430a720dafcb414 Mon Sep 17 00:00:00 2001 From: copyrat90 Date: Sun, 27 Jun 2021 19:33:00 +0900 Subject: [PATCH] Add spike collision & respawn --- audio/sfx_player_damage.wav | Bin 0 -> 1906 bytes graphics/bg_w0_s0_0.bmp | Bin 524406 -> 524406 bytes .../pal_ingame_protagonist_star_damage.bmp | Bin 0 -> 150 bytes .../pal_ingame_protagonist_star_damage.json | 3 + graphics/spr_ingame_protagonist_star.bmp | Bin 6262 -> 6262 bytes graphics_source/bg_w0_s0_0.tmx | 36 +-- .../spr_ingame_protagonist_star.aseprite | Bin 2376 -> 2385 bytes include/constant.h | 1 + include/effect_Transition.h | 72 ++++- include/game_entity_IEntity.h | 22 +- include/game_entity_INumberTextEntity.h | 9 +- include/game_entity_IPhysicsEntity.h | 8 +- include/game_entity_Player.h | 26 +- include/game_entity_Symbol.h | 25 ++ include/game_system_ISystem.h | 2 +- include/game_system_PhysicsMovement.h | 10 + include/game_system_Transition.h | 135 +++++++++ include/game_system_TriggerInteraction.h | 1 + include/game_system_ZoneSwitch.h | 14 +- include/helper_keypad.h | 5 +- include/helper_tilemap.h | 6 +- include/scene_Game.h | 9 - include/scene_GameState.h | 14 +- include/scene_GameState_fwd.h | 8 + license/sfx_player_damage.txt | 6 + src/effect_Transition.cpp | 72 ++++- src/game_entity_Door.cpp | 7 +- src/game_entity_HoverButton.cpp | 7 +- src/game_entity_IEntity.cpp | 53 +++- src/game_entity_INumberTextEntity.cpp | 22 +- src/game_entity_Player.cpp | 121 ++++---- src/game_entity_PressureButton.cpp | 7 +- src/game_entity_Shutter.cpp | 7 +- src/game_entity_Symbol.cpp | 67 ++++- src/game_system_KeyPress.cpp | 2 + src/game_system_PhysicsMovement.cpp | 157 +++++++++- src/game_system_Transition.cpp | 279 ++++++++++++++++++ src/game_system_TriggerInteraction.cpp | 1 + src/game_system_ZoneSwitch.cpp | 75 +++-- src/helper_keypad.cpp | 11 - src/main.cpp | 6 +- src/scene_Game.cpp | 72 +++-- 42 files changed, 1128 insertions(+), 250 deletions(-) create mode 100644 audio/sfx_player_damage.wav create mode 100644 graphics/pal_ingame_protagonist_star_damage.bmp create mode 100644 graphics/pal_ingame_protagonist_star_damage.json create mode 100644 include/game_system_Transition.h create mode 100644 include/scene_GameState_fwd.h create mode 100644 license/sfx_player_damage.txt create mode 100644 src/game_system_Transition.cpp delete mode 100644 src/helper_keypad.cpp diff --git a/audio/sfx_player_damage.wav b/audio/sfx_player_damage.wav new file mode 100644 index 0000000000000000000000000000000000000000..4028d18799adf1d50fb23f96e819aa2c746efb74 GIT binary patch literal 1906 zcmYk3X;)fT7=_8F_G5oSSN}qrwX)jA3{@1kjCWujFO!U-LW$Z&#sN*&LcSAP#pI6i1Q`K zY+N*QVP^lsyWhrF=O=@1t5!&@&ssEU9LGdcyou>=4WHiKUSD0D9`_EJYAzO-HEERu zE);Tk&!!(6KE1uY9$%cD^m`2^pWXCYOe&=e7l@|#&t|?eeuUdA_O{t5<{|+Htyjrq zQVcE6JT`p1xgC#3XD5SRnECzng40^t;U|IZDi8lA#@t5GSWL*7}FPAw-T z57)#d2)7z`TKVkY8unT;A1Nl3&30eAZ4$mJgzt?V7%h}|* z$4=|j3KC~WW?pcgdj1;2$T^twJFR*pp9u$DHj`eZBnh#EFXZxH@SYg|Ml+CPI5_Mu z^-?|+_PedLUZbQ)sRR?w@F#gsm4ml8~>pdFqe$3dL35UpnaH} z!G6Mip#QwQzCe?R+-@Yb5*d+EN{l~@lV#K=kdhIq-uat7x zMC7&C1;cu+T1nkc3nzt7&A*SXM(~9oL$B9qH<)UrkV_}R%X2Qfg*Je>f+BHTBE`f! z;goQ~d^@^2Kfj;vG#j;Qsd$jt-&>n^&)Uo;J=&0y1TK|`MHt5CbMfRD0B0x1N5g*a zu+wfbXeF0T#m#dvfh;B!0eRx@ox zL|6qRA(Nq`LLr|_+-)La7jm|m3^2>ZLN1$1#vtkt?Mlu+xe7-p=bqpU35}+bm|2QLooR0F^=^my;w;NO3Wa z5nTJ_5IzGkfavXZv&A%O$f8upA7sIfpR6?#>q(qpY;aWMsYX&DBbkLPe=awZt`O zu`yeXCex@hwR*KyL0MU6D1VU6WKyhoEE)-iwpN3I#RVVuyIm;xter(5#sfvK*Xgu6 zjaIEyX_Z=qj&OGwHZ)U5uZsLDr8@#V2toiOok}JXP$3rGi-dPW+i#YG0srE{JfMKZ z!hnWwHq^;tF`E(71Tuo);o#^DT7$}w14y-60ihmjlR_b%XHj>obQ&rl+IX_8>K&IQ$ABH(L-g?O?#@mqw7s>tv9_|j^ePB30s+5&aS^gC%!7QOIV3MD2!^tu zbSNN1e2~+Hj>F|}+XI;-ON6RW7V07_R7L_cf`cNUFw!n)2NVKrgSJ4Mo0}UO8|&+D a)>eQ0Wo2b$8ENUWUj0v>|6O9oVEkY7L8Sfw literal 0 HcmV?d00001 diff --git a/graphics/bg_w0_s0_0.bmp b/graphics/bg_w0_s0_0.bmp index 8d6b569fe2d825b0a5ed700d243c45afed1013dd..832f50a210ddfa6f9310700c4972b4ba9ffa9c76 100644 GIT binary patch delta 2301 zcma)6ZD?C%6z;i6lT>SyyOe93T^G|$gRHYzX8%|wlrgtabx}I^q1bCMuA74fq${^S z+H|AsE=`-e*ZQi}S&U9yb*Q&94*W5H=oAEhDKpr0ih|sZP%Nw;6zh5KM{-jTOt^5) zd!F<4yyv{P`-8XpgP+Q+bVo1jRXUvN&#jk%Mtk8gUD?f)q^az&D|@Gb?ns(G`|XxC zyYj@e!-RQ=l=UeiVIqsSNK-?P(p^(2`2Av(Mv|~k=|KDY<@OEa%!Q|j^np)F+q}FE zp*caDlCWR*`N&5KOGPv3J|fVaN!X*?rpn{_IKNnO`~)2bi;j9VJnt`7Lks7jir)D= zJfLJeR?VdQ1zsKMaBx;nRNDZDmCQ3lKDEk;f)$-=wQxkq97Mkr@RQUR?Nk%ssFG<{ zez*}1DVak=POmzmk!Fh?s@3V>tem!(_fW0g#4fC$KkWOlPqT!g3Fd!fyww-|>L zu=if`N_1x5QZi2F;S_l6!L->)?a#`6#o4Hg@$raAQyy+=9hI(_D2NGxnJ$*-bjIQl zf!tg=u4G!vC?)yfG?@)Ilu=6ZvP^z`@c#9blKjXpDXfO=l#=}DFv)LcgRw%+WM)aP z;#I~1R0d#dm1xYL8zvI*DH*gi!lK8|^Fl<7mgvmCihywj$jaj-Li4ZTG4)Yj6aqxf zF1aH@l#dEx@fz~4Bj61jdJJ5JNt;EUMtY4E$-jxV33NUSf;v2bQ)BEcPC^R=luQ@Z zsv*n@T5|HuJYLqAep$3|2_7Ny=O3q94TM$s$Lm1y9VmQ#9oP(`lx0#alYU~7z@%$T z3P3m~?}Hw|t?i)NMrN2|hB_wAFsYtFHbV!4^caCZW9JxHCx?DB4VTfjP0x^%x0+Br z4U(`-uYC!s0l;*se1&;qCcK3u`t4URZP+kl4tq25=xNPX4xkUVVmvVcy&2;O;IAzG1IiX4_r023mbBmtM z6-z{LvdItO5KGtsUaq3-Pws2ze5mZiv{$VA9puGCgco>`7s$-YCaksve4$|ZAEO;> zC_gf^b-~ClBb#vYtFg`hh|=^wqEz74Muh~Alkbm^8~@a?rJ>)=!{=mj*S+-n1HjY5 zBm~Aa@UaD2CZ~U&rGrnHDM1!66l-&qYQR8!rYifWKsL4jw7y4 z$Engx7b^8I#$cO`Xts)RB|E9M#f-TX)}U0a6WBt&l+(g6Rw`L^0Ncf5RNGc8cnyqN zlaQNhf+vFz!V!ElC&l0@aG@Y7yK>Ugs91(}xazRv!*5HidcgZKwDWC))*8ktaf{$bwgT3LhNzr+Db^cB!wQZ zyQN6WYTG^hz^M=mroJdX5Ds|M5Q7iip7aGGRV*MTriI!F;i46s`OjWT;-j1VIdjf@ zGxN>NKeIOyr8g3#$CAq>DHN*U56ul5XP2J@n?!PzaW-Vh+CYu*;|qrPt_`d-hQr6e zE(rq!RU;@P*G@66JAs(ATQ~WS$jl$rIs-hZT;Yr6ZqwRk6floR33x+!RzwV}Ljwe~ zlp_b4Dfzup2np2)^-Hi=OXcU(MJ^VM$=*BxsTPpc@Pw9fW+1%n6=r1=Cek{r0l$`V zWzSnU+2_O$5VnuoN9yh%0HQDHHvfC(Ws-BB-k3>BIy>q(l zW1ieP=~7rWOt^q@jznd2OMs7%&R+!{*%M^mJgXXEn-n@w2~TOMb|cvhSmbo)>w5m959v<&8NYDr4K1}CyOAk-Sfr$! zyN@59Ux8;fuixXtr;m@!pEi_i#gsEu#_W`zX7Ry=%lJfc4zGKg;nT-|UO0m%dnfZn zvoQZ!YO`|w0Y3iD%e=0)1fM=WK3P1J>;>$UHE4JBt*z&M;X|m5Ybro0QN6^0VN>} z@9W`r_W2-aY~Npm94sZx03SZk!^aQ!Y)Z`7G30=0eio1eOrZ-vtrU;}v>xy|Mi*b&Oh%WG8l#dU**desdDL0N8SXo#fq z$ft66xpv{Oq5k0l{p%m#1n!lPsXhliKpVzXS7fE(_=S!rcj(#HqEZFW5f zuam2ksmfSJ{j1|}(uxtlM0n!FC4BRlY6B2~Pb>n4dXu1^T2Mp1O~}s$(op{<;HeDo zA5wjhcJgeN#Q&Cn(e?cZXiYACJOR$42-Z{la4ci8VkEx2M9Pvzg(=wl=BygmmeDbE znUt(iW>FTCrzmM@8HqE()*E3;AR1F}Cs@CT67wrY{F`5eaRlRdf>X6oKV5?=*hyt= zVG-OO3e9iETr4poaWw5c>c?vn%&BpO`HlGbO0xc-B*GYa59EReS=8uI9H4(Y0mu1~ zW%ujfy$G{hxKVKS6|cD&KnC7*X#_L#HsboFxyZ%FKPWR^1~%ZGmoEy462<&tIS6e# zBmSGn4#Q(Mu_;>Ic33wF_|D%iQ0*ct7Nmj5MxcrG8;Q>lvTO7g5kZbAG!Iz_Ek7eZ zCL$C!QeSX6X0)bShBuAx94GgpsfAOTiY@K9wgLFqL^rBUbraNrmYT<}{JC4aZ-E-| zK6brFYjT?EexWbd--$u7o^aYEk{0Vn@YSfjSvK8lUqP2XA;B$kTQd}b{+0u-o9&gz z!R&OwEt}cC9twbWKV7e-eER5g=rgyiq*+MJfZO`jK`1c0ir|LbY!ARD&__!MumrY% zKE_aNe-bu>Ip%{t^t4nUW)tEW{H%}8fqtX?t{dm&7_^w9rO=Nki_yatqXIE>E&Av@ z=(lLm*tMFY^96Q2knt%%z+*XP$U&@mkD@-*4r$JxH0mW59+)rWyoVM!= z-z9Oi_IT4L!(+!I;mOD2Fx3st$-Vyq(8#f#i2LMOy2WbER delta 16 Xcmexn@XcU?^JZrzOUBJLjK9PHK0gMM diff --git a/graphics_source/bg_w0_s0_0.tmx b/graphics_source/bg_w0_s0_0.tmx index a956a2d..8140a5c 100644 --- a/graphics_source/bg_w0_s0_0.tmx +++ b/graphics_source/bg_w0_s0_0.tmx @@ -108,32 +108,32 @@ 51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,55,56,0,0,0,0,0,0,0,0,0,49,74,27,28,27,28,27,28,27,27,28,27,28,29,30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,83,84,75,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,55,56,0,0,0,0,0,0,0,0,0,121,122,123,124,123,35,7,7,7,51,51,51,51,51,104,5,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,60,51,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,77,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,60,7,7,51,51,51,51,51,51,29,30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,83,84,75,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -51,51,7,8,99,100,99,100,99,100,99,100,99,100,99,100,99,100,100,101,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,83,84,7,7,51,51,51,51,51,51,51,104,5,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,60,51,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -51,51,31,32,123,124,123,124,123,124,123,124,123,124,123,124,123,124,124,125,126,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,60,7,7,51,51,51,51,51,51,51,51,29,30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,83,84,75,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +51,51,7,8,99,100,99,100,99,100,99,100,99,100,99,100,99,100,100,101,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,83,84,7,7,51,51,51,51,51,51,51,104,5,6,57,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,60,51,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +51,51,31,32,123,124,123,124,123,124,123,124,123,124,123,124,123,124,124,125,126,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,60,7,7,51,51,51,51,51,51,51,51,29,30,57,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,83,84,75,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 51,51,77,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,83,84,7,7,51,51,51,51,51,51,51,51,51,104,5,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,60,51,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 51,51,77,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,4,3,4,3,107,51,7,7,51,51,51,51,51,51,51,51,51,51,29,30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,83,84,75,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -51,51,53,54,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,26,28,27,28,27,11,12,7,7,51,51,51,51,51,51,51,51,51,51,51,104,5,6,0,0,0,0,0,0,0,0,0,0,0,0,59,60,51,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -51,51,77,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,73,74,7,51,51,51,51,36,7,7,51,51,51,51,51,51,51,51,51,51,51,51,29,30,0,0,0,0,0,0,0,0,0,0,0,0,83,84,75,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -51,51,53,104,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,4,4,3,4,4,3,4,107,51,7,51,51,51,51,51,7,7,51,51,51,51,51,51,51,51,51,51,51,51,51,104,5,6,0,0,0,0,0,0,0,0,0,0,59,60,51,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -51,51,51,51,27,28,27,28,27,28,27,28,27,28,27,28,27,28,27,28,27,28,28,28,27,28,28,27,28,99,99,100,99,100,99,99,100,99,100,99,100,99,100,99,100,99,100,99,100,99,100,99,100,101,102,0,0,0,0,0,0,0,0,0,0,83,84,75,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -51,51,53,32,122,123,124,125,122,123,124,125,122,123,124,125,122,123,124,125,124,125,125,125,122,123,125,122,123,122,123,124,123,124,123,123,124,123,124,123,124,123,124,123,124,123,124,123,124,123,124,123,124,125,126,0,0,0,0,0,0,1,6,0,0,59,60,51,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -51,51,77,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,121,126,0,0,83,84,75,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -51,51,77,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,60,51,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -51,51,53,54,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,83,84,75,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -51,51,77,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,60,51,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -51,51,53,104,6,727,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,726,1,3,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,3,4,3,4,3,4,3,4,3,4,3,107,108,75,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -51,51,51,77,54,726,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,725,25,26,27,28,27,28,27,28,27,28,27,28,27,28,27,28,27,28,27,28,27,28,27,28,27,28,27,28,27,27,28,27,28,27,28,27,28,27,28,27,131,132,51,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -51,51,51,53,30,725,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,724,49,50,51,51,51,51,7,7,7,7,7,7,7,7,51,52,51,52,51,52,51,52,51,52,51,52,51,52,51,52,51,52,51,52,51,52,51,52,51,52,51,52,75,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -51,51,51,77,54,724,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,723,73,74,51,51,51,51,7,7,7,7,7,7,7,7,75,76,75,76,75,76,75,76,75,76,75,76,75,76,75,76,75,76,75,76,75,76,75,76,75,76,75,76,51,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -51,51,51,53,78,723,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,722,49,50,51,51,51,51,7,7,7,7,7,7,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -51,51,51,77,102,722,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,107,74,7,7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +51,51,53,54,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,26,28,27,28,27,11,12,7,7,51,51,51,51,51,51,51,51,51,51,51,104,5,6,0,0,0,0,0,0,0,0,0,0,0,82,59,60,51,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +51,51,77,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,73,74,7,51,51,51,51,36,7,7,51,51,51,51,51,51,51,51,51,51,51,51,29,30,0,0,0,0,0,0,0,0,0,0,0,82,83,84,75,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +51,51,53,104,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,4,4,3,4,4,3,4,107,51,7,51,51,51,51,51,7,7,51,51,51,51,51,51,51,51,51,51,51,51,51,104,5,6,0,0,0,0,0,0,0,0,0,82,59,60,51,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +51,51,51,51,27,28,27,28,27,28,27,28,27,28,27,28,27,28,27,28,27,28,28,28,27,28,28,27,28,99,99,100,99,100,99,99,100,99,100,99,100,99,100,99,100,99,100,99,100,99,100,99,100,101,102,0,0,0,0,0,0,0,0,81,81,83,84,75,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +51,51,53,32,122,123,124,125,122,123,124,125,122,123,124,125,122,123,124,125,124,125,125,125,122,123,125,122,123,122,123,124,123,124,123,123,124,123,124,123,124,123,124,123,124,123,124,123,124,123,124,123,124,125,126,0,0,0,0,1,2,3,4,3,4,107,108,51,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +51,51,77,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,58,58,58,58,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,58,58,58,58,58,0,0,0,0,25,26,27,28,27,28,131,132,75,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +51,51,77,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,49,50,51,51,51,51,51,51,51,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +51,51,53,54,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,73,74,51,51,51,51,51,51,75,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +51,51,77,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,83,84,51,51,51,51,51,51,51,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +51,51,53,104,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,3,4,3,4,3,107,108,51,51,51,51,51,51,75,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +51,51,51,77,54,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,25,26,27,28,27,28,27,28,27,28,27,28,27,28,27,28,27,28,27,28,27,28,27,28,27,28,27,28,27,27,28,27,28,27,131,132,51,51,51,51,51,51,51,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +51,51,51,53,30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,49,50,51,51,51,51,7,7,7,7,7,7,7,7,51,52,51,52,51,52,51,52,51,52,51,52,51,52,51,52,51,52,51,52,51,52,51,52,51,52,51,52,75,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +51,51,51,77,54,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,73,74,51,51,51,51,7,7,7,7,7,7,7,7,75,76,75,76,75,76,75,76,75,76,75,76,75,76,75,76,75,76,75,76,75,76,75,76,75,76,75,76,51,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +51,51,51,53,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,49,50,51,51,51,51,7,7,7,7,7,7,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +51,51,51,77,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,107,74,7,7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 51,51,51,51,104,3,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,107,51,7,7,7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 51,51,127,128,128,27,27,28,27,28,27,28,27,28,27,28,27,28,27,28,27,28,27,28,27,51,7,7,7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 51,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, diff --git a/graphics_source/spr_ingame_protagonist_star.aseprite b/graphics_source/spr_ingame_protagonist_star.aseprite index 54463153cf587d8ce201d57212149764e5732fd8..0512c287d3fed2d13132637bcabeb93ee449f106 100644 GIT binary patch delta 96 zcmX>hbWw;ga3Z5TBg;g^c*f5Y8&y4w7#J8N6 bgMosaicAction_; }; -inline Transition::Types operator|(Transition::Types t1, Transition::Types t2) +[[nodiscard]] constexpr Transition::Types operator|(Transition::Types t1, Transition::Types t2) { return static_cast(static_cast(t1) | static_cast(t2)); } -inline Transition::Types operator&(Transition::Types t1, Transition::Types t2) +[[nodiscard]] constexpr Transition::Types operator&(Transition::Types t1, Transition::Types t2) { return static_cast(static_cast(t1) & static_cast(t2)); } diff --git a/include/game_entity_IEntity.h b/include/game_entity_IEntity.h index 427f6a0..454bc0d 100644 --- a/include/game_entity_IEntity.h +++ b/include/game_entity_IEntity.h @@ -4,6 +4,7 @@ #include #include #include +#include #include namespace sym::game::entity @@ -54,25 +55,36 @@ class IEntity virtual void FreeGraphicResource(); virtual void AllocateGraphicResource(int z_order); + virtual void SetBlendingEnabled(bool isEnable); + [[nodiscard]] bool GetBlendingEnabled() const; + virtual void SetMosaicEnabled(bool isEnable); + [[nodiscard]] bool GetMosaicEnabled() const; + virtual void SetVisible(bool isVisible); + [[nodiscard]] bool GetVisible() const; + virtual void SetColors(const bn::sprite_palette_item& paletteItem); virtual void SetCamera(const bn::camera_ptr& camera); - bn::fixed_point GetPosition() const; + [[nodiscard]] bn::fixed_point GetPosition() const; void SetPosition(const bn::fixed_point& position); - bn::fixed GetX() const; - bn::fixed GetY() const; + [[nodiscard]] bn::fixed GetX() const; + [[nodiscard]] bn::fixed GetY() const; void SetX(bn::fixed x); void SetY(bn::fixed y); void SetHorizontalFlip(bool flip); - bool GetHorizontalFlip() const; + [[nodiscard]] bool GetHorizontalFlip() const; void SetVerticalFlip(bool flip); - bool GetVerticalFlip() const; + [[nodiscard]] bool GetVerticalFlip() const; protected: bn::fixed_point position_; bn::fixed_rect relativeInteractRange_; bn::optional sprite_; const bn::sprite_item* spriteItem_; + const bn::sprite_palette_item* paletteItem_; + bool isBlendingEnabled_ = true; + bool isMosaicEnabled_ = true; + bool isVisible_ = true; void SyncSpritePositionToPosition_(); }; diff --git a/include/game_entity_INumberTextEntity.h b/include/game_entity_INumberTextEntity.h index 38ea240..d4e19bc 100644 --- a/include/game_entity_INumberTextEntity.h +++ b/include/game_entity_INumberTextEntity.h @@ -19,10 +19,13 @@ class INumberTextEntity : public IEntity INumberTextEntity(const INumberTextEntity& other) = delete; INumberTextEntity& operator=(const INumberTextEntity& other) = delete; - void FreeGraphicResource(); - void AllocateGraphicResource(int z_order); + void FreeGraphicResource() override; + void AllocateGraphicResource(int z_order) override; - void SetCamera(const bn::camera_ptr& camera); + void SetBlendingEnabled(bool isEnable) override; + void SetMosaicEnabled(bool isEnable) override; + + void SetCamera(const bn::camera_ptr& camera) override; protected: bn::optional numberSprite_; diff --git a/include/game_entity_IPhysicsEntity.h b/include/game_entity_IPhysicsEntity.h index 0863068..a161801 100644 --- a/include/game_entity_IPhysicsEntity.h +++ b/include/game_entity_IPhysicsEntity.h @@ -67,19 +67,21 @@ class IPhysicsEntity : public IEntity bool isGrounded_ = false; }; -inline IPhysicsEntity::MoveDirections operator|(IPhysicsEntity::MoveDirections d1, IPhysicsEntity::MoveDirections d2) +[[nodiscard]] constexpr IPhysicsEntity::MoveDirections operator|(IPhysicsEntity::MoveDirections d1, + IPhysicsEntity::MoveDirections d2) { using MoveDirections = IPhysicsEntity::MoveDirections; return static_cast(static_cast(d1) | static_cast(d2)); } -inline IPhysicsEntity::MoveDirections operator&(IPhysicsEntity::MoveDirections d1, IPhysicsEntity::MoveDirections d2) +[[nodiscard]] constexpr IPhysicsEntity::MoveDirections operator&(IPhysicsEntity::MoveDirections d1, + IPhysicsEntity::MoveDirections d2) { using MoveDirections = IPhysicsEntity::MoveDirections; return static_cast(static_cast(d1) & static_cast(d2)); } -inline bool operator!(IPhysicsEntity::MoveDirections dir) +[[nodiscard]] constexpr bool operator!(IPhysicsEntity::MoveDirections dir) { using MoveDirections = IPhysicsEntity::MoveDirections; return dir == static_cast(0); diff --git a/include/game_entity_Player.h b/include/game_entity_Player.h index 4898dab..5ec0bd6 100644 --- a/include/game_entity_Player.h +++ b/include/game_entity_Player.h @@ -40,22 +40,28 @@ class Player final : public IPhysicsEntity bool GetControllable() const; void SetControllable(bool isControllable); - enum class ActionState + enum class AnimationState { IDLE, JUMP, FALL, LAND, MERGE_START, - MERGE_END + MERGE_END, }; - ActionState GetActionState() const; + AnimationState GetAnimationState() const; + bool GetAnimationDone() const; + + bn::fixed_point GetLastSafePosition() const; + void SetLastSafePosition(bn::fixed_point safePosition); private: - bn::optional> action2_; - bn::optional> action3_; - ActionState actionState_ = ActionState::IDLE; + bn::fixed_point lastSafePosition_; + + bn::optional> animation2_; + bn::optional> animation3_; + AnimationState animationState_ = AnimationState::IDLE; /** * @brief Additional wait update before the InitIdleAction() is called. * If it is `-1`, InitIdleAction() is not called. @@ -67,12 +73,12 @@ class Player final : public IPhysicsEntity bool isControllable_ = true; /** - * @brief Updates action. + * @brief Updates animation. * - * @return `true` if action is done, otherwise `false` + * @return `true` if animation is done, otherwise `false` */ - bool UpdateAction_(); - void DestroyActions_(); + bool UpdateAnimation_(); + void DestroyAnimation_(); void AddRelativeYPos_(bn::fixed_point& resultPos, bool isFront) const; }; diff --git a/include/game_entity_Symbol.h b/include/game_entity_Symbol.h index d9cb56a..0d9725a 100644 --- a/include/game_entity_Symbol.h +++ b/include/game_entity_Symbol.h @@ -33,6 +33,11 @@ class Symbol final : public IPhysicsEntity void AllocateGraphicResource(int z_order) final; + void Update() final; + + void InitMergeStartAction(); + void InitMergeEndAction(); + Type GetType() const; void SetType(Type); @@ -42,10 +47,30 @@ class Symbol final : public IPhysicsEntity bool GetThrown() const; void SetThrown(bool isThrown); + enum class AnimationState + { + IDLE, + MERGE_START, + MERGE_END + }; + + AnimationState GetAnimationState() const; + bool GetAnimationDone() const; + private: Symbol::Type type_; bool isPickedUp_ = false; bool isThrown_ = false; + + AnimationState animationState_ = AnimationState::IDLE; + + /** + * @brief Updates action. + * + * @return `true` if action is done, otherwise `false` + */ + bool UpdateAnimation_(); + void DestroyAnimation_(); }; } // namespace sym::game::entity diff --git a/include/game_system_ISystem.h b/include/game_system_ISystem.h index 2351bcd..bd6d70a 100644 --- a/include/game_system_ISystem.h +++ b/include/game_system_ISystem.h @@ -1,6 +1,6 @@ #pragma once -#include "scene_GameState.h" +#include "scene_GameState_fwd.h" namespace sym::game::system { diff --git a/include/game_system_PhysicsMovement.h b/include/game_system_PhysicsMovement.h index 19fb0cb..00c8c9d 100644 --- a/include/game_system_PhysicsMovement.h +++ b/include/game_system_PhysicsMovement.h @@ -2,6 +2,8 @@ #include "game_system_ISystem.h" +#include "game_entity_Symbol.h" + namespace sym::game::system { @@ -32,6 +34,14 @@ class PhysicsMovement final : public ISystem static constexpr int MAX_PLAYER_JUMP_COUNT = 1; int playerJumpCount = MAX_PLAYER_JUMP_COUNT; + + // enum class SpikeRespawnState + // { + // NONE, + // FADE_OUT, + // FADE_IN + // }; + // SpikeRespawnState spikeRespawnState_ = SpikeRespawnState::NONE; }; } // namespace sym::game::system diff --git a/include/game_system_Transition.h b/include/game_system_Transition.h new file mode 100644 index 0000000..10f5c0b --- /dev/null +++ b/include/game_system_Transition.h @@ -0,0 +1,135 @@ +#pragma once + +#include "game_system_ISystem.h" + +#include + +#include + +#include "effect_Transition.h" +#include "game_entity_IEntity.h" + +namespace sym::game::system +{ + +/** + * @brief Deals with blending & mosaic + * + */ +class Transition final : public ISystem +{ +public: + using Types = effect::Transition::Types; + using Direction = effect::Transition::Direction; + enum class FullDirection + { + NONE, + IN, + OUT, + IN_AND_OUT, + OUT_AND_IN + }; + enum class AppliedItems + { + NONE = 0, + MAP_BG = 1, + PLAYER = 2, + SYMBOLS_IN_HANDS = 4, + SPRITES_OF_ZONES = 8, + ALL = MAP_BG | PLAYER | SYMBOLS_IN_HANDS | SPRITES_OF_ZONES + }; + + Transition(scene::GameState& state); + + void Update() final; + + void InitInAndOut(Types in, int inUpdateCount, Types out, int outUpdateCount, int waitCountBetween = 0, + int waitCountTillDone = 0); + void InitInAndOut(Types inAndOut, int inUpdateCount, int outUpdateCount, int waitCountBetween = 0, + int waitCountTillDone = 0); + + void InitOutAndIn(Types out, int outUpdateCount, Types in, int inUpdateCount, int waitCountBetween = 0, + int waitCountTillDone = 0); + void InitOutAndIn(Types outAndIn, int outUpdateCount, int inUpdateCount, int waitCountBetween = 0, + int waitCountTillDone = 0); + + void InitIn(Types in, int updateCount, int waitCountTillDone = 0); + void InitOut(Types out, int updateCount, int waitCountTillDone = 0); + + [[nodiscard]] Types GetInTypes() const; + [[nodiscard]] Types GetOutTypes() const; + [[nodiscard]] FullDirection GetFullDirection() const; + + enum class State + { + NOT_STARTED, + FIRST_TRANSITION, + WAIT_BETWEEN, + LAST_TRANSITION, + WAIT_TILL_DONE, + DONE = NOT_STARTED + }; + [[nodiscard]] State GetState() const; + [[nodiscard]] bool IsOngoing() const; + + [[nodiscard]] AppliedItems GetBlendingAppliedItems() const; + void SetBlendingAppliedItems(AppliedItems); + [[nodiscard]] AppliedItems GetMosaicAppliedItems() const; + void SetMosaicAppliedItems(AppliedItems); + + void SetWaitBetweenEventHandler(std::function eventHandler); + void SetLastTransitionEventHandler(std::function eventHandler); + void SetWaitTillDoneEventHandler(std::function eventHandler); + void SetDoneEventHandler(std::function eventHandler); + +private: + FullDirection fullDirection_; + State transitionState_; + Types inTypes_; + Types outTypes_; + int inUpdateCount_; + int outUpdateCount_; + int waitCountBetween_; + int waitCountTillDone_; + + effect::Transition transition_; + int waitCounter_; + + AppliedItems blendingAppliedItems_ = AppliedItems::ALL; + AppliedItems mosaicAppliedItems_ = AppliedItems::ALL; + + // Each event handler is invoked right after transitionState_ reaches the same-named phase. + std::function waitBetweenEventHandler_; + std::function lastTransitionEventHandler_; + std::function waitTillDoneEventHandler_; + std::function doneEventHandler_; + + void Set_(FullDirection fullDirection, State state, Types inTypes, int inUpdateCount, Types outTypes, + int outUpdateCount, int waitCountBetween, int waitCountTillDone); + + /** + * @brief Clears all private members (but not appliedItems_). + * Automatically called when all transition procedures are done. + * + */ + void Clear_(); +}; + +[[nodiscard]] constexpr Transition::AppliedItems operator|(Transition::AppliedItems item1, + Transition::AppliedItems item2) +{ + return static_cast(static_cast(item1) | static_cast(item2)); +} + +[[nodiscard]] constexpr Transition::AppliedItems operator&(Transition::AppliedItems item1, + Transition::AppliedItems item2) +{ + return static_cast(static_cast(item1) & static_cast(item2)); +} + +[[nodiscard]] constexpr bool operator!(Transition::AppliedItems item) +{ + return item == Transition::AppliedItems::NONE; +} + +} // namespace sym::game::system diff --git a/include/game_system_TriggerInteraction.h b/include/game_system_TriggerInteraction.h index 0fd6980..ae8e587 100644 --- a/include/game_system_TriggerInteraction.h +++ b/include/game_system_TriggerInteraction.h @@ -6,6 +6,7 @@ #include #include "game_entity_HoverButton.h" +#include "game_entity_Symbol.h" namespace sym::game::system { diff --git a/include/game_system_ZoneSwitch.h b/include/game_system_ZoneSwitch.h index 68c9066..be745e2 100644 --- a/include/game_system_ZoneSwitch.h +++ b/include/game_system_ZoneSwitch.h @@ -4,6 +4,8 @@ #include +#include "game_stage_StageInfo.h" + namespace sym::game::system { using ExitInfo = stage::ZoneInfo::ExitInfo; @@ -23,19 +25,13 @@ class ZoneSwitch final : public ISystem void Update() final; private: - enum class ExitFadeState - { - NOT_STARTED, - FADE_OUT, - FADE_IN - }; - - ExitFadeState exitFadeState_ = ExitFadeState::NOT_STARTED; bn::optional nextZone_; - void UpdateNextZone_(); + void InitTransition_(); bn::optional GetNextZone_(); + + // wait between phase event handler void SwitchToNextZone_(); }; diff --git a/include/helper_keypad.h b/include/helper_keypad.h index 3ba56b6..0429756 100644 --- a/include/helper_keypad.h +++ b/include/helper_keypad.h @@ -5,6 +5,9 @@ namespace sym::helper::keypad { -bn::keypad::key_type operator|(bn::keypad::key_type a, bn::keypad::key_type b); +[[nodiscard]] constexpr bn::keypad::key_type operator|(bn::keypad::key_type a, bn::keypad::key_type b) +{ + return static_cast(static_cast(a) | static_cast(b)); +} } // namespace sym::helper::keypad diff --git a/include/helper_tilemap.h b/include/helper_tilemap.h index d4c45ab..e24f003 100644 --- a/include/helper_tilemap.h +++ b/include/helper_tilemap.h @@ -170,17 +170,17 @@ class TileInfo int MapIndex_(bn::fixed_point point) const; }; -inline TileInfo::Flags operator|(TileInfo::Flags f1, TileInfo::Flags f2) +[[nodiscard]] constexpr TileInfo::Flags operator|(TileInfo::Flags f1, TileInfo::Flags f2) { return static_cast(static_cast(f1) | static_cast(f2)); } -inline TileInfo::Flags operator&(TileInfo::Flags f1, TileInfo::Flags f2) +[[nodiscard]] constexpr TileInfo::Flags operator&(TileInfo::Flags f1, TileInfo::Flags f2) { return static_cast(static_cast(f1) & static_cast(f2)); } -inline bool operator!(TileInfo::Flags flags) +[[nodiscard]] constexpr bool operator!(TileInfo::Flags flags) { return flags == TileInfo::Flags::EMPTY; } diff --git a/include/scene_Game.h b/include/scene_Game.h index d366250..23a3bb3 100644 --- a/include/scene_Game.h +++ b/include/scene_Game.h @@ -21,9 +21,6 @@ class Game final : public IScene [[nodiscard]] bn::optional Update() final; private: - static constexpr int FADE_IN_UPDATE_COUNT = 30; - static constexpr int FADE_OUT_UPDATE_COUNT = 30; - /** * @brief All member variables reside in here. * to easily pass states by reference into Systems. @@ -31,12 +28,6 @@ class Game final : public IScene */ GameState state_; - system::KeyPress keyPress_; - system::TriggerInteraction triggerInteraction_; - // system::SymbolInteraction symbolInteraction_; - system::PhysicsMovement physicsMovement_; - system::ZoneSwitch zoneSwitch_; - void SetCurrentZone_(int zoneIdx); }; diff --git a/include/scene_GameState.h b/include/scene_GameState.h index 8389f02..a7d0f4b 100644 --- a/include/scene_GameState.h +++ b/include/scene_GameState.h @@ -11,6 +11,11 @@ #include "game_entity_PressureButton.h" #include "game_entity_Shutter.h" #include "game_stage_StageInfo.h" +#include "game_system_KeyPress.h" +#include "game_system_PhysicsMovement.h" +#include "game_system_Transition.h" +#include "game_system_TriggerInteraction.h" +#include "game_system_ZoneSwitch.h" #include "helper_tilemap.h" #include "scene_Param.h" @@ -34,9 +39,6 @@ struct GameState scene::Param& sceneParam_; const game::stage::StageInfo& stageInfo; - effect::Transition fadeIn; - effect::Transition fadeOut; - int currentZoneIdx; bn::affine_bg_ptr currentMapBg; @@ -65,6 +67,12 @@ struct GameState // static constexpr int KEYPRESS_COOLDOWN_UPDATE_COUNT = 20; // int lKeyCooldownCount; // int rKeyCooldownCount; + + game::system::KeyPress keyPress; + game::system::TriggerInteraction triggerInteraction; + game::system::PhysicsMovement physicsMovement; + game::system::ZoneSwitch zoneSwitch; + game::system::Transition transition; }; } // namespace sym::scene diff --git a/include/scene_GameState_fwd.h b/include/scene_GameState_fwd.h new file mode 100644 index 0000000..3215432 --- /dev/null +++ b/include/scene_GameState_fwd.h @@ -0,0 +1,8 @@ +#pragma once + +namespace sym::scene +{ + +struct GameState; + +} diff --git a/license/sfx_player_damage.txt b/license/sfx_player_damage.txt new file mode 100644 index 0000000..76891da --- /dev/null +++ b/license/sfx_player_damage.txt @@ -0,0 +1,6 @@ +Sound name : Hurt00.wav +Made by : sharesynth +Link : https://freesound.org/people/sharesynth/sounds/341245/ +License : CC0 1.0 (https://creativecommons.org/publicdomain/zero/1.0/) + +This sound is embedded into GBA, thus modified to 22050Hz, 8bit PCM. diff --git a/src/effect_Transition.cpp b/src/effect_Transition.cpp index db70b33..bf9c7c2 100644 --- a/src/effect_Transition.cpp +++ b/src/effect_Transition.cpp @@ -9,11 +9,16 @@ namespace sym::effect { Transition::Transition(Types types, Direction direction, int updateCount) - : types_(types), direction_(direction), updateCount_(updateCount) + : types_(types), direction_(direction), updateCount_(updateCount), updateCountDown_(updateCount) { BN_ASSERT(!((static_cast(types & Types::FADE) > 0) && ((static_cast(types & Types::TRANSPARENCY) > 0) || (static_cast(types & Types::INTENSITY)))), "FADE and other blendings cannot be enabled at the same time!"); + BN_ASSERT(updateCount_ > 0, "updateCount should be positive number"); +} + +Transition::Transition() : Transition(static_cast(0), Direction::NONE, 1) +{ } Transition::~Transition() @@ -23,6 +28,10 @@ Transition::~Transition() void Transition::Init() { + BN_ASSERT(static_cast(types_) != 0, "Cannot Init empty transition"); + BN_ASSERT(direction_ != Direction::NONE, "Cannot Init empty transition"); + BN_ASSERT(updateCount_ > 0, "updateCount should be positive number"); + updateCountDown_ = updateCount_; if (static_cast(types_ & Types::FADE) > 0) { @@ -58,17 +67,23 @@ void Transition::Init() state_ = State::ONGOING; } +void Transition::Init(Types types, Direction direction, int updateCount) +{ + Set(types, direction, updateCount); + Init(); +} + void Transition::Update() { BN_ASSERT(state_ != State::NOT_READY, "Cannot update Transition when it is not initialized"); BN_ASSERT(state_ != State::DONE, "Cannot update Transition when it is done"); - if (transparencyAction_) - transparencyAction_->update(); + if (fadeAction_) + fadeAction_->update(); else { - if (fadeAction_) - fadeAction_->update(); + if (transparencyAction_) + transparencyAction_->update(); if (intensityAction_) intensityAction_->update(); } @@ -93,4 +108,51 @@ void Transition::Destroy() bgMosaicAction_.reset(); } +void Transition::Set(Types types, Direction direction, int updateCount) +{ + BN_ASSERT(state_ != State::ONGOING, "Can't change transition options when it is ongoing"); + types_ = types; + direction_ = direction; + updateCount_ = updateCount; + updateCountDown_ = updateCount; +} + +Transition::Types Transition::GetTypes() const +{ + return types_; +} + +void Transition::SetTypes(Types types) +{ + BN_ASSERT(state_ != State::ONGOING, "Can't change transition types when it is ongoing"); + types_ = types; +} + +Transition::Direction Transition::GetDirection() const +{ + return direction_; +} + +void Transition::SetDirection(Direction direction) +{ + BN_ASSERT(state_ != State::ONGOING, "Can't change direction when transition is ongoing"); + direction_ = direction; +} + +int Transition::GetUpdateCount() const +{ + return updateCount_; +} + +void Transition::SetUpdateCount(int updateCount) +{ + BN_ASSERT(state_ != State::ONGOING, "Can't change update count when transition is ongoing"); + updateCount_ = updateCount; +} + +int Transition::GetRemainingUpdateCount() const +{ + return updateCountDown_; +} + } // namespace sym::effect diff --git a/src/game_entity_Door.cpp b/src/game_entity_Door.cpp index d3eb55b..6107b43 100644 --- a/src/game_entity_Door.cpp +++ b/src/game_entity_Door.cpp @@ -39,8 +39,11 @@ void Door::AllocateGraphicResource(int z_order) IOpenableEntity::AllocateGraphicResource(z_order); sprite_ = spriteItem_->create_sprite(position_, GetOpened() ? OPENED_GRAPHICS_INDEX : CLOSED_GRAPHICS_INDEX); sprite_->set_z_order(z_order); - sprite_->set_blending_enabled(true); - sprite_->set_mosaic_enabled(true); + sprite_->set_blending_enabled(isBlendingEnabled_); + sprite_->set_mosaic_enabled(isMosaicEnabled_); + sprite_->set_visible(isVisible_); + if (paletteItem_) + SetColors(*paletteItem_); } void Door::FreeGraphicResource() diff --git a/src/game_entity_HoverButton.cpp b/src/game_entity_HoverButton.cpp index bdd2b0e..ecd6a6c 100644 --- a/src/game_entity_HoverButton.cpp +++ b/src/game_entity_HoverButton.cpp @@ -37,8 +37,11 @@ void HoverButton::AllocateGraphicResource(int z_order) sprite_ = spriteItem_->create_sprite(position_, GetButtonOn() ? BUTTON_ON_GRAPHICS_INDEX : BUTTON_OFF_GRAPHICS_INDEX); sprite_->set_z_order(z_order); - sprite_->set_blending_enabled(true); - sprite_->set_mosaic_enabled(true); + sprite_->set_blending_enabled(isBlendingEnabled_); + sprite_->set_mosaic_enabled(isMosaicEnabled_); + sprite_->set_visible(isVisible_); + if (paletteItem_) + SetColors(*paletteItem_); } void HoverButton::FreeGraphicResource() diff --git a/src/game_entity_IEntity.cpp b/src/game_entity_IEntity.cpp index a2cbaa1..e1c38f5 100644 --- a/src/game_entity_IEntity.cpp +++ b/src/game_entity_IEntity.cpp @@ -49,8 +49,57 @@ void IEntity::AllocateGraphicResource(int z_order) { sprite_ = spriteItem_->create_sprite(position_); sprite_->set_z_order(z_order); - sprite_->set_blending_enabled(true); - sprite_->set_mosaic_enabled(true); + sprite_->set_blending_enabled(isBlendingEnabled_); + sprite_->set_mosaic_enabled(isMosaicEnabled_); + sprite_->set_visible(isVisible_); + if (paletteItem_) + SetColors(*paletteItem_); + } +} + +void IEntity::SetBlendingEnabled(bool isEnable) +{ + isBlendingEnabled_ = isEnable; + if (sprite_) + sprite_->set_blending_enabled(isEnable); +} + +bool IEntity::GetBlendingEnabled() const +{ + return isBlendingEnabled_; +} + +void IEntity::SetMosaicEnabled(bool isEnable) +{ + isMosaicEnabled_ = isEnable; + if (sprite_) + sprite_->set_mosaic_enabled(isEnable); +} + +bool IEntity::GetMosaicEnabled() const +{ + return isMosaicEnabled_; +} + +void IEntity::SetVisible(bool isVisible) +{ + isVisible_ = isVisible; + if (sprite_) + sprite_->set_visible(isVisible); +} + +bool IEntity::GetVisible() const +{ + return isVisible_; +} + +void IEntity::SetColors(const bn::sprite_palette_item& paletteItem) +{ + paletteItem_ = &paletteItem; + if (sprite_) + { + bn::sprite_palette_ptr pal = sprite_->palette(); + pal.set_colors(paletteItem); } } diff --git a/src/game_entity_INumberTextEntity.cpp b/src/game_entity_INumberTextEntity.cpp index faa2525..bf0dc34 100644 --- a/src/game_entity_INumberTextEntity.cpp +++ b/src/game_entity_INumberTextEntity.cpp @@ -40,8 +40,26 @@ void INumberTextEntity::AllocateGraphicResource(int z_order) numberSprite_ = bn::sprite_items::font_modern_dos_8x8.create_sprite(position_ + relativeNumberTextPosition_, textNumber_); numberSprite_->set_z_order(z_order); - numberSprite_->set_blending_enabled(true); - numberSprite_->set_mosaic_enabled(true); + numberSprite_->set_blending_enabled(isBlendingEnabled_); + numberSprite_->set_mosaic_enabled(isMosaicEnabled_); + numberSprite_->set_visible(isVisible_); + // TODO: Override SetColors() + // if (paletteItem_) + // SetColors(*paletteItem_); +} + +void INumberTextEntity::SetBlendingEnabled(bool isEnable) +{ + IEntity::SetBlendingEnabled(isEnable); + if (numberSprite_) + numberSprite_->set_blending_enabled(isEnable); +} + +void INumberTextEntity::SetMosaicEnabled(bool isEnable) +{ + IEntity::SetMosaicEnabled(isEnable); + if (numberSprite_) + numberSprite_->set_mosaic_enabled(isEnable); } void INumberTextEntity::SetCamera(const bn::camera_ptr& camera) diff --git a/src/game_entity_Player.cpp b/src/game_entity_Player.cpp index cbb8800..9f06cad 100644 --- a/src/game_entity_Player.cpp +++ b/src/game_entity_Player.cpp @@ -47,6 +47,7 @@ constexpr bn::fixed GRAVITY_SCALE = 0.1; constexpr int IDLE_ACTION_WAIT_UPDATE = 30; constexpr int OTHER_ACTIONS_WAIT_UPDATE = 5; +constexpr int DAMAGE_TRANSITION_UPDATE_COUNT = 30; } // namespace @@ -58,7 +59,7 @@ Player::Player(bn::fixed_point position) void Player::FreeGraphicResource() { - DestroyActions_(); + DestroyAnimation_(); IPhysicsEntity::FreeGraphicResource(); } @@ -66,9 +67,9 @@ void Player::Update() { IPhysicsEntity::Update(); - bool isActionDone = UpdateAction_(); + bool isAnimationDone = UpdateAnimation_(); - if (isActionDone && additionalWaitUpdateCount_ >= 0) + if (isAnimationDone && additionalWaitUpdateCount_ >= 0) { if (additionalWaitUpdateCount_-- == 0) { @@ -80,36 +81,36 @@ void Player::Update() void Player::InitIdleAction() { BN_ASSERT(sprite_, "Player action cannot be init without allocating graphics!"); - DestroyActions_(); - actionState_ = ActionState::IDLE; - action2_ = bn::create_sprite_animate_action_forever( + DestroyAnimation_(); + animationState_ = AnimationState::IDLE; + animation2_ = bn::create_sprite_animate_action_forever( *sprite_, IDLE_ACTION_WAIT_UPDATE, bn::sprite_items::spr_ingame_protagonist_star.tiles_item(), 0, 1); } void Player::InitJumpAction() { BN_ASSERT(sprite_, "Player action cannot be init without allocating graphics!"); - DestroyActions_(); - actionState_ = ActionState::JUMP; - action3_ = bn::create_sprite_animate_action_once( + DestroyAnimation_(); + animationState_ = AnimationState::JUMP; + animation3_ = bn::create_sprite_animate_action_once( *sprite_, OTHER_ACTIONS_WAIT_UPDATE, bn::sprite_items::spr_ingame_protagonist_star.tiles_item(), 2, 3, 4); } void Player::InitFallAction() { BN_ASSERT(sprite_, "Player action cannot be init without allocating graphics!"); - DestroyActions_(); - actionState_ = ActionState::FALL; - action2_ = bn::create_sprite_animate_action_once(*sprite_, OTHER_ACTIONS_WAIT_UPDATE, - bn::sprite_items::spr_ingame_protagonist_star.tiles_item(), 5, 6); + DestroyAnimation_(); + animationState_ = AnimationState::FALL; + animation2_ = bn::create_sprite_animate_action_once( + *sprite_, OTHER_ACTIONS_WAIT_UPDATE, bn::sprite_items::spr_ingame_protagonist_star.tiles_item(), 5, 6); } void Player::InitLandAction() { BN_ASSERT(sprite_, "Player action cannot be init without allocating graphics!"); - DestroyActions_(); - actionState_ = ActionState::LAND; - action3_ = bn::create_sprite_animate_action_once( + DestroyAnimation_(); + animationState_ = AnimationState::LAND; + animation3_ = bn::create_sprite_animate_action_once( *sprite_, OTHER_ACTIONS_WAIT_UPDATE, bn::sprite_items::spr_ingame_protagonist_star.tiles_item(), 7, 8, 0); additionalWaitUpdateCount_ = OTHER_ACTIONS_WAIT_UPDATE; } @@ -117,18 +118,18 @@ void Player::InitLandAction() void Player::InitMergeStartAction() { BN_ASSERT(sprite_, "Player action cannot be init without allocating graphics!"); - DestroyActions_(); - actionState_ = ActionState::MERGE_START; - action3_ = bn::create_sprite_animate_action_once( + DestroyAnimation_(); + animationState_ = AnimationState::MERGE_START; + animation3_ = bn::create_sprite_animate_action_once( *sprite_, OTHER_ACTIONS_WAIT_UPDATE, bn::sprite_items::spr_ingame_protagonist_star.tiles_item(), 9, 10, 11); } void Player::InitMergeEndAction() { BN_ASSERT(sprite_, "Player action cannot be init without allocating graphics!"); - DestroyActions_(); - actionState_ = ActionState::MERGE_END; - action3_ = bn::create_sprite_animate_action_once( + DestroyAnimation_(); + animationState_ = AnimationState::MERGE_END; + animation3_ = bn::create_sprite_animate_action_once( *sprite_, OTHER_ACTIONS_WAIT_UPDATE, bn::sprite_items::spr_ingame_protagonist_star.tiles_item(), 10, 9, 0); additionalWaitUpdateCount_ = OTHER_ACTIONS_WAIT_UPDATE; } @@ -190,75 +191,95 @@ void Player::SetControllable(bool isControllable) isControllable_ = isControllable; } -Player::ActionState Player::GetActionState() const +Player::AnimationState Player::GetAnimationState() const { - return actionState_; + return animationState_; } -bool Player::UpdateAction_() +bool Player::GetAnimationDone() const +{ + if (animation2_) + return animation2_->done(); + else if (animation3_) + return animation3_->done(); + BN_ERROR("GetAnimationDone() is called when there is no animation"); + return true; +} + +bn::fixed_point Player::GetLastSafePosition() const +{ + return lastSafePosition_; +} + +void Player::SetLastSafePosition(bn::fixed_point safePosition) +{ + lastSafePosition_ = safePosition; +} + +bool Player::UpdateAnimation_() { bool isActionDone = true; - if (action2_) + if (animation2_) { - if (!action2_->done()) + if (!animation2_->done()) { - action2_->update(); + animation2_->update(); isActionDone = false; } } - else if (action3_) + else if (animation3_) { - if (!action3_->done()) + if (!animation3_->done()) { - action3_->update(); + animation3_->update(); isActionDone = false; } } return isActionDone; } -void Player::DestroyActions_() +void Player::DestroyAnimation_() { additionalWaitUpdateCount_ = -1; - action2_.reset(); - action3_.reset(); + animation2_.reset(); + animation3_.reset(); } void Player::AddRelativeYPos_(bn::fixed_point& resultPos, bool isFront) const { - switch (actionState_) + switch (animationState_) { - case ActionState::IDLE: + case AnimationState::IDLE: if (isFront) - resultPos.set_y(resultPos.y() + IDLE_FRONT_SYMBOL_Y_POSITIONS[action2_->current_index()]); + resultPos.set_y(resultPos.y() + IDLE_FRONT_SYMBOL_Y_POSITIONS[animation2_->current_index()]); else - resultPos.set_y(resultPos.y() + IDLE_BACK_SYMBOL_Y_POSITIONS[action2_->current_index()]); + resultPos.set_y(resultPos.y() + IDLE_BACK_SYMBOL_Y_POSITIONS[animation2_->current_index()]); break; - case ActionState::JUMP: + case AnimationState::JUMP: if (isFront) - resultPos.set_y(resultPos.y() + JUMP_FRONT_SYMBOL_Y_POSITIONS[action3_->current_index()]); + resultPos.set_y(resultPos.y() + JUMP_FRONT_SYMBOL_Y_POSITIONS[animation3_->current_index()]); else - resultPos.set_y(resultPos.y() + JUMP_BACK_SYMBOL_Y_POSITIONS[action3_->current_index()]); + resultPos.set_y(resultPos.y() + JUMP_BACK_SYMBOL_Y_POSITIONS[animation3_->current_index()]); break; - case ActionState::FALL: + case AnimationState::FALL: if (isFront) - resultPos.set_y(resultPos.y() + FALL_FRONT_SYMBOL_Y_POSITIONS[action2_->current_index()]); + resultPos.set_y(resultPos.y() + FALL_FRONT_SYMBOL_Y_POSITIONS[animation2_->current_index()]); else - resultPos.set_y(resultPos.y() + FALL_BACK_SYMBOL_Y_POSITIONS[action2_->current_index()]); + resultPos.set_y(resultPos.y() + FALL_BACK_SYMBOL_Y_POSITIONS[animation2_->current_index()]); break; - case ActionState::LAND: + case AnimationState::LAND: if (isFront) - resultPos.set_y(resultPos.y() + LAND_FRONT_SYMBOL_Y_POSITIONS[action3_->current_index()]); + resultPos.set_y(resultPos.y() + LAND_FRONT_SYMBOL_Y_POSITIONS[animation3_->current_index()]); else - resultPos.set_y(resultPos.y() + LAND_BACK_SYMBOL_Y_POSITIONS[action3_->current_index()]); + resultPos.set_y(resultPos.y() + LAND_BACK_SYMBOL_Y_POSITIONS[animation3_->current_index()]); break; break; - case ActionState::MERGE_START: - case ActionState::MERGE_END: + case AnimationState::MERGE_START: + case AnimationState::MERGE_END: BN_ERROR("Merge Symbol Position not implemented!"); break; default: - BN_ERROR("Invalid Player::ActionState : ", static_cast(actionState_)); + BN_ERROR("Invalid Player::AnimationState : ", static_cast(animationState_)); break; } } diff --git a/src/game_entity_PressureButton.cpp b/src/game_entity_PressureButton.cpp index 2b70f4d..232b495 100644 --- a/src/game_entity_PressureButton.cpp +++ b/src/game_entity_PressureButton.cpp @@ -37,8 +37,11 @@ void PressureButton::AllocateGraphicResource(int z_order) sprite_ = spriteItem_->create_sprite(position_, GetButtonOn() ? BUTTON_ON_GRAPHICS_INDEX : BUTTON_OFF_GRAPHICS_INDEX); sprite_->set_z_order(z_order); - sprite_->set_blending_enabled(true); - sprite_->set_mosaic_enabled(true); + sprite_->set_blending_enabled(isBlendingEnabled_); + sprite_->set_mosaic_enabled(isMosaicEnabled_); + sprite_->set_visible(isVisible_); + if (paletteItem_) + SetColors(*paletteItem_); } void PressureButton::FreeGraphicResource() diff --git a/src/game_entity_Shutter.cpp b/src/game_entity_Shutter.cpp index d06a530..fd76d09 100644 --- a/src/game_entity_Shutter.cpp +++ b/src/game_entity_Shutter.cpp @@ -39,8 +39,11 @@ void Shutter::AllocateGraphicResource(int z_order) IOpenableEntity::AllocateGraphicResource(z_order); sprite_ = spriteItem_->create_sprite(position_, GetOpened() ? OPENED_GRAPHICS_INDEX : CLOSED_GRAPHICS_INDEX); sprite_->set_z_order(z_order); - sprite_->set_blending_enabled(true); - sprite_->set_mosaic_enabled(true); + sprite_->set_blending_enabled(isBlendingEnabled_); + sprite_->set_mosaic_enabled(isMosaicEnabled_); + sprite_->set_visible(isVisible_); + if (paletteItem_) + SetColors(*paletteItem_); } void Shutter::FreeGraphicResource() diff --git a/src/game_entity_Symbol.cpp b/src/game_entity_Symbol.cpp index d624365..675e7aa 100644 --- a/src/game_entity_Symbol.cpp +++ b/src/game_entity_Symbol.cpp @@ -14,9 +14,14 @@ namespace sym::game::entity namespace { -static constexpr bn::fixed_rect RELATIVE_INTERACT_RANGE = {{0, 0}, {24, 16}}; -static constexpr bool IS_GRAVITY_ENABLED_BY_DEFAULT = true; -static constexpr bn::fixed GRAVITY_SCALE = 0.3; +constexpr bn::fixed_rect RELATIVE_INTERACT_RANGE = {{0, 0}, {24, 16}}; +constexpr bool IS_GRAVITY_ENABLED_BY_DEFAULT = true; +constexpr bn::fixed GRAVITY_SCALE = 0.3; + +constexpr int MERGE_START_UPDATE_COUNT = 30; +constexpr int MERGE_END_UPDATE_COUNT = 30; +constexpr int DAMAGE_START_UPDATE_COUNT = 30; +constexpr int DAMAGE_END_UPDATE_COUNT = 30; bool IsComplexSymbol_(Symbol::Type type) { @@ -75,7 +80,8 @@ Symbol::Symbol(bn::fixed_point position, Symbol::Type type) } Symbol::Symbol(Symbol&& other) - : IPhysicsEntity(bn::move(other)), type_(other.type_), isPickedUp_(other.isPickedUp_), isThrown_(other.isThrown_) + : IPhysicsEntity(bn::move(other)), type_(other.type_), isPickedUp_(other.isPickedUp_), isThrown_(other.isThrown_), + animationState_(other.animationState_) { } @@ -85,6 +91,7 @@ Symbol& Symbol::operator=(Symbol&& other) type_ = other.type_; isPickedUp_ = other.isPickedUp_; isThrown_ = other.isThrown_; + animationState_ = other.animationState_; return *this; } @@ -98,8 +105,34 @@ void Symbol::AllocateGraphicResource(int z_order) sprite_ = spriteItem_->create_sprite(position_, spriteIdx); sprite_->set_z_order(z_order); - sprite_->set_blending_enabled(true); - sprite_->set_mosaic_enabled(true); + sprite_->set_blending_enabled(isBlendingEnabled_); + sprite_->set_mosaic_enabled(isMosaicEnabled_); + sprite_->set_visible(isVisible_); + if (paletteItem_) + SetColors(*paletteItem_); +} + +void Symbol::Update() +{ + IPhysicsEntity::Update(); + + UpdateAnimation_(); +} + +void Symbol::InitMergeStartAction() +{ + BN_ASSERT(sprite_, "Symbol action cannot be init without allocating graphics!"); + DestroyAnimation_(); + animationState_ = AnimationState::MERGE_START; + // TODO +} + +void Symbol::InitMergeEndAction() +{ + BN_ASSERT(sprite_, "Symbol action cannot be init without allocating graphics!"); + DestroyAnimation_(); + animationState_ = AnimationState::MERGE_END; + // TODO } Symbol::Type Symbol::GetType() const @@ -137,4 +170,26 @@ void Symbol::SetThrown(bool isThrown) isThrown_ = isThrown; } +Symbol::AnimationState Symbol::GetAnimationState() const +{ + return animationState_; +} + +bool Symbol::GetAnimationDone() const +{ + // TODO + return true; +} + +bool Symbol::UpdateAnimation_() +{ + // TODO + return true; +} + +void Symbol::DestroyAnimation_() +{ + // TODO +} + } // namespace sym::game::entity diff --git a/src/game_system_KeyPress.cpp b/src/game_system_KeyPress.cpp index 5a6bee4..e3cd079 100644 --- a/src/game_system_KeyPress.cpp +++ b/src/game_system_KeyPress.cpp @@ -2,6 +2,8 @@ #include +#include "scene_GameState.h" + namespace sym::game::system { diff --git a/src/game_system_PhysicsMovement.cpp b/src/game_system_PhysicsMovement.cpp index 5b3818b..c9e78e7 100644 --- a/src/game_system_PhysicsMovement.cpp +++ b/src/game_system_PhysicsMovement.cpp @@ -2,19 +2,24 @@ #include #include +#include #include #include #include #include +#include -#include "bn_vector.h" #include "helper_keypad.h" #include "helper_math.h" #include "helper_tilemap.h" +#include "scene_GameState.h" #include "bn_sound_items.h" #include "constant.h" +#include "bn_sprite_items_spr_ingame_protagonist_star.h" +#include "bn_sprite_palette_items_pal_ingame_protagonist_star_damage.h" + namespace sym::game::system { @@ -27,9 +32,20 @@ constexpr bn::fixed JUMP_VEL = -2.8; constexpr bn::fixed_point SYMBOL_DELTA_VEL = {0.3, 0.3}; constexpr bn::fixed VEL_FRICTION = 1.2; constexpr bn::fixed COLLISION_DELTA_EPSILON = 0.01; +constexpr int SPIKE_SIZE = 3; + +constexpr int PLAYER_DAMAGE_TRANSPARENCY_UPDATE_COUNT = 20; +constexpr int PLAYER_DAMAGE_WAIT_BETWEEN_TRANSPARENCY_AND_FADE = 10; +constexpr int PLAYER_DAMAGE_FADE_UPDATE_COUNT = 20; +constexpr int PLAYER_DAMAGE_WAIT_BETWEEN_FO_AND_FI = 5; constexpr int COLLISION_LOOP_MAX_COUNT = 100; +constexpr const bn::sprite_palette_item& PLAYER_NORMAL_PAL = + bn::sprite_items::spr_ingame_protagonist_star.palette_item(); +constexpr const bn::sprite_palette_item& PLAYER_DAMAGE_PAL = + bn::sprite_palette_items::pal_ingame_protagonist_star_damage; + static_assert(bn::abs(JUMP_VEL) <= MAX_ENTITY_VEL.y()); enum class PushbackDirection @@ -37,7 +53,8 @@ enum class PushbackDirection UP, DOWN, LEFT, - RIGHT + RIGHT, + SPIKE }; [[nodiscard]] bn::optional FloorCollisionResolution_(entity::IPhysicsEntity& entity) @@ -97,6 +114,60 @@ enum class PushbackDirection const MoveDirections moveDirs = entity.GetMoveDirections(); + // spike detection + if (!!(topLeftTileFlag & TileInfo::Flags::SPIKE)) + { + if (!!(topLeftTileFlag & TileInfo::Flags::CEILING)) + { + if ((collider.top() % 8) <= SPIKE_SIZE) + return PushbackDirection::SPIKE; + } + else if (!!(topLeftTileFlag & TileInfo::Flags::LEFT_BLOCKING_WALL)) + { + if ((collider.left() % 8) <= SPIKE_SIZE) + return PushbackDirection::SPIKE; + } + } + if (!!(topRightTileFlag & TileInfo::Flags::SPIKE)) + { + if (!!(topRightTileFlag & TileInfo::Flags::CEILING)) + { + if ((collider.top() % 8) <= SPIKE_SIZE) + return PushbackDirection::SPIKE; + } + else if (!!(topRightTileFlag & TileInfo::Flags::RIGHT_BLOCKING_WALL)) + { + if ((collider.right() % 8) >= 8 - SPIKE_SIZE) + return PushbackDirection::SPIKE; + } + } + if (!!(bottomLeftTileFlag & TileInfo::Flags::SPIKE)) + { + if (!!(bottomLeftTileFlag & TileInfo::Flags::FLOOR)) + { + if ((collider.bottom() % 8) >= 8 - SPIKE_SIZE) + return PushbackDirection::SPIKE; + } + else if (!!(bottomLeftTileFlag & TileInfo::Flags::LEFT_BLOCKING_WALL)) + { + if ((collider.left() % 8) <= SPIKE_SIZE) + return PushbackDirection::SPIKE; + } + } + if (!!(bottomRightTileFlag & TileInfo::Flags::SPIKE)) + { + if (!!(bottomRightTileFlag & TileInfo::Flags::FLOOR)) + { + if ((collider.bottom() % 8) >= 8 - SPIKE_SIZE) + return PushbackDirection::SPIKE; + } + else if (!!(bottomRightTileFlag & TileInfo::Flags::RIGHT_BLOCKING_WALL)) + { + if ((collider.right() % 8) >= 8 - SPIKE_SIZE) + return PushbackDirection::SPIKE; + } + } + // diagonal approach to a corner if (!!(moveDirs & MoveDirections::DOWN) && !!(moveDirs & MoveDirections::RIGHT)) { @@ -231,6 +302,9 @@ enum class PushbackDirection void ApplyGravity_(entity::IPhysicsEntity& entity) { + if (!entity.GetGravityEnabled()) + return; + bn::fixed_point velocity = entity.GetVelocity(); velocity.set_y(velocity.y() + entity.GetGravityScale()); entity.SetVelocity(velocity); @@ -266,14 +340,17 @@ void PhysicsMovement::Update() void PhysicsMovement::UpdatePlayer_() { - ApplyGravity_(state_.player); - PlayerKeyboardHandle_(); + if (state_.player.GetControllable()) + { + ApplyGravity_(state_.player); + PlayerKeyboardHandle_(); - ClampVelocity_(state_.player); - state_.player.SetPosition(state_.player.GetPosition() + state_.player.GetVelocity()); + ClampVelocity_(state_.player); + state_.player.SetPosition(state_.player.GetPosition() + state_.player.GetVelocity()); - PlayerCollision_(); - helper::tilemap::SnapEntityToZoneBoundary(state_.player, state_.zoneBoundary); + PlayerCollision_(); + helper::tilemap::SnapEntityToZoneBoundary(state_.player, state_.zoneBoundary); + } PlayerAnimation_(); } @@ -312,6 +389,8 @@ void PhysicsMovement::PlayerCollision_() { bn::optional collisionResult; bool nextGrounded = false; + bool nextSafe = true; + for (int i = 0; i < COLLISION_LOOP_MAX_COUNT; ++i) { // resolve collision @@ -327,6 +406,41 @@ void PhysicsMovement::PlayerCollision_() // additional work to do when collision is detected switch (*collisionResult) { + case PushbackDirection::SPIKE: + state_.player.SetControllable(false); + state_.player.SetGravityEnabled(false); + state_.player.SetVelocity({0, 0}); + state_.player.SetColors(PLAYER_DAMAGE_PAL); + bn::sound_items::sfx_player_damage.play(constant::volume::sfx_player_damage); + state_.transition.SetBlendingAppliedItems(Transition::AppliedItems::PLAYER | + Transition::AppliedItems::SYMBOLS_IN_HANDS); + state_.transition.InitOut(Transition::Types::TRANSPARENCY, PLAYER_DAMAGE_TRANSPARENCY_UPDATE_COUNT, + PLAYER_DAMAGE_WAIT_BETWEEN_TRANSPARENCY_AND_FADE); + state_.transition.SetDoneEventHandler([this] { + state_.player.SetVisible(false); + if (state_.symbolsInHands[0]) + state_.symbolsInHands[0]->SetVisible(false); + if (state_.symbolsInHands[1]) + state_.symbolsInHands[1]->SetVisible(false); + bn::blending::set_transparency_alpha(1); + state_.transition.SetBlendingAppliedItems(Transition::AppliedItems::ALL); + state_.transition.InitOutAndIn(Transition::Types::FADE, PLAYER_DAMAGE_FADE_UPDATE_COUNT, + PLAYER_DAMAGE_FADE_UPDATE_COUNT, PLAYER_DAMAGE_WAIT_BETWEEN_FO_AND_FI); + state_.transition.SetWaitBetweenEventHandler([this] { + state_.player.SetColors(PLAYER_NORMAL_PAL); + state_.player.SetVisible(true); + if (state_.symbolsInHands[0]) + state_.symbolsInHands[0]->SetVisible(true); + if (state_.symbolsInHands[1]) + state_.symbolsInHands[1]->SetVisible(true); + state_.player.SetPosition(state_.player.GetLastSafePosition()); + }); + state_.transition.SetDoneEventHandler([this] { + state_.player.SetControllable(true); + state_.player.SetGravityEnabled(true); + }); + }); + break; case PushbackDirection::UP: if (!nextGrounded) { @@ -348,40 +462,52 @@ void PhysicsMovement::PlayerCollision_() BN_ERROR("Invalid PushbackDirection: ", static_cast(*collisionResult)); } + if (collisionResult == PushbackDirection::SPIKE) + { + nextSafe = false; + break; + } + if (i == COLLISION_LOOP_MAX_COUNT - 1) BN_LOG("[WARN] Collision detection loop max count reached!"); } state_.player.SetGrounded(nextGrounded); + + if (nextGrounded && nextSafe && state_.player.GetControllable()) + { + state_.player.SetLastSafePosition(state_.player.GetPosition()); + } } void PhysicsMovement::PlayerAnimation_() { using entity::IPhysicsEntity; bn::fixed_point velocity = state_.player.GetVelocity(); + const entity::Player::AnimationState prevPlayerActionState = state_.player.GetAnimationState(); if (velocity.y() > IPhysicsEntity::EPSILON_VEL) { - if (state_.player.GetActionState() != entity::Player::ActionState::FALL) + if (prevPlayerActionState != entity::Player::AnimationState::FALL) state_.player.InitFallAction(); } else if (bn::keypad::left_held()) { state_.player.SetHorizontalFlip(true); - if (state_.player.GetActionState() == entity::Player::ActionState::IDLE && + if (prevPlayerActionState == entity::Player::AnimationState::IDLE && state_.player.GetVelocity().x() < -IPhysicsEntity::EPSILON_VEL) state_.player.InitFallAction(); } else if (bn::keypad::right_held()) { state_.player.SetHorizontalFlip(false); - if (state_.player.GetActionState() == entity::Player::ActionState::IDLE && + if (prevPlayerActionState == entity::Player::AnimationState::IDLE && state_.player.GetVelocity().x() > IPhysicsEntity::EPSILON_VEL) state_.player.InitFallAction(); } - else if (state_.player.GetGrounded() && state_.player.GetActionState() == entity::Player::ActionState::FALL && + else if (state_.player.GetGrounded() && prevPlayerActionState == entity::Player::AnimationState::FALL && bn::abs(velocity.x()) < IPhysicsEntity::EPSILON_VEL && bn::abs(velocity.y()) < IPhysicsEntity::EPSILON_VEL) { - if (state_.player.GetActionState() != entity::Player::ActionState::IDLE) + if (prevPlayerActionState != entity::Player::AnimationState::IDLE) state_.player.InitIdleAction(); } } @@ -436,13 +562,16 @@ void PhysicsMovement::SymbolCollision_(entity::Symbol& symbol) // additional work to do when collision is detected switch (*collisionResult) { + case PushbackDirection::SPIKE: + // TODO + break; case PushbackDirection::UP: if (!nextGrounded) { nextGrounded = true; if (!symbol.GetGrounded()) { - if (state_.fadeIn.GetState() != effect::Transition::State::ONGOING) + if (!state_.transition.IsOngoing()) bn::sound_items::sfx_symbol_ground_bump.play(constant::volume::sfx_symbol_ground_bump); } } diff --git a/src/game_system_Transition.cpp b/src/game_system_Transition.cpp new file mode 100644 index 0000000..a9738be --- /dev/null +++ b/src/game_system_Transition.cpp @@ -0,0 +1,279 @@ +#include "game_system_Transition.h" + +#include + +#include "scene_GameState.h" + +#include "bn_log.h" + +namespace sym::game::system +{ + +namespace +{ + +template void SetBlendingEnabledToEntites_(NestedIt begin, NestedIt end, bool isEnable) +{ + for (NestedIt i = begin; i != end; ++i) + { + for (auto j = i->begin(); j != i->end(); ++j) + { + j->SetBlendingEnabled(isEnable); + } + } +} + +template void SetMosaicEnabledToEntites_(NestedIt begin, NestedIt end, bool isEnable) +{ + for (NestedIt i = begin; i != end; ++i) + { + for (auto j = i->begin(); j != i->end(); ++j) + { + j->SetMosaicEnabled(isEnable); + } + } +} + +} // namespace + +Transition::Transition(scene::GameState& state) : ISystem(state) +{ + Clear_(); +} + +void Transition::Update() +{ + if (!IsOngoing()) + return; + + switch (transitionState_) + { + case State::FIRST_TRANSITION: + if (transition_.GetState() == effect::Transition::State::DONE) + { + waitCounter_ = waitCountBetween_; + transitionState_ = State::WAIT_BETWEEN; + if (waitBetweenEventHandler_) + waitBetweenEventHandler_(); + } + else + { + transition_.Update(); + } + break; + case State::WAIT_BETWEEN: + if (--waitCounter_ < 0) + { + const bool isInAndOut = fullDirection_ == FullDirection::IN_AND_OUT; + transition_.Init(isInAndOut ? outTypes_ : inTypes_, isInAndOut ? Direction::OUT : Direction::IN, + isInAndOut ? outUpdateCount_ : inUpdateCount_); + transitionState_ = State::LAST_TRANSITION; + if (lastTransitionEventHandler_) + lastTransitionEventHandler_(); + } + break; + case State::LAST_TRANSITION: + if (transition_.GetState() == effect::Transition::State::DONE) + { + waitCounter_ = waitCountTillDone_; + transitionState_ = State::WAIT_TILL_DONE; + if (waitTillDoneEventHandler_) + waitTillDoneEventHandler_(); + } + else + { + transition_.Update(); + } + break; + case State::WAIT_TILL_DONE: + if (--waitCounter_ < 0) + { + std::function doneEventHandler = std::move(doneEventHandler_); + Clear_(); + transitionState_ = State::DONE; + if (doneEventHandler) + doneEventHandler(); + } + break; + default: + BN_ERROR("Invalid transition state: ", static_cast(transitionState_), + ", on direction: ", static_cast(fullDirection_)); + } +} + +void Transition::InitInAndOut(Types in, int inUpdateCount, Types out, int outUpdateCount, int waitCountBetween, + int waitCountTillDone) +{ + BN_ASSERT(!IsOngoing(), "Can't Init transition when it's ongoing"); + Set_(FullDirection::IN_AND_OUT, State::FIRST_TRANSITION, in, inUpdateCount, out, outUpdateCount, waitCountBetween, + waitCountTillDone); + transition_.Init(in, Direction::IN, inUpdateCount); +} + +void Transition::InitInAndOut(Types inAndOut, int inUpdateCount, int outUpdateCount, int waitCountBetween, + int waitCountTillDone) +{ + InitInAndOut(inAndOut, inUpdateCount, inAndOut, outUpdateCount, waitCountBetween, waitCountTillDone); +} + +void Transition::InitOutAndIn(Types out, int outUpdateCount, Types in, int inUpdateCount, int waitCountBetween, + int waitCountTillDone) +{ + BN_ASSERT(!IsOngoing(), "Can't Init transition when it's ongoing"); + Set_(FullDirection::OUT_AND_IN, State::FIRST_TRANSITION, in, inUpdateCount, out, outUpdateCount, waitCountBetween, + waitCountTillDone); + transition_.Init(out, Direction::OUT, outUpdateCount); +} + +void Transition::InitOutAndIn(Types outAndIn, int outUpdateCount, int inUpdateCount, int waitCountBetween, + int waitCountTillDone) +{ + InitOutAndIn(outAndIn, outUpdateCount, outAndIn, inUpdateCount, waitCountBetween, waitCountTillDone); +} + +void Transition::InitIn(Types in, int updateCount, int waitCountTillDone) +{ + BN_ASSERT(!IsOngoing(), "Can't Init transition when it's ongoing"); + Set_(FullDirection::IN, State::LAST_TRANSITION, in, updateCount, Types::NONE, -1, -1, waitCountTillDone); + transition_.Init(in, Direction::IN, updateCount); +} + +void Transition::InitOut(Types out, int updateCount, int waitCountTillDone) +{ + BN_ASSERT(!IsOngoing(), "Can't Init transition when it's ongoing"); + Set_(FullDirection::OUT, State::LAST_TRANSITION, Types::NONE, -1, out, updateCount, -1, waitCountTillDone); + transition_.Init(out, Direction::OUT, updateCount); +} + +Transition::Types Transition::GetInTypes() const +{ + return inTypes_; +} + +Transition::Types Transition::GetOutTypes() const +{ + return outTypes_; +} + +Transition::State Transition::GetState() const +{ + return transitionState_; +} + +bool Transition::IsOngoing() const +{ + return transitionState_ != State::NOT_STARTED; +} + +Transition::FullDirection Transition::GetFullDirection() const +{ + return fullDirection_; +} + +Transition::AppliedItems Transition::GetBlendingAppliedItems() const +{ + return blendingAppliedItems_; +} + +void Transition::SetBlendingAppliedItems(AppliedItems appliedItems) +{ + state_.currentMapBg.set_blending_enabled(!!(appliedItems & AppliedItems::MAP_BG)); + state_.player.SetBlendingEnabled(!!(appliedItems & AppliedItems::PLAYER)); + if (state_.symbolsInHands[0]) + state_.symbolsInHands[0]->SetBlendingEnabled(!!(appliedItems & AppliedItems::SYMBOLS_IN_HANDS)); + if (state_.symbolsInHands[1]) + state_.symbolsInHands[1]->SetBlendingEnabled(!!(appliedItems & AppliedItems::SYMBOLS_IN_HANDS)); + + if (!!(appliedItems & AppliedItems::SPRITES_OF_ZONES) != !!(blendingAppliedItems_ & AppliedItems::SPRITES_OF_ZONES)) + { + const bool isEnable = !!(appliedItems & AppliedItems::SPRITES_OF_ZONES); + SetBlendingEnabledToEntites_(state_.doorsOfZones.begin(), state_.doorsOfZones.end(), isEnable); + SetBlendingEnabledToEntites_(state_.shuttersOfZones.begin(), state_.shuttersOfZones.end(), isEnable); + SetBlendingEnabledToEntites_(state_.hoverButtonsOfZones.begin(), state_.hoverButtonsOfZones.end(), isEnable); + SetBlendingEnabledToEntites_(state_.pressureButtonsOfZones.begin(), state_.pressureButtonsOfZones.end(), + isEnable); + SetBlendingEnabledToEntites_(state_.symbolsOfZones.begin(), state_.symbolsOfZones.end(), isEnable); + } + + BN_LOG("map_bg: ", !!(appliedItems & AppliedItems::MAP_BG) ? 1 : 0); + BN_LOG("player: ", !!(appliedItems & AppliedItems::PLAYER) ? 1 : 0); + BN_LOG("hands: ", !!(appliedItems & AppliedItems::SYMBOLS_IN_HANDS) ? 1 : 0); + BN_LOG("entity: ", !!(appliedItems & AppliedItems::SPRITES_OF_ZONES) ? 1 : 0); + + blendingAppliedItems_ = appliedItems; +} + +Transition::AppliedItems Transition::GetMosaicAppliedItems() const +{ + return mosaicAppliedItems_; +} + +void Transition::SetMosaicAppliedItems(AppliedItems appliedItems) +{ + state_.currentMapBg.set_mosaic_enabled(!!(appliedItems & AppliedItems::MAP_BG)); + state_.player.SetMosaicEnabled(!!(appliedItems & AppliedItems::PLAYER)); + if (state_.symbolsInHands[0]) + state_.symbolsInHands[0]->SetMosaicEnabled(!!(appliedItems & AppliedItems::SYMBOLS_IN_HANDS)); + if (state_.symbolsInHands[1]) + state_.symbolsInHands[1]->SetMosaicEnabled(!!(appliedItems & AppliedItems::SYMBOLS_IN_HANDS)); + + if (!!(appliedItems & AppliedItems::SPRITES_OF_ZONES) != !!(mosaicAppliedItems_ & AppliedItems::SPRITES_OF_ZONES)) + { + const bool isEnable = !!(appliedItems & AppliedItems::SPRITES_OF_ZONES); + SetMosaicEnabledToEntites_(state_.doorsOfZones.begin(), state_.doorsOfZones.end(), isEnable); + SetMosaicEnabledToEntites_(state_.shuttersOfZones.begin(), state_.shuttersOfZones.end(), isEnable); + SetMosaicEnabledToEntites_(state_.hoverButtonsOfZones.begin(), state_.hoverButtonsOfZones.end(), isEnable); + SetMosaicEnabledToEntites_(state_.pressureButtonsOfZones.begin(), state_.pressureButtonsOfZones.end(), + isEnable); + SetMosaicEnabledToEntites_(state_.symbolsOfZones.begin(), state_.symbolsOfZones.end(), isEnable); + } + + mosaicAppliedItems_ = appliedItems; +} + +void Transition::SetWaitBetweenEventHandler(std::function eventHandler) +{ + waitBetweenEventHandler_ = std::move(eventHandler); +} + +void Transition::SetLastTransitionEventHandler(std::function eventHandler) +{ + lastTransitionEventHandler_ = std::move(eventHandler); +} + +void Transition::SetWaitTillDoneEventHandler(std::function eventHandler) +{ + waitTillDoneEventHandler_ = std::move(eventHandler); +} + +void Transition::SetDoneEventHandler(std::function eventHandler) +{ + doneEventHandler_ = std::move(eventHandler); +} + +void Transition::Set_(FullDirection fullDirection, State state, Types inTypes, int inUpdateCount, Types outTypes, + int outUpdateCount, int waitCountBetween, int waitCountTillDone) +{ + fullDirection_ = fullDirection; + transitionState_ = state; + inTypes_ = inTypes; + inUpdateCount_ = inUpdateCount; + outTypes_ = outTypes; + outUpdateCount_ = outUpdateCount; + waitCountBetween_ = waitCountBetween; + waitCountTillDone_ = waitCountTillDone; +} + +void Transition::Clear_() +{ + Set_(FullDirection::NONE, State::NOT_STARTED, Types::NONE, -1, Types::NONE, -1, -1, -1); + transition_.Destroy(); + waitCounter_ = -1; + + waitBetweenEventHandler_ = nullptr; + lastTransitionEventHandler_ = nullptr; + waitTillDoneEventHandler_ = nullptr; + doneEventHandler_ = nullptr; +} + +} // namespace sym::game::system diff --git a/src/game_system_TriggerInteraction.cpp b/src/game_system_TriggerInteraction.cpp index 4c15067..61b418d 100644 --- a/src/game_system_TriggerInteraction.cpp +++ b/src/game_system_TriggerInteraction.cpp @@ -8,6 +8,7 @@ #include "bn_sound_items.h" #include "constant.h" #include "helper_math.h" +#include "scene_GameState.h" namespace sym::game::system { diff --git a/src/game_system_ZoneSwitch.cpp b/src/game_system_ZoneSwitch.cpp index df848dc..57b0ab3 100644 --- a/src/game_system_ZoneSwitch.cpp +++ b/src/game_system_ZoneSwitch.cpp @@ -3,60 +3,49 @@ #include #include "constant.h" +#include "scene_GameState.h" + +#include "bn_log.h" namespace sym::game::system { -using namespace sym::effect; + +namespace +{ + +constexpr Transition::Types TRANSITION_TYPES = + Transition::Types::FADE | Transition::Types::BG_MOSAIC | Transition::Types::SPRITE_MOSAIC; + +constexpr int FADE_IN_UPDATE_COUNT = 30; +constexpr int FADE_OUT_UPDATE_COUNT = 30; + +} // namespace void ZoneSwitch::Update() { if (nextZone_) - UpdateNextZone_(); - else - { - nextZone_ = GetNextZone_(); - if (nextZone_) - { - UpdateNextZone_(); - } - } + return; + + nextZone_ = GetNextZone_(); + if (nextZone_) + InitTransition_(); } -void ZoneSwitch::UpdateNextZone_() +void ZoneSwitch::InitTransition_() { - switch (exitFadeState_) - { - case ExitFadeState::NOT_STARTED: - exitFadeState_ = ExitFadeState::FADE_OUT; - state_.fadeOut.Init(); - state_.player.SetControllable(false); - break; - case ExitFadeState::FADE_OUT: - if (state_.fadeOut.GetState() == Transition::State::DONE) - { - exitFadeState_ = ExitFadeState::FADE_IN; - SwitchToNextZone_(); - state_.fadeIn.Init(); - state_.player.SetControllable(true); - } - break; - case ExitFadeState::FADE_IN: - if (state_.fadeIn.GetState() == Transition::State::DONE) - { - exitFadeState_ = ExitFadeState::NOT_STARTED; - nextZone_.reset(); - } - break; - default: - BN_ERROR("Invalid ExitState: ", static_cast(exitFadeState_)); - break; - } + state_.player.SetControllable(false); + + state_.transition.SetBlendingAppliedItems(Transition::AppliedItems::ALL); + state_.transition.SetMosaicAppliedItems(Transition::AppliedItems::ALL); + state_.transition.InitOutAndIn(TRANSITION_TYPES, FADE_OUT_UPDATE_COUNT, FADE_IN_UPDATE_COUNT); + state_.transition.SetWaitBetweenEventHandler([this] { SwitchToNextZone_(); }); + state_.transition.SetLastTransitionEventHandler([this] { state_.player.SetControllable(true); }); + state_.transition.SetDoneEventHandler([this] { nextZone_.reset(); }); } bn::optional ZoneSwitch::GetNextZone_() { - if (state_.fadeOut.GetState() != Transition::State::ONGOING && - state_.fadeIn.GetState() != Transition::State::ONGOING && !state_.isPaused) + if (!state_.transition.IsOngoing() && !state_.isPaused) { const auto playerCollider = state_.player.GetPhysicsCollider(); const auto exits = state_.stageInfo.zoneInfos[state_.currentZoneIdx].exits; @@ -95,10 +84,12 @@ void ZoneSwitch::SwitchToNextZone_() // Set bg and tiles if (currentZoneInfo.mapBg != state_.stageInfo.zoneInfos[prevZoneIdx].mapBg) { + const bool isBlendingEnabled = state_.currentMapBg.blending_enabled(); + const bool isMosaicEnabled = state_.currentMapBg.mosaic_enabled(); state_.currentMapBg = currentZoneInfo.mapBg.create_bg({0, 0}); state_.currentMapBg.set_wrapping_enabled(false); - state_.currentMapBg.set_blending_enabled(true); - state_.currentMapBg.set_mosaic_enabled(true); + state_.currentMapBg.set_blending_enabled(isBlendingEnabled); + state_.currentMapBg.set_mosaic_enabled(isMosaicEnabled); state_.currentMapBg.set_camera(state_.camera); state_.currentMapTileInfo = helper::tilemap::TileInfo(state_.currentMapBg); } diff --git a/src/helper_keypad.cpp b/src/helper_keypad.cpp deleted file mode 100644 index f6ce8cb..0000000 --- a/src/helper_keypad.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "helper_keypad.h" - -namespace sym::helper::keypad -{ - -bn::keypad::key_type operator|(bn::keypad::key_type a, bn::keypad::key_type b) -{ - return static_cast(static_cast(a) | static_cast(b)); -} - -} // namespace sym::helper::keypad diff --git a/src/main.cpp b/src/main.cpp index d78aa5b..192473c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -70,10 +70,12 @@ int main() textGen->generate({-120, -70}, bn::format<9>("CPU: {}%", bn::core::last_cpu_usage().integer()), resourceUsageSprites); - const int iwramUsedPercent = (bn::fixed(bn::memory::used_static_iwram()) / IWRAM_BYTES * 100).integer(); + const int iwramUsedPercent = + (bn::fixed(bn::memory::used_static_iwram() + bn::memory::used_stack_iwram()) / IWRAM_BYTES * 100) + .integer(); const int ewramUsedPercent = (bn::fixed(EWRAM_BYTES - bn::memory::available_alloc_ewram()) / EWRAM_BYTES * 100).integer(); - const int iwramFree = IWRAM_BYTES - bn::memory::used_static_iwram(); + const int iwramFree = IWRAM_BYTES - bn::memory::used_static_iwram() - bn::memory::used_stack_iwram(); const int ewramFree = bn::memory::available_alloc_ewram(); textGen->set_right_alignment(); diff --git a/src/scene_Game.cpp b/src/scene_Game.cpp index 965fd28..fbe24dd 100644 --- a/src/scene_Game.cpp +++ b/src/scene_Game.cpp @@ -15,6 +15,8 @@ namespace sym::scene namespace { +constexpr int FADE_IN_UPDATE_COUNT = 30; + [[nodiscard]] const game::stage::StageInfo& GetStageInfo(game::stage::Id stageId) { using namespace game; @@ -38,32 +40,31 @@ namespace using namespace effect; Game::Game(scene::Param& sceneParam) - : IScene(sceneParam), - state_{ - sceneParam, - GetStageInfo(sceneParam.GetCurrentStage()), - {Transition::Types::FADE | Transition::Types::BG_MOSAIC | effect::Transition::Types::SPRITE_MOSAIC, - Transition::Direction::IN, FADE_IN_UPDATE_COUNT}, - {Transition::Types::FADE | Transition::Types::BG_MOSAIC | effect::Transition::Types::SPRITE_MOSAIC, - Transition::Direction::OUT, FADE_OUT_UPDATE_COUNT}, - 0, - state_.stageInfo.zoneInfos[0].mapBg.create_bg({0, 0}), - bn::camera_ptr::create(0, 0), - helper::tilemap::ConvertIndexRectToPositionRect( - state_.stageInfo.zoneInfos[state_.currentZoneIdx].zoneBoundary), - bn::fixed_point{0, 0}, - {}, - {}, - {}, - {}, - {}, - {}, - false, - helper::tilemap::TileInfo(state_.currentMapBg), - -1, - -1, - }, - keyPress_(state_), triggerInteraction_(state_), physicsMovement_(state_), zoneSwitch_(state_) + : IScene(sceneParam), state_{ + sceneParam, + GetStageInfo(sceneParam.GetCurrentStage()), + 0, + state_.stageInfo.zoneInfos[0].mapBg.create_bg({0, 0}), + bn::camera_ptr::create(0, 0), + helper::tilemap::ConvertIndexRectToPositionRect( + state_.stageInfo.zoneInfos[state_.currentZoneIdx].zoneBoundary), + bn::fixed_point{0, 0}, + {}, + {}, + {}, + {}, + {}, + {}, + false, + helper::tilemap::TileInfo(state_.currentMapBg), + -1, + -1, + {state_}, + {state_}, + {state_}, + {state_}, + {state_}, + } { // Set bg state_.currentMapBg.set_wrapping_enabled(false); @@ -141,7 +142,8 @@ Game::Game(scene::Param& sceneParam) state_.player.InitIdleAction(); // Init Fade-in effect - state_.fadeIn.Init(); + state_.transition.InitIn(Transition::Types::FADE | Transition::Types::BG_MOSAIC | Transition::Types::SPRITE_MOSAIC, + FADE_IN_UPDATE_COUNT); } Game::~Game() @@ -152,11 +154,11 @@ Game::~Game() bn::optional Game::Update() { // TODO - keyPress_.Update(); - triggerInteraction_.Update(); - // symbolInteraction_.Update(); - physicsMovement_.Update(); - zoneSwitch_.Update(); + state_.keyPress.Update(); + state_.triggerInteraction.Update(); + state_.physicsMovement.Update(); + state_.zoneSwitch.Update(); + state_.transition.Update(); // Update sprite graphics state_.player.Update(); @@ -171,12 +173,6 @@ bn::optional Game::Update() for (auto& pressureButton : state_.pressureButtonsOfZones[state_.currentZoneIdx]) pressureButton.Update(); - // Update fade effects - if (state_.fadeIn.GetState() == effect::Transition::State::ONGOING) - state_.fadeIn.Update(); - if (state_.fadeOut.GetState() == effect::Transition::State::ONGOING) - state_.fadeOut.Update(); - // Move camera (follows player) state_.camera.set_position(state_.player.GetPosition()); helper::tilemap::SnapCameraToZoneBoundary(state_.camera, state_.zoneBoundary);