From 2948684ad32e7ed2153891f60487a443cdabe91c Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Sun, 28 Jul 2024 10:45:14 +0200 Subject: [PATCH] eliminat el punter al renderer de 50.000 llocs --- data/gfx/balloon1.ani | 31 +-- data/gfx/balloon1.gif | Bin 0 -> 265 bytes data/gfx/balloon1.png | Bin 1823 -> 0 bytes data/gfx/balloon1_explosion.ani | 9 + data/gfx/balloon1_explosion.png | Bin 0 -> 760 bytes data/gfx/balloon2.ani | 31 +-- data/gfx/balloon2.gif | Bin 0 -> 484 bytes data/gfx/balloon2.png | Bin 4557 -> 0 bytes data/gfx/balloon2_explosion.ani | 9 + data/gfx/balloon2_explosion.png | Bin 0 -> 1202 bytes data/gfx/balloon3.ani | 31 +-- data/gfx/balloon3.gif | Bin 0 -> 908 bytes data/gfx/balloon3.png | Bin 6258 -> 0 bytes data/gfx/balloon3_explosion.ani | 9 + data/gfx/balloon3_explosion.png | Bin 0 -> 2085 bytes data/gfx/balloon4.ani | 38 +--- data/gfx/balloon4.gif | Bin 0 -> 1782 bytes data/gfx/balloon4.png | Bin 13094 -> 0 bytes data/gfx/balloon4_explosion.ani | 9 + data/gfx/balloon4_explosion.png | Bin 0 -> 4227 bytes data/gfx/balloon_blue_pal.gif | Bin 0 -> 69 bytes data/gfx/balloon_green_pal.gif | Bin 0 -> 69 bytes data/gfx/balloon_yellow_pal.gif | Bin 0 -> 69 bytes data/gfx/powerball.png | Bin 0 -> 536 bytes source/background.cpp | 14 +- source/balloon.cpp | 41 ++-- source/balloon.h | 14 +- source/bullet.cpp | 4 +- source/bullet.h | 2 +- source/common/animatedsprite.cpp | 6 +- source/common/animatedsprite.h | 4 +- source/common/movingsprite.cpp | 5 +- source/common/movingsprite.h | 2 +- source/common/smartsprite.cpp | 3 +- source/common/smartsprite.h | 2 +- source/common/sprite.cpp | 31 +-- source/common/sprite.h | 13 +- source/common/text.cpp | 6 +- source/common/texture.cpp | 16 +- source/common/texture.h | 9 +- source/define_buttons.cpp | 3 +- source/define_buttons.h | 3 +- source/director.cpp | 21 +- source/explosions.cpp | 39 ++++ source/explosions.h | 48 ++++ source/game.cpp | 370 ++++++++++++++++++------------- source/game.h | 24 +- source/game_logo.cpp | 10 +- source/instructions.cpp | 4 +- source/intro.cpp | 2 +- source/item.cpp | 4 +- source/item.h | 2 +- source/logo.cpp | 4 +- source/player.cpp | 9 +- source/player.h | 3 +- source/scoreboard.cpp | 2 +- source/tiledbg.cpp | 2 +- source/title.cpp | 4 +- 58 files changed, 492 insertions(+), 401 deletions(-) create mode 100644 data/gfx/balloon1.gif delete mode 100644 data/gfx/balloon1.png create mode 100644 data/gfx/balloon1_explosion.ani create mode 100644 data/gfx/balloon1_explosion.png create mode 100644 data/gfx/balloon2.gif delete mode 100644 data/gfx/balloon2.png create mode 100644 data/gfx/balloon2_explosion.ani create mode 100644 data/gfx/balloon2_explosion.png create mode 100644 data/gfx/balloon3.gif delete mode 100644 data/gfx/balloon3.png create mode 100644 data/gfx/balloon3_explosion.ani create mode 100644 data/gfx/balloon3_explosion.png create mode 100644 data/gfx/balloon4.gif delete mode 100644 data/gfx/balloon4.png create mode 100644 data/gfx/balloon4_explosion.ani create mode 100644 data/gfx/balloon4_explosion.png create mode 100644 data/gfx/balloon_blue_pal.gif create mode 100644 data/gfx/balloon_green_pal.gif create mode 100644 data/gfx/balloon_yellow_pal.gif create mode 100644 data/gfx/powerball.png create mode 100644 source/explosions.cpp create mode 100644 source/explosions.h diff --git a/data/gfx/balloon1.ani b/data/gfx/balloon1.ani index 3fbe8c1..21c1d83 100644 --- a/data/gfx/balloon1.ani +++ b/data/gfx/balloon1.ani @@ -1,37 +1,16 @@ -frameWidth=8 -frameHeight=8 +frameWidth=10 +frameHeight=10 [animation] -name=orange +name=normal speed=10 loop=0 frames=0,1,2,3,4,5,6,7,8,9 [/animation] [animation] -name=blue +name=stopped speed=20 loop=0 -frames=12,13,14,15,16,17,18,19,20,21 -[/animation] - -[animation] -name=green -speed=10 -loop=0 -frames=24,25,26,27,28,29,30,31,32,33 -[/animation] - -[animation] -name=red -speed=20 -loop=0 -frames=36,37,38,39,40,41,42,43,44,45 -[/animation] - -[animation] -name=pop -speed=5 -loop=-1 -frames=48,49,50,51,52,53,54,55,56,57,58,59 +frames=0,1,2,3,4,5,6,7,8,9 [/animation] \ No newline at end of file diff --git a/data/gfx/balloon1.gif b/data/gfx/balloon1.gif new file mode 100644 index 0000000000000000000000000000000000000000..173179c554567a6312c2f46700de14150f9c1cf9 GIT binary patch literal 265 zcmV+k0rvh!Nk%v~VKM*|0FeLy00022GBW$}Hvj+sA^!_bMO0HmK~P09E-(WD0000X z`2-0H0000i00000G5{0+00PH^g<=b-+!BmvIw*n;?`+OwTi1M~sCD8nq#nzHCG3_# zEN5`5p!ev*AwI3t>Sxpxfkftw##!N_O6c$@3_7RO&GM>rdXr=F&O8MpyJwKE_Rf9a zbNO6l3gs8R)7~?JAt6{nNOCY3lE}A+Sg82O80mP}rx(cgXHx^nsU!3Px{3K2^AOh) zX7W~a)#j=SOXHfRWfm)y71qLY^kvIt#d^yd{M&SkM63HVJ4$yKYT8L!hlfe+hdrvz PNomnYaVQS{SO5S!sup%) literal 0 HcmV?d00001 diff --git a/data/gfx/balloon1.png b/data/gfx/balloon1.png deleted file mode 100644 index 8487e7fecf8a445054b50d7ad00d3f0185f81794..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1823 zcmV+)2jKXLP)Px**-1n}RA_}o+S%dA{>*^$!+_6&1f zWM>JQ%$H1@xpgk((r{@m< z(IL?p@IQ6YM13NwWv$2l>AO&5uX+E-(=Xp7Cw)IjR05BXU ztUo01a^71P!`+?>=?PC#Tk@`RVxsfcR+8DW0o$go|5vwGACp{jQRbBEPPZ5GOtwG>k9B zI9Km5s!zHY{|;~$uwyNa<3WTGHeB4o+tzFbHp(X8E@0p;V5!X$?`)p(qAsLy2lV5Ii(7cRdv?nF(}nIPY+JJ#^oGz0q~s^_ry9v4 z)B2(?GVT7NFv8MfGX1GQ+GIZZ>N7>~^Isl;d=s*GW8U-)ph4us%hqSV?0mYAehacK z`angsDMl8bnok#Y03bps`8+Ht`dlKE62|>4WAT&oX24MK&b|&002IzIl3KCv7Tb9M zuy|wM>`kx%z)!W6TyLb;DHoTcrp(9n^!B)#>;G_7pQ+OAgCkvi&i0dSjuXBLUTs6i zRKKRo$DQz1XucELPqsN~%6uCAnlc|3>FP7gulh`tl%JkI0QB|uI)lHrI!^d1c(n~3 zQ~l~QRf_zo&s1@J{l@h%1BM8tWPbS%iP52$q7{2*`4R*-ZU6wd50z^ii&lCN+&KPT z%>AM&5t%o{8u63)yAPFPZogCNvm^6{*i7m#IQnB^bR<44{ux;Tdd0u}ce|le(Mk_G zu1q`(dc~3RllfB(dSqH(uXxkxKV=Z1l(_b15!e1KvhwV5;@Y1@h)_!8eD=OMBzxZ+ zvhwT-lD%(^#mjgzkd}{HP`$J)J~f{%tp5khFr@DQ;nT$_`(TSV=FNbi;ZcQ z6C zO}JHkNgC@F=ceyhLs30GUj$1JHE&j5uXvgEk0nHw9+T-$1=1!%R{<^lhC7QP--PH> zM1ybXe8b{1u?f?YneL-sbv|88+yK&}48SbNNB|3|VFMY&-2@J=-=%qynmX?>M#ZQ6ma5Z?QSs>Yboq3i?iWGEehaEO z^0gs%c>OMN@N!6TO}+vSuir%;4*!L{0UvYnI*YvlpQZ@Am+d4=vu)VDY-d`_-z-0E ztAdaoLP!s3YPz8~==Ds*(0iZ1Z14D)!g!yn+6UC{e+$zGs|}rD{13HF9JO>PuSNg> N002ovPDHLkV1jzsj7k6i diff --git a/data/gfx/balloon1_explosion.ani b/data/gfx/balloon1_explosion.ani new file mode 100644 index 0000000..30cb568 --- /dev/null +++ b/data/gfx/balloon1_explosion.ani @@ -0,0 +1,9 @@ +frameWidth=10 +frameHeight=10 + +[animation] +name=default +speed=5 +loop=-1 +frames=0,1,2,3,4,5,6,7,8,9 +[/animation] \ No newline at end of file diff --git a/data/gfx/balloon1_explosion.png b/data/gfx/balloon1_explosion.png new file mode 100644 index 0000000000000000000000000000000000000000..30871f027edcff6304a0a25c6735848801780f2b GIT binary patch literal 760 zcmVPx%vPnciR9J=WR!wVDK@>eVA4Zy}X>AFOiG;Qq8=;8Z=pqkSqHDpG8wLMC|AAfm z7X;IV2(A^e3tz<+M63^KNli;iQd3Aj(oi23Q^!T~hRM9ow$B!%2f~}&d*;qPZ|<8r z#8@2y7&<|GKz;BNZy(-w<=lSu(!{f~c}1xGuKLCFr9f~dtsldW7X zn{1g(MmC8rm>g`FUfu!#Ji2}tS~Y}`RLhd5WCx+7`=Rf2AsOod0F1qU!HEG#V#TLL z0%?5vy(nsIk5GlY^?28oM(TXWD9zX{*7G zb&VaCMe_gc-IjOSO{6PNTZ$kU-N4mE)M*}ROA*wXJIHk1;LZovenVS|unnpD03aSt z;nKM{P0WTF09=T%4o(0ti}eH5g*iumqPvCNpFM2+<7YbxPjobXk(Kosl=T_ZT1}dm z4FjikO=1ny^_cC84!GofU^Lh3c=hy&C$1#Aqn!7PcsK!OBUeaUl3wS(wi?Xpa0O0#p1MzT- zv^B!>F9plEi3riM{s)POIZbM}B?fesws2Ad0R79hB(@bhyI&xo4|CD7Sit{2d|aU8 zx_BHH4tzNH0jo<4V11DhxmJF!2pPeYbU*6)FZ6Yt1^|q|``{@-yTxU$%(D{?29BnbKJg@Nt9I9mj!cA-Vd^Z)o6``d20XUWo z*^KSrMTBd-!<4azkUQnTAn9ob27vq$Y^#mvQkMS3d=nx^WQq1N60000TAUE zDc!iEf4NSxsRn~xt!LaIeTX4(1Y5F%9%6Av4Op*Cs#ON@exb_Fb{uwUXUA&siFL!t z!somz-{Nfg^(^c5*TZ$f2S->agXp4jw{kPa=;SDJ*7rDxXfkwTaw(`t3FwFk2?po~ z8rkU;D5-Ypn!0DoR%Qv8mdB+l8)x>}TLso8Rjjotj7(ex+}VWmf=YJ$4DC$a48*g| zZ5`DO{(a4i@fSjcV(x-|UXo6Op^iTPUSDx9ACJGUuYr)^--Le~0={$CqEI__2N@<@ zQKCn@X%i*>7*{QuwsE4J1lOSix$|+BE6S zuWFm-gjv;0%35?X@ye*_2&uYVpW`7OF**pOOB(l#E3^G*{BinW62;BN2b_N aVP=S%^KJ4BPoP11{a}o?R~lfw0suRu_~8ct literal 0 HcmV?d00001 diff --git a/data/gfx/balloon2.png b/data/gfx/balloon2.png deleted file mode 100644 index efca82cc32e5d456cf7171469e042c296bf75007..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4557 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 QL;wH)07*qoM6N<$g6thSssI20 literal 0 HcmV?d00001 diff --git a/data/gfx/balloon3.ani b/data/gfx/balloon3.ani index e1fd440..ee716a3 100644 --- a/data/gfx/balloon3.ani +++ b/data/gfx/balloon3.ani @@ -1,37 +1,16 @@ -frameWidth=21 -frameHeight=21 +frameWidth=26 +frameHeight=26 [animation] -name=orange +name=normal speed=10 loop=0 frames=0,1,2,3,4,5,6,7,8,9 [/animation] [animation] -name=blue +name=stopped speed=20 loop=0 -frames=12,13,14,15,16,17,18,19,20,21 -[/animation] - -[animation] -name=green -speed=10 -loop=0 -frames=24,25,26,27,28,29,30,31,32,33 -[/animation] - -[animation] -name=red -speed=20 -loop=0 -frames=36,37,38,39,40,41,42,43,44,45 -[/animation] - -[animation] -name=pop -speed=5 -loop=-1 -frames=48,49,50,51,52,53,54,55,56,57,58,59 +frames=0,1,2,3,4,5,6,7,8,9 [/animation] \ No newline at end of file diff --git a/data/gfx/balloon3.gif b/data/gfx/balloon3.gif new file mode 100644 index 0000000000000000000000000000000000000000..0ba4add628f8009985b2499d01a5a551a6d7bd16 GIT binary patch literal 908 zcmV;719SXGNk%v~VS)fO0FeLy00022GBW$}Hvj+sA^!_bMO0HmK~P09E-(WD0000X z`2-0H0000i00000f&erC00RGnkD`n1z1W*63W|ZfdF~D=!AMHoLY4}siD_VF=o@2m zT6^yfpFHjRm4d>atT^IO1jymCnY2NTI;ir&v_7X)2)CQ~Uc=n+Av-l|nuE5JEOwwr z?fQUco~PyCDEw!4_qO&D=(cmEXLty7hGf@hFt-?p<5*EdA+-C-aS>T%E5!DZ{HMo2J;29 z2j!eXgaixzJNT}cKY;%aGh##t(Nsc#5l1#`XOc<3GW4pgJ1K4?Npt!bB8!>uQ^l3J zaMtT-%F{D|9PtcIX7briXE!-2BNo&sGJ;YsQWM&=%+Wr}G**=*@mN-KQnzZo#5GaW zNMn(V`N#CnFS%O0AQg-DtlhbL>+;dt7uq1Y(!MU@x)T1M?kYnL>XVE8O%RXcKb_>_Kchi=U`}T+4!(X4? z#~Qci(zTZ-mqhyc?$xFvQ{GGj`}NG2%R-*~{qkSy;kB3N9vFOj@rl)kQH7VVdAjiZ zz^VT@@lX4XcC!C9OCEsubumdr`6V5bS!dOTu?$31Ed}BNj)$~RC1O5xmH45G941JiQxKkr4oxn(ae;(Z&=?R*K89r^ zRWu+tB3KiFD9=plY~<5^MmiQ!k1_`H?>Ls3AWrHMum-fOZQx`>fVU$=Qh-0Ug9&=5f8bbOhSN6f$r&@A)M`MGxa2M=< z#qwt=d&f$G(H45mdeu-D*4TU|0lr9=G9QTQ0Jo iImg0r^GGM}Zxz66T6Dq%CtGp*@}`@={qoyD0RTH5e7&Op literal 0 HcmV?d00001 diff --git a/data/gfx/balloon3.png b/data/gfx/balloon3.png deleted file mode 100644 index 82991dd6134e052019dc1dfdef9c171d5aa02acf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6258 zcmai(cOV;o+{dF@ilRST(X>VE8Pq7cw4%n(2(^L|qo^9O300e_O$n`8yRkP#C?aaq z-g|~7ilF*Lf6w#x^T*xg*5|(Wz02!f@4Luwm86g-kj?!+@mGdVK%vbyZJ@jZ)Y77#KLUgaLMQc6z9d@LoW9+kwTp%?Z3vLM@~ zH-=38R<|}fDr1}^MYmTcW+zc798kF}%c9Mv;`EnPLAcMn@JmlWKNX^1+ja{+-6wD1 z(!?sK+@w0Si_&YOe zg^=@u2xCBy#Q{){f>z{6?o^>&lD=vz4U*h%Z?_<0U;dt9-};rRcR_rhbGmXPn8B8R z=ge8Mmpyv#&n+(M#8WwOkkO2_%f-4)sbMRS@w=~$l!bgt7@BW9AN6-KdCzZ#Z7NKq zrNbaMOnbtYK_h z{M3ISBmM+5$;F=NkN&-o-klfM!lbEjE}xeCjsIr0AoiAm1-(X7U?QUNv&L2Z9h`1@ z5+G{^pt*$U9W?|Lq#d|Q23RvEY;N}lVWS@iZPL?;V-TPE;zN`DGJ=O^ao}ZXEr4XB ziaV^^z`WB>s#BcRF?JJyd<)izxiNPcz}!=iFI8NPg4k`X_}7T;n!EI)HpEAx1vFU# z$MM}?cxo(rotxugfS<6>6hD-W2aF3%bF7XN()&*r$OtMiydds|(lx4U(`kmEOt7f!%j`)gZu zVWH1rYEyRKDOUPF8elh-O51rv=_ks&<^(jUB$j#8ACYyWiDi(v2O-BbZl!%bC z%pMuq6x^pgBNTJqhQl?wZaDX!L;49Lokp#$2J1muNQ|x`yiH=K&I3vcem4%M6MYh@ z3-~ghD~ahY9*)F6R7P)C*8WZ%%{P-GWGIsqWPCp3XiU;v*ZpM$DJLk||NNUOmUqT| zpK@=&*x2pnfLx1$NQv)IQKH*qHjf0W0RQ(e(PHdQMn1t5PwTzp>R>#-)iDDR@4IoMN5aCE`-P4(KxnX~1- z2~DyXa-VOl7FdrOB3FJ9^CVK|kqgc(Ho3>dskFo}&hyg4Kofbn5Jd=8gc(lYbQc;v zolS0(sip2G*XWqJO#Xpj<7`eqoFBhi>y4G-%-QM2b|u*QVWQAShM=aB!4qtdI|J)s z2YearXUc9U*I;qq20u4;pPr%S#9U^wx%;@_&YUNc2s>#SqFJfq^yI+b9EqQrN^Z=< z;YIur9vkcVtaPzb_AxfrtIbSRGM?$G3W@Gr9fcfaCIRU+o0DLYgv1*W0r@J++fbVn zjCzVGk*&!cB6}$BrqU~%A?#xb@OlktQ8T}p_UnViZq zu-$b~B)bi_HPS(+yurrqb%B$tEFyu2Pvub3vv0x`qwa*~U+W$H(A53RD56p7gQ5_- z;uF^uf4$^GRSX;A!MPxV*hqRi$=I-x@+SAiG$=9R99u&$U%ka`R^i%7w{Cp*^lhT69yBfI-fj zIu8!qMx@Wwxk@!G-8{|fslaRc#)z|kd)>+x5m5od%SK+qs#za*!P%+!UDmPmWXqc_ z^CKMWiKk0rd%sDR1_c|_@@aQewUK&NafuKTOR`UMfDZ5Afc)-gFDb8ovP%!KyJVEc zH$*r0QT@aakYw(JCzv!;;b~5dTGUPJX#ozgoAul&S$g+^=YE5Nbu} z50y`25tMj!9rSa_W=r_0zUGO1S|FOH|9}Ypx1ii3y-^Ni&N;V90HR8$gRrZ)eTTBl zO&LxLo;^(iN3ZOzV=ya+-CtRHfT2Z%vKWQ^^NMW>%i|cG6TGsKmQ++{_DozdM-zLM zN%=aeZk60i4qa#bfSnE_)|P8aA0YT2ev8(1XWwN{HGO_ERx1hcx5Ti&)pyXP{1K1C zy6&U^R?C|pgfv^*?cGWrI3}bNxR~^Q-E}{ZlF5V^JhJ8X3MUcOa1>3*=JFl=%LtO>8w*+ z6|#3E$`#Gdu}25+kw^JjN)9u3c;`n127J=nO)bcyTGm`Q4mm;7NBlX#~r#`5%lIUQeT?$={3bG@*|bQ z9j)WU=O#0szj(JsD>ywa{^DLzeXHy3z{PRv{4upwq0`#mc35^q9G`SGziJ3*eXqGR zL7cXLz`J8EBULQ#-X0QY)Fc!-m1eHL&~xoOqw$J~;AK<62nH*C`;^Mq?r~dH!5OIAGRo6T8+g8pUp7uaq93ofB?D0QDY6bR4|sVdX_P zNqEI% zpB85P44cq+8EC< zGuKU*%RzoqQ|1<&NecH1Cw$_g+rq6*=;gHwj1t1Myibe`KR$>yKX5j%&F>Z$76%ir3Dv110r0PlXCL~7NVT^bE$Pq#{qs_8yxRP9K2;hy?& z8DK3Co7(+(*b{^*G8uNa{ZIH1zX>)ZQ1CLBSz9r!c>(=knMH%iGi|&Z$e)r zSC;7>-!|`2AY}WOTmUlH@zD5Jk7JGVuF4!#?odl-s`*x?M#=Vp5F}=0eG8kJ(b|S~ zB}kvPspH983`WD&8xDxPjAg`ob*J7&%H2)Nv;gO}Htp#;vOFF~4$yT7RXs~u(3xdb zm;EMmj11gDuMM8#oz@vQgOjcRxc=a?Z;YRB0)?s1a{pAzMZUN>G^u6{{n^X8^D)gP^os`rf6G?pEj1nMG^xG5VX8>V z+M-6Sw;aur%IKfe1N2(?G(xCa>*~dZU$HQn3IZk1pdBq-YU{Z772GN+7MhP=Hvh$- zWIe6wZ-WwfBBL#Fny#8$vARx~{upUXIGpnf{5ghJDAF)iW;97X|E&rDcz>nz9766d zE#3osi^_@$Snx-tWX%uxQUWZo^XI&PAf+Uam4QbbepBX|fbYt9e?!d(PGUKBr!~-l z79f5)*LIEJV6{>h1Q22u65*HWFR0T7 zVuQp}Hf}T!?rL_0u|E2If0|l~z~0%Hd3W^RK5N)c_`FI))%@{|poB*hb^1aZK~3^P zw;OJJuwDF?5&oTMXYs?fZzA*0q@$hbMT3xpISF`(G~}L@&_5wly}Qc;g4gtayzN4V zqxHEhuxm)P5+^{4+oYhpB+9J-wVjT zDLn7-^Xz(%UOe$>x^}c0!F?iI-IQ9$$?*`BVt_r< z74<|LA4g_lfNFMIR1;*Z-AH3M5o$lbe#v4in((2Q^po5PAF8U+zBj9nD|_#HBLvSxRR9`QQ9Um>A#{!;}(ztlkN9omF3y9Z~0U@;)BqYC>(N~ zoYf(_93MDQ+%8NfmZTkp{}RnqF+|EOo`{5asi{Sd-#;7bPbd2z#1>>eyw|ynJqW~z zOCuB=uG?LZJU!h&sEzj;0CtyPFMHkN=|2@*{G-lfZc9+vGObRNl60;q*k9f8s6O$7ZafaOMug^;SY%vw`V_5VFQ^q_~W zHiH5BiuT{l9_{_!`u;9;-lLVR;kX;Lp79t)&e_G+o+-MIJD%R4SXgUezIQi#6wV}} zeUYy%syzbjhOIq5r9o2M=_~YiqFtP}@{rBPe)x<#v(qA_V3DsgzouHd>(i3Bu zGtCR5mIk1842Ff|dg4AbOhVmnmdXiZPj1+*35ad>>2?rUFHVD`Rz>D-O<^h|Avu&e zlF+Y={dsQ^_ydQ#VKfEB_d6wjM+u20E-{Dpa@oyzM#=T1{kS!5?rU5aT`Z}o@xA{4 zH%_6sO)8Mt)MWr~&pWq6+2vVn1pS~axnKS=S+bvGVnbM3f$&Qs!B$BvLK_p${x@$Y z0HLAALP{m8zH>gN`2AX3H>X!M0C3Vc_=A`uP!x5xU#l%(%)XRpB5`(*!Z5y5WvfK`s6e7wUVf(JI&O>Idxqy}IpRfbP!TjuLsY&8YIlk&wHsA|# z`=(LMnpm631#y8w&=Apecn^L(w_gV`!dw16xht8kGGi?f** zJ)fGtw~S5)kkypY32*;|s@(Z))|lXP#qb0eLi>GAVcx5>FQX2D0beBgJu; zms-0&CC=3FD~$;GG1mSzJ(BU|Z|-CCXvPV*RJoONN}MRBM{kT0-okW=l@K` zh&(x!r5*dZzMd*<(LYEn9eIw;-?>G?n8K?PpD~-D>f=Nk4eO-->8uC_K{x>${q*W} z%$I@`Hk}R&Lmvq2s|w3q%y`<&zCH>|^s2TA`a@}{)QFVKUVX6iA?xWO<);k_FTjz@ z?8wAEDWCJF4`N4-<_gS4bC6dABnsfJB-Hz8Ioig&Cflnk+u_S6c-Na0mI8&|u&!@21ID#{1xb-)inu0hHiC^@Z}9i6lSKE8^*8S|VD#@!-<=uL|9x`&asMH; z-d7G|Vh_ax>YiL8&F zeTFK(zokxd4rQ|(naZY<`I%~GzqTIt0$uVURAbbbl)Irhn{b z&Uj7+qhVS)pAUO8LQna46b@DO=FK%p^oQ)}ZomQh$4{O>a|s!q6j8ImX*qYLi)kBF zym>_qd6WW;4|NREKvo8*m!_}nmaKU&-QlKVpg@0JgQ+e(K@+HJ$+>Nmig9sR$7Ls_ zW%2Lye%Z7wOa7Lp-O;`^FOlWX^>!LfnvcC^+J#|rF2-I>R{$bof11`gHtr>ilaejB zBBBJH2>Q2mDXPWlN22u9yE2u;*nOPx#I|46Exn-dwf3)vmq7=#K9w$nuqZ{c2h^}N zKYtz6v|)o}AJmmXB~pDu<2Q=}^Dm!j@#LUl{>^uNKb_%3Kt+^^;rlsF`xoJl69oE2u${A@ZH z9NI2twCu$F^s7LbLtYLJ&o^rfGu+Ahq9!5Ysh1z6;zS@g;yz!QuU*h~#M__B#iUJG z(dn=2-Lk(8edG!%lN8C1-a^LB9&A`VwT%e%-zEH0?@5ZNB-WNT&C*uh`Iw<^u;O00 z`g+{ok2+t{E38NoIMFJl7TU4vL+(Nr*^paPUyh1cbk5{ookxc9SyMURy2JYtJ@yby z$!`3$;^f5QiS1?cv2C(NeRfQZYd0rSOL>{#Ff=bZJH;H!E>6dp4qu%$Q#iA(_sl@O znF52(`yqt8rKRJfv9x`quF}&(m-U`e+9b@--o-A09_M&m;yGwEZ`Q?B zGz1UJ-V;)<)N^0B*Z2&WwA!n95? z(f#0vd1<7b6Do9KBIL=N8?9D;2^wIko%DPo=wklmdy-0Xye@t3j<>aq!6RwEDNfEG c@6UmALuO2oXk~TsM+5*wP5W{AL(4b+15w#>4FCWD diff --git a/data/gfx/balloon3_explosion.ani b/data/gfx/balloon3_explosion.ani new file mode 100644 index 0000000..957e88d --- /dev/null +++ b/data/gfx/balloon3_explosion.ani @@ -0,0 +1,9 @@ +frameWidth=26 +frameHeight=26 + +[animation] +name=default +speed=5 +loop=-1 +frames=0,1,2,3,4,5,6,7,8,9 +[/animation] \ No newline at end of file diff --git a/data/gfx/balloon3_explosion.png b/data/gfx/balloon3_explosion.png new file mode 100644 index 0000000000000000000000000000000000000000..552a6686af9b93cc5fa3c9f05614f165033fa067 GIT binary patch literal 2085 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 YSdXoYWhm<_$rj5p$ev8H9w-0+J7PU@c>n+a literal 0 HcmV?d00001 diff --git a/data/gfx/balloon4.png b/data/gfx/balloon4.png deleted file mode 100644 index 45ec694c3c004dc0ed1025150930833ecad83108..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13094 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 literal 0 HcmV?d00001 diff --git a/data/gfx/powerball.png b/data/gfx/powerball.png new file mode 100644 index 0000000000000000000000000000000000000000..1b9933c2b115a71456b3642f17e557847139adad GIT binary patch literal 536 zcmV+z0_XjSP)Px$(n&-?RCt{2n^AJZAPhtoPY#w#^%S|3Z>D~DXk}s>FtQMg-e0E}HfwnUF$4%h zM0EB45JHe1QvxmBuhtGyq3`!kRr{VdfNRO=sA+q}?F*xToWVKP^|J|4G(Kv-J7&xE z)fY$^ouXlUtI-nu6*qj!=#(dnmo~bk{~`fIL{A%?vaTNygNTT<;;Lk^E~SvmsD#y{FkZ4a-?$D`o@R7jdPk&E_0Mi?!6?U{7_YE|9)&xxj#P`t9-pkM)JRNHz1vE_MGlgetHeight(), -clouds1speed, 0.0f, 0.0f, 0.0f, clouds1Texture, renderer); - clouds1B = new MovingSprite(rect.w, clouds1y, rect.w, clouds1Texture->getHeight(), -clouds1speed, 0.0f, 0.0f, 0.0f, clouds1Texture, renderer); + clouds1A = new MovingSprite(0, clouds1y, rect.w, clouds1Texture->getHeight(), -clouds1speed, 0.0f, 0.0f, 0.0f, clouds1Texture); + clouds1B = new MovingSprite(rect.w, clouds1y, rect.w, clouds1Texture->getHeight(), -clouds1speed, 0.0f, 0.0f, 0.0f, clouds1Texture); - clouds2A = new MovingSprite(0, clouds2y, rect.w, clouds2Texture->getHeight(), -clouds2speed, 0.0f, 0.0f, 0.0f, clouds2Texture, renderer); - clouds2B = new MovingSprite(rect.w, clouds2y, rect.w, clouds2Texture->getHeight(), -clouds2speed, 0.0f, 0.0f, 0.0f, clouds2Texture, renderer); + clouds2A = new MovingSprite(0, clouds2y, rect.w, clouds2Texture->getHeight(), -clouds2speed, 0.0f, 0.0f, 0.0f, clouds2Texture); + clouds2B = new MovingSprite(rect.w, clouds2y, rect.w, clouds2Texture->getHeight(), -clouds2speed, 0.0f, 0.0f, 0.0f, clouds2Texture); - buildingsSprite = new Sprite(0, 0, buildingsTexture->getWidth(), buildingsTexture->getHeight(), buildingsTexture, renderer); - gradientSprite = new Sprite(0, 0, rect.w, rect.h, gradientsTexture, renderer); - grassSprite = new Sprite(0, 0, grassTexture->getWidth(), grassTexture->getHeight() / 2, grassTexture, renderer); + buildingsSprite = new Sprite(0, 0, buildingsTexture->getWidth(), buildingsTexture->getHeight(), buildingsTexture); + gradientSprite = new Sprite(0, 0, rect.w, rect.h, gradientsTexture); + grassSprite = new Sprite(0, 0, grassTexture->getWidth(), grassTexture->getHeight() / 2, grassTexture); // Inicializa objetos clouds1A->setSpriteClip(0, 0, clouds1Texture->getWidth(), clouds1Texture->getHeight()); diff --git a/source/balloon.cpp b/source/balloon.cpp index 4bab7b2..99d4508 100644 --- a/source/balloon.cpp +++ b/source/balloon.cpp @@ -4,7 +4,7 @@ // Constructor Balloon::Balloon(float x, float y, Uint8 kind, float velx, float speed, Uint16 creationtimer, Texture *texture, std::vector *animation, SDL_Renderer *renderer) { - sprite = new AnimatedSprite(texture, renderer, "", animation); + sprite = new AnimatedSprite(texture, "", animation); disable(); enabled = true; @@ -210,14 +210,7 @@ Balloon::Balloon(float x, float y, Uint8 kind, float velx, float speed, Uint16 c // Añade rotación al sprite sprite->setRotate(false); sprite->setRotateSpeed(0); - if (velX > 0.0f) - { - sprite->setRotateAmount(2.0); - } - else - { - sprite->setRotateAmount(-2.0); - } + velX > 0.0f ? sprite->setRotateAmount(2.0) : sprite->setRotateAmount(-2.0); break; @@ -289,9 +282,13 @@ void Balloon::allignTo(int x) posX = float(x - (width / 2)); if (posX < PLAY_AREA_LEFT) + { posX = PLAY_AREA_LEFT + 1; + } else if ((posX + width) > PLAY_AREA_RIGHT) + { posX = float(PLAY_AREA_RIGHT - width - 1); + } // Posición X,Y del sprite sprite->setPosX(getPosX()); @@ -304,7 +301,7 @@ void Balloon::allignTo(int x) // Pinta el globo en la pantalla void Balloon::render() { - if ((visible) && (enabled)) + if (visible && enabled) { if (bouncing.enabled) { @@ -325,7 +322,7 @@ void Balloon::render() sprite->render(); if (kind == POWER_BALL) { - Sprite *sp = new Sprite(sprite->getRect(), sprite->getTexture(), sprite->getRenderer()); + Sprite *sp = new Sprite(sprite->getRect(), sprite->getTexture()); sp->setSpriteClip(407, 0, 37, 37); sp->render(); delete sp; @@ -338,7 +335,7 @@ void Balloon::render() if (kind == POWER_BALL and !popping) { - Sprite *sp = new Sprite(sprite->getRect(), sprite->getTexture(), sprite->getRenderer()); + Sprite *sp = new Sprite(sprite->getRect(), sprite->getTexture()); sp->setSpriteClip(407, 0, 37, 37); sp->render(); delete sp; @@ -579,16 +576,16 @@ void Balloon::updateState() { stoppedCounter--; } - // Quitarles el estado "detenido" si no estan explosionando + // Si el contador ha llegado a cero else if (!isPopping()) - { + { // Quitarles el estado "detenido" si no estan explosionando + setStop(false); + // Si es una powerball vuelve a rodar if (kind == POWER_BALL) { sprite->setRotate(true); } - - setStop(false); } } } @@ -864,4 +861,16 @@ void Balloon::updateBounce() bounceStop(); } } +} + +// Indica si el globo se puede explotar +bool Balloon::canBePopped() +{ + return isEnabled() && !isPopping() && !isBeingCreated(); +} + +// Indica si el globo se puede destruir +bool Balloon::canBeDestroyed() +{ + return isEnabled() && !isPopping(); } \ No newline at end of file diff --git a/source/balloon.h b/source/balloon.h index 38cfa87..5a94f6f 100644 --- a/source/balloon.h +++ b/source/balloon.h @@ -56,10 +56,10 @@ #define BALLOON_SPEED_5 1.00f // Tamaño de los globos -#define BALLOON_WIDTH_1 8 -#define BALLOON_WIDTH_2 13 -#define BALLOON_WIDTH_3 21 -#define BALLOON_WIDTH_4 37 +#define BALLOON_WIDTH_1 10 +#define BALLOON_WIDTH_2 16 +#define BALLOON_WIDTH_3 26 +#define BALLOON_WIDTH_4 46 // PowerBall #define POWERBALL_SCREENPOWER_MINIMUM 10 @@ -246,4 +246,10 @@ public: // Obtiene le valor de la variable Uint8 getPower(); + + // Indica si el globo se puede explotar + bool canBePopped(); + + // Indica si el globo se puede destruir + bool canBeDestroyed(); }; \ No newline at end of file diff --git a/source/bullet.cpp b/source/bullet.cpp index deaab39..1a3de1a 100644 --- a/source/bullet.cpp +++ b/source/bullet.cpp @@ -2,9 +2,9 @@ #include "bullet.h" // Constructor -Bullet::Bullet(int x, int y, int kind, bool poweredUp, int owner, Texture *texture, SDL_Renderer *renderer) +Bullet::Bullet(int x, int y, int kind, bool poweredUp, int owner, Texture *texture) { - sprite = new Sprite({x, y, 10, 10}, texture, renderer); + sprite = new Sprite({x, y, 10, 10}, texture); // Posición inicial del objeto posX = x; diff --git a/source/bullet.h b/source/bullet.h index 36054b5..d27923f 100644 --- a/source/bullet.h +++ b/source/bullet.h @@ -36,7 +36,7 @@ private: public: // Constructor - Bullet(int x, int y, int kind, bool poweredUp, int owner, Texture *texture, SDL_Renderer *renderer); + Bullet(int x, int y, int kind, bool poweredUp, int owner, Texture *texture); // Destructor ~Bullet(); diff --git a/source/common/animatedsprite.cpp b/source/common/animatedsprite.cpp index 6501bd3..f624286 100644 --- a/source/common/animatedsprite.cpp +++ b/source/common/animatedsprite.cpp @@ -146,11 +146,10 @@ animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, b } // Constructor -AnimatedSprite::AnimatedSprite(Texture *texture, SDL_Renderer *renderer, std::string file, std::vector *buffer) +AnimatedSprite::AnimatedSprite(Texture *texture, std::string file, std::vector *buffer) { // Copia los punteros setTexture(texture); - setRenderer(renderer); // Carga las animaciones if (file != "") @@ -174,11 +173,10 @@ AnimatedSprite::AnimatedSprite(Texture *texture, SDL_Renderer *renderer, std::st } // Constructor -AnimatedSprite::AnimatedSprite(SDL_Renderer *renderer, animatedSprite_t *animation) +AnimatedSprite::AnimatedSprite(animatedSprite_t *animation) { // Copia los punteros setTexture(animation->texture); - setRenderer(renderer); // Inicializa variables currentAnimation = 0; diff --git a/source/common/animatedsprite.h b/source/common/animatedsprite.h index f225f87..8e834da 100644 --- a/source/common/animatedsprite.h +++ b/source/common/animatedsprite.h @@ -37,8 +37,8 @@ private: public: // Constructor - AnimatedSprite(Texture *texture = nullptr, SDL_Renderer *renderer = nullptr, std::string file = "", std::vector *buffer = nullptr); - AnimatedSprite(SDL_Renderer *renderer, animatedSprite_t *animation); + AnimatedSprite(Texture *texture = nullptr, std::string file = "", std::vector *buffer = nullptr); + AnimatedSprite(animatedSprite_t *animation); // Destructor ~AnimatedSprite(); diff --git a/source/common/movingsprite.cpp b/source/common/movingsprite.cpp index 8b48765..5c505dd 100644 --- a/source/common/movingsprite.cpp +++ b/source/common/movingsprite.cpp @@ -1,11 +1,10 @@ #include "movingsprite.h" // Constructor -MovingSprite::MovingSprite(float x, float y, int w, int h, float velx, float vely, float accelx, float accely, Texture *texture, SDL_Renderer *renderer) +MovingSprite::MovingSprite(float x, float y, int w, int h, float velx, float vely, float accelx, float accely, Texture *texture) { // Copia los punteros this->texture = texture; - this->renderer = renderer; // Establece el alto y el ancho del sprite this->w = w; @@ -96,7 +95,7 @@ void MovingSprite::render() { if (enabled) { - texture->render(renderer, (int)x, (int)y, &spriteClip, zoomW, zoomH, angle, center, currentFlip); + texture->render((int)x, (int)y, &spriteClip, zoomW, zoomH, angle, center, currentFlip); } } diff --git a/source/common/movingsprite.h b/source/common/movingsprite.h index 9a460c7..567eb68 100644 --- a/source/common/movingsprite.h +++ b/source/common/movingsprite.h @@ -32,7 +32,7 @@ protected: public: // Constructor - MovingSprite(float x = 0, float y = 0, int w = 0, int h = 0, float velx = 0, float vely = 0, float accelx = 0, float accely = 0, Texture *texture = nullptr, SDL_Renderer *renderer = nullptr); + MovingSprite(float x = 0, float y = 0, int w = 0, int h = 0, float velx = 0, float vely = 0, float accelx = 0, float accely = 0, Texture *texture = nullptr); // Mueve el sprite void move(); diff --git a/source/common/smartsprite.cpp b/source/common/smartsprite.cpp index 5edea95..cb7e4d8 100644 --- a/source/common/smartsprite.cpp +++ b/source/common/smartsprite.cpp @@ -1,11 +1,10 @@ #include "smartsprite.h" // Constructor -SmartSprite::SmartSprite(Texture *texture, SDL_Renderer *renderer) +SmartSprite::SmartSprite(Texture *texture) { // Copia punteros setTexture(texture); - setRenderer(renderer); // Inicializa el objeto init(); diff --git a/source/common/smartsprite.h b/source/common/smartsprite.h index 1f469af..305fa0d 100644 --- a/source/common/smartsprite.h +++ b/source/common/smartsprite.h @@ -25,7 +25,7 @@ private: public: // Constructor - SmartSprite(Texture *texture, SDL_Renderer *renderer); + SmartSprite(Texture *texture); // Inicializa el objeto void init(); diff --git a/source/common/sprite.cpp b/source/common/sprite.cpp index bbb722c..866a0f5 100644 --- a/source/common/sprite.cpp +++ b/source/common/sprite.cpp @@ -1,7 +1,7 @@ #include "sprite.h" // Constructor -Sprite::Sprite(int x, int y, int w, int h, Texture *texture, SDL_Renderer *renderer) +Sprite::Sprite(int x, int y, int w, int h, Texture *texture) { // Establece la posición X,Y del sprite this->x = x; @@ -11,9 +11,6 @@ Sprite::Sprite(int x, int y, int w, int h, Texture *texture, SDL_Renderer *rende this->w = w; this->h = h; - // Establece el puntero al renderizador de la ventana - this->renderer = renderer; - // Establece la textura donde están los gráficos para el sprite this->texture = texture; @@ -24,7 +21,7 @@ Sprite::Sprite(int x, int y, int w, int h, Texture *texture, SDL_Renderer *rende enabled = true; } -Sprite::Sprite(SDL_Rect rect, Texture *texture, SDL_Renderer *renderer) +Sprite::Sprite(SDL_Rect rect, Texture *texture) { // Establece la posición X,Y del sprite x = rect.x; @@ -34,9 +31,6 @@ Sprite::Sprite(SDL_Rect rect, Texture *texture, SDL_Renderer *renderer) w = rect.w; h = rect.h; - // Establece el puntero al renderizador de la ventana - this->renderer = renderer; - // Establece la textura donde están los gráficos para el sprite this->texture = texture; @@ -51,7 +45,6 @@ Sprite::Sprite(SDL_Rect rect, Texture *texture, SDL_Renderer *renderer) Sprite::~Sprite() { texture = nullptr; - renderer = nullptr; } // Muestra el sprite por pantalla @@ -59,7 +52,7 @@ void Sprite::render() { if (enabled) { - texture->render(renderer, x, y, &spriteClip); + texture->render(x, y, &spriteClip); } } @@ -88,10 +81,10 @@ int Sprite::getHeight() } // Establece la posición del objeto -void Sprite::setPos(SDL_Rect rect) +void Sprite::setPos(SDL_Point p) { - this->x = rect.x; - this->y = rect.y; + this->x = p.x; + this->y = p.y; } // Establece el valor de la variable @@ -148,18 +141,6 @@ void Sprite::setTexture(Texture *texture) this->texture = texture; } -// Obten el valor de la variable -SDL_Renderer *Sprite::getRenderer() -{ - return renderer; -} - -// Establece el valor de la variable -void Sprite::setRenderer(SDL_Renderer *renderer) -{ - this->renderer = renderer; -} - // Establece el valor de la variable void Sprite::setEnabled(bool value) { diff --git a/source/common/sprite.h b/source/common/sprite.h index 7be4e12..27b057f 100644 --- a/source/common/sprite.h +++ b/source/common/sprite.h @@ -12,7 +12,6 @@ protected: int w; // Ancho del sprite int h; // Alto del sprite - SDL_Renderer *renderer; // Puntero al renderizador de la ventana Texture *texture; // Textura donde estan todos los dibujos del sprite SDL_Rect spriteClip; // Rectangulo de origen de la textura que se dibujará en pantalla @@ -20,8 +19,8 @@ protected: public: // Constructor - Sprite(int x = 0, int y = 0, int w = 0, int h = 0, Texture *texture = nullptr, SDL_Renderer *renderer = nullptr); - Sprite(SDL_Rect rect, Texture *texture, SDL_Renderer *renderer); + Sprite(int x = 0, int y = 0, int w = 0, int h = 0, Texture *texture = nullptr); + Sprite(SDL_Rect rect, Texture *texture); // Destructor ~Sprite(); @@ -42,7 +41,7 @@ public: int getHeight(); // Establece la posición del objeto - void setPos(SDL_Rect rect); + void setPos(SDL_Point p); // Establece el valor de la variable void setPosX(int x); @@ -77,12 +76,6 @@ public: // Establece el valor de la variable void setTexture(Texture *texture); - // Obten el valor de la variable - SDL_Renderer *getRenderer(); - - // Establece el valor de la variable - void setRenderer(SDL_Renderer *renderer); - // Establece el valor de la variable void setEnabled(bool value); diff --git a/source/common/text.cpp b/source/common/text.cpp index e273d96..ae67c2d 100644 --- a/source/common/text.cpp +++ b/source/common/text.cpp @@ -94,7 +94,7 @@ Text::Text(std::string bitmapFile, std::string textFile, SDL_Renderer *renderer) // Crea los objetos texture = new Texture(renderer, bitmapFile); - sprite = new Sprite({0, 0, boxWidth, boxHeight}, texture, renderer); + sprite = new Sprite({0, 0, boxWidth, boxHeight}, texture); // Inicializa variables fixedWidth = false; @@ -118,7 +118,7 @@ Text::Text(std::string textFile, Texture *texture, SDL_Renderer *renderer) // Crea los objetos this->texture = nullptr; - sprite = new Sprite({0, 0, boxWidth, boxHeight}, texture, renderer); + sprite = new Sprite({0, 0, boxWidth, boxHeight}, texture); // Inicializa variables fixedWidth = false; @@ -139,7 +139,7 @@ Text::Text(textFile_t *textFile, Texture *texture, SDL_Renderer *renderer) // Crea los objetos this->texture = nullptr; - sprite = new Sprite({0, 0, boxWidth, boxHeight}, texture, renderer); + sprite = new Sprite({0, 0, boxWidth, boxHeight}, texture); // Inicializa variables fixedWidth = false; diff --git a/source/common/texture.cpp b/source/common/texture.cpp index 5229523..e40d56f 100644 --- a/source/common/texture.cpp +++ b/source/common/texture.cpp @@ -29,7 +29,7 @@ Texture::Texture(SDL_Renderer *renderer, std::string path, bool verbose) // .png if (extension == "png") { - loadFromFile(path, renderer, verbose); + loadFromFile(path, verbose); } // .gif @@ -38,7 +38,7 @@ Texture::Texture(SDL_Renderer *renderer, std::string path, bool verbose) surface = loadSurface(path.c_str()); addPalette(path.c_str()); setPaletteColor(0, 0, 0x00000000); - createBlank(renderer, width, height, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING); + createBlank(width, height, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING); SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); flipSurface(); } @@ -53,7 +53,7 @@ Texture::~Texture() } // Carga una imagen desde un fichero -bool Texture::loadFromFile(std::string path, SDL_Renderer *renderer, bool verbose) +bool Texture::loadFromFile(std::string path, bool verbose) { const std::string filename = path.substr(path.find_last_of("\\/") + 1); int req_format = STBI_rgb_alpha; @@ -131,7 +131,7 @@ bool Texture::loadFromFile(std::string path, SDL_Renderer *renderer, bool verbos } // Crea una textura en blanco -bool Texture::createBlank(SDL_Renderer *renderer, int width, int height, SDL_PixelFormatEnum format, SDL_TextureAccess access) +bool Texture::createBlank(int width, int height, SDL_PixelFormatEnum format, SDL_TextureAccess access) { // Crea una textura sin inicializar texture = SDL_CreateTexture(renderer, format, access, width, height); @@ -187,7 +187,7 @@ void Texture::setAlpha(Uint8 alpha) } // Renderiza la textura en un punto específico -void Texture::render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip, float zoomW, float zoomH, double angle, SDL_Point *center, SDL_RendererFlip flip) +void Texture::render(int x, int y, SDL_Rect *clip, float zoomW, float zoomH, double angle, SDL_Point *center, SDL_RendererFlip flip) { // Establece el destino de renderizado en la pantalla SDL_Rect renderQuad = {x, y, width, height}; @@ -373,4 +373,10 @@ void Texture::setPalette(int palette) paletteIndex = palette; flipSurface(); } +} + +// Obtiene el renderizador +SDL_Renderer *Texture::getRenderer() +{ + return renderer; } \ No newline at end of file diff --git a/source/common/texture.h b/source/common/texture.h index 7dcae0b..9c15b16 100644 --- a/source/common/texture.h +++ b/source/common/texture.h @@ -52,10 +52,10 @@ public: ~Texture(); // Carga una imagen desde un fichero - bool loadFromFile(std::string path, SDL_Renderer *renderer, bool verbose = false); + bool loadFromFile(std::string path, bool verbose = false); // Crea una textura en blanco - bool createBlank(SDL_Renderer *renderer, int width, int height, SDL_PixelFormatEnum format = SDL_PIXELFORMAT_RGBA8888, SDL_TextureAccess = SDL_TEXTUREACCESS_STREAMING); + bool createBlank(int width, int height, SDL_PixelFormatEnum format = SDL_PIXELFORMAT_RGBA8888, SDL_TextureAccess = SDL_TEXTUREACCESS_STREAMING); // Libera la memoria de la textura void unload(); @@ -70,7 +70,7 @@ public: void setAlpha(Uint8 alpha); // Renderiza la textura en un punto específico - void render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip = nullptr, float zoomW = 1, float zoomH = 1, double angle = 0.0, SDL_Point *center = nullptr, SDL_RendererFlip flip = SDL_FLIP_NONE); + void render(int x, int y, SDL_Rect *clip = nullptr, float zoomW = 1, float zoomH = 1, double angle = 0.0, SDL_Point *center = nullptr, SDL_RendererFlip flip = SDL_FLIP_NONE); // Establece la textura como objetivo de renderizado void setAsRenderTarget(SDL_Renderer *renderer); @@ -95,4 +95,7 @@ public: // Cambia la paleta de la textura void setPalette(int palette); + + // Obtiene el renderizador + SDL_Renderer *getRenderer(); }; \ No newline at end of file diff --git a/source/define_buttons.cpp b/source/define_buttons.cpp index 5c4b4a0..ba804db 100644 --- a/source/define_buttons.cpp +++ b/source/define_buttons.cpp @@ -1,10 +1,9 @@ #include "define_buttons.h" // Constructor -DefineButtons::DefineButtons(SDL_Renderer *renderer, Input *input, Text *text, param_t *param, options_t *options, section_t *section) +DefineButtons::DefineButtons(Input *input, Text *text, param_t *param, options_t *options, section_t *section) { // Copia punteros a los objetos - this->renderer = renderer; this->input = input; this->text = text; this->param = param; diff --git a/source/define_buttons.h b/source/define_buttons.h index 9e76ac5..4bd18ae 100644 --- a/source/define_buttons.h +++ b/source/define_buttons.h @@ -17,7 +17,6 @@ class DefineButtons { private: // Objetos - SDL_Renderer *renderer; // El renderizador de la ventana Input *input; // Objeto pata gestionar la entrada Text *text; // Objeto para escribir texto @@ -47,7 +46,7 @@ private: public: // Constructor - DefineButtons(SDL_Renderer *renderer, Input *input, Text *text, param_t *param, options_t *options, section_t *section); + DefineButtons(Input *input, Text *text, param_t *param, options_t *options, section_t *section); // Destructor ~DefineButtons(); diff --git a/source/director.cpp b/source/director.cpp index 0773d05..35a1cfa 100644 --- a/source/director.cpp +++ b/source/director.cpp @@ -320,14 +320,27 @@ bool Director::setFileList() asset->add(prefix + "/data/shaders/crtpi.glsl", t_data); // Texturas - asset->add(prefix + "/data/gfx/balloon1.png", t_bitmap); + asset->add(prefix + "/data/gfx/balloon1.gif", t_bitmap); asset->add(prefix + "/data/gfx/balloon1.ani", t_data); - asset->add(prefix + "/data/gfx/balloon2.png", t_bitmap); + asset->add(prefix + "/data/gfx/balloon2.gif", t_bitmap); asset->add(prefix + "/data/gfx/balloon2.ani", t_data); - asset->add(prefix + "/data/gfx/balloon3.png", t_bitmap); + asset->add(prefix + "/data/gfx/balloon3.gif", t_bitmap); asset->add(prefix + "/data/gfx/balloon3.ani", t_data); - asset->add(prefix + "/data/gfx/balloon4.png", t_bitmap); + asset->add(prefix + "/data/gfx/balloon4.gif", t_bitmap); asset->add(prefix + "/data/gfx/balloon4.ani", t_data); + asset->add(prefix + "/data/gfx/balloon1_explosion.png", t_bitmap); + asset->add(prefix + "/data/gfx/balloon1_explosion.ani", t_data); + asset->add(prefix + "/data/gfx/balloon2_explosion.png", t_bitmap); + asset->add(prefix + "/data/gfx/balloon2_explosion.ani", t_data); + asset->add(prefix + "/data/gfx/balloon3_explosion.png", t_bitmap); + asset->add(prefix + "/data/gfx/balloon3_explosion.ani", t_data); + asset->add(prefix + "/data/gfx/balloon4_explosion.png", t_bitmap); + asset->add(prefix + "/data/gfx/balloon4_explosion.ani", t_data); + asset->add(prefix + "/data/gfx/balloon_blue_pal.gif", t_bitmap); + asset->add(prefix + "/data/gfx/balloon_yellow_pal.gif", t_bitmap); + asset->add(prefix + "/data/gfx/balloon_green_pal.gif", t_bitmap); + asset->add(prefix + "/data/gfx/powerball.png", t_bitmap); + asset->add(prefix + "/data/gfx/bullet.png", t_bitmap); asset->add(prefix + "/data/gfx/game_buildings.png", t_bitmap); diff --git a/source/explosions.cpp b/source/explosions.cpp new file mode 100644 index 0000000..244605f --- /dev/null +++ b/source/explosions.cpp @@ -0,0 +1,39 @@ +#include "explosions.h" + +// Constructor +Explosions::Explosions() +{ + textures.clear(); + explosions.clear(); +} + +// Destructor +Explosions::~Explosions() +{ + for (auto explosion : explosions) + { + } +} + +// Actualiza la lógica de la clase +void Explosions::update() +{ +} + +// Dibuja el objeto en pantalla +void Explosions::render() +{ +} + +// Añade texturas al objetp +void Explosions::addTexture(Texture *texture) +{ + textures.push_back(texture); +} + +// Añade una explosión +void Explosions::add(int x, int y, int size) +{ + AnimatedSprite *sprite = new AnimatedSprite(textures[0]); + sprite->setPos({x,y}); +} \ No newline at end of file diff --git a/source/explosions.h b/source/explosions.h new file mode 100644 index 0000000..2d80c20 --- /dev/null +++ b/source/explosions.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include "common/texture.h" +#include "common/animatedsprite.h" +#include + +struct explosion_t +{ + AnimatedSprite *sprite; // Sprite para dibujar la explosión + bool ended; // Indica si la explosión ha terminado +}; + +struct explision_texture_t +{ + Texture *texture; // Textura para la explosión + int size; // Tamaño de la explosión +}; + +// Clase explosions +class Explosions +{ +private: + // Objetos y punteros + + // Variables + std::vector textures; // Vector con las texturas a utilizar + std::vector explosions; // Lista con todas las explosiones + +public: + // Constructor + Explosions(); + + // Destructor + ~Explosions(); + + // Actualiza la lógica de la clase + void update(); + + // Dibuja el objeto en pantalla + void render(); + + // Añade texturas al objetp + void addTexture(Texture *texture); + + // Añade una explosión + void add(int x, int y, int size); +}; \ No newline at end of file diff --git a/source/game.cpp b/source/game.cpp index e6889a0..49206f2 100644 --- a/source/game.cpp +++ b/source/game.cpp @@ -27,15 +27,7 @@ Game::Game(int playerID, int currentStage, SDL_Renderer *renderer, Screen *scree eventHandler = new SDL_Event(); scoreboard = new Scoreboard(renderer, screen, asset, lang, options); background = new Background(renderer, screen, asset, param); - - // Inicializa vectores - playerAnimations.clear(); - balloonAnimations.clear(); - itemAnimations.clear(); - player1Textures.clear(); - player2Textures.clear(); - itemTextures.clear(); - balloonTextures.clear(); + explosions = new Explosions(); // Carga los recursos loadMedia(); @@ -50,15 +42,12 @@ Game::Game(int playerID, int currentStage, SDL_Renderer *renderer, Screen *scree loadDemoFile(asset->get("demo2.bin"), &this->demo.dataFile[index2]); } - // Establece la máxima puntuación desde fichero o desde las puntuaciones online + // Carga las puntuaciones desde el fichero y establece la máxima puntuación setHiScore(); - n1000Sprite = new SmartSprite(gameTextTexture, renderer); - n2500Sprite = new SmartSprite(gameTextTexture, renderer); - n5000Sprite = new SmartSprite(gameTextTexture, renderer); - - gameOverSprite = new Sprite(16, 80, 128, 96, gameOverTexture, renderer); - gameOverEndSprite = new Sprite(PLAY_AREA_CENTER_X - gameOverEndTexture->getWidth() / 2, 80, 128, 96, gameOverEndTexture, renderer); + n1000Sprite = new SmartSprite(gameTextTexture); + n2500Sprite = new SmartSprite(gameTextTexture); + n5000Sprite = new SmartSprite(gameTextTexture); canvas = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, playArea.w, playArea.h); SDL_SetTextureBlendMode(canvas, SDL_BLENDMODE_BLEND); @@ -74,130 +63,24 @@ Game::~Game() saveDemoFile(); #endif - if (!demo.enabled) - { - hiScoreEntry_t entry = {"Sergio", players[0]->getScore()}; - ManageHiScoreTable *m = new ManageHiScoreTable(&options->game.hiScoreTable); - m->add(entry); - delete m; - } - // Elimina todos los objetos contenidos en vectores deleteAllVectorObjects(); - bulletTexture->unload(); - delete bulletTexture; - - gameTextTexture->unload(); - delete gameTextTexture; - - gameOverTexture->unload(); - delete gameOverTexture; - - gameOverEndTexture->unload(); - delete gameOverEndTexture; - - // Animaciones - for (auto animation : playerAnimations) - { - if (animation) - { - delete animation; - } - } - playerAnimations.clear(); - - for (auto animation : balloonAnimations) - { - if (animation) - { - delete animation; - } - } - balloonAnimations.clear(); - - for (auto animation : itemAnimations) - { - if (animation) - { - delete animation; - } - } - itemAnimations.clear(); - - // Texturas - for (auto texture : player1Textures) - { - if (texture) - { - texture->unload(); - delete texture; - } - } - player1Textures.clear(); - - for (auto texture : player2Textures) - { - if (texture) - { - texture->unload(); - delete texture; - } - } - player2Textures.clear(); - - for (auto texture : itemTextures) - { - if (texture) - { - texture->unload(); - delete texture; - } - } - itemTextures.clear(); - - for (auto texture : balloonTextures) - { - if (texture) - { - texture->unload(); - delete texture; - } - } - balloonTextures.clear(); + // Libera los recursos + unloadMedia(); delete scoreboard; delete background; + delete explosions; - delete text; - delete textBig; - delete textNokia2; - delete textNokiaBig2; delete fade; delete eventHandler; + delete n1000Sprite; delete n2500Sprite; delete n5000Sprite; - delete gameOverSprite; - delete gameOverEndSprite; SDL_DestroyTexture(canvas); - - JA_DeleteSound(balloonSound); - JA_DeleteSound(bulletSound); - JA_DeleteSound(playerCollisionSound); - JA_DeleteSound(hiScoreSound); - JA_DeleteSound(itemDropSound); - JA_DeleteSound(itemPickUpSound); - JA_DeleteSound(coffeeOutSound); - JA_DeleteSound(stageChangeSound); - JA_DeleteSound(bubble1Sound); - JA_DeleteSound(bubble2Sound); - JA_DeleteSound(bubble3Sound); - JA_DeleteSound(bubble4Sound); - JA_DeleteSound(clockSound); - JA_DeleteSound(powerBallSound); - JA_DeleteSound(coffeeMachineSound); } // Inicializa las variables necesarias para la sección 'Game' @@ -217,10 +100,10 @@ void Game::init(int playerID) players.clear(); // Crea los dos jugadores - Player *player1 = new Player((PLAY_AREA_CENTER_FIRST_QUARTER_X * ((0 * 2) + 1)) - 11, PLAY_AREA_BOTTOM - 30, renderer, playerTextures[0], playerAnimations); + Player *player1 = new Player((PLAY_AREA_CENTER_FIRST_QUARTER_X * ((0 * 2) + 1)) - 11, PLAY_AREA_BOTTOM - 30, playerTextures[0], playerAnimations); players.push_back(player1); - Player *player2 = new Player((PLAY_AREA_CENTER_FIRST_QUARTER_X * ((1 * 2) + 1)) - 11, PLAY_AREA_BOTTOM - 30, renderer, playerTextures[1], playerAnimations); + Player *player2 = new Player((PLAY_AREA_CENTER_FIRST_QUARTER_X * ((1 * 2) + 1)) - 11, PLAY_AREA_BOTTOM - 30, playerTextures[1], playerAnimations); players.push_back(player2); // Habilita el jugador seleccionado. playerID es player 1 o player 2 @@ -432,6 +315,15 @@ void Game::loadMedia() << "** LOADING RESOURCES FOR GAME SECTION" << std::endl; } + playerAnimations.clear(); + balloonAnimations.clear(); + itemAnimations.clear(); + player1Textures.clear(); + player2Textures.clear(); + itemTextures.clear(); + balloonTextures.clear(); + explosionsTextures.clear(); + // Texturas bulletTexture = new Texture(renderer, asset->get("bullet.png")); gameTextTexture = new Texture(renderer, asset->get("game_text.png")); @@ -439,18 +331,43 @@ void Game::loadMedia() gameOverEndTexture = new Texture(renderer, asset->get("menu_game_over_end.png")); // Texturas - Globos - Texture *balloon1Texture = new Texture(renderer, asset->get("balloon1.png")); + Texture *balloon1Texture = new Texture(renderer, asset->get("balloon1.gif")); + balloon1Texture->addPalette(asset->get("balloon_blue_pal.gif")); + balloon1Texture->addPalette(asset->get("balloon_yellow_pal.gif")); + balloon1Texture->addPalette(asset->get("balloon_green_pal.gif")); balloonTextures.push_back(balloon1Texture); - Texture *balloon2Texture = new Texture(renderer, asset->get("balloon2.png")); + Texture *balloon2Texture = new Texture(renderer, asset->get("balloon2.gif")); + balloon2Texture->addPalette(asset->get("balloon_blue_pal.gif")); + balloon2Texture->addPalette(asset->get("balloon_yellow_pal.gif")); + balloon2Texture->addPalette(asset->get("balloon_green_pal.gif")); balloonTextures.push_back(balloon2Texture); - Texture *balloon3Texture = new Texture(renderer, asset->get("balloon3.png")); + Texture *balloon3Texture = new Texture(renderer, asset->get("balloon3.gif")); + balloon3Texture->addPalette(asset->get("balloon_blue_pal.gif")); + balloon3Texture->addPalette(asset->get("balloon_yellow_pal.gif")); + balloon3Texture->addPalette(asset->get("balloon_green_pal.gif")); balloonTextures.push_back(balloon3Texture); - Texture *balloon4Texture = new Texture(renderer, asset->get("balloon4.png")); + Texture *balloon4Texture = new Texture(renderer, asset->get("balloon4.gif")); + balloon4Texture->addPalette(asset->get("balloon_blue_pal.gif")); + balloon4Texture->addPalette(asset->get("balloon_yellow_pal.gif")); + balloon4Texture->addPalette(asset->get("balloon_green_pal.gif")); balloonTextures.push_back(balloon4Texture); + // Texturas - Explosiones + Texture *explosion1Texture = new Texture(renderer, asset->get("balloon1_explosion.png")); + explosionsTextures.push_back(explosion1Texture); + + Texture *explosion2Texture = new Texture(renderer, asset->get("balloon1_explosion.png")); + explosionsTextures.push_back(explosion2Texture); + + Texture *explosion3Texture = new Texture(renderer, asset->get("balloon1_explosion.png")); + explosionsTextures.push_back(explosion3Texture); + + Texture *explosion4Texture = new Texture(renderer, asset->get("balloon1_explosion.png")); + explosionsTextures.push_back(explosion4Texture); + // Texturas - Items Texture *item1 = new Texture(renderer, asset->get("item_points1_disk.png")); itemTextures.push_back(item1); @@ -520,6 +437,23 @@ void Game::loadMedia() loadAnimations(asset->get("balloon4.ani"), balloon4Animation); balloonAnimations.push_back(balloon4Animation); + // Animaciones -- Explosiones + std::vector *explosions1Animation = new std::vector; + loadAnimations(asset->get("balloon1_explosion.ani"), explosions1Animation); + explosionsAnimations.push_back(explosions1Animation); + + std::vector *explosions2Animation = new std::vector; + loadAnimations(asset->get("balloon2_explosion.ani"), explosions2Animation); + explosionsAnimations.push_back(explosions2Animation); + + std::vector *explosions3Animation = new std::vector; + loadAnimations(asset->get("balloon3_explosion.ani"), explosions3Animation); + explosionsAnimations.push_back(explosions3Animation); + + std::vector *explosions4Animation = new std::vector; + loadAnimations(asset->get("balloon4_explosion.ani"), explosions4Animation); + explosionsAnimations.push_back(explosions4Animation); + // Animaciones -- Items std::vector *item1Animation = new std::vector; loadAnimations(asset->get("item_points1_disk.ani"), item1Animation); @@ -575,6 +509,121 @@ void Game::loadMedia() } } +// Libera los recursos previamente cargados +void Game::unloadMedia() +{ + // Texturas + delete bulletTexture; + delete gameTextTexture; + delete gameOverTexture; + delete gameOverEndTexture; + + for (auto texture : player1Textures) + { + if (texture) + { + delete texture; + } + } + player1Textures.clear(); + + for (auto texture : player2Textures) + { + if (texture) + { + delete texture; + } + } + player2Textures.clear(); + + for (auto texture : itemTextures) + { + if (texture) + { + delete texture; + } + } + itemTextures.clear(); + + for (auto texture : balloonTextures) + { + if (texture) + { + delete texture; + } + } + balloonTextures.clear(); + + for (auto texture : explosionsTextures) + { + if (texture) + { + delete texture; + } + } + explosionsTextures.clear(); + + // Animaciones + for (auto animation : playerAnimations) + { + if (animation) + { + delete animation; + } + } + playerAnimations.clear(); + + for (auto animation : balloonAnimations) + { + if (animation) + { + delete animation; + } + } + balloonAnimations.clear(); + + for (auto animation : explosionsAnimations) + { + if (animation) + { + delete animation; + } + } + explosionsAnimations.clear(); + + for (auto animation : itemAnimations) + { + if (animation) + { + delete animation; + } + } + itemAnimations.clear(); + + // Text + delete text; + delete textBig; + delete textNokia2; + delete textNokiaBig2; + + // Sonidos + JA_DeleteSound(balloonSound); + JA_DeleteSound(bulletSound); + JA_DeleteSound(playerCollisionSound); + JA_DeleteSound(hiScoreSound); + JA_DeleteSound(itemDropSound); + JA_DeleteSound(itemPickUpSound); + JA_DeleteSound(coffeeOutSound); + JA_DeleteSound(stageChangeSound); + JA_DeleteSound(bubble1Sound); + JA_DeleteSound(bubble2Sound); + JA_DeleteSound(bubble3Sound); + JA_DeleteSound(bubble4Sound); + JA_DeleteSound(clockSound); + JA_DeleteSound(powerBallSound); + JA_DeleteSound(coffeeMachineSound); +} + // Carga el fichero de puntos bool Game::loadScoreFile() { @@ -733,6 +782,10 @@ bool Game::loadDemoFile(std::string f, demoKeys_t (*dataFile)[TOTAL_DEMO_DATA]) // Guarda el fichero de puntos bool Game::saveScoreFile() { + // Almacena la máxima puntuación en el fichero junto con un checksum + scoreDataFile[0] = hiScore; + scoreDataFile[1] = hiScore % 43; + bool success = true; const std::string p = asset->get("score.bin"); const std::string filename = p.substr(p.find_last_of("\\/") + 1); @@ -1564,12 +1617,6 @@ void Game::increaseStageCurrentPower(int power) stage[currentStage].currentPower += power; } -// Establece el valor de la variable -void Game::setHiScore(Uint32 score) -{ - hiScore = score; -} - // Actualiza el valor de hiScore en caso necesario void Game::updateHiScore() { @@ -1580,10 +1627,6 @@ void Game::updateHiScore() // Actualiza la máxima puntuación hiScore = player->getScore(); - // Almacena la máxima puntuación en el fichero junto con un checksum - scoreDataFile[0] = hiScore; - scoreDataFile[1] = hiScore % 43; - // Si se supera la máxima puntuación emite sonido if (hiScoreAchieved == false) { @@ -1932,38 +1975,32 @@ void Game::popBalloon(Balloon *balloon) evaluateAndSetMenace(); } -// Explosiona un globo. Lo destruye +// Explosiona un globo. Lo destruye = no crea otros globos void Game::destroyBalloon(Balloon *balloon) { int score = 0; - int power = 0; // Calcula la puntuación y el poder que generaria el globo en caso de romperlo a él y a sus hijos switch (balloon->getSize()) { case BALLOON_SIZE_4: score = BALLOON_SCORE_4 + (2 * BALLOON_SCORE_3) + (4 * BALLOON_SCORE_2) + (8 * BALLOON_SCORE_1); - power = 15; break; case BALLOON_SIZE_3: score = BALLOON_SCORE_3 + (2 * BALLOON_SCORE_2) + (4 * BALLOON_SCORE_1); - power = 7; break; case BALLOON_SIZE_2: score = BALLOON_SCORE_2 + (2 * BALLOON_SCORE_1); - power = 3; break; case BALLOON_SIZE_1: score = BALLOON_SCORE_1; - power = 1; break; default: score = 0; - power = 0; break; } @@ -1975,6 +2012,7 @@ void Game::destroyBalloon(Balloon *balloon) updateHiScore(); // Aumenta el poder de la fase + const int power = balloon->getPower(); increaseStageCurrentPower(power); balloonsPopped += power; @@ -1990,7 +2028,7 @@ void Game::popAllBalloons() { for (auto balloon : balloons) { - if ((balloon->isEnabled()) && (!balloon->isPopping()) && (!balloon->isBeingCreated())) + if (balloon->canBePopped()) { popBalloon(balloon); } @@ -2004,7 +2042,7 @@ void Game::destroyAllBalloons() { for (auto balloon : balloons) { - if ((balloon->isEnabled()) && (!balloon->isPopping())) + if (balloon->canBeDestroyed()) { destroyBalloon(balloon); } @@ -2061,7 +2099,7 @@ int Game::countBalloons() return num; } -// Vacia el vector de globos +// Vacia del vector de globos los globos que ya no sirven void Game::freeBalloons() { if (balloons.empty() == false) @@ -2243,7 +2281,7 @@ void Game::renderBullets() // Crea un objeto bala void Game::createBullet(int x, int y, int kind, bool poweredUp, int owner) { - Bullet *b = new Bullet(x, y, kind, poweredUp, owner, bulletTexture, renderer); + Bullet *b = new Bullet(x, y, kind, poweredUp, owner, bulletTexture); bullets.push_back(b); } @@ -2368,7 +2406,7 @@ int Game::dropItem() // Crea un objeto item void Game::createItem(int kind, float x, float y) { - Item *item = new Item(kind, x, y, itemTextures[kind - 1], itemAnimations[kind - 1], renderer); + Item *item = new Item(kind, x, y, itemTextures[kind - 1], itemAnimations[kind - 1]); items.push_back(item); } @@ -2391,7 +2429,7 @@ void Game::freeItems() // Crea un objeto SmartSprite para mostrar la puntuación al coger un objeto void Game::createItemScoreSprite(int x, int y, SmartSprite *sprite) { - SmartSprite *ss = new SmartSprite(nullptr, renderer); + SmartSprite *ss = new SmartSprite(nullptr); smartSprites.push_back(ss); // Crea una copia del objeto @@ -2423,7 +2461,7 @@ void Game::freeSmartSprites() // Crea un SmartSprite para arrojar el item café al recibir un impacto void Game::throwCoffee(int x, int y) { - SmartSprite *ss = new SmartSprite(itemTextures[4], renderer); + SmartSprite *ss = new SmartSprite(itemTextures[4]); smartSprites.push_back(ss); ss->setPosX(x - 8); @@ -2487,6 +2525,10 @@ void Game::killPlayer(Player *player) JA_PlaySound(coffeeOutSound); player->setAlive(false); allPlayersAreDead() ? JA_StopMusic() : JA_ResumeMusic(); + if (!demo.enabled) + { + addScoreToScoreBoard("Sergio", player->getScore()); + } } } @@ -2638,6 +2680,8 @@ void Game::update() // Mueve los globos updateBalloons(); + explosions->update(); + // Mueve las balas moveBullets(); @@ -2731,6 +2775,7 @@ void Game::fillCanvas() background->render(); renderItems(); renderSmartSprites(); + explosions->render(); renderBalloons(); renderBullets(); renderMessages(); @@ -2783,7 +2828,7 @@ void Game::updateMenace() if (menaceCurrent < menaceThreshold) { // Crea una formación de enemigos - deployEnemyFormation(); + // deployEnemyFormation(); // Recalcula el nivel de amenaza con el nuevo globo evaluateAndSetMenace(); @@ -3397,7 +3442,7 @@ void Game::reloadTextures() background->reloadTextures(); } -// Establece la máxima puntuación desde fichero o desde las puntuaciones online +// Carga las puntuaciones desde el fichero y establece la máxima puntuación void Game::setHiScore() { // Carga el fichero de puntos @@ -3432,4 +3477,13 @@ void Game::pause(bool value) { paused = value; screen->attenuate(paused); +} + +// Añade una puntuación a la tabla de records +void Game::addScoreToScoreBoard(std::string name, int score) +{ + hiScoreEntry_t entry = {name, score}; + ManageHiScoreTable *m = new ManageHiScoreTable(&options->game.hiScoreTable); + m->add(entry); + delete m; } \ No newline at end of file diff --git a/source/game.h b/source/game.h index 043d975..dbb3191 100644 --- a/source/game.h +++ b/source/game.h @@ -20,6 +20,7 @@ #include "background.h" #include "lang.h" #include "manage_hiscore_table.h" +#include "explosions.h" #include // Cantidad de elementos a escribir en los ficheros de datos @@ -114,6 +115,7 @@ private: section_t *section; // Seccion actual dentro del juego Scoreboard *scoreboard; // Objeto para dibujar el marcador Background *background; // Objeto para dibujar el fondo del juego + Explosions *explosions; // Objeto para dibujar explosiones SDL_Texture *canvas; // Textura para dibujar la zona de juego std::vector players; // Vector con los jugadores @@ -125,6 +127,7 @@ private: Texture *bulletTexture; // Textura para las balas std::vector itemTextures; // Vector con las texturas de los items std::vector balloonTextures; // Vector con las texturas de los globos + std::vector explosionsTextures; // Vector con las texturas de las explosiones std::vector player1Textures; // Vector con las texturas del jugador std::vector player2Textures; // Vector con las texturas del jugador std::vector> playerTextures; // Vector con todas las texturas de los jugadores; @@ -133,9 +136,10 @@ private: Texture *gameOverTexture; // Textura para la pantalla de game over Texture *gameOverEndTexture; // Textura para la pantalla de game over de acabar el juego - std::vector *> itemAnimations; // Vector con las animaciones de los items - std::vector *> playerAnimations; // Vector con las animaciones del jugador - std::vector *> balloonAnimations; // Vector con las animaciones de los globos + std::vector *> itemAnimations; // Vector con las animaciones de los items + std::vector *> playerAnimations; // Vector con las animaciones del jugador + std::vector *> balloonAnimations; // Vector con las animaciones de los globos + std::vector *> explosionsAnimations; // Vector con las animaciones de las explosiones Text *text; // Fuente para los textos del juego Text *textBig; // Fuente de texto grande @@ -149,9 +153,6 @@ private: SmartSprite *n2500Sprite; // Sprite con el texto 2.500 SmartSprite *n5000Sprite; // Sprite con el texto 5.000 - Sprite *gameOverSprite; // Sprite para dibujar los graficos del game over - Sprite *gameOverEndSprite; // Sprite para dibujar los graficos del game over de acabar el juego - JA_Sound_t *balloonSound; // Sonido para la explosión del globo JA_Sound_t *bulletSound; // Sonido para los disparos JA_Sound_t *playerCollisionSound; // Sonido para la colisión del jugador con un enemigo @@ -226,6 +227,9 @@ private: // Carga los recursos necesarios para la sección 'Game' void loadMedia(); + // Libera los recursos previamente cargados + void unloadMedia(); + // Carga el fichero de puntos bool loadScoreFile(); @@ -253,9 +257,6 @@ private: // Aumenta el poder de la fase void increaseStageCurrentPower(int power); - // Establece el valor de la variable - void setHiScore(Uint32 score); - // Actualiza el valor de HiScore en caso necesario void updateHiScore(); @@ -448,7 +449,7 @@ private: // Recarga las texturas void reloadTextures(); - // Establece la máxima puntuación desde fichero o desde las puntuaciones online + // Carga las puntuaciones desde el fichero y establece la máxima puntuación void setHiScore(); // Actualiza el marcador @@ -466,6 +467,9 @@ private: // Comprueba si la música ha de estar sonando void checkMusicStatus(); + // Añade una puntuación a la tabla de records + void addScoreToScoreBoard(std::string name, int score); + public: // Constructor Game(int playerID, int currentStage, SDL_Renderer *renderer, Screen *screen, Asset *asset, Lang *lang, Input *input, bool demo, param_t *param, options_t *options, section_t *section, JA_Music_t *music); diff --git a/source/game_logo.cpp b/source/game_logo.cpp index 3244b96..47f9df0 100644 --- a/source/game_logo.cpp +++ b/source/game_logo.cpp @@ -17,11 +17,11 @@ GameLogo::GameLogo(SDL_Renderer *renderer, Screen *screen, Asset *asset, param_t crisisTexture = new Texture(renderer, asset->get("title_crisis.png")); arcadeEditionTexture = new Texture(renderer, asset->get("title_arcade_edition.png")); - coffeeBitmap = new SmartSprite(coffeeTexture, renderer); - crisisBitmap = new SmartSprite(crisisTexture, renderer); - arcadeEditionBitmap = new Sprite((param->gameWidth - arcadeEditionTexture->getWidth()) / 2, param->arcadeEdition, arcadeEditionTexture->getWidth(), arcadeEditionTexture->getHeight(), arcadeEditionTexture, renderer); - dustBitmapL = new AnimatedSprite(dustTexture, renderer, asset->get("title_dust.ani")); - dustBitmapR = new AnimatedSprite(dustTexture, renderer, asset->get("title_dust.ani")); + coffeeBitmap = new SmartSprite(coffeeTexture); + crisisBitmap = new SmartSprite(crisisTexture); + arcadeEditionBitmap = new Sprite((param->gameWidth - arcadeEditionTexture->getWidth()) / 2, param->arcadeEdition, arcadeEditionTexture->getWidth(), arcadeEditionTexture->getHeight(), arcadeEditionTexture); + dustBitmapL = new AnimatedSprite(dustTexture, asset->get("title_dust.ani")); + dustBitmapR = new AnimatedSprite(dustTexture, asset->get("title_dust.ani")); // Sonidos crashSound = JA_LoadSound(asset->get("title.wav").c_str()); diff --git a/source/instructions.cpp b/source/instructions.cpp index 4ec962d..9f24e31 100644 --- a/source/instructions.cpp +++ b/source/instructions.cpp @@ -98,8 +98,8 @@ void Instructions::iniSprites() // Inicializa los sprites for (int i = 0; i < (int)itemTextures.size(); ++i) { - Sprite *sprite = new Sprite(0, 0, param->itemSize, param->itemSize, itemTextures[i], renderer); - sprite->setPos({spritePos.x, spritePos.y + ((param->itemSize + itemSpace) * i), param->itemSize, param->itemSize}); + Sprite *sprite = new Sprite(0, 0, param->itemSize, param->itemSize, itemTextures[i]); + sprite->setPos({spritePos.x, spritePos.y + ((param->itemSize + itemSpace) * i)}); sprites.push_back(sprite); } } diff --git a/source/intro.cpp b/source/intro.cpp index a996068..cc3d959 100644 --- a/source/intro.cpp +++ b/source/intro.cpp @@ -29,7 +29,7 @@ Intro::Intro(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input, const int totalBitmaps = 6; for (int i = 0; i < totalBitmaps; ++i) { - SmartSprite *ss = new SmartSprite(texture, renderer); + SmartSprite *ss = new SmartSprite(texture); ss->setWidth(128); ss->setHeight(96); ss->setEnabledCounter(20); diff --git a/source/item.cpp b/source/item.cpp index 834837d..8e3329e 100644 --- a/source/item.cpp +++ b/source/item.cpp @@ -2,9 +2,9 @@ #include "item.h" // Constructor -Item::Item(int kind, float x, float y, Texture *texture, std::vector *animation, SDL_Renderer *renderer) +Item::Item(int kind, float x, float y, Texture *texture, std::vector *animation) { - sprite = new AnimatedSprite(texture, renderer, "", animation); + sprite = new AnimatedSprite(texture, "", animation); this->kind = kind; enabled = true; diff --git a/source/item.h b/source/item.h index e8704e2..e77b296 100644 --- a/source/item.h +++ b/source/item.h @@ -43,7 +43,7 @@ public: Uint16 timeToLive; // Temporizador con el tiempo que el objeto está presente // Constructor - Item(int kind, float x, float y, Texture *texture, std::vector *animation, SDL_Renderer *renderer); + Item(int kind, float x, float y, Texture *texture, std::vector *animation); // Destructor ~Item(); diff --git a/source/logo.cpp b/source/logo.cpp index 3ceb412..5ea6633 100644 --- a/source/logo.cpp +++ b/source/logo.cpp @@ -16,7 +16,7 @@ Logo::Logo(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input, p eventHandler = new SDL_Event(); jailTexture = new Texture(renderer, asset->get("logo_jailgames.png")); sinceTexture = new Texture(renderer, asset->get("logo_since_1998.png")); - sinceSprite = new Sprite((param->gameWidth - sinceTexture->getWidth()) / 2, 83 + jailTexture->getHeight() + 5, sinceTexture->getWidth(), sinceTexture->getHeight(), sinceTexture, renderer); + sinceSprite = new Sprite((param->gameWidth - sinceTexture->getWidth()) / 2, 83 + jailTexture->getHeight() + 5, sinceTexture->getWidth(), sinceTexture->getHeight(), sinceTexture); sinceSprite->setSpriteClip(0, 0, sinceTexture->getWidth(), sinceTexture->getHeight()); sinceTexture->setColor(0, 0, 0); @@ -36,7 +36,7 @@ Logo::Logo(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input, p // Crea los sprites de cada linea for (int i = 0; i < jailTexture->getHeight(); ++i) { - Sprite *temp = new Sprite(0, i, jailTexture->getWidth(), 1, jailTexture, renderer); + Sprite *temp = new Sprite(0, i, jailTexture->getWidth(), 1, jailTexture); temp->setSpriteClip(0, i, jailTexture->getWidth(), 1); const int posX = (i % 2 == 0) ? param->gameWidth + (i * 3) : -jailTexture->getWidth() - (i * 3); temp->setPosX(posX); diff --git a/source/player.cpp b/source/player.cpp index 0fac4dc..043b2d3 100644 --- a/source/player.cpp +++ b/source/player.cpp @@ -2,14 +2,11 @@ #include "player.h" // Constructor -Player::Player(float x, int y, SDL_Renderer *renderer, std::vector texture, std::vector *> animations) +Player::Player(float x, int y, std::vector texture, std::vector *> animations) { - // Copia los punteros - this->renderer = renderer; - // Reserva memoria para los objetos - playerSprite = new AnimatedSprite(texture[0], renderer, "", animations[0]); - powerSprite = new AnimatedSprite(texture[1], renderer, "", animations[1]); + playerSprite = new AnimatedSprite(texture[0], "", animations[0]); + powerSprite = new AnimatedSprite(texture[1], "", animations[1]); powerSprite->getTexture()->setAlpha(224); // Establece la posición inicial del jugador diff --git a/source/player.h b/source/player.h index 497b04f..93c2230 100644 --- a/source/player.h +++ b/source/player.h @@ -26,7 +26,6 @@ class Player { private: // Objetos y punteros - SDL_Renderer *renderer; // El renderizador de la ventana AnimatedSprite *playerSprite; // Sprite para dibujar el jugador AnimatedSprite *powerSprite; // Sprite para dibujar el aura del jugador con el poder a tope @@ -72,7 +71,7 @@ private: public: // Constructor - Player(float x, int y, SDL_Renderer *renderer, std::vector texture, std::vector *> animations); + Player(float x, int y, std::vector texture, std::vector *> animations); // Destructor ~Player(); diff --git a/source/scoreboard.cpp b/source/scoreboard.cpp index 29a6cfa..21ea5df 100644 --- a/source/scoreboard.cpp +++ b/source/scoreboard.cpp @@ -31,7 +31,7 @@ Scoreboard::Scoreboard(SDL_Renderer *renderer, Screen *screen, Asset *asset, Lan // Crea objetos gamePowerMeterTexture = new Texture(renderer, asset->get("game_power_meter.png")); - powerMeterSprite = new Sprite(offsetPowerMeter.x - 20, offsetPowerMeter.y, 40, 7, gamePowerMeterTexture, renderer); + powerMeterSprite = new Sprite(offsetPowerMeter.x - 20, offsetPowerMeter.y, 40, 7, gamePowerMeterTexture); textScoreBoard = new Text(asset->get("8bithud.png"), asset->get("8bithud.txt"), renderer); // Crea la textura para dibujar el marcador diff --git a/source/tiledbg.cpp b/source/tiledbg.cpp index cf32853..3265038 100644 --- a/source/tiledbg.cpp +++ b/source/tiledbg.cpp @@ -56,7 +56,7 @@ void Tiledbg::fillTexture() { // Crea los objetos para pintar en la textura de fondo Texture *bgTileTexture = new Texture(renderer, asset->get("title_bg_tile.png")); - Sprite *tile = new Sprite({0, 0, tileWidth, tileHeight}, bgTileTexture, renderer); + Sprite *tile = new Sprite({0, 0, tileWidth, tileHeight}, bgTileTexture); // Prepara para dibujar sobre la textura SDL_Texture *temp = SDL_GetRenderTarget(renderer); diff --git a/source/title.cpp b/source/title.cpp index ab58b06..917e821 100644 --- a/source/title.cpp +++ b/source/title.cpp @@ -24,14 +24,14 @@ Title::Title(SDL_Renderer *renderer, Screen *screen, Input *input, Asset *asset, text2 = new Text(asset->get("8bithud.png"), asset->get("8bithud.txt"), renderer); miniLogoTexture = new Texture(renderer, asset->get("logo_jailgames_mini.png")); - miniLogoSprite = new Sprite(GAMECANVAS_CENTER_X - miniLogoTexture->getWidth() / 2, 0, miniLogoTexture->getWidth(), miniLogoTexture->getHeight(), miniLogoTexture, renderer); + miniLogoSprite = new Sprite(GAMECANVAS_CENTER_X - miniLogoTexture->getWidth() / 2, 0, miniLogoTexture->getWidth(), miniLogoTexture->getHeight(), miniLogoTexture); tiledbg = new Tiledbg(renderer, screen, asset, {0, 0, param->gameWidth, param->gameHeight}, TILED_MODE_RANDOM); gameLogo = new GameLogo(renderer, screen, asset, param, GAMECANVAS_CENTER_X, param->titleCC); gameLogo->enable(); - defineButtons = new DefineButtons(renderer, input, text2, param, options, section); + defineButtons = new DefineButtons(input, text2, param, options, section); // Inicializa los valores init();