From 24c8c3fe2c58d4c4db5d9aed830862f1702146b4 Mon Sep 17 00:00:00 2001 From: Rene Kievits Date: Mon, 14 Oct 2024 22:45:46 +0200 Subject: [PATCH] finish title screen, fix game logic, add textures, somehow forgot the T tetromino lol --- CMakeLists.txt | 2 +- assets/BORDER.png | Bin 0 -> 236 bytes assets/I.png | Bin 622 -> 0 bytes assets/I_END.png | Bin 0 -> 240 bytes assets/I_ENDR.png | Bin 0 -> 223 bytes assets/I_MID.png | Bin 0 -> 242 bytes assets/I_MIDR.png | Bin 0 -> 231 bytes assets/I_START.png | Bin 0 -> 246 bytes assets/I_STARTR.png | Bin 0 -> 231 bytes assets/J.png | Bin 4610 -> 225 bytes assets/L.png | Bin 630 -> 205 bytes assets/O.png | Bin 580 -> 210 bytes assets/S.png | Bin 581 -> 223 bytes assets/T.png | Bin 0 -> 224 bytes assets/Z.png | Bin 4627 -> 210 bytes assets/tetris-gb.ttf | Bin 0 -> 18640 bytes assets/title.png | Bin 0 -> 9290 bytes assets/title_bg.png | Bin 0 -> 12133 bytes src/Game.cpp | 32 +++++- src/Game.hpp | 2 + src/GameBoard.cpp | 82 +++++++++++--- src/Renderer.cpp | 263 +++++++++++++++++++++++++++++++++++++------ src/Renderer.hpp | 45 +++++++- src/Tetromino.cpp | 40 +++++-- src/Tetromino.hpp | 12 +- 25 files changed, 399 insertions(+), 79 deletions(-) create mode 100644 assets/BORDER.png delete mode 100644 assets/I.png create mode 100644 assets/I_END.png create mode 100644 assets/I_ENDR.png create mode 100644 assets/I_MID.png create mode 100644 assets/I_MIDR.png create mode 100644 assets/I_START.png create mode 100644 assets/I_STARTR.png create mode 100644 assets/T.png create mode 100644 assets/tetris-gb.ttf create mode 100644 assets/title.png create mode 100644 assets/title_bg.png diff --git a/CMakeLists.txt b/CMakeLists.txt index c3c527a..0cfc851 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,7 +30,7 @@ target_link_libraries(SDL_TD ) file(GLOB ASSETS - "assets/*.png" + "assets/*" ) foreach(ASSET ${ASSETS}) diff --git a/assets/BORDER.png b/assets/BORDER.png new file mode 100644 index 0000000000000000000000000000000000000000..f9a11c3e8333c268bc0d44f3f6818207fb1734a1 GIT binary patch literal 236 zcmV^{*YRm zrFo{b3Mi(5{FN!+1&JU;EP65zy$zxe95si7mvSEeHr~TqH&b4?_MP8tCHgR>jC8j! zN6n0RT4?>pw*&G3)AZOxQ^!T!-(39B)dvaOqDX1Y7AN=XVr(0#H%rc(hg%K*qPK4I m^rF;?iTHKO>~Gid)PWBw(rpWxv}g_h0000|3`PTVX+lufJBZk&RdP?5>wI;llE?otlv2!OikNT(k?426{n_N#rknLXn zf3Im(xyPWur0lzdvTfFSmvcYly6!b3*c7e1%s81q!SD_infVH@Seu0P6o4TyuD6?x zzyaNRmHX|$OF5GqhuaN?ehoQK zB@=MpGpf=6%|o-ZKqx5MyP8&bleX zpU8SJC@b9R0Z@R07*qo IM6N<$f?5R@w*UYD diff --git a/assets/I_END.png b/assets/I_END.png new file mode 100644 index 0000000000000000000000000000000000000000..d73ca8aae554645bcd077d7e85f35344a54b917e GIT binary patch literal 240 zcmV);K03c+i!EknuEp~YxQ8LDkL5>UXl#!|4A=Xagr!CTU&GEV&5Gq2&Fx>Me+ zqXh*SG7;aq{RA%9{bP0l+XkKSnyPZ literal 0 HcmV?d00001 diff --git a/assets/I_MID.png b/assets/I_MID.png new file mode 100644 index 0000000000000000000000000000000000000000..69083054fafd3b5c0dc6ff822a0aceb768369494 GIT binary patch literal 242 zcmV+X7?K>PlocFFQLQ5Nyw$mZOx2LqmdlO!dzm)%&Fg-a}` snhF!0kEs{jOnDJQR>QTS>8fe?2bC*X9llksxBvhE07*qoM6N<$f&+qO+yDRo literal 0 HcmV?d00001 diff --git a/assets/I_MIDR.png b/assets/I_MIDR.png new file mode 100644 index 0000000000000000000000000000000000000000..593e853eada3f5913e2a137449cd8f1503187a52 GIT binary patch literal 231 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqoCO|{#S9F5M?jcysy3fAP;jQF zi(`nyRNX@da}OH`xLmZ~o#!j$`aMD6uH??yi>BP#^4ME$-ju|5hZtWjsS$2q^{}an z)8DqXI8OcbwI9~@I%_AVPPq8{doF`aOE0UE#PO7TZpKcIXNHANH#!z=ZBuz9B^>ys z)>Sp{!45UW#RePg!o55dj@g`S*jDo7(T_PU({>(PB4hKL&F`3vM#6h*r9!DwPBZ>1 cY&ar*B-O`O;ppbOKu0ooy85}Sb4q9e0EvfJl>h($ literal 0 HcmV?d00001 diff --git a/assets/I_START.png b/assets/I_START.png new file mode 100644 index 0000000000000000000000000000000000000000..7d247a218e0604ae9779f52171ed82643c90aa68 GIT binary patch literal 246 zcmVWpOK@ wDJn@+NzJJ{DZ)%t$BOWOasn@z?9y`K0sUA}C9de$c>n+a07*qoM6N<$f(spMiU0rr literal 0 HcmV?d00001 diff --git a/assets/I_STARTR.png b/assets/I_STARTR.png new file mode 100644 index 0000000000000000000000000000000000000000..0e6a956f22ac5195cc0a63c00cfbc9b9fee0bba6 GIT binary patch literal 231 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqoCO|{#S9F5M?jcysy3fAP;jQF zi(`nyRMm5aWz7x(E(h-$@4Ds1{iLq!h^C;n#ce<9fRId0qqm%4jV`~mJ61i~_})6Z zKCrF8;9c{zaHh|nf4hI#moU?iEg|Z50B7>1E)M6=O?uo3Ocv*v!-FQe+>DtoJYC{@ zYs$8@&1&;Lbcme(%-VEMDk5RWIqAehtj0}+dmT>}?qA7ORsTr9t5v;qj*G}qa|w>y af0*yug$nSVcrF2SB!j1`pUXO@geCxeo>UJ2 literal 0 HcmV?d00001 diff --git a/assets/J.png b/assets/J.png index 70aa092b7a884dff100eb8b5866c2ae2fc724535..ff192615d400dcf1121fb7c6bfe5e7158be38a6e 100644 GIT binary patch literal 225 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqD?D8sLnOj&`y=@dEAY4+cMH98 zZ@t5$&#kJq3A6fd$VRPH(Am>F-&IiNm4I=Kl)#Y#`p!*-8Aq$%7s&JR-rpd_VwmPJ z;lWn%CvyyD9cgK8x+Xm@v#n#r_FEIK^?bItv9{t)zDDZtNh=-h$Je@d2_FCbr_BGd z?AF|n*mfq#EZ4a7A`SN#2ZmGEB0i+w=RPgg&ebxsLQ0D#n3O#lD@ literal 4610 zcmeHKdr%w48JEBWP*6fK1cGsq9nWQ39i;#2NF2M zfEnA6G{nXZhLQqqT954zYWLxZc^J2TGl(+6u^HT??szCBX-R^?bnhfyZDu;m zH2sE>g{@A1tw0BrUX!aaGwVwvaaT#Z&ILL@R+B1ge^7*XId7?;UKhzys@ zaYPBw{LTfBSSHKqJE4H3o>r@M8ns&FaM{hYh2rtN?bZ8KdB4kuJOBNy*~w7dm}oS- z3%`|}9k)HIQMc~Tf^PiKD^o$**!_{wxo3YpGIG&)29p<2@%!9IkF`Ak~zIQ2J}OVKBxZJ6CTv>|0^AaN%F_w;OXzw>Fxe#5zl z=l1G!>Sv=q+WW_2&Bk@wN1;#8{^CK)?|=5z@vxjXgY;dQ6*D6{ANGFtIGl3pCBgGG zccL$T6%#mBQEMJ{4m7PjQW@}NNA1S`dp)T&xAOn=U@cU&D$EiXeRHk$R-nXF)0L=B zrHVeg9w`VKnR#O%Ik?_lJ6Ll3)MWaW_?octgQxjVJykm)rh0bt^`7ZHwe#w)9zEjk z&Tzfo()Mm8h(Rx{H!ue6%Q$JbN(htPNJ+d_2fJasv=_Y&g4|9qA|q8w+f?H5-ZNqm zZBmJgQnawvp{B~{yeb#9wQ7r=tlCauCh?2uf;2A<2&@!Ch`d&d&5e6iVvZLFHrp%} zi#Q0gT_rYvI8xhPlt>{_NMI=2OIIM`bb%<%WisQ1Svh_R@TL-%F^mJ3Ne}=3dWI_&BmCH|e4s3~jfGSWd!dFK1L@G3Xb~`Db-# zwe$2gw_gRIhtx|rq%sLCwOXZ%N4S~n3P9p_=xax~^_31vT1dI=91x7#$)TjV{nSe_efhtl=C_$1wZ%ibfV|Q5z zu${D(D5azhTPZgOD>$C1)2PIV#0TYCbQXd!g8?e>%e1ZBy8zYGR%$CluxiSb2#P9D z7*=9(3{j>ofVNRCH;6=*lgpi454$ZmSPT%BVB-`JaP43%xY|V#jNPTT+bt^beAb=s z)`H_?A{ZizU?@O3pNI8xd3Ym?;PAZexYll>&6WQP%^n_6ns3YVXg8R@l56svsI8RK z_vU-G(A-fHiMT_76QpkmZlZ!Raee|WUl&PUsmI57tRv@EPo zAQ=qFAkAE+|$tgsl zl}VPR?}}V2axF`NWr0_sYelYQDX=W?N_73-(;!z3yA`^=?+a+rXIcg zqXPx5^|@i{_-pBHP)ANwVq$Uk)sHjM(fwok-{j25ufO-h2wrAm^XHRQM>plw{5Ik* zhXv>R+7lkuJ@{ASfcOCK;e*MBs}ZaChj$BJ`k?feSpG==+4Fo)xS^^qO{?SA#s(OE zoTV%4$m>KR#fI?OkbjgpH;hiUA<26xej1!Pp>)nV?%ciG7S>eTH<%z0{4Jz}Xc#?u zTO4&WPnDlBGUc4e9dcp-Yg#hN-GBIkA?|5&b&qj)e&pEFR2q64Xs`Kj+F87 zE5n=Bp+V!pQ}F>qXAwctg`xg$4PGeQcBS)i)6Xx(9PQeRtH%q9`oh{@6VA$Jq>4`JL<&`_TPlv3by~Y!v7Gcam{iZA4>*3EH bpMEmWHe5iKypRuekEhArlJ)*~eo*&sx+P4( diff --git a/assets/L.png b/assets/L.png index 9edaaec12b682cf3a48e080ee31f42bc3d64ade7..aa94a9d474ba36d8be0e0dafbf60f1c33b7af78d 100644 GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqQ#@T9LnOjg`x*HTEATMOemXC@ ztGsl>+qp-rX9Tz$x#`E@S}1aIj*+wC%Vqtcey+=EY;K83B%WJz`@ocY$qGFsx$R7= zWu27IpNuW3wSI5?aHajihTZ(xdpr)jTparBFk{Y=o!4^Ttc;&f|{Ez(~3V`lo@O1TaS?83{ F1OVoaQRV;u literal 630 zcmV-+0*U>JP)q&Z1Wo%d~W7R{x~Qk~3p4s&J| z*D=}ay>apHk86CF##^6fIIH-N`CKp|EVix}0BzT$p$9r5@G47cGrxqTQt?&1D0N-}$rV`Mga?vQ;94{v-S?0;M*9Ab+`t&p0sW}Rx(BI3V zVS4@tg9ZjaMZ~P!Iabc5X|eZqp@H{J(#nuR9@rT-Z1@m(t4<=7axa@@v8~afQ2U4b zlmG*VhzgRhv^PA%!)g*LoAp4+1iw_t@x*4=(9U=EgR>3vBx5i!%nR>18-~&=AB!o^ zV6@B+0W@js$$=(7J<$*92=(-|JaU^4!zpsEsDzGD?e07xjzl?S{L_Kb2@itA&S=B2 zKv6`RC^L?v&Hy0dt^c*r0q=5GMhnZF8)_KuM^brqY754^NCS4|QM~|q(MR%W{m6uX zu&Ic6Jjo&}B#aY5b1lsjrLa_!6VTJnUS+$OC3Uf@))M%a2pO1M)l{+DA2$UlrswQT QfB*mh07*qoM6N<$f>$0WrT_o{ diff --git a/assets/O.png b/assets/O.png index 1258fe2ee66497477369bf76df5a87003ba1507c..36f8d95ef462796a1f202b11b66d7cb563dec50a 100644 GIT binary patch literal 210 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqGd*1#LnOjw{ThW@6*!~|W?uVW zpOv|H@?KSS1%qQe54Uh0@O9Kw@0f5p>Cl67-|H9_b16-=Wj5|e*4`lSKOOc3t2h*J%~Mnpe&9Yw;_&;#|Tsq06u5qw{UC0~W^)Y<%yrD zXYc-u-2c;J8lvT8CuFUR{dY8I31ixn3#taeO0MhsvTVKoFpAChQBqiSdjrss44$rj JF6*2UngHKpQ1k!* literal 580 zcmV-K0=xZ*P);sI*&6(APl^cMZ(-{MRTp)|~Y_?%qqf?YoW;XkRAff(;fXWW( z4QNOuo!O=p9RL7*F29T6UA=d)CD?ESZYkIhpsD~M6Bi0fd1DqL=q+GW>m7-=Jfj5w zV2c+oCsHnjAIo?IKmh;~1x~Sk#6SjsVj?wjPT$`slPLi+biC$F3$JgC>U*;seQ62e}ZFUnf&?uZo6m~fgeFmQg-lEeQb_lC~&4e;JO|3%+jYXt+oI}sc6&&bzm W1xfgQVO$M#F@vY8pUXO@geCwckX7mc literal 581 zcmV-L0=oT)P)SSxZC)AFNcK z@tE_Cr$2}B0O-1&s%0ELi+LGon&^@9{{T(X)EFbBan$fM6Sz>_zYj9v)`^lsUg_*GUNpn9c>}uxyTJqPlH->uTtGWL|d; z&{HC9DX2%>GTcF=X(Z!3R0vveu>qqZl>ix2N_4qc3bLPsjxh*TtNH}{#=}Sf5yo+X zjNby_TlfGfOju)HtEtxg*1u5{fN2AmAldbvg+%LH98geR=t2;N*Y8Xg&uTPgHIQkL zLIlM$a0;phg9IFy@DkWk*T1F+w^I*>U)VR!d0eLOEDcA1k7SHoB>ZNuZEye<_<{ha zfpZOxuvRJ;YP6}bfGxLNWy9Bubqm$`@V{4;F0qfE43U=rjOn89$&zxI)e&zU#o)%hEk1$eKwNJTcu2rrdd zb6xVWMZm%d1&90+e!n@f@~VlB`ssG^0Atga|I<*GI^h#jd~EUhVD^9M^6&1OWbQG< YUkD4*iQHxM9_VBSPgg&ebxsLQ054lwJpcdz literal 0 HcmV?d00001 diff --git a/assets/Z.png b/assets/Z.png index 09db90e0782d993af64ef7e557d556b08066af6d..c3d556d3aa402774d17d79dfe1a827f7a35e648c 100644 GIT binary patch literal 210 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqGd*1#LnOj=`vRq!6?mF2f9nx0 z`5rvQ_>#`o+un_8e>x*sW^yk$czB}rL$)RNqMV|i%P`MWl@Mzz&}X;1AIrvl?l+U> zQI`wr7c67gE4!8H_@4MX_pC+Qp6^O@wb;cGaKuk7EzK;2fSs^h$vdd zE_Vr@@9QGibl#?M>4p>Hb9oHJzP*(f+;sJSdC1CDQRSw87-ic+71(=b{s20X!PC{x JWt~$(696cYO`ZS% literal 4627 zcmeHKdsGuw8lQkXj8LCdinNa78=Yh(laS1q@GwD%YlI>ydbB#3nS?2MnFI*9pewGr zTXnUv>bh}@T`O%ti`x2RReYUNY}e!C6d$#FkX;tnYNZNPkFa+p;o)x2+2c9e|Hz!1 z`^~-I_q*TsyWjni`gjcJBV&<_DECNdm+|4?2W1-i>zw$WlV#zT?d z1!zhJKoTGcdXk_V1LP1%C=?3%b)XFcvY;chSV@@JZv^t_pj-yz$w8eEAmfq{C>r#B z&=f!(0s4drYCEaE!tUSbo~pl zGIFu>Zb{9__G2p}BKOB%y>x0odCT^##t9del+2H+K{jB>5PU3gIB}AZ_ig@UWk*NR zsOCj?nmgm@&z39BOd2*R`J8R}{Zw;tgD>zeTR56{l0?Ny&#d_OYgcDU@o$z6vcmOOy; z>3KJ{yk3_+Z}P}rwG&VGX@?vSTa)W>?k@HxLW}Oj7l+2hg)kGoc&pvlp6qmX{i)?~ zduaVV_ZQDAYb+oKeSB87H`_FaVw`pv%{tAT%x8BA8wP2Ud@h>F<-D+&v+@od^6=zo z1m;;CvQTBhOfEf_!>1Lwxp_r%vzVe>hGdbXM5)$C0RTJarD31l=I~HH9U|gVKo*AO z2rR02b9G2I$RoYe&B02UQih?aK0aT8BuZheo3&7xhM7SK@TNm@yj~Y2mlqTi$O;IV z(`}XGBuUCKghO#cAOaW$&cnEQmzQ@sU;&dhJM+9c1OfAKw|{n* z$DP(Vn!880!Nhur$K48#)7I<7KNEKs}dNJ z?gNqT=0R4{w!U5oP%MBVRjkFV)R<91fsv@vf|DqT6B?9Lm^Efi0zoHWtO&(2)J&(_ zPJ`{_?X;DXyBt<=LLi(<$uQ~=g$(N*$*|F03oy_jb9hIduXiGgw{!Enw7@2=R%kRz zHK|b%m{N@g!WQusaBdICL;+K*ouaw0Effd_5K9Yr3IN1$5DTSubF|m#&T=|!I;5xS z_Dq|=abjsNZJ@mz0PU&6S>1JbDyE>YfcpZR$;tAT!vCc$93EH;^ud;=@gA^#p*R#c zQS-PJfw#b`jTes+42y??qM1Ml9y*^3FbuE)Q%nx+uyUY!1k<&9od2m*NKh(pHO-(H zZBe31mD!Ba78XY}Dl z4kzpaAPmJZ6es?ZFnKUwxll8@Bi73QixaJ=(5J`%yTBMIUZ57rdx~L@GvL9``3dgD z&$$E)_b>8N{Pxq;PuEK^@KVbC+0{?iOEK_L%Kh2(f1^v{G0 zTH)qj%rZb-!c+d2ifv$Ipet>W2Z9C-7n%gxMT?CMQI7o9Gt>6%t@`rHv+B@26&1BfbqAZaDr1fJ{e0{= zC~WO&r~vbviD`r4&564c)FFeK-Y=_9T%8JK%&uJlOKSbZ_2MzmsO8Y@9n+!pEl@I& zSO4u4=v3*w#_O&!*|FZhgE2~vs7k;(rOms5*X?rIVcW#0DlW6_A_Dtnw zrlxVt)andR+Z!=k^bKth;X8Jw{}^GI-u%OBmv(wejxS8_Dmsp3?@!K{oic3brYC-D zrs8e;w72U2ux0;+ZJvoy>n3j8-txTd`rlXDN+fl=bhon~)W5UzI)3RrcAPe$X7=yS z);tS?S8bo(aZ|d!Mf3b}a{1;R*gpPk_k$0vu~7quj!$f!vt0i1wxBVA0y@CV$t` zg5M`}eSDs=ev6X@id5Y8`*D_2Q=|7dIZfF=lY(!yU`79r>_icfog| z!!hIQqS>)IjdYbggIi*X1p}b>#G;&d{SL>fTJBTk%`4oscnguHnFp=g-Y#@N^SX&3O}GfKtjSrk%B0dC={e3?+(xN zp7Y*&?%nxvsX(fHoipd0_q-p^`*F^_^RbbFh)hZ>qcVH`%1ak91LeiPKtF!zN_lQ+ zqxKDu-iP^z7FH|k@BjA8Ul$pj6&YEnt!yrBP5tGkMM_woir_G;zEx_m_5!gxQJqP5Cu z_18=5`$V4oyvSYOT5q)4QkQ3d@AtSa#Ev%6{F9HrcK7rDDN+PM3pMe zv-6Lg&vpLj)>m)+?#-XL`C_(GAoYWH-HFxh=5!eXZ114`E9wnr<;eR`tv67m??+?* zcQ`{q+l8{-bs6o$XyD)V6`aj4pkZ8s?Dz`WO`MpJoA{E*?h|M@e<#sT;!K^y+7$Fm z{Q=s$B6~i72HHKx(EeED-d9ELgN^&3|Gs|{nf@Tk9`n7wB69y;w9kk<@F6tF@59>u zDKv}^K<9(wXs~f`1?_7h4}tH{5wx$1JbX*!kxyciyoeT~VgBd|H1IzP-p8iUAotk2 zB8P$L@b93({*hTUjE`Xa`15FQi~P_Lw99B;5jhIGN1^v9){lKchrq#yby7Ggi;80P=kPlDR?W2R1I|a}upE^qrHto?Qv*k4or@HBTQj zH~)-}_e-VeD?Q~5J^$^EfDk^Z~5M6tbH5z zT{nc*$5t(_$161TiAvmqwnklV^ZvyAzC*Cq~XG=ZfEqi zn%S%U^?MCwhZ?LB)Q;*`>p4!=jdJkZjD!5K?uW~p*J$=EZ-yo8IS%J)+0#JB$S9rI zMYj_JVakz=$(L=$FTPB4FXv8J2GPzHj&1HnAw^>k4zlpQ2s%W_)vhOd`}Esq3QPrL z5lB!5@q>)McElThtIZwuvFP;ww#|=swBi24d}H0c zoOuLIDcgy4LqX}#Z`G!Yny2aRd4gKE-`S(_4CA{eXC>&f9tRw17jv`iV5`kBxworT za{FdBX)p8_^=Mqw9IO&y7h9v!$3x2VGHdiuPiypnry)$w$mo>h^4pyfFT|YF1*sa3v*h`={6tw2g z0kw&HE2A^S^RxSi2);vr=dsF7$R6m}z3b-?$yHrC#G6U(R6o6mOMBezzD>pdM}^wwMH z49%C9gZ7M`Vb{0cW8}7DU`CJojoxQ4k8^lOc`x#Hba%gsrW_+cz4X_gUrDq$ClBul z%1hg*|7|=?I|`-v%;M;@n$mA^Tnw<3aHl;8-hLNEoG#bXDqE0^T?EQQ9P7J)97&=XQRitVYcY$T&2w;o*2euG?xQVp&^uH)q)!4 zcCzP_3uFzM>1CE^D;qT;$Uo6`i4qR$Bu+i85-riYDs|_(M=eFr6Hhe;#7At_%<491 zj4b-p=0uO@LGbmnMqMrvv|<)ROJ*&wH7$q0+xJpWsT=KftH2>P7d;`tu^s#U0s%(v7JH?;c!Og}ueeUU?6DT!2L@KY?i(-b-YSq%eh2Cf4PrHcGvaaR8152Ub12j&S_jR> zp&gPj|b5PRGjZiYL(RjiL<1P@!_WnVqp2b&@10e0O(U$HeOpV65#XF6& zt+G#JoyLMFi%>$1xqH;UVLxdNpC?_G(;S*zciO@b?6?TJaTpy(F_h#Cxm60Jlm-fT zOam?NIJ--|J}ab^%!!J55sf%;pu~7Vqs=Wuh;zF?AkOJ|vxi^)_b$jp57Zfc_NJR- zt2~~_x~8j?w0*!avzt_uU!w$brcx=U>7nxmc_L9X=%^=b$yz|qqfHT$n}`f`es1VV zXU@n+emixbDfHoyesOgXrxvTLZnzCUV;AC15IP)KB_}nIi+D`ZY2Eo8<@r;*hyOR< z!KojxOlyf{3`3tXYdK!qF@~JHp}!`}9pdWSteB+tCyT&aNl*wb&{AIgE=1?FmbXG{ zo;Qutz`GqQBC&#@<~O9pXLE>mf)km1Q+?uZ@0tLb5dixs9gW=Zg|d+H{Vp0 zI>MHn1uJ=JVCspP3&gCxsz&o#YZ=S@L>2pEI`!3jW)IN>hfZQQPcUH0vHPCO@Q15; zn#Bopm^B;Rp}1nFjXb!+#-QTcF(7$ zfyr!8tDbS7QG&?5ets6&BX(iEP)cpZ7@$#O+S87HUZpGBs^0wc9yy8BuO2p2oj&K( zsM?)3Y6&!4c(qzETcmL(m=;B;Od8A4{O?xuR02Es7&DVgpNttOuKN9z;_vbuAbH8B z`w=o~c$ipZY6J>YCe-98>LpfvpJMqQV@W;4iVLs(VySTjPf(X#{3jRnX^z0Gr=auS zi`qG;D~f;6_o+lhoYd`JL!3S zgeM4*rSGxq6iKoVZb1fvGnl{jJDAsQR$QOxr(g_kd~eb4dDk`KQVisA+%foKje+$V zQ#|?TdKb^#v4iXbKkpMgf2ly(B#RgmS%TKtOyjTC__XCDw&NYqfrR%@L3#TFcAiE7 zf(Z_G|`Oeai(T^mPr9a;93x*0IbU7hW;qKlDJFnQz4! z7SKqyX80L>8wYjN<)jL2b8Ib<*8NKT%IP^wzs8aat}cem52cd*hcRt26V8VDV!hci zMC_eU662F4C}LVDtrGfalYV9d8h&5K`s(uBp!Q-XLp+MX`RJ*%OO0wzf3KPO9zFfF z>ri!}r2~buYc*jQ!aEFUw5$$cOa!)W{FK+R;foWT;0E59tMp2>Ia(6sF5m8^^7yql ze(NqpCdhu5dJv!79G7S148CLjS*hS}msaIEbpJnHQ}hQY@q>2li+=u1^o#?~6N{ep zF1s3=WQ{vjbL(X&%g9om<9@P5tmkDp|8_tR<^M}^`nvFuAIEi~m$@SiJw~{1Xf`dY z{LY@M_RTp@Y4eCk$Y-AD9K7lk=uRJHoi(oCuB`1DJMR*m&_ygo(~Vy5N}v%h`EQ}P z9ClPT>1fvD`v@+90~>pY^F*1wJpIrHdG<~fIh-}`F&E;1hH+qXm^(fsbdORpXkk3F z_Kiz9AY@3p;n?vTYVe!9`~4MXh(Da_#;d-918aEom{1Bm|BeFcO@G*DY`FkIAM6g$ zW%k+IID;j`g0ulbkyj3j_vwyKfX(5 zN{{*Rv^-I|?8fkAytK(}TI8MYLg^!ZjJ%Zo+>eo$(%<_r@=|)wkCB(scl{W789(U9 z$jkU~KSo~0&-gL&GX9%>jJ%A0*^iNz@o)Mu^0IrwkCB(%Mn_&IjgGube%13JFH?`Y zG4nFj!tdJ}vM!s_#Qm#=zeHEZUd{4%*ib7 zfphXIR@Je}c|@y@coF|~jM_la9p!F04}Tb$8Y06eMe1P-=$XfL$hxSV4m3pY zqN(0RIV3K=v{wcHMc`S*=qz}d;}i?y$Ve`Nx&UrwwxSVtnVJFp94PCGz5-ud7MiM; z6?GjPm*8g`YpgALLC>quQUSfCoDPYTq79;=bOb5ta2`{_@pr?*8er9!S2b|cs~OpS zTiNZNdl%gnDx(E$#8k$2O56=6^j{fv(;e{|@-+W_u-ZT@vNli3Nj!m`(&x}JJk0J} z=E3b-t6%QOP2`9%t!S0Ji4n8Ls$a$H8Z7VxVEwa}Sd~^y5q<^hvQC*Zn!{_5x836Q z3TrUb?sk;vo`H=f;!#%V1#r?L>!1u?&$*8PbeTB(KAU+efRuf-8uFtFuMa^~>OT2^y{ua^k^&8cd3yrn*#f{BqZua=xtJQY1-ij`seWhC4SgACVc`}In%GGMKRd1|C$7g2U z+QqX}bfw+gSZGJkQHk2k%3^i3(!3TmmZEfVW}&gV+-|S8PM6C|5NW9hsoh}xO=9_P zqwAGcG`~?_X-C)V?d3q_`D&|PTdOvs#cFGzSzm7h*=b#mmYR*#$m;;y_Hs44i2onM z*~X?*QdwNAE=CK>m1bq34WDMBbCvaayRrfgn$>8naXq@U(O#*qRbjijP}yizsRT=I zIa+C4hv9_^=&6>d?o8ESYNorhf$u=uDz}y!*UP8oW>1_rQEqD*UaQRy6m2xU_`Z?XBy2~d8NKkU29ca<@wF0Tb1%NGqdFj)Hq+SMQ?0W7OtU~qPME+%bU$s^m+ps zT19*-HxRPLvoE(^TDW?=cIO6+Lxo38_NHn_%AFhVog1*-yuydCJ2&7Tm>V$PCh}uX PUQ7CyCT^U4EpYljtyj*c literal 0 HcmV?d00001 diff --git a/assets/title.png b/assets/title.png new file mode 100644 index 0000000000000000000000000000000000000000..e7f0bd1851fb20c26aff1d0a9b5fcfe597454e8d GIT binary patch literal 9290 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 literal 0 HcmV?d00001 diff --git a/assets/title_bg.png b/assets/title_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..750f9e4e328ca58ca25081704f81fae5bdcdfd71 GIT binary patch literal 12133 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 SDL_CreateRenderer(window.get( ), -1, SDL_RENDERER_ACCELERATED), [ ](SDL_Renderer* r) { SDL_DestroyRenderer(r); } @@ -28,11 +30,15 @@ bool Game::init(const char* title, int w, int h) { SDL_Log("Failed to create renderer: %s", SDL_GetError( )); return false; } + int ww, wh; + SDL_GetWindowSize(window.get( ), &ww, &wh); - gameRenderer = make_shared(renderer); + gameRenderer = make_shared(renderer, ww, wh); gameBoard = make_shared( ); - bgm = std::shared_ptr(Mix_LoadMUS("/home/crylia/Dokumente/git/tetris_sdl/assets/bgm.mp3"), [ ](Mix_Music* m) { + handleWindowResize( ); + + bgm = std::shared_ptr(Mix_LoadMUS("assets/bgm.mp3"), [ ](Mix_Music* m) { Mix_FreeMusic(m); }); @@ -73,7 +79,10 @@ void Game::run( ) { void Game::inputHandler( ) { SDL_Event event; while (SDL_PollEvent(&event)) { - if (event.type == SDL_QUIT) { SDL_Quit( ); } else if (event.type == SDL_KEYDOWN) { + if (event.type == SDL_QUIT) { + SDL_Quit( ); + quit = true; + } else if (event.type == SDL_KEYDOWN) { switch (event.key.keysym.sym) { case SDLK_LEFT: case SDLK_a: @@ -106,10 +115,25 @@ void Game::inputHandler( ) { default: break; } + } else if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED) { + handleWindowResize( ); } } } +void Game::handleWindowResize( ) { + int windowWidth, windowHeight; + SDL_GetWindowSize(window.get( ), &windowWidth, &windowHeight); + + gameRenderer->setBlockSize(windowHeight / gameBoard->getLockedTetrominos( ).size( )); + + int offsetX = (windowWidth - gameBoard->getLockedTetrominos( )[0].size( ) * gameRenderer->getBlockSize( )) / 2; + int offsetY = (windowHeight - gameBoard->getLockedTetrominos( ).size( ) * gameRenderer->getBlockSize( )) / 2; + gameRenderer->setOffset(offsetX, offsetY); + + gameRenderer->setWindowSize(windowWidth, windowHeight); +} + void Game::update( ) { Uint32 currentTime = SDL_GetTicks( ); Uint32 deltaTime = currentTime - lastUpdateTime; @@ -122,7 +146,7 @@ void Game::update( ) { void Game::render( ) { //Set default color to black - SDL_SetRenderDrawColor(renderer.get( ), 20, 20, 20, 255); + SDL_SetRenderDrawColor(renderer.get( ), 248, 248, 248, 255); SDL_RenderClear(renderer.get( )); gameRenderer->renderBoard(*gameBoard); diff --git a/src/Game.hpp b/src/Game.hpp index 50d3cdd..1134472 100644 --- a/src/Game.hpp +++ b/src/Game.hpp @@ -18,6 +18,8 @@ private: void render( ); void inputHandler( ); + void handleWindowResize( ); + unique_ptr window; shared_ptr renderer; diff --git a/src/GameBoard.cpp b/src/GameBoard.cpp index f4ee67b..1669046 100644 --- a/src/GameBoard.cpp +++ b/src/GameBoard.cpp @@ -2,7 +2,7 @@ #include GameBoard::GameBoard( ) - : lockedTetrominos(20, vector(10, 0)), lockedColors(20, std::vector(10, { 0, 0, 0, 0 })), score(0), level(1), collision(false) { + : lockedTetrominos(20, vector(10, 0)), lockedColors(20, std::vector(10, { 0, 0, 0, 255 })), score(0), level(1), collision(false) { spawnNewTetromino( ); } @@ -41,37 +41,86 @@ bool GameBoard::checkCollision(const Tetromino& tetromino) const { void GameBoard::lockTetromino( ) { const auto& shape = currentTetromino->getShape( ); int x = currentTetromino->getX( ), y = currentTetromino->getY( ); + double angle = currentTetromino->getRotationAngle( ); + TetrominoShape tetrominoShape = currentTetromino->getShapeEnumn( ); - for (int row = 0; row < shape.size( ); ++row) - for (int col = 0; col < shape[row].size( ); ++col) - if (shape[row][col] != 0) { + if (tetrominoShape == TetrominoShape::I) { + if (angle == 90 || angle == 270) { + for (int col = 0; col < shape[0].size( ); ++col) { int lockedTetrominosX = x + col; - int lockedTetrominosY = y + row; - if (lockedTetrominosY >= 0 && lockedTetrominosX < height) { - lockedTetrominos[lockedTetrominosY][lockedTetrominosX] = 1; + int lockedTetrominosY = y; + + if (lockedTetrominosY >= 0 && lockedTetrominosX >= 0 && lockedTetrominosX < width) { + if (col == 0) { + lockedTetrominos[lockedTetrominosY][lockedTetrominosX] = static_cast(TetrominoShape::I_ENDR) + 1; + } else if (col == 3) { + lockedTetrominos[lockedTetrominosY][lockedTetrominosX] = static_cast(TetrominoShape::I_STARTR) + 1; + } else { + lockedTetrominos[lockedTetrominosY][lockedTetrominosX] = static_cast(TetrominoShape::I_MIDR) + 1; + } lockedColors[lockedTetrominosY][lockedTetrominosX] = currentTetromino->getColor( ); } } + } else { + for (int row = 0; row < shape.size( ); ++row) { + for (int col = 0; col < shape[row].size( ); ++col) { + if (shape[row][col] != 0) { + int lockedTetrominosX = x; + int lockedTetrominosY = y + row; + + if (lockedTetrominosY >= 0 && lockedTetrominosX >= 0 && lockedTetrominosX < width && lockedTetrominosY < height) { + if (row == 0) { + lockedTetrominos[lockedTetrominosY][lockedTetrominosX] = static_cast(TetrominoShape::I_END) + 1; + } else if (row == 3) { + lockedTetrominos[lockedTetrominosY][lockedTetrominosX] = static_cast(TetrominoShape::I_START) + 1; + } else { + lockedTetrominos[lockedTetrominosY][lockedTetrominosX] = static_cast(TetrominoShape::I_MID) + 1; + } + lockedColors[lockedTetrominosY][lockedTetrominosX] = currentTetromino->getColor( ); + } + } + } + } + } + } else { + for (int row = 0; row < shape.size( ); ++row) { + for (int col = 0; col < shape[row].size( ); ++col) { + if (shape[row][col] != 0) { + int lockedTetrominosX = x + col; + int lockedTetrominosY = y + row; + + if (lockedTetrominosY >= 0 && lockedTetrominosX >= 0 && lockedTetrominosX < width && lockedTetrominosY < height) { + lockedTetrominos[lockedTetrominosY][lockedTetrominosX] = static_cast(tetrominoShape) + 1; + lockedColors[lockedTetrominosY][lockedTetrominosX] = currentTetromino->getColor( ); + } + } + } + } + } } void GameBoard::clearLines( ) { - for (int row = 0; row < height; row++) - if (all_of(lockedTetrominos[row].begin( ), lockedTetrominos[row].end( ), [ ](int cell) {return cell != 0;})) { + for (int row = 0; row < height; row++) { + if (all_of(lockedTetrominos[row].begin( ), lockedTetrominos[row].end( ), [ ](int cell) { return cell != 0; })) { lockedTetrominos.erase(lockedTetrominos.begin( ) + row); - lockedTetrominos.insert(lockedTetrominos.begin( ), vector(width, 0)); - score += 100; - if ((score % 1000) == 0) - level++; - } -} + lockedColors.erase(lockedColors.begin( ) + row); + lockedTetrominos.insert(lockedTetrominos.begin( ), vector(width, 0)); + lockedColors.insert(lockedColors.begin( ), vector(width, { 0, 0, 0, 0 })); + + score += 100; + if (score % 1000 == 0) { + level++; + } + } + } +} void GameBoard::spawnNewTetromino( ) { random_device dev; mt19937 rng(dev( )); uniform_int_distribution dist6(0, static_cast(TetrominoShape::COUNT) - 1); TetrominoShape shape = static_cast(dist6(rng)); currentTetromino = make_unique(shape); - currentTetromino->setTexture(shape); currentTetromino->move(width / 2 - 1, 0); if (checkCollision(*currentTetromino)) @@ -117,4 +166,5 @@ void GameBoard::reset( ) { lockedColors.clear( ); score = 0; level = 1; + collision = false; } diff --git a/src/Renderer.cpp b/src/Renderer.cpp index 130646b..b0d0778 100644 --- a/src/Renderer.cpp +++ b/src/Renderer.cpp @@ -1,18 +1,27 @@ #include "Renderer.hpp" #include -Renderer::Renderer(shared_ptr renderer) : renderer(renderer), blockSize(30) { +Renderer::Renderer(shared_ptr renderer, int w, int h) : renderer(renderer), blockSize(30), windowHeight(h), windowWidth(w) { setRenderer(renderer); } void Renderer::setRenderer(shared_ptr renderer) { this->renderer = renderer; - loadTexture("/home/crylia/Dokumente/git/tetris_sdl/assets/single.png", TetrominoShape::I); - loadTexture("/home/crylia/Dokumente/git/tetris_sdl/assets/single.png", TetrominoShape::J); - loadTexture("/home/crylia/Dokumente/git/tetris_sdl/assets/single.png", TetrominoShape::L); - loadTexture("/home/crylia/Dokumente/git/tetris_sdl/assets/single.png", TetrominoShape::S); - loadTexture("/home/crylia/Dokumente/git/tetris_sdl/assets/single.png", TetrominoShape::O); - loadTexture("/home/crylia/Dokumente/git/tetris_sdl/assets/single.png", TetrominoShape::Z); + loadTexture("assets/single.png", TetrisAssets::SINGLE); + loadTexture("assets/border.png", TetrisAssets::BORDER); + loadTexture("assets/J.png", TetrisAssets::J); + loadTexture("assets/L.png", TetrisAssets::L); + loadTexture("assets/T.png", TetrisAssets::T); + loadTexture("assets/O.png", TetrisAssets::O); + loadTexture("assets/S.png", TetrisAssets::S); + loadTexture("assets/Z.png", TetrisAssets::Z); + loadTexture("assets/I_MID.png", TetrisAssets::I); + loadTexture("assets/I_END.png", TetrisAssets::I_END); + loadTexture("assets/I_MID.png", TetrisAssets::I_MID); + loadTexture("assets/I_START.png", TetrisAssets::I_START); + loadTexture("assets/I_ENDR.png", TetrisAssets::I_ENDR); + loadTexture("assets/I_MIDR.png", TetrisAssets::I_MIDR); + loadTexture("assets/I_STARTR.png", TetrisAssets::I_STARTR); } void Renderer::renderBoard(const GameBoard& gameBoard) { @@ -29,14 +38,22 @@ void Renderer::drawScoreboard(int score, int level) { } void Renderer::drawGrid(const GameBoard& board) { - SDL_SetRenderDrawColor(renderer.get( ), 100, 100, 100, 255); + int borderThickness = 10, gridThickness = 1; + int innerBorderThickness = blockSize / 4; - int w = board.getLockedTetrominos( )[0].size( ), h = board.getLockedTetrominos( ).size( ); - for (int x = 0; x <= w; ++x) - SDL_RenderDrawLine(renderer.get( ), x * blockSize, 0, x * blockSize, h * blockSize); + int w = board.getLockedTetrominos( )[0].size( ); + int h = board.getLockedTetrominos( ).size( ); - for (int y = 0; y <= h; ++y) - SDL_RenderDrawLine(renderer.get( ), 0, y * blockSize, w * blockSize, y * blockSize); + int totalWidth = w * blockSize; + int totalHeight = h * blockSize; + + for (int y = 0; y < (h + (innerBorderThickness * h)); ++y) { + SDL_Rect leftBlock = { offsetX - blockSize, offsetY + y * blockSize, blockSize, blockSize }; + renderTexture(TetrisAssets::BORDER, leftBlock.x, leftBlock.y - (innerBorderThickness * y + 1), leftBlock.w, leftBlock.h); + + SDL_Rect rightBlock = { offsetX + totalWidth, offsetY + y * blockSize, blockSize, blockSize }; + renderTexture(TetrisAssets::BORDER, rightBlock.x, rightBlock.y - (innerBorderThickness * y + 1), rightBlock.w, rightBlock.h); + } } void Renderer::drawLockedBlocks(const GameBoard& gameBoard) { @@ -47,16 +64,19 @@ void Renderer::drawLockedBlocks(const GameBoard& gameBoard) { for (int col = 0; col < lockedTetrominos[row].size( ); ++col) { int blockType = lockedTetrominos[row][col]; if (blockType != 0) { - SDL_Rect block = { col * blockSize, row * blockSize, blockSize, blockSize }; + SDL_Rect block = { offsetX + col * blockSize, offsetY + row * blockSize, blockSize, blockSize }; - SDL_SetTextureBlendMode(textures[TetrominoShape::I], SDL_BLENDMODE_BLEND); + TetrominoShape shape = static_cast(blockType - 1); + TetrisAssets asset = shapeToAsset(shape); - SDL_Color color = lockedColors[row][col]; - if (textures[TetrominoShape::I]) { - SDL_SetTextureColorMod(textures[TetrominoShape::I], color.r, color.g, color.b); - renderTexture(TetrominoShape::I, block.x, block.y, block.w, block.h); + if (textures[asset]) { + SDL_Color color = lockedColors[row][col]; + SDL_SetTextureBlendMode(textures[asset], SDL_BLENDMODE_BLEND); + SDL_SetTextureColorMod(textures[asset], color.r, color.g, color.b); + renderTexture(asset, block.x, block.y, block.w, block.h); } else { - SDL_SetRenderDrawColor(renderer.get( ), color.r, color.g, color.b, 255); + SDL_Log("Texture not found for asset: %d", asset); + SDL_SetRenderDrawColor(renderer.get( ), 255, 0, 0, 255); SDL_RenderFillRect(renderer.get( ), &block); } } @@ -64,52 +84,203 @@ void Renderer::drawLockedBlocks(const GameBoard& gameBoard) { } } +TetrisAssets Renderer::shapeToAsset(const TetrominoShape shape) { + switch (shape) { + case TetrominoShape::I: + return TetrisAssets::I; + case TetrominoShape::O: + return TetrisAssets::O; + case TetrominoShape::T: + return TetrisAssets::T; + case TetrominoShape::J: + return TetrisAssets::J; + case TetrominoShape::L: + return TetrisAssets::L; + case TetrominoShape::S: + return TetrisAssets::S; + case TetrominoShape::Z: + return TetrisAssets::Z; + case TetrominoShape::I_END: + return TetrisAssets::I_END; + case TetrominoShape::I_START: + return TetrisAssets::I_START; + case TetrominoShape::I_MID: + return TetrisAssets::I_MID; + case TetrominoShape::I_ENDR: + return TetrisAssets::I_ENDR; + case TetrominoShape::I_STARTR: + return TetrisAssets::I_STARTR; + case TetrominoShape::I_MIDR: + return TetrisAssets::I_MIDR; + default: + break; + } +} + void Renderer::drawTetromino(const Tetromino& tetromino) { const auto& shape = tetromino.getShape( ); int x = tetromino.getX( ), y = tetromino.getY( ); - auto t = tetromino.getTexture( ); double angle = tetromino.getRotationAngle( ); - SDL_SetTextureBlendMode(textures[t], SDL_BLENDMODE_BLEND); - SDL_Color color = tetromino.getColor( ); - SDL_SetTextureColorMod(textures[t], color.r, color.g, color.b); + TetrominoShape tetrominoShape = tetromino.getShapeEnumn( ); - for (int row = 0; row < shape.size( ); ++row) { - for (int col = 0; col < shape[row].size( ); ++col) { - if (shape[row][col] != 0) { - SDL_Rect destRect = { (x + col) * blockSize, (y + row) * blockSize, blockSize, blockSize }; - SDL_Point center = { blockSize / 2, blockSize / 2 }; - SDL_RenderCopyEx(renderer.get( ), textures[t], nullptr, &destRect, angle, ¢er, SDL_FLIP_NONE); + SDL_SetTextureBlendMode(textures[shapeToAsset(tetrominoShape)], SDL_BLENDMODE_BLEND); + SDL_Color color = tetromino.getColor( ); + SDL_SetTextureColorMod(textures[shapeToAsset(tetrominoShape)], color.r, color.g, color.b); + + if (tetrominoShape == TetrominoShape::I) { + SDL_SetTextureColorMod(textures[TetrisAssets::I_START], color.r, color.g, color.b); + SDL_SetTextureColorMod(textures[TetrisAssets::I_MID], color.r, color.g, color.b); + SDL_SetTextureColorMod(textures[TetrisAssets::I_END], color.r, color.g, color.b); + + if (angle == 90) { + for (int i = 0; i < 4; ++i) { + SDL_Rect destRect = { offsetX + (x + i) * blockSize, offsetY + y * blockSize, blockSize, blockSize }; + SDL_RenderCopyEx(renderer.get( ), textures[TetrisAssets::I_MID], nullptr, &destRect, angle, nullptr, SDL_FLIP_NONE); + } + + SDL_Rect startRect = { offsetX + (x + 0) * blockSize, offsetY + y * blockSize, blockSize, blockSize }; + SDL_RenderCopyEx(renderer.get( ), textures[TetrisAssets::I_START], nullptr, &startRect, angle, nullptr, SDL_FLIP_NONE); + + SDL_Rect endRect = { offsetX + (x + 3) * blockSize, offsetY + y * blockSize, blockSize, blockSize }; + SDL_RenderCopyEx(renderer.get( ), textures[TetrisAssets::I_END], nullptr, &endRect, angle, nullptr, SDL_FLIP_NONE); + } else if (angle == 270) { + for (int i = 0; i < 4; ++i) { + SDL_Rect destRect = { offsetX + (x + i) * blockSize, offsetY + y * blockSize, blockSize, blockSize }; + SDL_RenderCopyEx(renderer.get( ), textures[TetrisAssets::I_MID], nullptr, &destRect, angle, nullptr, SDL_FLIP_NONE); + } + + SDL_Rect startRect = { offsetX + (x + 0) * blockSize, offsetY + y * blockSize, blockSize, blockSize }; + SDL_RenderCopyEx(renderer.get( ), textures[TetrisAssets::I_END], nullptr, &startRect, angle, nullptr, SDL_FLIP_NONE); + + SDL_Rect endRect = { offsetX + (x + 3) * blockSize, offsetY + y * blockSize, blockSize, blockSize }; + SDL_RenderCopyEx(renderer.get( ), textures[TetrisAssets::I_START], nullptr, &endRect, angle, nullptr, SDL_FLIP_NONE); + } else { + SDL_Rect destRect1 = { offsetX + (x + 0) * blockSize, offsetY + (y + 0) * blockSize, blockSize, blockSize }; + SDL_Rect destRect2 = { offsetX + (x + 0) * blockSize, offsetY + (y + 1) * blockSize, blockSize, blockSize }; + SDL_Rect destRect3 = { offsetX + (x + 0) * blockSize, offsetY + (y + 2) * blockSize, blockSize, blockSize }; + SDL_Rect destRect4 = { offsetX + (x + 0) * blockSize, offsetY + (y + 3) * blockSize, blockSize, blockSize }; + + renderTexture(TetrisAssets::I_END, destRect1.x, destRect1.y, destRect1.w, destRect1.h); + renderTexture(TetrisAssets::I_MID, destRect2.x, destRect2.y, destRect2.w, destRect2.h); + renderTexture(TetrisAssets::I_MID, destRect3.x, destRect3.y, destRect3.w, destRect3.h); + renderTexture(TetrisAssets::I_START, destRect4.x, destRect4.y, destRect4.w, destRect4.h); + } + } else { + for (int row = 0; row < shape.size( ); ++row) { + for (int col = 0; col < shape[row].size( ); ++col) { + if (shape[row][col] != 0) { + SDL_Rect destRect = { offsetX + (x + col) * blockSize, offsetY + (y + row) * blockSize, blockSize, blockSize }; + SDL_Point center = { blockSize / 2, blockSize / 2 }; + SDL_RenderCopy(renderer.get( ), textures[shapeToAsset(tetrominoShape)], nullptr, &destRect); + } } } } } -bool Renderer::loadTexture(const string& filePath, const TetrominoShape shape) { +bool Renderer::loadTexture(const string& filePath, const TetrisAssets asset) { SDL_Texture* texture = IMG_LoadTexture(renderer.get( ), filePath.c_str( )); if (!texture) { SDL_Log("Failed to load Texture: %s\n%s", filePath, SDL_GetError( )); return false; } - textures[shape] = texture; + textures[asset] = texture; return true; } -void Renderer::renderTexture(const TetrominoShape shape, int x, int y, int width, int height) { +void Renderer::renderTexture(const TetrisAssets asset, int x, int y, int width, int height) { SDL_Rect destRect{ x,y,width,height }; - SDL_RenderCopy(renderer.get( ), textures[shape], nullptr, &destRect); + SDL_RenderCopy(renderer.get( ), textures[asset], nullptr, &destRect); } void Renderer::renderStartScreen( ) { - SDL_SetRenderDrawColor(renderer.get( ), 0, 0, 0, 255); + SDL_SetRenderDrawColor(renderer.get( ), 248, 248, 248, 255); SDL_RenderClear(renderer.get( )); - renderText("Tetris", 100, 100, 128, SDL_Color{ 200,200,200 }); + int borderThickness = 20; + SDL_Rect borderRect = { + borderThickness, + borderThickness, + windowWidth - 2 * borderThickness, + windowHeight - 2 * borderThickness + }; + SDL_SetRenderDrawColor(renderer.get( ), 0, 0, 0, 255); + SDL_RenderDrawRect(renderer.get( ), &borderRect); + + SDL_Surface* titleSurface = IMG_Load("assets/title.png"); + if (!titleSurface) { + SDL_Log("Failed to load title surface: %s", SDL_GetError( )); + return; + } + + auto titleTexture = SDL_CreateTextureFromSurface(renderer.get( ), titleSurface); + SDL_FreeSurface(titleSurface); + if (!titleTexture) { + SDL_Log("Failed to create title texture: %s", SDL_GetError( )); + return; + } + + float titleScaleFactor = 0.5f; + int titleWidth = static_cast(windowWidth * titleScaleFactor); + int titleHeight = static_cast(titleWidth * 0.315f); + + SDL_Rect titleRect = { + (windowWidth / 2) - (titleWidth / 2), + static_cast(windowHeight * 0.2f), + titleWidth, + titleHeight + }; + + SDL_RenderCopy(renderer.get( ), titleTexture, nullptr, &titleRect); + SDL_DestroyTexture(titleTexture); + + SDL_Surface* titleBg = IMG_Load("assets/title_bg.png"); + if (!titleBg) { + SDL_Log("Failed to load background surface: %s", SDL_GetError( )); + return; + } + + auto titleBgTexture = SDL_CreateTextureFromSurface(renderer.get( ), titleBg); + int originalBgWidth = titleBg->w; + int originalBgHeight = titleBg->h; + SDL_FreeSurface(titleBg); + if (!titleBgTexture) { + SDL_Log("Failed to create background texture: %s", SDL_GetError( )); + return; + } + + float bgScaleFactor = 0.8f; + int titleBgWidth = static_cast(windowWidth * bgScaleFactor); + int titleBgHeight = static_cast(titleBgWidth * (static_cast(originalBgHeight) / originalBgWidth)); + if (titleBgHeight > windowHeight * 0.4f) { + titleBgHeight = static_cast(windowHeight * 0.4f); + titleBgWidth = static_cast(titleBgHeight * (static_cast(originalBgWidth) / originalBgHeight)); + } + + SDL_Rect titleBgRect = { + (windowWidth / 2) - (titleBgWidth / 2), + static_cast(windowHeight * 0.5f), + titleBgWidth, + titleBgHeight + }; + + SDL_RenderCopy(renderer.get( ), titleBgTexture, nullptr, &titleBgRect); + SDL_DestroyTexture(titleBgTexture); + + int w, h; + TTF_Font* font = TTF_OpenFont("assets/tetris-gb.ttf", 16); + TTF_SizeText(font, "PRESS START", &w, &h); + TTF_CloseFont(font); + + renderText("press G to start", (windowWidth / 2) - (w / 2), windowHeight - 100, 16, SDL_Color{ 0, 0, 0 }); SDL_RenderPresent(renderer.get( )); } + + void Renderer::renderGameOver(int score, int level) { SDL_SetRenderDrawColor(renderer.get( ), 0, 0, 0, 128); SDL_RenderClear(renderer.get( )); @@ -123,7 +294,7 @@ void Renderer::renderGameOver(int score, int level) { } void Renderer::renderText(string text, int x, int y, int size, SDL_Color color) { - TTF_Font* font = TTF_OpenFont("/usr/share/fonts/TTF/OpenSans-Regular.ttf", size); + TTF_Font* font = TTF_OpenFont("assets/tetris-gb.ttf", size); SDL_Surface* surface = TTF_RenderText_Solid(font, text.c_str( ), color); if (!surface) { SDL_Log("Failed to create surface: %s", TTF_GetError( )); @@ -149,3 +320,21 @@ void Renderer::renderText(string text, int x, int y, int size, SDL_Color color) SDL_DestroyTexture(texture); TTF_CloseFont(font); } + +const int Renderer::getBlockSize( ) const { return blockSize; } + +void Renderer::setBlockSize(int newBlockSize) { blockSize = newBlockSize; } + +void Renderer::setOffset(int newX, int newY) { + offsetX = newX; + offsetY = newY; +} + +const int Renderer::getOffsetX( ) const { return offsetX; } + +const int Renderer::getOffsetY( ) const { return offsetY; } + +void Renderer::setWindowSize(int w, int h) { + windowWidth = w; + windowHeight = h; +} diff --git a/src/Renderer.hpp b/src/Renderer.hpp index df17a25..79e62ba 100644 --- a/src/Renderer.hpp +++ b/src/Renderer.hpp @@ -12,6 +12,24 @@ extern "C" { #include "GameBoard.hpp" +enum class TetrisAssets { + BORDER, + SINGLE, + I, + I_MID, + I_START, + I_END, + I_MIDR, + I_STARTR, + I_ENDR, + J, + L, + O, + S, + Z, + T, +}; + class Renderer { private: void drawGrid(const GameBoard& gameBoard); @@ -19,19 +37,34 @@ private: void drawTetromino(const Tetromino& tetromino); void drawScoreboard(int score, int level); - shared_ptr renderer; - int blockSize; + TetrisAssets shapeToAsset(const TetrominoShape shape); - unordered_map textures; + shared_ptr renderer; + + int blockSize; + int offsetX; + int offsetY; + int screenSpacing = 50; + int windowHeight = 0; + int windowWidth = 0; + + unordered_map textures; public: - Renderer(shared_ptr renderer); + Renderer(shared_ptr renderer, int w, int h); void setRenderer(shared_ptr renderer); void renderBoard(const GameBoard& gb); - bool loadTexture(const string& filePath, const TetrominoShape shape); - void renderTexture(const TetrominoShape shape, int x, int y, int width, int height); + bool loadTexture(const string& filePath, const TetrisAssets shape); + void renderTexture(const TetrisAssets shape, int x, int y, int width, int height); void renderStartScreen( ); void renderGameOver(int score, int level); void renderText(string text, int x, int y, int size, SDL_Color color); + + const int getBlockSize( ) const; + void setBlockSize(int newBlockSize); + void setOffset(int newX, int newY); + const int getOffsetX( ) const; + const int getOffsetY( ) const; + void setWindowSize(int w, int h); }; diff --git a/src/Tetromino.cpp b/src/Tetromino.cpp index 26d97eb..47f42b6 100644 --- a/src/Tetromino.cpp +++ b/src/Tetromino.cpp @@ -1,7 +1,7 @@ #include "Tetromino.hpp" #include "GameBoard.hpp" - -Tetromino::Tetromino(TetrominoShape shape) : x(0), y(0) { +#include +Tetromino::Tetromino(TetrominoShape shape) : x(0), y(0), textureShape(shape) { initializeShape(shape); currentRotationState = 1; @@ -16,29 +16,44 @@ Tetromino::Tetromino(TetrominoShape shape) : x(0), y(0) { switch (dist6(rng)) { case 0: - color.r = 255; + color.r = 0; + color.g = 191; + color.b = 255; break; case 1: - color.g = 255; + color.r = 255; + color.g = 215; + color.b = 0; break; case 2: - color.b = 255; + color.r = 138; + color.g = 43; + color.b = 226; break; case 3: - color.r = 255; - color.g = 255; + color.r = 0; + color.g = 204; + color.b = 102; break; case 4: - color.g = 255; - color.b = 255; + color.r = 255; + color.g = 69; + color.b = 0; break; case 5: + color.r = 30; + color.g = 144; color.b = 255; + break; + case 6: color.r = 255; + color.g = 140; + color.b = 0; break; default: break; } + } void Tetromino::initializeShape(TetrominoShape s) { @@ -61,6 +76,9 @@ void Tetromino::initializeShape(TetrominoShape s) { case TetrominoShape::L: shape = { {0, 0, 1}, {1, 1, 1} }; break; + case TetrominoShape::T: + shape = { {1, 1, 1}, {0, 1, 0} }; + break; default: shape = { {0} }; break; @@ -102,11 +120,9 @@ double Tetromino::getRotationAngle( ) const { } const vector>& Tetromino::getShape( ) const { return shape; } +const TetrominoShape Tetromino::getShapeEnumn( ) const { return textureShape; } int Tetromino::getX( ) const { return x; } int Tetromino::getY( ) const { return y; } -void Tetromino::setTexture(const TetrominoShape shape) { this->textureShape = shape; } -const TetrominoShape Tetromino::getTexture( ) const { return textureShape; } - SDL_Color Tetromino::getColor( ) const { return color; } diff --git a/src/Tetromino.hpp b/src/Tetromino.hpp index db49086..d07782c 100644 --- a/src/Tetromino.hpp +++ b/src/Tetromino.hpp @@ -17,7 +17,14 @@ enum class TetrominoShape { S, Z, J, - COUNT //Used to know the ammount of shapes + T, + COUNT, //Used to know the ammount of shapes + I_END, + I_START, + I_MID, + I_ENDR, + I_STARTR, + I_MIDR, }; class GameBoard; @@ -42,10 +49,9 @@ public: double getRotationAngle( ) const; const vector>& getShape( ) const; + const TetrominoShape getShapeEnumn( ) const; int getX( ) const; int getY( ) const; - void setTexture(const TetrominoShape textureName); - const TetrominoShape getTexture( ) const; SDL_Color getColor( ) const; };