From e973a129b5b83b628ba3f09e8c95682fc74080cd Mon Sep 17 00:00:00 2001 From: Charles McGarvey Date: Sat, 23 Jan 2010 18:14:26 -0700 Subject: [PATCH] library class revamped as manager, goodbye tilemap --- data/scenes/Classic.lua | 11 +- data/textures/AlienWarrior.png | Bin 11985 -> 3694 bytes data/textures/BackgroundFar.png | Bin 7707 -> 7824 bytes data/textures/BackgroundNear.png | Bin 18076 -> 17779 bytes data/textures/BigExplosion.png | Bin 11305 -> 4880 bytes data/textures/Bonuses.png | Bin 9207 -> 1649 bytes data/textures/Building.png | Bin 8781 -> 2517 bytes data/textures/Font.png | Bin 19065 -> 5694 bytes data/textures/Heroine.png | Bin 14129 -> 3967 bytes data/textures/Jetbot.png | Bin 9634 -> 1489 bytes data/textures/Particles.png | Bin 2387 -> 1452 bytes data/textures/RobotTrooper.png | Bin 12162 -> 2688 bytes data/textures/Scenery.png | Bin 6872 -> 1280 bytes data/textures/StatusBars.png | Bin 5267 -> 414 bytes data/textures/TowerBlock1.png | Bin 7866 -> 1373 bytes data/textures/Trees.png | Bin 1128 -> 1247 bytes data/tilemaps/AlienWarrior.lua | 4 - data/tilemaps/BackgroundFar.lua | 6 - data/tilemaps/BackgroundNear.lua | 6 - data/tilemaps/BigExplosion.lua | 6 - data/tilemaps/Bonuses.lua | 6 - data/tilemaps/Building.lua | 6 - data/tilemaps/Font.lua | 4 - data/tilemaps/Heroine.lua | 4 - data/tilemaps/Jetbot.lua | 4 - data/tilemaps/Particles.lua | 6 - data/tilemaps/RobotTrooper.lua | 4 - data/tilemaps/Scenery.lua | 6 - data/tilemaps/StatusBars.lua | 4 - data/tilemaps/TowerBlock1.lua | 6 - data/tilemaps/Trees.lua | 6 - src/Animation.cc | 38 ++---- src/Character.cc | 7 +- src/Character.hh | 4 +- src/Hud.cc | 6 +- src/Hud.hh | 8 +- src/Makefile.am | 4 +- src/Moof/Core.cc | 42 ++----- src/Moof/Core.hh | 3 +- src/Moof/Error.hh | 7 +- src/Moof/Image.cc | 66 ++++++----- src/Moof/Image.hh | 10 +- src/Moof/Library.hh | 121 ------------------- src/Moof/Sound.cc | 85 +++++++++++--- src/Moof/Texture.cc | 196 ++++++++++++++++++++++--------- src/Moof/Texture.hh | 50 +++++++- src/Moof/Video.cc | 45 ++++--- src/Moof/Video.hh | 47 +++----- src/Scene.cc | 26 ++-- src/Tilemap.cc | 189 ----------------------------- src/Tilemap.hh | 110 ----------------- src/TilemapFont.cc | 8 +- src/TilemapFont.hh | 6 +- 53 files changed, 405 insertions(+), 762 deletions(-) delete mode 100644 data/tilemaps/AlienWarrior.lua delete mode 100644 data/tilemaps/BackgroundFar.lua delete mode 100644 data/tilemaps/BackgroundNear.lua delete mode 100644 data/tilemaps/BigExplosion.lua delete mode 100644 data/tilemaps/Bonuses.lua delete mode 100644 data/tilemaps/Building.lua delete mode 100644 data/tilemaps/Font.lua delete mode 100644 data/tilemaps/Heroine.lua delete mode 100644 data/tilemaps/Jetbot.lua delete mode 100644 data/tilemaps/Particles.lua delete mode 100644 data/tilemaps/RobotTrooper.lua delete mode 100644 data/tilemaps/Scenery.lua delete mode 100644 data/tilemaps/StatusBars.lua delete mode 100644 data/tilemaps/TowerBlock1.lua delete mode 100644 data/tilemaps/Trees.lua delete mode 100644 src/Moof/Library.hh delete mode 100644 src/Tilemap.cc delete mode 100644 src/Tilemap.hh diff --git a/data/scenes/Classic.lua b/data/scenes/Classic.lua index 2ec9e02..10ba6a2 100644 --- a/data/scenes/Classic.lua +++ b/data/scenes/Classic.lua @@ -1,10 +1,9 @@ --- Scene: Classic Yoink --- created by Neil Carter --- converted to Lua by Charles McGarvey - -LogInfo("-----", "Scene: Classic", "Created by Neil Carter", - "Converted to Lua by Charles McGarvey", "-----") +LogInfo("-----", + "Scene: Classic", + "Created by Neil Carter", + "Converted to Lua by Charles McGarvey", + "-----") -- Scene API: -- diff --git a/data/textures/AlienWarrior.png b/data/textures/AlienWarrior.png index ece94d08932ef3ffadec3113e823a074e7df9d12..c93ee69e9891c01c1303b4c16a82cb380047b263 100644 GIT binary patch delta 163 zcmcZ@`%Y$p3KwH>kh>GZx^prwCz@&2Gq9I<`ns~;ViaW&wYr?v)5pNT;9KGvQ4*3` zQBqoz>Y108&rp(?lUf{KtYE8P!3ANL0NEy7xtV$KX_+}CsYO7ppQ~e#Yj6lxZeluy upi~*B6$1nBR8JSjkcwMxWACoj+0L8B|L(x%nezR-oD80>elF{r5}E*JZ#NbI delta 8497 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 Hu~`-X;ASpn delta 21 dcmbPWJKJVL9M?@A76CQ>KL!h~Y`nW!764bb2+05d diff --git a/data/textures/BackgroundNear.png b/data/textures/BackgroundNear.png index fd30b7f7a9ef352b9a9c0a1ad14bd1c72bba411e..94e674727402fd7b3e35973b0ccc320dc7afcc32 100644 GIT binary patch delta 152 zcmbQ!%lNsAal<>2dWP&0*NBpk)QXbQqEyekw0wq=%$(HX_+kZH1w$?fy9CV6&CH8W z%giZBEdp|VJpEi9gSc`N(=o)#ixLaK+JjsJTpdHWzKiC3rig-I;mYoPXFKImgb+z#5i7H~-6I=v+2eLYA{GHlF`Zx| z_yB?m@hPnG79v6#U%)-VSXkIh^_%(6%;#0%Zc=!juTJ^e3L5X~N>fJ}rR*L1luS zl4TRuC$7~!yR8~s%k_w+^*RYr{M$(@Qg57fDVLRT34Et?}G4o-- d0}r+x7DN~acI4PwvOh6%LA7!mJ|49$zX0DZj3EF3 diff --git a/data/textures/BigExplosion.png b/data/textures/BigExplosion.png index 6bfc83792b0bf5d78c030219551b28bfa5b1a8e3..58bfe0df355a512a928548a6a83d6fddb4dddcfb 100644 GIT binary patch delta 173 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 diff --git a/data/textures/Building.png b/data/textures/Building.png index 43a458653a99f05ddd2f5d9c08480d6fdcdde8fd..5cb2a63f4d7c0e118f01ea9bd48d1cf3ec98b763 100644 GIT binary patch delta 173 zcmX@>a#eVO3KwH>kh>GZx^prwCz@&2Gq9I<`ns~;ViaYO5DKo1vSeUj$S!e>C<#fe zC@C#U^~_7lXDG?cNiB{qRkE3q@7nln&gA>fR51KP~^LFvK9GncEu6{1-oD!M75Xe9w3D720V1B(vd3CrS}*>1tNsr zdyx*IN)?2M=Z<^dhj+(#bFBRzbMEn5Ypy-_T3_ZUb+2+9$GzJqgn}IiL;$+BKu|a* z|8YD&4{%?^_oX3H$I6Qh;qGc{?*wN<`XJzJlGgUlAdvUew!gZIV^ula;zOg-LiP|s zIi9#=e|7#-XlDB}JO{K7yg;zBu;ApVdtXIIJzthZuc=boF#msKThc5qpqx&o3)a-wPlub7kbghMS^ zkl^lPvAP_KqD1+Lsi7~U9U~Fx#>((;D(>&`AIlUGNuP>UK8BNoJ2f{-?iCcEyu1pl z0f}R{Oc_`}M&*4m&HFNDjZ9PjuBcic=R6Hljc|T5|BZfxPetts1WlDOA&goKCXb2@ zDHdp17Z#|Frd?!u?_|`Z%|n--5osiC#9;pXG2B>s^1#`7#rl<6*ND$v?rZzSsX6p9 z>$ANVfs2YO*0_nUBO%=rT_Xb>QyVZPpz>4_ZCaAiTFH8Hc0L-#NB)VQ86z0bzpS~s zj~Vc?G3PHx4u(QQTTb8h2TxCLIZpo78!$3=YMhWg?fRL1ug18dN%%wV4_sfa-_biL_4hZt0v_{ER~K9Nad#Y zejzMaA}F|LYq`|hR+K?`WK!3k5M!5w#~YxmQDnUWLow1n%oB?YFf>H0o3S5V%bz=2 zJAP(e8)5zZD`d}N>4h}LJ2n?bLn`-c(6#D&h{MGlzC2;3E5fMP@Jm0#!>)_gjy!?f zW25QlsQsOo53w;37E-I;o$VG6fg$g}NUcXhr)lx6UVZx^>sk+o7Jf;Di)I-d1Sm7e z313iB+50nXx2ojtml^OfGEOxaAB_?(?LI{gE}Tl=GnDEQZzsce>#yoHZ*dA=jwqGzEk{~;4+y)*E z(EnkXyk+(l)Sq~7;J?LPqDZ3WbNlV~=v$St`}-iT!({u3@fLaielyE>?Z-Nuq}%@H zV?D>jybf0qP^AYta%piftv?3tkVXGTqtC8Fl>`DsE+dr$@K_7C^^PR0M9T$$u>F1I zeb{<4wxx3MRAO+j(DLx4Nc2(@X(RSWq^_l1@LG_ggYzFA4ez_=eaOJCpA;?Q9YhZU zQrh;ao6DVX-95(V_0zF}_7|K=Xo;du&pIMaCo}||n*KTNNgBia&&^mR{|iR{T9%W& z{np4hz-Z`{K(!@z8Su^)k^S0LD0m)4Q^q=R*q6}xf$W4LfzT{0dH9s9&>~*0fJI_| z$>uWVBFWguXI3XRHuD#g-9>=PmdQe^=ghuq&b+_O8WDxzelFk5xx%q;fMb^Mi*a$0U84O{zu=?s z=w?cJnHJR_+1D`+@9Q|apJ@b;c6fa-ey*A&r-Hk4bSl&cyc_?smX>t%SM%gr)xwXc6ssKa9@jpk;Qo^)^QV{g43vfCy1nwoT;XkkA?`!oxT z4S>Cd`?N;!U~A5Pe_(Ty$(WaWzWYy*>i#Ei58USymkVCqKlfk9 z94>j8K(inE_`m6rlXVlx>fLSCKK8ht_%Akid4KwipcduSuFe0AT{L7;3t!&EHyiRQE@-Kj(KCDvaGGS}} z>%pmd`PD4LbcN!|e#*PJ>z@rXWC6O4S|usZ&b57HGPa~8Q~jaT*w*i7a=pKS+i_PJ z5%arCAAoyou|WJ!Ts4CQz<9LQbS1c!Ah&v9frrbn8pHta7-yvn&uD*MNv+xakh)aq zyL$6@EE}7$WU+iT$X z2_$SWFC80mIBdEouVCkVvx!~K>N0#F2>Um2W%9aiaOksaF&f5o~)xf+y*=b3B zHuYoj5Hm8){ z2yL7usm?el-ZGvu1pf(=n^NkS3Tlg~OFC2YSx!xF`V0WWVh?E@aVNw->){P&K?E(H zy%z~>mBlsb%u<(AAp*_$u1Dqf7Nhhpwv+gP_*-Tk9$bzFVJ0Q9tF1jpxS8an;-pec zTgTneh60y$b7W#@Ise#?0{sGL%6F^_86pBITRG=i7PfI`uyiQpqtq7<7eVujg$ftJ z9jc3N^0~y`awzJhvS-Q6&&3oWMC@u(e11*S2JKt^_>V<&=|DbO44|K`Q_;=luYM1} zOP+QMRoB=5?DlObWZ}2?Ug=~keU^+1Ai7#M`TYa*ZQ`YDe5-F&YC3)M)P73A*b%Mn za`NxS{`rZQa`8aNYk9h~J0{arsOH^o;k%)?x(XSVIzQm1HjmETt59($PdD)+wQt_j zLd>@Oa%{4yWBjxR7_}?6L#(Gp|Lz1Z-{W{H%izP>-6at}N&lK zh}oSgX*(~o*Y&TWy6&L`+1sWQbI|udF*y-+@x}F(93X8k8qmnJH0a&gSltd;AP)#( z`StJHcQ~00D;L-l+d}1)LqdseG0<=c3qKJ)Xp10O+ur@%kbOli85l=J6{j5skZ5a@ zaBFL8a|>u`b2s#|&An!9O(B4u5P+0ZK}!6`*7EEiHf4EB<+h!k(z|vicjb3VOSu<% z=fl#HD~_qP1re#0mP)2IHPU+X9rr~8<@7tYc8v)LiGn~u!Ee40-w6HYUmQt7rWoE% z0wJa$kB?yD5)R7co1x=Y)(9>EkOSdq9rikTf|48TE1_RiVRmCd^*pbH)4p5NP!B3) zm`x14dl{vX5nRXwMS)!&JhG^UJA5B{#PcB^?zlcUGNdmi(qNCP4`Ej4b%fCxNO)zp z`1_siA0D7SFDHtYlO{8oNzrj{WpI+v$IJ6OAUG6n!qXe6R`Nm>{Iz+2s-U#?q5=CM zb}RTxm|e1}P9^Q*z;{(F&zrenBF$Y?dT zfsBDq#~{x5I#rG1^;Bw!9=*A9KE&Aaz?+EgY?8E{NPNvpLA=JiaTIPC(mv%&Nv`Fx zxGX+jnpZLm!QdV>b(jE+)Mx@yU1Y<)X&gn2Hz!G7R@hCyJ_j{Pg}aXS%Asx{xgI+l z>qXAyEX6;W%pK$TGqFLdoX|sr%%jO46IHb+-S6tLrDy`^u90q8pdrk42t4Oeo;CDh zM*WSWOZPTWt}e6b9wK_6iPN8&D^Xs~Q~Xpm+GVtXuytf}R#T7l z^u<|5ZQGh!uK+V$J9UjAb<~iD{ie>os0M8>qDrS#^O|u^mvr`wziy$+BY059Sn3{=XrVZAo<{x0o1(O_cl9-Gvwk(l}wC!X_Phyca1vhYqwo$zLs%Ii5%2y&CHY{Y8thZ=xr{*r9 z?9A^~JiBZo@+1?i-59XbLw|>M&@Gk4x7#tWq(((GssTy#e)FcJqB(D&WA0t1sUJ;W znh9QNKmY^krQ1awPQ#MYO1ROFCk{9YQt8EKpIqi{VQlmHo|Nf!co;oj?n#*PBnf0soLbC3q*BN8d98$P;J=pzo){RBLvxPq?44O6* zomr)ZeFf@jX98>sVVRY0owjl&vS!GQV7t_Ho4|YKXtXs=pUkR$vc6hBu-4=@ho z74*fM1FJD=e)`)O8T|!lokt&OhB;Gh1Ai*lwDlynXKe z43LMZ)2$hGjMr))6QJ0dK);bv*E;B#s}9ZG$8$)mB+bR6d*5j`>1!j2+JwytoSk&? z8*2;rDNA!EjOqPiDJZaf;XGKcm5o=XFKUJ`wpoFJN;&R@oLJdXL`JB)8B! zV=48nnMP?Xk211~H!cY}s{uU?sI85gKvyz_W)_;)=41cdhFA`odg8m6=XR=;uI8ek z@hg*EUAAFs0o

7VsM(ExT8tJo+JPfzY4HA6sgAgHcaid0av?qc9#}ZY*Tk+6ez< zsKfY24Qx#bu2k(Mv8_s|>ge%i zyReY<42TMiZ6V5iTX$v)XdD6omv;h`bcuP$6IfFGonw#%wug#lUd`7 zanqa11H&ER{whN0hmFF&63gdsfXUdw%PowT>t}JQ&@7Yj^p(NsJBRljn?sx#F~b@- zb|pa|Ws%#L1JFYK~1-{}%+N$)PTq(tq)vl4&WcoAvL;EL}H z5$I~tjaNTy&$FIax(BA@7g^gQu_n#M;#W#A&+`;zJW)@Hu`Gi>)XF6395z4{hY&(O`P%A(tu$q4IE7R$FG&23e;zt)IRXk}tY zGck{oX1|FzsvvV-EHgl0_R}%1a(A3Zxtd;0N%^AmQHqCO&8K65lFrUoLh}l}O>8IK z^?&&@Y-y;KY(Z`u2saq#-o206sC70gdzk6B#hKMHNK-!>S@Y&LwjATDB(3d^TIsOU z-e|Y|+KU|PD>t(*VhdXQQ#F84NG6^7ULChfFrH)k!j-` zQ|fLdHE)Q#=N{-Fe|D@N0R~LzK|%+wo3&NT;_( zC$WA0jf|LF^g$IYxzO=Jd7Va~iKRpH0bc|S&8(?CXR%01AB8bY!U(CO>I`#Dp3LS5 z5`MHT4pG3Ak|8J9(WTKR zn^aXSedRNNod-@4JF(90l9%9;lW)SSz_${5+k@iAs-YG+^zY0MEtY>#6%${!DY%u3ps;1al# zf0=w*8oaOL4sURI?fTnx<@pin#*t?~WyQ2Vx!_xnh5*{?SM~lJ==Ebn3yBZ_TyV<;(5gWis zUGm+>W_1BG^6CmX(d5tW%e5Hrx}U9$@2)H^E&>nlJ1?dUk3KURdDaocQS{w`0l$}8 zIBfs*sRJphG4(M-7g?ASSu%BRv@};|T}<`%U@4S6gK%~EDR2M#Zct0Y*r8U($M}$a%4R>kjM0zOnX%8LW-jYmiT;l`fzxh2(S-6^J z@s%at7Tam4hwGimGTH}3Z8U7f#lhRH87$#`tQdG-sW_8yjf=rAHz~&Vc2j%mKdP1c9P!DNPlAh7u!;yzq)x6Rwv9IC$4SgwTvD+uadIqhC z_&9Hro;iz}`6E#kT2C5swOW!nvL3x$9v4e4Jdz4~{dIS61F+L{*(ZP1 zfwxliB0GGril~i+QOKV^v5l=Y!F?IN(zl{`dj2YfIrzBlJ3jH4>!6i(YSjJou+=nE`0~c+Ej|e)1m+~YXMy!ekrh^I9OQnrI0X0R0<*_b{#?l1-p~INUkpx-Jc0? zZ+lyaw!Jsp$xzwe8Sdg?@9F{)784(^tWf^HjM4uxLc)@31L~#M%s+{p0aqJ)Tc7_Y za}pPU%=HY~KbevCwzd!}C&Vi&kf)24hleZ7{(9FoZ@GzTt`VC5AnvYS9$*CA9qfU0 zw?}{^iFcgouYrgE0X$r7kzQ7SI~=57<7y3O(|+ZOboF@UieQuA7esC_C0^6)|DloB zU+ICgy1w_<^$~#x{wWKaun^>Whzh^gu^7Il)&J1mRtQZ^h_Wlp^SUg^XUZU}KdVD* zuJ>sJLHs)hL_*M70uF;&^MTmFORl6tj|m2?<#ViCFj$G1QjmE;vjb?hIQv;UQRSqt!H2_@$_|Nzr`rZA}=NM+~o`d1A}jgYeY#% zYDGzDQL1NNT0TQbW=?8xe6fP9f&~|ZT>@t3X6D7GW#*Km76G|_u8u*j!696^iRl=E t9WI$Y3=E=~o-U3d6}R5b{T(grd8_U9|M<;0#>t|b44$rjF6*2UngEUiIDr5F delta 13618 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 diff --git a/data/textures/Heroine.png b/data/textures/Heroine.png index aff328252d9a81d75ef84b2d774e994caa9c7a46..b08bf9ac34e1162634d947661d59c770a53a70c2 100644 GIT binary patch delta 163 zcmdm(_g`*;3KwH>kh>GZx^prwCz@&2Gq9I<`ns~;ViaYORpZ|mb&`RB!MDUUq9i1> zqNKDa)iWf*WeJY+{APY uL8&rMD+UI>Wu7jMAr-gY#yYOkvF1IS_K#=t3$+D&oD80>elF{r5}E)a-!>=! delta 10383 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 delta 8350 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 delta 2316 zcmV+n3G?=>3)2#iV1EMw6De?g9wz_*08ey9Sad^gZEa<4bO3Z|Y-MvGJs^8HEFd&} z3T;Q1b=`Qv z0RP#7KqM~s`vXlV9_FF3SOc9W=n9zZW_q#5<#>L;szO<+HLs(1hZAUKRk19-=?n<@mLBCjyEd|pJJpkHalGyC4R7cs>wJf7DPc@F@9lLa6bo)WpS64Y5M zyI)|HN`D>vxWb}!W8oY@V)?v?Ji)m$Q_s#e2)Xc-2*bq5LLiCMWbU!bM;a~?sz{K{ zD(OdWsB_LMCDK@|LGduJR47Ua`&Abdp_oSLm8?|P04BLS;`|dJvrmmO_k_yFZucj` zvQi=qsAF+HFZ2YdRs(@-p2^;gtAH5sKVUkXE`QVP-6RL#@&Kb_4JrauICXurFGVo#Vy=UBH0*l|>5!5ZMep9)L-71r62$++vVnVi*xb z%zyfI?yc3WlsV|Gm6JbQ(k>mGWDEShH-L@=XIsum!7rBp0HCj2itY&B&`c&;pBj0v(a&W~`KrQo_b9 zgZZwfVkI;f^ZVX_u$N5tX|2-JQ#i=^n}2mK!RUyUhn%7Z3ADAN+*7f0zcYX5zLkzp zJKg&%4*>$pXJvn&X%-F`%ct|GPUCRE>9Cs1=_$-l#3DhI8)AIxWn0;k_rO}u;6LKu zO@&(xRp$UJCGvZ_4gdhHjaFz~xp>$P0{{TOx9jrWvZse0OZBuiTIzWU9aeKWJ%6Wi zGvrw){n#*I<^Gd&;XPi4_DTpKx+=iP@>NM(6zgSUcn@1}ZzX{ePtdDLn3IIUfdlam zCxN>NPMkP#a#qFF$X(3-Ll--Px7TNv0DS(@1La_nPdCRo4GF%&agur9dC4ddeDHbT zdGUzQ1rp%;>Jki%i~#_^-sg{S=YQcG#n|7+jc1Gi4ETlliNLPLV(oNEz!H=D{t)+jY@3t6zmx_`dt**5yN zi&$YK!aWI{r*6gHABg)Z@OctI==p^J_&>kz!BJ}$F6VCgQ|UflSnC#8dB_W}AwWrh z!a)uJ02)_XB-%v_TCkJ^jFqV#arPf?mU#irT6t-JM-0Q8TKMykt}g20zRY8AUVsIk z{(jWjMRwdoRIcCH0~8K&NPqwM;z1s*NN`H|18c29dF4GNtMf(z@Y~j3>*}9CfoCn9 z1>f@qS{#N(#z2%442_J1bex&@19XQ-9q?1Qw}4#E-2_62(9$nm8w$S{Kw;T3&%hH% z>H!*8TBLZ8w+{iQCEoM#1pbqUfW=zdiZwu<0{DE^k0Q?i0Kzwu+<$pE=T`xHpFaw7 z0xIjPOK6+}L;{|9Q9!R{9QVfjSZ|vI`pIk44*cqxeI6ix zV+mfmHWcszY)Fvg0c7vK^;S<7ab^=ek5u|ALSakv8 zHG)LVAl=(WWnDn(_N9#=*9uNZveF7>>U^M|W#DJe1H|bhW{CtMBBZkz#J7u8>jRK& z0`#zCY&p31-gZ7SIe{~i6Yh4j6r^9ml-O*kjFx?U8=Kq227mnF8`u4FdReVGFO>oT z0xL?NwzgpD_50AOlPNhWqh%~zy~vD|k&=KCgC)hxRBEq>?AH!uY>${Z*9 z5a5GL!4{E%j(<}RK>^PX4#URgwhwyq>yH1k{^OS)3QAWmVt#NK>OVdNPQ(UCCPX-i zOMtnlasPt|d=7M>5^Cj)YsUw7Zvz1Mmd+mg_T2}6>}9n^URLc^*`^;oCN2ad7y>Bh zv}Gt0w!6fK0GmY5Nwz`&@!YvqC^`5f(ShIF9)M5wkbe&WA`vBnPI^y5H-s#`eh;6v zwzLyXNFtM!7tfLH6S$^NMydeN++q4@YfA{csJ7QNh}xxM8UOxk0ETZ|2iru@NwOXQ z=cdMyg3N<~?f_E;TICV8gmGdR0%Y|*1)Ek2EcmqU zr(Hk_Zhmms+rV!Sb&eN@4BFw-wShgtxIRFFRRD4gp~(O9mTv{~jUbh<3qh{Un|>LX m*grRjx)R7%1P=UkyTm)LJpU7;sP+7>y$>8bg=d#Wzp$P!S!8G6i delta 9690 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 sQDOnufFRcZSH}=8Fdt|Lw*o|9@{)Nqnb%7 delta 5809 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 delta 5031 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 diff --git a/data/textures/TowerBlock1.png b/data/textures/TowerBlock1.png index 67ec31b637cd1c6ae9bcc73865fa6dd2402bb2e6..677aa21ac9accdd6d5c1f6225bf3433e3c88be35 100644 GIT binary patch delta 173 zcmdmGdzWj13KwH>kh>GZx^prwCz@&2Gq9I<`ns~;ViaYOk-4yPlNAF4Lw1R4L`g_$ zMM-H6n7$ qMTrGq1Dt&veFM0_T#y-@V7_lO*Tl`UB}!R189ZJ6T-G@yGywo5n>Qu^ delta 6715 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 AivR!s diff --git a/data/textures/Trees.png b/data/textures/Trees.png index f665ff6c444135ee45c422b2b522be5d27f1824f..fc9fc35189de544451170532449a06e610bb2e91 100644 GIT binary patch delta 140 zcmaFCai4QST>ULZQ5GrHo8RVcVPIg$E^&=02}!LeDJ@F%%uCB>D9Ox8Esif%uvIYP zg0M?~Y(uWx%)I!t%$$ #include -#include +#include #include #include @@ -47,7 +47,7 @@ class Animation::Impl { - friend class Animation; +public: /** * Contains "global" animation data for the various animations which get @@ -55,10 +55,9 @@ class Animation::Impl * which wants to use these loaded sequences. */ - class Data : public Mf::Library + class Data : public Mf::Manager { - friend class Impl; - friend class Mf::Library; + public: /** * A frame of an animation sequence. A frame is merely an index which @@ -68,7 +67,7 @@ class Animation::Impl class Frame { - friend class Impl; + public: unsigned mIndex; ///< Frame index. Mf::Scalar mDuration; ///< Frame duration. @@ -98,9 +97,9 @@ class Animation::Impl * that they should be played. */ - struct Sequence + class Sequence { - friend class Impl; + public: std::vector mFrames; ///< List of frames. Mf::Scalar mDelay; ///< Scale frame durations. @@ -161,10 +160,10 @@ class Animation::Impl * individual sequence. */ - void loadFromFile() + void init(const std::string& name) { Mf::Script script; - std::string filePath = Animation::getPath(getName()); + std::string filePath = Animation::getPath(name); script.importBaseLibrary(); importLogFunctions(script); @@ -186,7 +185,7 @@ class Animation::Impl std::string nameStr; name.get(nameStr); - sequences.insert(std::pair(nameStr, + mSequences.insert(std::pair(nameStr, Sequence(script, table))); return 0; @@ -208,18 +207,7 @@ class Animation::Impl } - /** - * Construction is initialization. The animation class data container - * registers itself as a mippleton and then loads the animation data. - */ - - explicit Data(const std::string& name) : - Mf::Library(name) - { - loadFromFile(); - } - - std::map sequences; ///< List of sequences. + std::map mSequences; ///< List of sequences. }; @@ -246,9 +234,9 @@ class Animation::Impl { std::map::iterator it; - it = mData->sequences.find(name); + it = mData->mSequences.find(name); - if (it != mData->sequences.end()) + if (it != mData->mSequences.end()) { mCurrentSequence = &(*it).second; mFrameCounter = 0; diff --git a/src/Character.cc b/src/Character.cc index 9da4344..2290e3c 100644 --- a/src/Character.cc +++ b/src/Character.cc @@ -126,11 +126,10 @@ void Character::draw(Mf::Scalar alpha) const //glColor3f(1.0f, 1.0f, 1.0f); tilemap.bind(); - Tilemap::Index frame = animation.getFrame(); + Mf::Texture::TileIndex frame = animation.getFrame(); + Mf::Texture::Orientation orientation = Mf::Texture::NORMAL; - Tilemap::Orientation orientation = Tilemap::NORMAL; - - if (mState.velocity[0] < 0.0) orientation = Tilemap::REVERSE; + if (mState.velocity[0] < 0.0) orientation = Mf::Texture::REVERSE; Mf::Scalar coords[8]; tilemap.getTileCoords(frame, coords, orientation); diff --git a/src/Character.hh b/src/Character.hh index 6507906..82804ba 100644 --- a/src/Character.hh +++ b/src/Character.hh @@ -36,9 +36,9 @@ #include #include #include +#include #include "Animation.hh" -#include "Tilemap.hh" @@ -67,7 +67,7 @@ public: //virtual int getOctant(const Mf::Aabb<3>& aabb) const; - Tilemap tilemap; + Mf::Texture tilemap; Animation animation; }; diff --git a/src/Hud.cc b/src/Hud.cc index 1fdf39b..f8f40d9 100644 --- a/src/Hud.cc +++ b/src/Hud.cc @@ -33,7 +33,7 @@ #include "Hud.hh" -ProgressBar::ProgressBar(const Tilemap& tilemap, Tilemap::Index index) : +ProgressBar::ProgressBar(const Mf::Texture& tilemap, Mf::Texture::TileIndex index) : mProgress(0.0), mTilemap(tilemap) { @@ -120,8 +120,8 @@ void ProgressBar::draw(Mf::Scalar alpha) const Hud::Hud(GameState& state) : mState(state), - mBar1(Tilemap("StatusBars"), 0), - mBar2(Tilemap("StatusBars"), 2), + mBar1(Mf::Texture("StatusBars"), 0), + mBar2(Mf::Texture("StatusBars"), 2), mFont("Font") { ASSERT(Mf::video && "no current video context from which to get dimensions"); diff --git a/src/Hud.hh b/src/Hud.hh index 75ced92..2262b06 100644 --- a/src/Hud.hh +++ b/src/Hud.hh @@ -38,9 +38,9 @@ #include #include #include +#include #include "GameState.hh" -#include "Tilemap.hh" // TODO this stuff is still just hacked up @@ -49,7 +49,7 @@ class ProgressBar : public Mf::Drawable { public: - ProgressBar(const Tilemap& tilemap, Tilemap::Index index); + ProgressBar(const Mf::Texture& tilemap, Mf::Texture::TileIndex index); void resize(const Mf::Rectangle& rect); @@ -64,7 +64,7 @@ private: Mf::Vector2 mVertices[8]; Mf::Scalar mWidth; - Tilemap mTilemap; + Mf::Texture mTilemap; Mf::Scalar mTexCoords[8]; Mf::Scalar mMidCoords[2]; }; @@ -112,7 +112,7 @@ private: ProgressBar mBar2; unsigned mNumber; - Tilemap mFont; + Mf::Texture mFont; Mf::Matrix4 mProjection; }; diff --git a/src/Makefile.am b/src/Makefile.am index 3c3fc53..58b3111 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -35,10 +35,10 @@ libmoof_a_SOURCES = \ Moof/Image.hh \ Moof/Interpolator.hh \ Moof/Layer.hh \ - Moof/Library.hh \ Moof/Line.hh \ Moof/Log.cc \ Moof/Log.hh \ + Moof/Manager.hh \ Moof/Math.hh \ Moof/ModalDialog.hh \ Moof/Octree.hh \ @@ -100,8 +100,6 @@ yoink_SOURCES = \ Main.hh \ Scene.cc \ Scene.hh \ - Tilemap.cc \ - Tilemap.hh \ TilemapFont.cc \ TilemapFont.hh \ TitleLayer.cc \ diff --git a/src/Moof/Core.cc b/src/Moof/Core.cc index 9002730..190f4c8 100644 --- a/src/Moof/Core.cc +++ b/src/Moof/Core.cc @@ -32,7 +32,6 @@ #include #include -#include #include #include "fastevents.h" @@ -368,9 +367,7 @@ class Backend_ { public: - Backend_() : - mAlDevice(0), - mAlContext(0) + Backend_() { #if defined(_WIN32) || defined(__WIN32__) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) @@ -397,31 +394,11 @@ public: return; // fatal } - mAlDevice = alcOpenDevice(0); - mAlContext = alcCreateContext(mAlDevice, 0); - if (!mAlDevice || !mAlContext) - { - const char* error = alcGetString(mAlDevice,alcGetError(mAlDevice)); - gError.init(Error::OPENAL_INIT, error); - return; - } - else - { - alcMakeContextCurrent(mAlContext); - logInfo << "opened sound device `" - << alcGetString(mAlDevice, ALC_DEFAULT_DEVICE_SPECIFIER) - << "'" << std::endl; - } - gError.init(Error::NONE); } ~Backend_() { - alcMakeContextCurrent(0); - alcDestroyContext(mAlContext); - alcCloseDevice(mAlDevice); - FE_Quit(); SDL_Quit(); } @@ -443,17 +420,13 @@ public: } } - static bool check(Error& error) + static const Error& getError() { - error = gError; - return error.code() == Error::NONE; + return gError; } private: - ALCdevice* mAlDevice; - ALCcontext* mAlContext; - static Error gError; static int gRetainCount; static BackendP gInstance; @@ -474,9 +447,14 @@ Backend::~Backend() Backend_::release(); } -bool Backend::check(Error& error) +bool Backend::isInitialized() +{ + return getError().code() == Error::NONE; +} + +const Error& Backend::getError() { - return Backend_::check(error); + return Backend_::getError(); } diff --git a/src/Moof/Core.hh b/src/Moof/Core.hh index fcb0340..109999a 100644 --- a/src/Moof/Core.hh +++ b/src/Moof/Core.hh @@ -100,7 +100,8 @@ public: Backend(); ~Backend(); - static bool check(Error& error); + static bool isInitialized(); + static const Error& getError(); }; diff --git a/src/Moof/Error.hh b/src/Moof/Error.hh index 05c6377..c452ae6 100644 --- a/src/Moof/Error.hh +++ b/src/Moof/Error.hh @@ -57,7 +57,7 @@ public: UNKNOWN_IMAGE_FORMAT, // name of resource }; - explicit Error(unsigned code, const std::string& what = "") + explicit Error(unsigned code = NONE, const std::string& what = "") { init(code, what); } @@ -70,7 +70,7 @@ public: mCode = code; } - virtual void raise() + virtual void raise() const { throw *this; } @@ -85,8 +85,9 @@ public: return mWhat; } - bool isError() const throw() + operator bool () const { + // resolves to true if error code is not NONE return mCode != NONE; } diff --git a/src/Moof/Image.cc b/src/Moof/Image.cc index 51e7ad8..ee44dd7 100644 --- a/src/Moof/Image.cc +++ b/src/Moof/Image.cc @@ -29,30 +29,28 @@ #include // FILE #include // strncmp +#include + #include #include #include "Core.hh" #include "Error.hh" #include "Image.hh" -#include "Library.hh" #include "Log.hh" +#include "Manager.hh" namespace Mf { -class Image::Impl : public Library +class Image::Impl : public Manager { public: - explicit Impl(const std::string& name, bool flipped = false) : - Library(name), + explicit Impl() : mContext(0), - mPixels(0) - { - init(getName(), flipped); - } + mPixels(0) {} ~Impl() { @@ -89,23 +87,12 @@ public: } - SDL_Surface* mContext; - char* mPixels; - - unsigned mDepth; - GLuint mColorMode; - - std::string mComment; - - -private: - - Backend mBackend; - - bool init(const std::string& filePath, bool flipped) + bool init(const std::string& name, bool flipped = false) { - logInfo("opening image file..."); - FILE* fp = fopen(filePath.c_str(), "rb"); + std::string path = Image::getPath(name); + + logInfo << "opening image file " << path << std::endl; + FILE* fp = fopen(path.c_str(), "rb"); if (!fp) return false; png_byte signature[8]; @@ -185,7 +172,7 @@ private: logInfo << "num texts: " << numTexts << std::endl; for (int i = 0; i < numTexts; ++i) { - if (strncmp(texts[i].key, "Comment", 7) == 0) + if (strncmp(texts[i].key, "TextureInfo", 11) == 0) { mComment = texts[i].text; break; @@ -248,6 +235,19 @@ private: return mContext; } + + + SDL_Surface* mContext; + char* mPixels; + + unsigned mDepth; + GLuint mColorMode; + + std::string mComment; + +private: + + Backend mBackend; }; @@ -281,7 +281,7 @@ unsigned Image::getPitch() const return mImpl->mContext->pitch; } -GLuint Image::getColorMode() const +GLuint Image::getMode() const { return mImpl->mColorMode; } @@ -315,11 +315,19 @@ void Image::setAsIcon() const } - std::string Image::getPath(const std::string& name) { - std::string path = Resource::getPath("images/" + name + ".png"); - return path; + if (boost::find_last(name, ".png")) + { + return Resource::getPath(name); + } + else + { + std::string path("images/"); + path += name; + path += ".png"; + return Resource::getPath(path); + } } diff --git a/src/Moof/Image.hh b/src/Moof/Image.hh index 5f7c5a3..e958edc 100644 --- a/src/Moof/Image.hh +++ b/src/Moof/Image.hh @@ -38,10 +38,18 @@ namespace Mf { +class Image; +typedef boost::shared_ptr ImageP; + class Image : public Resource { public: + static ImageP alloc(const std::string& name) + { + return ImageP(new Image(name)); + } + explicit Image(const std::string& name); bool isValid() const; @@ -51,7 +59,7 @@ public: unsigned getDepth() const; unsigned getPitch() const; - GLuint getColorMode() const; + GLuint getMode() const; std::string getComment() const; diff --git a/src/Moof/Library.hh b/src/Moof/Library.hh deleted file mode 100644 index c215567..0000000 --- a/src/Moof/Library.hh +++ /dev/null @@ -1,121 +0,0 @@ - -/******************************************************************************* - - Copyright (c) 2009, Charles McGarvey - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*******************************************************************************/ - -#ifndef _MOOF_LIBRARY_HH_ -#define _MOOF_LIBRARY_HH_ - -/** - * @file Library.hh - * A library is a collection of named objects of the same type. Libraries use - * reference counting to automagically delete objects which no longer have any - * interested code. - */ - -#include - -#include - -#include - - -namespace Mf { - - -template -class Library -{ - typedef std::pair PtrValue; - typedef stlplus::hash PtrMap; - - static PtrMap mPtrMap; - std::string mName; - - static T* retain(const std::string& name) - { - typename PtrMap::iterator it = mPtrMap.find(name); - - if (it != mPtrMap.end()) - { - ++((*it).second.first); - return (*it).second.second; - } - else - { - T* newObj(new T(name)); - if (newObj) - { - mPtrMap.insert(std::make_pair(name, std::make_pair(1, newObj))); - } - return newObj; - } - } - - static void release(T* obj) - { - releaseByName(obj->mName); - } - - static void releaseByName(const std::string& name) - { - typename PtrMap::iterator it; - - if ((it = mPtrMap.find(name)) != mPtrMap.end() && - --(*it).second.first == 0) - { - delete (*it).second.second; - mPtrMap.erase((*it).first); - } - } - -public: - - explicit Library(const std::string& name) : - mName(name) {} - - const std::string& getName() const - { - return mName; - } - - static boost::shared_ptr getInstance(const std::string& name) - { - return boost::shared_ptr(retain(name), &release); - } -}; - -template -stlplus::hash< std::string,std::pair,getHash > - Library::mPtrMap; - - -} // namespace Mf - -#endif // _MOOF_LIBRARY_HH_ - -/** vim: set ts=4 sw=4 tw=80: *************************************************/ - diff --git a/src/Moof/Sound.cc b/src/Moof/Sound.cc index ca3ecfe..f8f05ba 100644 --- a/src/Moof/Sound.cc +++ b/src/Moof/Sound.cc @@ -31,13 +31,15 @@ #include #include +#include + #include +#include #include #include -#include "Core.hh" #include "Error.hh" -#include "Library.hh" +#include "Manager.hh" #include "Log.hh" #include "Sound.hh" #include "Timer.hh" @@ -62,16 +64,14 @@ public: class Buffer; typedef boost::shared_ptr BufferP; - class Buffer : public Library + class Buffer : public Manager { public: - explicit Buffer(const std::string& name) : - Library(name), + Buffer() : mBuffer(-1) { mOggStream.datasource = 0; - openFile(); } ~Buffer() @@ -84,7 +84,7 @@ public: } - void openFile() + void init(const std::string& name) { if (mOggStream.datasource) { @@ -92,14 +92,13 @@ public: mOggStream.datasource = 0; } - std::string filePath = Sound::getPath(getName()); - int result = ov_fopen((char*)filePath.c_str(), &mOggStream); + std::string path = Sound::getPath(name); + int result = ov_fopen((char*)path.c_str(), &mOggStream); if (result < 0) { - logWarning << "error while loading sound " - << getName() << std::endl; - throw Error(Error::UNKNOWN_AUDIO_FORMAT, getName()); + logWarning << "couldn't load sound: " << path << std::endl; + throw Error(Error::UNKNOWN_AUDIO_FORMAT, path); } vorbis_info* vorbisInfo = ov_info(&mOggStream, -1); @@ -110,7 +109,7 @@ public: void loadAll(ALuint source) { - if (!mOggStream.datasource) openFile(); + if (!mOggStream.datasource) init(getName()); if (!mOggStream.datasource) return; char data[BUFFER_SIZE]; @@ -180,7 +179,7 @@ public: void rewind() { - if (!mOggStream.datasource) openFile(); + if (!mOggStream.datasource) init(getName()); else ov_raw_seek(&mOggStream, 0); } @@ -207,6 +206,8 @@ public: void init() { + retainBackend(); + mIsLoaded = false; mIsPlaying = false; mIsLooping = false; @@ -233,6 +234,8 @@ public: alDeleteBuffers(1, &mBuffers.back()); mBuffers.pop_back(); } + + releaseBackend(); } @@ -426,6 +429,39 @@ public: // than a timer, probably as a compile-time option } + static void retainBackend() + { + if (gRetainCount++ == 0) + { + gAlDevice = alcOpenDevice(0); + gAlContext = alcCreateContext(gAlDevice, 0); + if (!gAlDevice || !gAlContext) + { + const char* error = alcGetString(gAlDevice, + alcGetError(gAlDevice)); + logError << "audio subsystem initialization failure: " + << error << std::endl; + } + else + { + alcMakeContextCurrent(gAlContext); + logInfo << "opened sound device `" + << alcGetString(gAlDevice, ALC_DEFAULT_DEVICE_SPECIFIER) + << "'" << std::endl; + } + } + } + + static void releaseBackend() + { + if (--gRetainCount == 0) + { + alcMakeContextCurrent(0); + alcDestroyContext(gAlContext); + alcCloseDevice(gAlDevice); + } + } + ALuint mSource; std::list mBuffers; @@ -438,9 +474,15 @@ public: Timer mStreamTimer; - Backend mBackend; + static unsigned gRetainCount; + static ALCdevice* gAlDevice; + static ALCcontext* gAlContext; }; +unsigned Sound::Impl::gRetainCount = 0; +ALCdevice* Sound::Impl::gAlDevice = 0; +ALCcontext* Sound::Impl::gAlContext = 0; + Sound::Sound() : // pass through @@ -550,8 +592,17 @@ void Sound::setListenerOrientation(const Vector3& forward, const Vector3& up) std::string Sound::getPath(const std::string& name) { - std::string path = Resource::getPath("sounds/" + name + ".ogg"); - return path; + if (boost::find_last(name, ".ogg")) + { + return Resource::getPath(name); + } + else + { + std::string path("sounds/"); + path += name; + path += ".ogg"; + return Resource::getPath(path); + } } diff --git a/src/Moof/Texture.cc b/src/Moof/Texture.cc index 5341af3..801acba 100644 --- a/src/Moof/Texture.cc +++ b/src/Moof/Texture.cc @@ -29,15 +29,15 @@ #include // FILE #include // strncmp +#include #include #include "Dispatch.hh" -#include "Core.hh" #include "Error.hh" -#include "Image.hh" -#include "Library.hh" +#include "Manager.hh" #include "Log.hh" #include "OpenGL.hh" +#include "Script.hh" #include "Texture.hh" #include "Video.hh" @@ -50,11 +50,11 @@ namespace Mf { * which is worth having in memory. The image data itself is not worth keeping * in memory if the texture has been loaded to GL, but the name of the resource * is retained so that it can be reloaded if necessary. The implementation is a - * library so that multiple texture objects can share the same internal objects + * manager so that multiple texture objects can share the same internal objects * and avoid having duplicate textures loaded to GL. */ -class Texture::Impl : public Library +class Texture::Impl : public Manager { /** @@ -103,33 +103,40 @@ class Texture::Impl : public Library return value; } + + static void bindScriptConstants(Mf::Script& script) + { + script.push(GL_CLAMP); script.set("CLAMP"); + script.push(GL_REPEAT); script.set("REPEAT"); + script.push(GL_LINEAR); script.set("LINEAR"); + script.push(GL_NEAREST); script.set("NEAREST"); + script.push(GL_LINEAR_MIPMAP_LINEAR); script.set("LINEAR_MIPMAP_LINEAR"); + script.push(GL_LINEAR_MIPMAP_NEAREST); script.set("LINEAR_MIPMAP_NEAREST"); + script.push(GL_NEAREST_MIPMAP_LINEAR); script.set("NEAREST_MIPMAP_LINEAR"); + script.push(GL_NEAREST_MIPMAP_NEAREST); script.set("NEAREST_MIPMAP_NEAREST"); + } + public: /** * Construction is initialization. */ - explicit Impl(const std::string& name) : - Library(name), - //mContext(0), - mImage(Texture::getPath(getName())), - mWidth(0), - mHeight(0), - mMode(0), + Impl() : mMinFilter(GL_NEAREST), mMagFilter(GL_NEAREST), mWrapS(GL_CLAMP), mWrapT(GL_CLAMP), + mTilesS(1), + mTilesT(1), mObject(0) { // make sure we have a video context - //ASSERT(video && "cannot load textures without a current video context"); + ASSERT(video && "cannot load textures without a current video context"); // we want to know when the GL context is recreated mDispatchHandler = core.addHandler("video.newcontext", boost::bind(&Impl::contextRecreated, this)); - - loadFromFile(); } ~Impl() @@ -214,19 +221,55 @@ public: * @return Image data. */ - void loadFromFile() + void init(const std::string& name) { - if (!mImage.isValid()) + std::string path = Texture::getPath(name); + + mImage = Image::alloc(path); + if (!mImage->isValid()) + { + logWarning << "texture not found: " << path << std::endl; + Error(Error::RESOURCE_NOT_FOUND, path).raise(); + } + + mImage->flip(); + + Mf::Script script; + + importLogFunctions(script); + bindScriptConstants(script); + + if (script.doString(mImage->getComment()) != Mf::Script::SUCCESS) { - logWarning << "texture not found: " << getName() << std::endl; - throw Error(Error::RESOURCE_NOT_FOUND, getName()); + std::string str; + script[-1].get(str); + Mf::logWarning(str); } + else + { + Mf::logInfo << "loading tiles from texture " << path << std::endl; + + Mf::Script::Slot globals = script.getGlobalTable(); + Mf::Script::Slot top = script[-1]; - mImage.flip(); + globals.pushField("tiles_s"); + top.get(mTilesS); - mWidth = mImage.getWidth(); - mHeight = mImage.getHeight(); - mMode = mImage.getColorMode(); + globals.pushField("tiles_t"); + top.get(mTilesT); + + globals.pushField("min_filter"); + top.get(mMinFilter); + + globals.pushField("mag_filter"); + top.get(mMagFilter); + + globals.pushField("wrap_s"); + top.get(mWrapS); + + globals.pushField("wrap_t"); + top.get(mWrapT); + } } @@ -243,8 +286,6 @@ public: return; } - //if (!mContext) loadFromFile(); - glGenTextures(1, &mObject); glBindTexture(GL_TEXTURE_2D, mObject); @@ -253,20 +294,17 @@ public: ( GL_TEXTURE_2D, 0, - mMode, + mImage->getMode(), //3, - mWidth, - mHeight, + mImage->getWidth(), + mImage->getHeight(), 0, - mMode, + mImage->getMode(), GL_UNSIGNED_BYTE, - mImage.getPixels() + mImage->getPixels() ); setProperties(); - - //SDL_FreeSurface(mContext); - //mContext = 0; } @@ -326,15 +364,35 @@ public: } - Image mImage; - unsigned mWidth; ///< Horizontal dimension of the image. - unsigned mHeight; ///< Vertical dimension. + bool getTileCoords(Texture::TileIndex index, Scalar coords[8]) const + { + // make sure the index represents a real tile + if (index >= mTilesS * mTilesT) return false; + + Scalar w = 1.0 / Scalar(mTilesS); + Scalar h = 1.0 / Scalar(mTilesT); + + coords[0] = Scalar(index % mTilesS) * w; + coords[1] = (Scalar(mTilesT - 1) - + Scalar(index / mTilesS)) * h; + coords[2] = coords[0] + w; + coords[3] = coords[1]; + coords[4] = coords[2]; + coords[5] = coords[1] + h; + coords[6] = coords[0]; + coords[7] = coords[5]; + + return true; + } + + ImageP mImage; - GLuint mMode; ///< GL_RGB or GL_RGBA. - GLuint mMinFilter; ///< Minifcation filter. + GLuint mMinFilter; ///< Minification filter. GLuint mMagFilter; ///< Magnification filter. GLuint mWrapS; ///< Wrapping behavior horizontally. GLuint mWrapT; ///< Wrapping behavior vertically. + unsigned mTilesS; + unsigned mTilesT; GLuint mObject; ///< GL texture handle. static GLuint gObject; ///< Global GL texture handle. @@ -346,6 +404,7 @@ GLuint Texture::Impl::gObject = 0; Texture::Texture(const std::string& name) : + Image(Texture::getPath(name)), // pass through mImpl(Texture::Impl::getInstance(name)) {} @@ -379,19 +438,6 @@ void Texture::resetBind() } -unsigned Texture::getWidth() const -{ - // pass through - return mImpl->mWidth; -} - -unsigned Texture::getHeight() const -{ - // pass through - return mImpl->mHeight; -} - - void Texture::setMinFilter(GLuint filter) { // pass through @@ -417,10 +463,54 @@ void Texture::setWrapT(GLuint wrap) } +bool Texture::getTileCoords(TileIndex index, Scalar coords[8]) const +{ + // pass through + return mImpl->getTileCoords(index, coords); +} + +bool Texture::getTileCoords(TileIndex index, Scalar coords[8], + Orientation orientation) const +{ + if (getTileCoords(index, coords)) + { + if (orientation & FLIP) + { + // this looks kinda weird, but it's just swapping in a way that + // doesn't require an intermediate variable + coords[1] = coords[5]; + coords[5] = coords[3]; + coords[3] = coords[7]; + coords[7] = coords[5]; + } + if (orientation & REVERSE) + { + coords[0] = coords[2]; + coords[2] = coords[6]; + coords[4] = coords[6]; + coords[6] = coords[0]; + } + + return true; + } + + return false; +} + + std::string Texture::getPath(const std::string& name) { - std::string path = Resource::getPath("textures/" + name + ".png"); - return path; + if (boost::find_last(name, ".png")) + { + return Resource::getPath(name); + } + else + { + std::string path("textures/"); + path += name; + path += ".png"; + return Resource::getPath(path); + } } diff --git a/src/Moof/Texture.hh b/src/Moof/Texture.hh index 4e311ea..41add2b 100644 --- a/src/Moof/Texture.hh +++ b/src/Moof/Texture.hh @@ -36,8 +36,8 @@ #include +#include #include -#include namespace Mf { @@ -47,10 +47,26 @@ class Texture; typedef boost::shared_ptr TextureP; -class Texture : public Resource +class Texture : public Image { public: + /** + * Possible orientations for texture coordinates. + */ + + typedef unsigned TileIndex; + static const TileIndex NO_TILE = -1; + + typedef enum + { + NORMAL = 0, ///< Normal orientation. + FLIP = 1, ///< Flip over a horizontal axis. + REVERSE = 2, ///< Flip over a vertical axis. + FLIP_AND_REVERSE = 3 ///< Flip over both. + } Orientation; + + static TextureP alloc(const std::string& name) { return TextureP(new Texture(name)); @@ -63,14 +79,38 @@ public: static void resetBind(); - unsigned getWidth() const; - unsigned getHeight() const; - void setMinFilter(GLuint filter); void setMagFilter(GLuint filter); void setWrapS(GLuint wrap); void setWrapT(GLuint wrap); + + /** + * Calculate texture coordinates for a tile at a certain index. Tiles are + * indexed start with zero as the to-left tile and moving across, then down. + * @param index The tile index. + * @param coords An array of scalars where the texture coordinates will be + * stored after this call. The first coordinate (u,v) will be in the first + * two places and so on until all four coordinates are stored, therefore + * requiring enough room for an array of eight scalars. The winding of the + * coordinates is always counter-clockwise (the GL default). + * @return True if index is valid, false otherwise. + */ + + bool getTileCoords(TileIndex index, Scalar coords[8]) const; + + + /** + * This version let's you specify an orientation that will be reflected in + * the texture coordinates. This allows you to easily map a texture + * backwards or upside-down. + * @param what The orientation; can be flip, reverse, or flip_and_reverse. + * @return True if index is valid, false otherwise. + */ + + bool getTileCoords(TileIndex index, Scalar coords[8], Orientation what) const; + + static std::string getPath(const std::string& name); private: diff --git a/src/Moof/Video.cc b/src/Moof/Video.cc index 62addb4..e071609 100644 --- a/src/Moof/Video.cc +++ b/src/Moof/Video.cc @@ -39,42 +39,39 @@ namespace Mf { Video::Video() { - init(mAttribs); + init(); } -Video::Video(const Attributes& attribs) +Video::Video(const Attributes& attribs) : + mAttribs(attribs) { - init(attribs); + init(); } Video::Video(const std::string& caption, const std::string& icon) { - if (mAttribs.caption == "Untitled") - { - mAttribs.caption = caption; - } - if (mAttribs.icon == "") - { - mAttribs.icon = icon; - } + mAttribs.caption = caption; + mAttribs.icon = icon; - init(mAttribs); + init(); } -void Video::init(const Attributes& attribs) +void Video::init() { + Error error = Backend::getError(); + if (error) error.raise(); + mContext = 0; mFlags = 0; - mAttribs = attribs; - setFull(attribs.fullscreen); - setResizable(attribs.resizable); + setFull(mAttribs.fullscreen); + setResizable(mAttribs.resizable); setOpenGLAttributes(); - setCaption(attribs.caption); + setCaption(mAttribs.caption); setIcon(); - setCursorVisible(attribs.cursorVisible); - setCursorGrab(attribs.cursorGrab); - setVideoMode(attribs.mode); + setCursorVisible(mAttribs.cursorVisible); + setCursorGrab(mAttribs.cursorGrab); + setVideoMode(mAttribs.mode); video = this; } @@ -104,7 +101,7 @@ void Video::setOpenGLAttributes() SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, mAttribs.multisampleBuffers); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, mAttribs.multisampleSamples); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, mAttribs.swapControl); - SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, mAttribs.hardwareonly); + SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, mAttribs.hardwareOnly); } @@ -312,7 +309,7 @@ Video::Attributes::Attributes() multisampleBuffers = 0; multisampleSamples = 0; swapControl = false; - hardwareonly = false; + hardwareOnly = false; mode[0] = 640; mode[1] = 480; mode[2] = 0; @@ -344,7 +341,7 @@ Video::Attributes::Attributes() settings.get("multiesamplebuffers", multisampleBuffers); settings.get("multiesamplesamples", multisampleSamples); settings.get("swapcontrol", swapControl); - settings.get("hardwareonly", hardwareonly); + settings.get("hardwareonly", hardwareOnly); if (!settings.get("caption", caption)) { @@ -364,7 +361,7 @@ Video::Attributes::Attributes() mode[0] = dimensions[0]; mode[1] = dimensions[1]; } - else if (fullscreen) + else if (fullscreen && Backend::isInitialized()) { SDL_Rect** modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE); diff --git a/src/Moof/Video.hh b/src/Moof/Video.hh index 0199bc5..0cc1a4e 100644 --- a/src/Moof/Video.hh +++ b/src/Moof/Video.hh @@ -1,30 +1,13 @@ -/******************************************************************************* - - Copyright (c) 2009, Charles McGarvey - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*******************************************************************************/ +/*] Copyright (c) 2009-2010, Charles McGarvey [************************** +**] All rights reserved. +* +* vi:ts=8 sw=4 tw=75 +* +* Distributable under the terms and conditions of the 2-clause BSD license; +* see the file COPYING for a complete text of the license. +* +**************************************************************************/ #ifndef _MOOF_VIDEO_HH_ #define _MOOF_VIDEO_HH_ @@ -62,7 +45,7 @@ public: long multisampleBuffers; long multisampleSamples; bool swapControl; - bool hardwareonly; + bool hardwareOnly; // Window attributes std::string caption; @@ -77,11 +60,13 @@ public: private: - Backend backend; + Backend mBackend; + }; - static VideoP alloc(const std::string& caption, const std::string& icon) + static VideoP alloc(const std::string& caption, + const std::string& icon) { return VideoP(new Video(caption, icon)); } @@ -125,7 +110,7 @@ public: private: - void init(const Attributes& attribs); + void init(); void recreateContext(); void setOpenGLAttributes(); @@ -147,5 +132,3 @@ extern Video* video; #endif // _MOOF_VIDEO_HH_ -/** vim: set ts=4 sw=4 tw=80: *************************************************/ - diff --git a/src/Scene.cc b/src/Scene.cc index aa2249c..45fc3a0 100644 --- a/src/Scene.cc +++ b/src/Scene.cc @@ -31,20 +31,20 @@ #include #include #include -#include +#include #include #include #include //#include #include #include +#include #include "Character.hh" #include "Scene.hh" -#include "Tilemap.hh" -struct Scene::Impl : public Mf::Library +struct Scene::Impl : public Mf::Manager { struct Quad : public Mf::Entity { @@ -57,7 +57,7 @@ struct Scene::Impl : public Mf::Library }; Quad(const Mf::Vector3* vertices[4], const std::string& texture, - Tilemap::Index tileIndex) : + Mf::Texture::TileIndex tileIndex) : mTilemap(texture), mBlending(false), mFog(false), @@ -143,7 +143,7 @@ struct Scene::Impl : public Mf::Library Mf::Vector3 mVertices[4]; Mf::Scalar mTexCoords[8]; - Tilemap mTilemap; + Mf::Texture mTilemap; bool mBlending; bool mFog; @@ -170,8 +170,8 @@ struct Scene::Impl : public Mf::Library }; - explicit Impl(const std::string& name) : - Mf::Library(name) {} + void init(const std::string& name) {} + void importSceneBindings(Mf::Script& script) { @@ -372,7 +372,7 @@ struct Scene::Impl : public Mf::Library table.pushField(i); - Tilemap::Index index; + Mf::Texture::TileIndex index; top.get(index); script.pop(); @@ -380,7 +380,7 @@ struct Scene::Impl : public Mf::Library vertices[h][wPlus1] = Mf::demote(mTransform * Mf::Vector4(wPlus1, h, 0.0, 1.0)); - if (index == Tilemap::NO_TILE) continue; + if (index == Mf::Texture::NO_TILE) continue; const Mf::Vector3* corners[4] = { &vertices[h][w], @@ -425,10 +425,10 @@ struct Scene::Impl : public Mf::Library Mf::Script::Slot param = script[1]; Mf::Script::Slot top = script[-1]; - Tilemap::Index index = 0; - int width = 1; - bool blending = false; - bool fog = false; + Mf::Texture::TileIndex index = 0; + int width = 1; + bool blending = false; + bool fog = false; if (param.isTable()) { diff --git a/src/Tilemap.cc b/src/Tilemap.cc deleted file mode 100644 index dc3785a..0000000 --- a/src/Tilemap.cc +++ /dev/null @@ -1,189 +0,0 @@ - -/******************************************************************************* - - Copyright (c) 2009, Charles McGarvey - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*******************************************************************************/ - -#include -#include -#include - -#include "Tilemap.hh" - - -struct Tilemap::Impl : public Mf::Library -{ - Impl(const std::string& name) : - Mf::Library(name), - mMagFilter(GL_NEAREST), - mMinFilter(GL_NEAREST), - mTilesS(1), - mTilesT(1), - mWrapS(GL_CLAMP), - mWrapT(GL_CLAMP) - { - loadFromFile(); - } - - - static void bindScriptConstants(Mf::Script& script) - { - script.push(GL_CLAMP); script.set("CLAMP"); - script.push(GL_REPEAT); script.set("REPEAT"); - script.push(GL_LINEAR); script.set("LINEAR"); - script.push(GL_NEAREST); script.set("NEAREST"); - script.push(GL_LINEAR_MIPMAP_LINEAR); script.set("LINEAR_MIPMAP_LINEAR"); - script.push(GL_LINEAR_MIPMAP_NEAREST); script.set("LINEAR_MIPMAP_NEAREST"); - script.push(GL_NEAREST_MIPMAP_LINEAR); script.set("NEAREST_MIPMAP_LINEAR"); - script.push(GL_NEAREST_MIPMAP_NEAREST); script.set("NEAREST_MIPMAP_NEAREST"); - } - - void loadFromFile() - { - Mf::Script script; - std::string filePath = Tilemap::getPath(getName()); - - script.importStandardLibraries(); - importLogFunctions(script); - bindScriptConstants(script); - - if (script.doFile(filePath) != Mf::Script::SUCCESS) - { - std::string str; - script[-1].get(str); - Mf::logWarning(str); - return; // TODO needs a better exit strategy - } - - Mf::logInfo << "loading tiles from tilemap " << filePath << std::endl; - - Mf::Script::Slot globals = script.getGlobalTable(); - Mf::Script::Slot top = script[-1]; - - globals.pushField("tiles_s"); - top.get(mTilesS); - - globals.pushField("tiles_t"); - top.get(mTilesT); - - globals.pushField("min_filter"); - top.get(mMinFilter); - - globals.pushField("mag_filter"); - top.get(mMagFilter); - - globals.pushField("wrap_s"); - top.get(mWrapS); - - globals.pushField("wrap_t"); - top.get(mWrapT); - } - - - bool getTileCoords(Tilemap::Index index, Mf::Scalar coords[8]) const - { - // make sure the index represents a real tile - if (index >= mTilesS * mTilesT) return false; - - Mf::Scalar w = 1.0 / Mf::Scalar(mTilesS); - Mf::Scalar h = 1.0 / Mf::Scalar(mTilesT); - - coords[0] = Mf::Scalar(index % mTilesS) * w; - coords[1] = (Mf::Scalar(mTilesT - 1) - - Mf::Scalar(index / mTilesS)) * h; - coords[2] = coords[0] + w; - coords[3] = coords[1]; - coords[4] = coords[2]; - coords[5] = coords[1] + h; - coords[6] = coords[0]; - coords[7] = coords[5]; - - return true; - } - - - GLuint mMagFilter; - GLuint mMinFilter; - unsigned mTilesS; - unsigned mTilesT; - GLuint mWrapS; - GLuint mWrapT; -}; - - -Tilemap::Tilemap(const std::string& name) : - Texture(name), - mImpl(Tilemap::Impl::getInstance(name)) -{ - setMinFilter(mImpl->mMinFilter); - setMagFilter(mImpl->mMagFilter); - setWrapS(mImpl->mWrapS); - setWrapT(mImpl->mWrapT); -} - - -bool Tilemap::getTileCoords(Index index, Mf::Scalar coords[8]) const -{ - // pass through - return mImpl->getTileCoords(index, coords); -} - -bool Tilemap::getTileCoords(Index index, Mf::Scalar coords[8], - Orientation orientation) const -{ - if (getTileCoords(index, coords)) - { - if (orientation & FLIP) - { - // this looks kinda weird, but it's just swapping in a way that - // doesn't require an intermediate variable - coords[1] = coords[5]; - coords[5] = coords[3]; - coords[3] = coords[7]; - coords[7] = coords[5]; - } - if (orientation & REVERSE) - { - coords[0] = coords[2]; - coords[2] = coords[6]; - coords[4] = coords[6]; - coords[6] = coords[0]; - } - - return true; - } - - return false; -} - - -std::string Tilemap::getPath(const std::string& name) -{ - return Resource::getPath("tilemaps/" + name + ".lua"); -} - - -/** vim: set ts=4 sw=4 tw=80: *************************************************/ - diff --git a/src/Tilemap.hh b/src/Tilemap.hh deleted file mode 100644 index 9277387..0000000 --- a/src/Tilemap.hh +++ /dev/null @@ -1,110 +0,0 @@ - -/******************************************************************************* - - Copyright (c) 2009, Charles McGarvey - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*******************************************************************************/ - -#ifndef _TILEMAP_HH_ -#define _TILEMAP_HH_ - -/** - * @file Tilemap.hh - * Small subclass to give some basic tile-mapping functionality to textures. - */ - -#include - -#include -#include - - -/** - * A tilemap is a texture which is meant to be divided into smaller sprites. - * This class provides all the functionality of a texture and adds some methods - * to get texture coordinates to individual tiles within the tilemap. For - * simplicity, this class assumes square tiles. - */ - -class Tilemap : public Mf::Texture -{ -public: - - /** - * Possible orientations for texture coordinates. - */ - - typedef unsigned Index; - static const Index NO_TILE = -1; - - typedef enum - { - NORMAL = 0, ///< Normal orientation. - FLIP = 1, ///< Flip over a horizontal axis. - REVERSE = 2, ///< Flip over a vertical axis. - FLIP_AND_REVERSE = 3 ///< Flip over both. - } Orientation; - - - explicit Tilemap(const std::string& name); - - /** - * Calculate texture coordinates for a tile at a certain index. Tiles are - * indexed start with zero as the to-left tile and moving across, then down. - * @param index The tile index. - * @param coords An array of scalars where the texture coordinates will be - * stored after this call. The first coordinate (u,v) will be in the first - * two places and so on until all four coordinates are stored, therefore - * requiring enough room for an array of eight scalars. The winding of the - * coordinates is always counter-clockwise (the GL default). - * @return True if index is valid, false otherwise. - */ - - bool getTileCoords(Index index, Mf::Scalar coords[8]) const; - - - /** - * This version let's you specify an orientation that will be reflected in - * the texture coordinates. This allows you to easily map a texture - * backwards or upside-down. - * @param what The orientation; can be flip, reverse, or flip_and_reverse. - * @return True if index is valid, false otherwise. - */ - - bool getTileCoords(Index index, Mf::Scalar coords[8], Orientation what) const; - - - static std::string getPath(const std::string& name); - -private: - - class Impl; - boost::shared_ptr mImpl; -}; - - -#endif // _TILEMAP_HH_ - -/** vim: set ts=4 sw=4 tw=80: *************************************************/ - diff --git a/src/TilemapFont.cc b/src/TilemapFont.cc index da0e9a6..48b0fc3 100644 --- a/src/TilemapFont.cc +++ b/src/TilemapFont.cc @@ -32,13 +32,13 @@ TilemapFont::TilemapFont() : - Tilemap("Font") {} + Mf::Texture("Font") {} void TilemapFont::getTileCoords(char symbol, Mf::Scalar coords[8], - Tilemap::Orientation what) + Mf::Texture::Orientation what) { - Tilemap::Index index = 0; + Mf::Texture::TileIndex index = 0; if (symbol >= ' ' && symbol <= '_') { @@ -53,7 +53,7 @@ void TilemapFont::getTileCoords(char symbol, Mf::Scalar coords[8], index = 0; } - Tilemap::getTileCoords(index, coords, what); + Mf::Texture::getTileCoords(index, coords, what); } diff --git a/src/TilemapFont.hh b/src/TilemapFont.hh index 98a3a13..89cb062 100644 --- a/src/TilemapFont.hh +++ b/src/TilemapFont.hh @@ -34,17 +34,17 @@ * Text on the screen. */ -#include "Tilemap.hh" +#include -class TilemapFont : public Tilemap +class TilemapFont : public Mf::Texture { public: TilemapFont(); void getTileCoords(char symbol, Mf::Scalar coords[8], - Tilemap::Orientation what = Tilemap::NORMAL); + Mf::Texture::Orientation what = Mf::Texture::NORMAL); }; -- 2.43.0