From da7075864be48d2701107c945e69610622dda55e Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Thu, 23 Jan 2025 02:42:43 -0500 Subject: [PATCH] Now have a basic sprite system that uses SFML's sprites, but the algorithm for determining how much of a sprite to display is wrong. Need to use the alternate algorithm from LODE's tutorial that draws sprites after rendering. --- assets/undead_peasant-256.png | Bin 16354 -> 21015 bytes constants.hpp | 2 ++ main.cpp | 1 - raycaster.cpp | 61 +++++++++++++++------------------- texture.cpp | 5 +++ texture.hpp | 5 ++- 6 files changed, 38 insertions(+), 36 deletions(-) diff --git a/assets/undead_peasant-256.png b/assets/undead_peasant-256.png index 5aa90abfeed39c5f5f6ee8aa502556a66de54ce4..10fc9654eafff199ccad5a5d4b92916ec94e0440 100644 GIT binary patch delta 19858 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
;xK=%Uj=pv6Yz4 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

&8}#VK z!+84H8{MOw(@1C>#hdGDCxb4SJH(>Qs6?6*7o2#cboS}f0bjUd2Rh?_TQCQJJ;u-f z`(I4}&wQuv|A$|D{Hc46ms>Y~1I<m6BSVJHW>5TviP&xn$Li^C#rre zBERC!P0jkmwQDy&_ry0&Zuv#~0xW?M&(;&1d=nV)V%7T|JUY03aJpTufhV6t0Kh#L zu-T4zSpbKcD5dO7NaaR<1>wzM2u0F+$L;ubU=9HLggF4*lTd2Ov#qOFuE$ z^8nDc=KAqxZvE05?>qX%VXUVeaWstMlg~e!&;OsB+xq)1cq6|wy)Iw+<^hyAn;a5KY!HYiIV}J_~D(%jPD13a{#!@VeWrj(h?LI zp_nYfcTeJMBYECfkNo^MUVIe5=Ju=Wx4We9l7+zUh8p>iWhsg=m}+VxZSz=^(m1_= zQf|g$fp2r+zaF|iavJ#jEB&|6c;%RhKzBP7okgvvRjd_ttZiI3NrAA@`VI~F(WUzX zuhP46VSGyj{>tfpX0!+qYGcMpHAH<^Qe+h{3aA1qsUE=n#rUz~jz6<>9${xrFyoG3 z&H(OqkYAPZl&KVd{b@s}O?!^V%%fN7T{{y0B18Ao$o4x#z}-0xqiCi~kx&OP zNO*G?YNDZC*S%x8TK)4YS1$jjQv9*&FJ8apwSFen*ROkjkNTx+FE0a`@yam=fV&(L zev`l-mGr@sdPz1d5@FizuLMStPlmMlUe|k>pt+&es8ev6EX)#TXB*NeC=CEbcnUPZ z%ngKie0-s-R;zcdR;zbp=E>2870- zfV&(Ai}IL%MLe(6`vqK((1paQklzaUl7L?a@J#@p0&x9Rc-tiTSsH%^paJXwSx##P zk^;~m!7<62C(dQaI1B^Vn+?y-&U_rlRju`syT27??>6cKMEUTQg*|uRc$m=x7D$Z zW369*$k25|{)EVPfOs0ICk~dqis3C8c`ryONi(a9#j-Rr6XwGBoVkB7mH#`o!>1$a z$G>vz?B);a^Z#MT8~|p#V%&S-;9l$eACL@5j}K%0mFu_G&#Z_?SnRKo`pp{p>KpF6 zl0^R8IMzQNsrS^(gH*ogR!&Oi_Y`v56@HC)!Y2X!w@7{M%g@}rhL<^(obml*ZUWAD z#qi{dRrw1JZbxBr{nq*nfY!n%FOZMgDsP?MKpZ$b`0{~eiH9TNbGJ5|-&k+rkD$Yk vb>b(y_zh$}M)0XGK7Hfbo&I8^LX!l8ASjR+5fFjUq}NadsZl_X-m7$_Jd_riNEIo92#BFe6KPTe z=^z3E(nLT61f&E)$>#Ulo!y!Je`nvkHzH?p_LVkkJFELR805Aqq z!T2Q8CGz zqL`av|NUG-N>)Pbf7(Qeq$blmV)#E+QxUWxDKvhmYP3qwOXqL80RSXCHI9}G9KL}y zMD!?~gJ1pkMo8!Z=Uu4r1+Ms)CxSwb8kgK1UlAR@odmVq`f6Y5&UQ^I?B*fkcR{xz zd|KHQE7xAm>bvBD##vt_V(_rcY_M=pfs3RaZcmjj`&Q>06$d`4QWFJ34aUSnmuICJ zm`j&pjlRx#qRlr5Gw*P+f2~R_M?fLAK0;KCN#_7#61~3ADs#-OsO)i*5S2sI5B+J3 z3|4ZFJC-$LQiVZjca2WuwgmJ>uT{?BXV<;~Xn+5X!`It?hC_2+1l4W$VJ8A!dYDFD zx`ywN?u>+v^yD7`vwLG#<#c`#!&dc^Q!Q}KDv(t5l)^7#*Z!oKOxlmDPlEP^0@A1C znR~a1#HR5Um6DLE%@^lOro)H*XTs(iHixPC+hS_mF-i?|)RhI5?2_}s-zqzL9~s_u zZ(rlAoxAi<{Oo3W|K4v|c^(x@rYzytjzgPM!!j`qFw5l1kKvnFey1Ihjzpf3oep)x z!lfv9q4(A@^92Czj{iKVXgWA(R_1swfMZ2+qh)wopV($Rh!eUqJNWARpL+X74>upg z3?6YiBaJ^6PK!THi;?eAiGJIB4ho}zP|?7cxRQBtuo`G}?*gPxp=TrAyX?Ug-HT?Q zIk!T{YdJMBb^p9Q4WFUZ3544jO&{9msDvIM$i9Eg$cn*Rbra{lycYud-wXZ!yuttX ze@_i8^qfM(fbatT?xme6ai=n0y)i)9EMsiVdVj&7^PRJcm!( z4r5ne<=xR7R@@y3sXkl=N%~&1ACDsD$weP40s;c(gLV^@4krSgc0VtjRp}RB29jcY z|1ye%J@k-0TI3N%N%H7I{R@D|xDrZ>`%=TgUq3 zRPx5rs$#n?Ko6I?RX^AEaA{&NyY1f%^31KaGf5m0t3BI3H|L58CT_Y3d@e7)=}74N z*#K_2q5gdk`Pr+IbW9zxVbOTXfWNF(eKW({U=j|aD^5<(*PbjT^+GT*JuJm4I#a%|W>TcMm>-dk>qq&pAg}jrm zN{@-t_pwj{-a2zqV|*%6+fo*rHMkOgBo-O8bMo?kf8J}aXTl~C8^lw7v+U;IxsR<) zzV{%^a1<+R_=E2cxWKznb{6Fsm8~QV1ly+_=Y&ir&$oPZpENf&UixApVI8jH2nUzk z8-Eu2MOx4d_s5bY&ml6a1akyAR$#^n52doX>Z1p{NgpvQ53RaVug>=+nd8P$1Od45 z_Uu;J@{P6={VkFR#_;-tt3e z(y{C-*dv<5lGz|K$xqgQ2$A9Ss0=Fu_|D~dFYw6f()SOI@i#CE1#ae>}D9r>(qo586N1h+4^XS`~Gcw#Mkc3 z6l>PQuH9jG577O=cZ>N~&n{}xiL{-}F8l2N$8*V6PZV9ZnvY20FGMQJ%j-OvEQCc~ zDc!P?f{po%U%tuJdCug9hP`KKb67C3M&t`i*t}E!*GK6bKXaSp1h%OECyFvkahCUn zrbZ;aTK>h54_};(e(=ukh#VXBmMzPZtqF5+^RNeFm2bN}2;Lm5Fe}%;p8u!p=&zfX z!rvP~|HX8`=4{|Koo&S+^7uUYv?}MyaK_NTbjBGG`Ot@M@}jzvo^zH`mNwGpM(@8T zb%9>B;Rej>gn^k)Z*RO+4f%GlfBB$$+Frgs<2*57KJ@sC-ddEC2zeb``>burLMT`d zu>>z7`RoQ7H^u!e12N6py{m1f-AxRn;Q1hdqRZ58`I0CITsZw1L>?+9hEBSBR`5#Ghb5t8 zcB_-G@p;so%xY;=6e~l8S)gc*9yvU@ai-9OP2p_{M!~bv8cVt51$W z{s+2pmCXUiLzc>fn~9|bRnd5%rNo)0ys*DMtVk+DJ%O9k0rJ8Ob^CrnyX9c>;qL1% zsS8P2EQ`)ka^~V^i6L7xmm`&%beO` zJURb3P>h@V$}kU+R^f?{$7l={Jg@2T^44i?-mYS;M^hsv9TBUA1-vC*7INI(z4WA& zL}w)@FZ(fMt)qx>6`ZNh9bCzt$zC1yET1;WI4E!GDK4374C^;LUa4E3KbZ(ja+G1Z zV|+fG<#Q5w`vo~Sk3^4E$6~WYF4ED(L`ra&v>$h#wiJ7aSTxsGH-?=i-kW>0w68vv zroNca;&XITbelc1iZh|irW#k8nIc#M{d?u|*-w$vO0U-4IdG}9^}6OO>YVrcYt!K2 z*4cpm$zjq{0wMfQNTY?MhZ&-$rzW5g-@di6d26mGZ74_Kf}O=p_EryEySW_Yl)Lk` zRI02}-*PdfV}~H_9*c+3`R|A39s8}GZc<`FQBP>O{?p6ATYC7}QrqzsIgy8K=;%6g z*C-D2V`i2J&WV5ZX*88eyrIMMbgTKPr-$eH7)gRG$}w!^rPENZg4NxKQD>7hS`78i z<3Qpwr`^ST4HO`nAQJL(Dsg}9wn$qBV<)#|1)a1c{%}cY??vT<)`b=#k~02QY1vm- zQ;3V(hy2|ofFj>gj&FsK4l2&Dc*d!;-CK2e2gJB;c)MsK@5kX-C_=7oHfaTD=+zA;;Y)78?mpj+KhdvK#08 zbB#EeHN*1>Gc)%mWO(cl4vuy~2KW3e2~V}&55X6?yjp$zf$@=`MqWe^@5*!nLc@){HLupn%Q{KUB^YyDiW3>nY!~`X6CV#^gUdi z{{-j#2?tAD_0*>dzjVl8y1Y!lz0m?t>E#puqY?{$OjDK!h;PEpmi9x|`m?{mh?ru3btl%rz zMypUjadkM9y??xpSn*t12F># z;|;{K3=f^y=Xe;+gW%K6Wmicn;p^*Mc}FL!SatMg4gdz9nBdd5Y(2~rISaNpA8wq_ zAks!M$8p%A3XW_Qvjm&rMQa9f;-?z_XHmt8NMaU$AI+osvv*UKiijw%EwXWvEUT;&+AMR zB(mq!31}GP4zI+-)I_{_i8+TTt0PR8aRRe5N(OK{>FAOAO}d*E3~t@&WBkW-n)8pB z%TK3NvG?@EFEg3*Gz?pP2s-ka3x zH#>E--94<<)lR27%WP~gqd&&fOeE*{htmV;nmQzsw`0d$Do+G~fUqH8Wf<*3!VRf< zmn>LnVXehYNY&=YkHY1W8V-wN?u~njygzSjH51=CRn+#6FOKezy3dJ=yy!=FbQQeM z6p?Chki8;)L3Z~9thv{AntM;5%pEEpa+x|`^n_7~^rF(UT;%+-C!%K56E2H$t-f3L z+DLZ(os1l@6)59t6*DNV!vp9D8aPEWYD2Oa%hZ6g@PUl!SBh3(1;g_RCbcZN-)d_Gf;b+AJ3dJFDU1T5pfZZtx5!_nMh7jSsi{ZHsqU zWXeVxW#G)fi;>co&$GurVl^!6xI{~X4Ny13Z4wNlDt2*e64%taCQ!TGD=Xg8?$a8^ z2zaMss9j%l%NF|c{83BgP3|hIpPvWUz#T><;%9w@-IMfq!(S^cbn$uDyL&J|h>q8f znb4)Vx$#}6A@}kc$$IZ)=Pv_Ab-2a37T@9PHpLv^7@bujeuT%R9owmLY6tF%gpyK+ zL+70y1ReB!u6G%7_o~e54rVDBl39%-2oZ@at;c<(bH|B^{^&gDzQ7+bPg9d2A-t$BGP&X--p)M=(ZH7zqXcB0q~Uqa~qK7Y1q zr2xvlIz8F~P+@-?--iAE%pR@&@MvS=wwF~~UCmpDq0Em$QrDNn$6}w7V0nkhi%a_q zeva~4w>FKPq~>R*+Cn_z>Gnwz=K#RgL`4;1$;BLYW_5hyfz8@!;9P5%v{eXklPERW zo!9L1S}+Gez14Z->m-~bC&ytDKh?bcu>;KV3R_xt-*9aNKCO`+&jetKiapd4Zh6jT zmFW$=l8GpcU$&LzKml+8R%E^6hXQLiTOC0ZFdX(%2DOn@Ayn3|JpIzw*+Z8eK^M{P z+9=x1Ys`v?jxR73&KOoA4>aBKJUiN=z7Tq}E7FCI9t){IJmNY2$NsA2y{~jz2ZFrx7H zj?s;ho!9#|@1?kz=)g@8PjqtIL4;LVzpa}rJ@T(e*5i+j7Uh2kwrbrR+S)kv@yZO0 z2I{;be>h=?oskAM%C$8=J^jNLq{eh*qAqxNdU9XpzT}nyg^+#V zh7PrhvRn7`?8+TF{S~S*`rlg!UtH=nHDXO}+dH*7ET2D8a1#>0d2f(sJC1PEFx@?Sy*FMw_@Gnpr|imIHWa>tQQzup5cCSW-gUk4 zN`DVOAhf&Uz5Q)sWpS~+ieGoF+y7GYJw6GGw9jYl?SDr%oTs4HlHB+FM^#lJ6%Tc4Xn6MQyc!-! zvo3TY79S@_b)l5%0`fIRR|`baXj4JEBB9VPLxhq5W|U6KREQ#XVwof!tsMgOnBkOi zz+LP5YBE?aWTjH-_!jLt1>!gix>Mrw=!3^l|Ej8AE2JsM7kDuqDUeALW{Y zt3C2sA3J!w*XY(tSa(b9_=x^@P%cOAB>!{UU3NVvymghtF$hU<1(#08%bD%;SgrZc z=P|-B^tetIN8MMqox%Dac{iV3>>sxst+QNJgTCIJb{q#%P_UnaO>!PHS9pe1nVjnD zfrW|98G-JlsSpE}eu4?DT>`!$gK?|VwJr`*QLZ-T+4SAQ4~>=tZCs!=*v zX3qmj?{=N~-g{5*JL?J*(rBq0mSr$sYI=0A;q1Zuy*2Q7uHgX~OmtTCn!ZP&^miKt#QW$yru(BE4J|X4Hz7nypnJFYbbKKhE zX+Aiceg1R!>|Ws34*|`k;A730n$IEC3unQc?Z+@Xp}v2oTwClF z9Qu5ib8H?nD=UNd_pS38w7=f>YCUCd-7BhC&&*^FoRf0`AZ*GiSU4O8O-@vyaho#r ztx{q{ULFKj2x4V!hVR@iC7vtA-NphppH^ge*pzQgFTeNCP}+}m>MyX@Yc+d_eba9t(ZD$j~irr^DXNyY5tHYM^MDXOZ@4cZ*b_1iM)iqLIc4mW#Uu3Z~ z%2F#sv%%|QYtGWsvombzxwF9(V%Oj`FC#CzF)h_)aF;q6jf!7>?~+9jEcb8ST^i-r zXmjOK-guD>gFr}ct#B_&FV@CmqG3tTo|Q{luJ$b1m|dKsv*UoPr{h!5Tb;J8nZv98 zpyf-{hXRT2C{ad5bn;NJ0k17~r zdssFgAZfL2CwG#hwAOZ{c=)7vcmB~TsXXFMo@uswQYJnG3bS3@aIaQ%MA1ZzyVlj! zHCo(kAz}{ACLaV7r(1Go7eW(~@t!}x5G(9U7+}&R6NAS@s#r!jhd@zJ!%yj~9o_UM z{V~N3W1Mzc0^OPDd+#A4ApFXiF!3>U7` z($aoL|NA>Q({_^GCPxOhxI*0ZbB{95eIifh9S+`0|J=B{I^p^jQ$uceY;J7$d91e(TZ4(SZrEad12ttf2oCj1x0}H=(>Nu!Wp*&ppKmE)zn$84 zUi9h9+#4DFMZD1*GsWe7f|21f6kE}a zcuy%7Ow`Dw)n+PQ6`k^}2Vh&k>8(~$B5o`!jd)1boY`QXp}t>%-Jx}?n)r+NHzpYjBY{MJrh zrr0QEYvbae?{`oPyr{WgoJZ48uu|TY(l~BogPnW<2FNyI{>)Iu9F}GVlp&vf%OD+!lDee4iMQU4Q(cWuE-#7jS4C`+NU> zV4h-AEWRgReQkr_0@23lU*uQMpa@=>;I=jLRapVvl@;8_Jl;}~{Cqf67kGUMgSz?R zhM`JV{d$E}+e1J3s|77BryM^UN1eUAl4AScqfzUZ`TZ34K#$4VZcb&1j2HbGnMTlo z%c>Fs-I*L?Q@&2jzOGH_UUQGgLz7mImse(UdxE*hY(&g7T@bY9=pSQVi0o(ng8p$G zlPF!?wGJ?9SF@*Q$Q=HN^zO#k+Bb8#?BSP}fXrUHow)|RY$J-yb37n*kT}Z1f*a?s zOOTO$H9Iv$KgT{HW@wgfzj4;Ch{|y2jn4IjPS@TniR<&J_MSL@u5++_Fl-1G^1*-i z?wADD;)QyGi&Qr9>(Jcab*~m8m(>wzM?TPmEDloEiaZttGm@=QR8bX^>iVTlNqU19 zPZ~$PO9(UB>kfu6--OpLSq1!MzDRAIpP^bQ8gEAZK1y*g!Fq$|AIy3I`4R+~$D z%xGv6@`2R4wZ!`k7K^Y^&iiRagvay#bCq|QO9DKyjeh)?wwO2Fx>ug#yDFUXaOmPt zI_NK1Lf7p*77!SC&`K)5XZts2fAu-_!f;ivcgW(#UCWC|4G5`gW9e-S}z5L4r z_T85(i-$puiHR7#@y`UePy^i7skK2;&zl;jVU%^7zbNNrRaM73C}_A=xO3)e{Ab&0Jf^?~_2+G~ZX^gTFrTd3 zlC`xh=rEi2*VNQ>-#mCJzBL;JHd@qKuB&Njuf!MeOU#kaZnf>^PR_{==oRu{E8d1# zXLGIR9sTmfbbEyo$Cuwv<=nyA*PFsq(eUy2RaR#|S1G(V92$Olg8|jD*LOqLB7J#< z^i8&@sVQ)EPQh_bF}Pl+6y&(dI*ya!VEVpoFLo)ZXMjo2W2W`s50|E9&-%JCHfXmc zyTZG5mr{9PAI_VppJ?45YHA~`x3x5Y+aIM-ZoPbWng?uq+cWAFJr=Vn9y z{z)%(0Z(s%x3TpNQj^!0KD#<3?$5;&>O3W0ULJlC@sTqr#?9>l8+fgtKq$u_XF1!_ z;Jdm~-kx8vF4(;YxL66RFzt%#<^z0sOnA-6(RbCWNyb^bDB0AFq5_?xKTXjR0 zr&+V$qaafd3O4*hN}o@Lgww01#!*=tX1HtNa+f)nA!48kj;(+BhZt)Op*xL4U3+^q zM|?MCZ87EaAw{Z0U=M#xVfYal$^6&WK8_Uq%5lKndkF0{U!oS`^2)URZG<(1C~LXG zlqG5254px6)p>r7Ox4*Wx@Q&Nh(qx_e<=9x#z@Rl7$h8)=`3rOU1=WiOKnfv989UQ zkP$C&Uj~`PudBG_qJQ^0WIl%}(_+tIb#rV_HkLPys6NAtJ~jnPfS(lkr~VW3V^mGp zJxnV?*7_3n>8WI-=!ob4Jak~Xm3R;5xDi5NsG;!YKQ^vvxXDm%mpqGa_cnENsXM!; z4J~E+fs%TI0y(*+q+`K68p_PD*GAbNd~i(!uY9|PmYJ4gNNgyQQ{oOlN?G!Dq}94i ze}1pckW$F2-1U_M!oft?b*jIDk=9J`U{bLW<<^u43^)iNCUFz@73h6@f3PrKofxXn zk0zL>S9qAy@B$GbVW!}pf$n@Elh?b|``Rh^LIgELv;<-e1Ni$p#@XQG4oJYzVHupE z?0MM9e^f~9D;m)B+(4=!GrqgZ#`SLQQ_i2-HZNhcaZe|^hcs!&BbF{AN<^6B>6MRj zpg8_Nf_1sBg5@?(N9yn!WuZSNiIHEfev0YfMg6pw*j5xxCXU90W2u0ALkT`J;U-wB zmaT@7vLViZO|3Bhw7q0Pl$ZA>NN{0vqBlh7&d(s_m?@PP0~ksyDW;AEj)*8kkXFv} z0qw}xtO>482NeuMP7cS_Q-mqNVW^x6Wi3kkC`@4BvSaRvjH&_4;*^4=Wq>>LRe}|s zl`n=k-R^qu=Q1jGXDTae!;$!l(dyP@>vmm#7gCfljR}rMR}dN=4nhF}3MFXCUfS`L z0m-@yU-0{NFMo{q*-6;5lG*A*$b{IwYK6{M~0?`w2@v^f5_#{<0c zss#9?eczGR#JV%I2|@MyqxVC@mK!uif<~+xrY4p6qM-57aB9viE2=T>?gmd0de(eJOy{i!gC7h}T zXsQkU@BQ3*6v^%`TLv6rJsLoG`dnE>Jy{w4TH--h449cRba&Hr91{*ewTxKdZspbW z9&)<81wH+aLJ;g^;FY9dBSpmGO z5eUJlTRRo-^TLwxPYL|RXhIeMtrA584EShBEvL!Ddgp0RHlu_BY(fk!_Jn}>=6{>>*#ZD?Fll2|OceRF1>jG8AHk$) zDH9x=&L^FW@20Axn}jChSJg?awXG+^Obk_0OMdqP%F2;YYsQNPxNGM?9KEGxq##wK zE-ypqqFusQ|7wr~uO0AGc}poJy*nB(UX3o|nq0P>B4r9XRlb_~)f&%cpulb7AYcdp zPoN{Bi9I+o87B`VP5>n+3UO66Fxd=Fq_VX_kC2`h?0I1$rWIBg!%)8f=_?c4?0HQR zB|5mwa&sO#%Zpq~qhQfydFg8X)c3~*ERz~AT7&`4L@u3XB$g&wu`w}LD8+^kt09UW zGSUG;cQ14zu~>ixKE=V}quTYRAL1?hN~S5J9C9g?*pQN4h@!JFCv)?y_$#Sb*qP_Hh>z0C&V|3bvUJMV<= zZ97~}ZwhMo3h`LHGqZm5@>1*G)+34^o=Aqc_?8RnB3??~M3G=Z$t8tps(1iQYZoba zT7n;`1Y=NpG4wen*9-i7eC(A>!X+btiduSaU%UL26b3l!Vt(IPxMn)_0zy92)7Q>K zyxpg6H(V>m;wUUIkk*z9RoyOk40N9+=K86GIxSd~z99U)RbCF>by~!Gt zkTP9iJdQT{(42Hs;sfM7y)k2K7~9^HS)~Nxcs2TU@!j4D^Z+b8GZ7Q<@v_Oas}No) zPChy$GJ&&e-9XqiL_@Dr&7j8$KJd?nprETt1HHRF_M>%!2!?QZfWX4$=vw6 zxO^|)*qi8G?<+w^%kw$rgCe2yJ@`AX?*&B^X>(2yY(jO>-~sbVHr}$tbJ4urwWddD zXpLAyCgZl-KqPA_9%Y@U@{NQrZnL8l762^??q5;)|0&yi+tcID66RRpFt+M*V?IVS z4b@b;Gx5HoLW(`KOh?7x3j`S)%y?OWSV6dpQS3YYcYj~RQi5F~3IGLDNHVp(^zbA~ z)4>{lLaZT>pD1u`&FztzRw?c}6;L3E$LeA(YUJUL`-zA z40Y&fc;VAXQ1YECm{6|)`LyWW<=)qE5bT1bVL)Z2u&%n}HB;_AxdTC^4Mk=WI?lmy zJIKT5o|_vznF-b5G+!9-*j7gSL^OOv1s7LB5Wa8Y$n+&Y9F{_3sF9Xt;c}H1e#s8U zThuCL%8Uf0v%!cYG^LUTK-N2iX2QcQ5%BcP2VmGSiKqGTrt_$v*!}o?Xg)(JE(WjI zy-X5O=2guB`>8<8XEGSP}2Ro;7jxDHR&$q?b;N z;88gru8A{kt-=WBN=71MYc$w|xHdsK8#u%W%n~@58i>5U!>i+Gw2UV(7@21yum~8$ z5ErTiyGjM{L-_gmc@MmF_))r|ed(AaUb;_j1j`yfVE(qfW$f=HpjB; z(#?sv29;J3shE1<^$rqiNJER2O0gxUU8wH*^d&Ctv{e{&;hHvKS|1+@!$Gh#dWui| z0fv0-+FcbKtX-@ci8bw~z>hZxNa}mps`t9yFv51dldy|%v6O|tXla-fd0A2W_pR~Y ziRV&UXJY5Je4ibPoPx-3!3*#3>EExb6CV`-Rj!={YouAgNyh23LM^4Oicsa~Yjo8X zffyIo;4vDT^(?kJa;}1Lkank;o7n4_0i|(I8so`f<`27Upv>lSc#1e z3gd!*w~5;K$3&*ugfTwWI%4~6n7D34%Ni$0;HT(B6a3PvR=ZJjpyys0I0G$jj|k%deLxX2_xNeeZ5eQM>IhuZk?{9 z-3VMQC;@@9JX2OG4C8u$6E8I^<0IPkPjBBP+TU&e_R;IBg~qnJKgW8jZ#Uw8tMykZC%MX& zEd07{fkVJ?$E_@nAGw9NFvcDZ%`t^{1*4v(futd2JU%XT`iJ(@x31*7WJ-Ub;2vl* z&-t6C0RL2VlGaVSxJ%~RUmFTFO?JO?E>&fXi8w#pEsDb9br`gzuJ1SQBQNMAWTB(Z zS1BoPg{4BjwR-$MRs6#nO84XVDiHUxmk|bpqt_bFll=0-s-X}89?qkxf6#3$#o$Na zj2M!awOSCq-$Uhx+;cMhM$7(#c%uDBjojSVJE>5j3I?HJuOw6<&>ef=_k1+T(oXpg z`HQGpo7afaDfF}yfz(kHS!!Pff`Xvi-wqG}wEeolNM;K0b)}h1o1%$2_T&7&NR#El zc}iOY-*}otcL~*L_4g>SUv_(PG5`)oB9(P~q_f}s$@kHYgoWsyHZ}L1zIlqP)@N0PedeDQNz9^m6Zt}`#tTNj1Pt(Z&_@cj_QM<5q zAR1m9Z>S=v-EquZdB;3^FFup9&7MOuwIpTwDUhderlnSGHL2`jm%KK}^H zrff8jMDFap`l+*t5>}XJ=clRMZlWr(D!|tD_sWIOdE*e#CPr;3Q*Zype>pv`G(t{= z#eU-Ci)`H#zwq9nx-bKzeeKeOj>8XKy7-A7_PGIWLXRAd;JI@?Jcjt~;3HKW73>(M zZeQ)n##>Z~dPYwls(Y%bes#oH#Az8uKb$m!M8!eXwJdC0L zof7)o-^uQh$2@jc^zW|gd9$Tmf{gHTbf>eM>lQ`M=OlVP5BZ^bT zTOx7hs$;kAW3@m6G2VWm(CV>L+K6_k0WOot$84aJ(hwD6&vAT>lg7NR925O=dWhIK zFyyV}Y6_7kE)0L_o@--p=SRTJ{Cq0T4|z<3JOj_*;~YAMYro)ITt#j=aZmyJ@aWWU zva~o#b?c2FyM|(dJe7Px2PfQrfS?oUu*l$~uD?{w^YJ{qKC?sNQ|wefhA|>_xjeg5G$Us>ng;? zJj}Il@Ys%8HGvW(0UFW7%!`x`k3K5-G9Q=k)cufcQKqq@HK>U}Iy2E@l)dyW)<_3x zz?K2aEb)k7!0(OkSeHw7E4PtiOA4ZswU2x5V~^v4?7nbnM8cK|)@*gI_w<*Rs2Z^; z)0$vS@P-gTr61KcqF5Eu&)q$>78GhgRRZ$EFeunR+eTKnBO&Kqj?K^K1uRH}zKu-V?Zeui#yKu~7*O3~QuLT_;)hqFf@Fi-~#v0mwUASr{Sk`+< zg+-9E!@raCFV2~#_W z0V3g{CEjE8*dcqZgbJWZLw_GOgTQNR2XrGv`5E~numy$61aGplXp7a6aA*eD#`JCY zG31>H&sFRwHVqa59MsrQ@@a5IgiJ@F_fIV6%()O5FV(LVeJ393Ys15#%)T~d$bbnF z408NO1ETi~24UzFv5-;XzpeVGDKDacN_k$2iuA)}Gx#h=LiOG?=_!$j)DV<98buo( zsew?{Ju1wMp-8z;JoGdoIu4S&O#ZlCQvb$D9ggKlIYi*2T=05dt7^mU0{}KERykea&3BC+(^ZI9CJZff=i7JpdK<70!6RHjqrx~K zzr@@TUZ;B+F_Zv)3xpXd1Da4R2t)-oYK~~{1$v6qJ4y`9)gn{=DQ^QlfIM$x@h&B$ zP=#lnKL=!D3(zPX%mKY>3i>rcOP5d(Y04qUgh{p0z`|7uI(Xqdna`^jlj+|G#$Jqm zvv*AQ)hi6Hl}Oc%?D*PHU=2eRAVm|j3JaE|IXf~zrw$er-KPk{sN&t4?w&M_2nb4m z3i*WULPPbHyVoFs&d?{&h~K9tx1_ZfpB%sRKxMr1u7_ylQ}<-_BHeU5JNSS8paV8{ z<+ULyZcf0%H8~ADCblF=8*vG)OmSf&vkVotG6g#aUz-9SG={OjTDK`3AUjyI9>-7dogN4wVwd65ttzFeiM|T zNIc=YKQgw9w>{?J8mZeH(_7-xbA$Y0YlN60PakHjSe(vMD%{)__$|=q09nG1N{IG1 zGu?XQa2~TCpM72ZIU%&T_9xwuM+rmGGPw3hZ{60&tlva#Qs3TKmo>G71I1^LHQZeK z#Oo^i@^TEn2m8V=kP4T~MWc{O3E^8qXFIdAr}evfGgP1Q3CeZD6DHwOksqg}yBcEG&-8uM{*A5kO|N2?n zo*WhL*SD<@WgdxNOczwGRHojlUCr4uSsTV%)v2WN+Uceg$WJu=Yq?JMNlms*@@S3c z@k8>0X+g;G{<`2(X!eq9F=4G4v^gk+azvf`FJEE%OM zb90M}A!g=+48|-vklZ^l4F^OlDp`7F^-iFN+`J;lJ?f`O6^=opFnr)@g74jHi`w*P z2pXr(rmCY2oq_>fl-Ba+X!sL5)e*G0^gqMysM!aVUK@iv#Ka@+)K!4x9V3SC5=(z? z$=R=()kzHpoSA)9#w{tnE)(goEn5sSC9ZqFZn4{3;qrFD%OtuApR!Sr3}2c$nk5xX z*+4!j9L=h7)rE?_6Qpu|8^snmQmeO~4U^-`{bpg#hw4YzzMn|Y3AB+7`f+O|SeJ6f zq^0okBc(h_Q4xLngLi1!FY)~vmF$sqdD}@lG9DP$ZvT74LYgGKc_VHJ`cf%rr*^$ zZ8kpUtSG38cX*RUdL|IsS_8c}lv}ui--}99jD(Gq2tw3xnTFW=Jf!+OU}Os-j>1G1 z0=$G!pGbVhv$xPxn{)*1osvS37$NtyuznQz2Zd-p&vc$TbQqH=*VoQGis-6)?=8Sb zqfWK9+QI;0t~sho%h2(5Ayl!yhpD<#S4N;HR$CfCUO?cSs@B)HSskb1@AdyJGQGxx z^5xcBvZt7)wvBS@wpvlV@Or??U}ZfdXoA+=4A<6-p; zfwK~>H|kkxGi0*N@KGgYq8I6CI@5m2(({@KX!V^#kK<@DZf1_d*Ei%_%LEqO*RSU%fb zbm&1yEX{}~_3X%{kn%pK z{5In(ofwm+flmE_1OHqbeXybIw!9$ix^1QFyX{OLz1-4iw}~hlTS{Zg_4?OZ z5C)7rQZ@b+u;ch^`LV1OGy9g5>mc8$)d=d-DSUi?@bIT?=!f6K8I#!-(F3J=RN-%X zl0 zqfY-Y6~}ys+dqDedV#N+`0Pu~pK(%m1W0(IrmI!dOZ8VH9$;B^Jc(KFF;2Gj#1JLl z4HoIfP6{#P150UPCkN8>`8qnJ6U)2fwKu}fL!sM>=`C4`rhVhAwy9l!2{S@A$$sHV zf$df`o_6H@R@-UOh}5SC%3W{NljOAJ*$qdDr%&Tc_f}RUOCPHmHeGWhf2f~j0t>EE zYn7c_2vj?#JBZ9w;YCC|9pyWE&fz?)&*EcndrY zk2XlWsHUu0;)>4)?9Tz>F~D z4}Yai6?)$>6Jo1ys);!Rvxf6BXtv(end - start); stats.sample(1/elapsed.count()); - draw_gui(window, text, stats); window.display(); diff --git a/raycaster.cpp b/raycaster.cpp index 85c1efe..7e43fb8 100644 --- a/raycaster.cpp +++ b/raycaster.cpp @@ -17,7 +17,7 @@ union ColorConv { }; inline uint32_t dumb_lighting(uint32_t pixel, double distance) { - if(distance < 1) return pixel; + if(distance < 1.0) return pixel; ColorConv conv{.as_int=pixel}; conv.as_color.r /= distance; @@ -84,7 +84,8 @@ void Raycaster::sprite_casting() { for(int i = 0; i < $textures.NUM_SPRITES; i++) { int sprite_index = spriteOrder[i]; Sprite& sprite_rec = $textures.get_sprite(sprite_index); - auto& sprite_texture = $textures.get_texture(sprite_rec.texture); + // auto& sprite_texture = $textures.get_texture(sprite_rec.texture); + sf::Sprite *sf_sprite = sprite_rec.sprite; double spriteX = sprite_rec.x - $posX; double spriteY = sprite_rec.y - $posY; @@ -103,18 +104,10 @@ void Raycaster::sprite_casting() { int spriteScreenX = int(($width / 2) * (1 + transformX / transformY)); - int vMoveScreen = int(sprite_rec.elevation * -1 / transformY); - // calculate the height of the sprite on screen //using "transformY" instead of the real distance prevents fisheye int spriteHeight = abs(int($height / transformY)) / sprite_rec.vDiv; - //calculate lowest and highest pixel to fill in current stripe - int drawStartY = -spriteHeight / 2 + $height / 2 + vMoveScreen; - if(drawStartY < 0) drawStartY = 0; - int drawEndY = spriteHeight / 2 + $height / 2 + vMoveScreen; - if(drawEndY >= $height) drawEndY = $height - 1; - // calculate width the the sprite // same as height of sprite, given that it's square int spriteWidth = abs(int($height / transformY)) / sprite_rec.uDiv; @@ -123,29 +116,29 @@ void Raycaster::sprite_casting() { int drawEndX = spriteWidth / 2 + spriteScreenX; if(drawEndX > $width) drawEndX = $width; - //loop through every vertical stripe of the sprite on screen - for(int stripe = drawStartX; stripe < drawEndX; stripe++) { - int texX = int(256 * (stripe - (-spriteWidth / 2 + spriteScreenX)) * textureWidth / spriteWidth) / 256; - // the conditions in the if are: - // 1) it's in front of the camera plane so you don't see things behind you - // 2) ZBuffer, with perpendicular distance - if(transformY > 0 && transformY < ZBuffer[stripe]) { - for(int y = drawStartY; y < drawEndY; y++) { - //256 and 128 factors to avoid floats - int d = (y - vMoveScreen) * 256 - $height * 128 + spriteHeight * 128; - int texY = ((d * textureHeight) / spriteHeight) / 256; - //get current color from the texture - // BUG: this crashes sometimes when the math goes out of bounds - int index = textureWidth * texY + texX; - if(index < 0 || (size_t)index >= sprite_texture.size()) continue; - uint32_t color = sprite_texture[index]; - // poor person's transparency, get current color from the texture - if((color & 0x00FFFFFF) != 0) { - RGBA pixel = color; - $pixels[pixcoord(stripe, y)] = pixel; - } - } - } + + if(drawStartX < drawEndX && transformY > 0 && transformY < ZBuffer[drawStartX]) { + int vMoveScreen = int(sprite_rec.elevation * -1 / transformY); + //calculate lowest and highest pixel to fill in current stripe + int drawStartY = -spriteHeight / 2 + $height / 2 + vMoveScreen; + if(drawStartY < 0) drawStartY = 0; + int drawEndY = spriteHeight / 2 + $height / 2 + vMoveScreen; + if(drawEndY >= $height) drawEndY = $height - 1; + + float x = float(drawStartX + RAY_VIEW_X); + float y = float(drawStartY + RAY_VIEW_Y); + float sprite_w = float(spriteWidth) / float(textureWidth); + float sprite_h = float(spriteHeight) / float(textureHeight); + int texX = int(256 * (drawStartX - (-spriteWidth / 2 + spriteScreenX)) * textureWidth / spriteWidth) / 256; + int texX_end = int(256 * (drawEndX - (-spriteWidth / 2 + spriteScreenX)) * textureWidth / spriteWidth) / 256; + + int d = (y - vMoveScreen) * 256 - $height * 128 + spriteHeight * 128; + int texY = ((d * textureHeight) / spriteHeight) / 256; + + sf_sprite->setScale({sprite_h, sprite_w}); + sf_sprite->setTextureRect(sf::IntRect({texX, texY}, {texX_end, textureHeight})); + sf_sprite->setPosition({x, y}); + $window.draw(*sf_sprite); } } } @@ -328,8 +321,8 @@ void Raycaster::draw_ceiling_floor() { void Raycaster::render() { draw_ceiling_floor(); cast_rays(); - sprite_casting(); draw_pixel_buffer(); + sprite_casting(); } bool Raycaster::empty_space(int new_x, int new_y) { diff --git a/texture.cpp b/texture.cpp index 991d6a2..bad6f10 100644 --- a/texture.cpp +++ b/texture.cpp @@ -28,6 +28,11 @@ void TexturePack::load_textures() { floor = load_image(assets["floor"]); ceiling = load_image(assets["ceiling"]); + + sf::Texture* sprite_texture = new sf::Texture("assets/undead_peasant-256.png"); + sf::Sprite* sf_sprite = new sf::Sprite(*sprite_texture); + + sprites.push_back({4.0, 3.55, 6, sf_sprite, sprite_texture}); } Image& TexturePack::get_texture(size_t num) { diff --git a/texture.hpp b/texture.hpp index b112f4e..28bf7e4 100644 --- a/texture.hpp +++ b/texture.hpp @@ -3,11 +3,14 @@ #include #include #include +#include struct Sprite { double x; double y; int texture; + sf::Sprite *sprite = nullptr; + sf::Texture *sprite_texture = nullptr; // ZED: this should be a separate transform parameter double elevation=0; int uDiv=1; @@ -22,7 +25,7 @@ struct TexturePack { constexpr static const int TEXTURE_HEIGHT=256; // must be power of two std::vector images; - std::vector sprites{{4.0, 3.55, 6}}; + std::vector sprites; Image floor; Image ceiling;