From 17621fbd59b33b09ecb3ad3c24109ca6e2c25ae2 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 7 Mar 2026 23:40:15 +0000 Subject: [PATCH] feat: switch to LPC tileset with layered autotiling Replace the 16x16 tileset with LPC Base Assets (32x32 tiles, 1.5x scale). Uses a 4-layer rendering approach: - Layer 0: solid grass base (grass.png) - Layer 1: water transitions (watergrass.png) with LPC autotile edges - Layer 2: dirt transitions (dirt.png) with LPC autotile edges - Layer 3: tree canopy decorations (treetop.png) LPC autotile format: 3x6 grid with inner/outer corners, edges, and fill tiles. Edge tiles are selected based on 8-neighbor terrain analysis. Co-Authored-By: Claude Opus 4.6 --- client/public/assets/lpc/dirt.png | Bin 0 -> 8607 bytes client/public/assets/lpc/grass.png | Bin 0 -> 8500 bytes client/public/assets/lpc/treetop.png | Bin 0 -> 11062 bytes client/public/assets/lpc/watergrass.png | Bin 0 -> 9980 bytes client/public/assets/tileset_16x16.png | Bin 12112 -> 0 bytes client/src/scenes/BootScene.ts | 5 +- client/src/scenes/GameScene.ts | 155 +++++++++++++----------- server/src/map/mapGenerator.ts | 11 +- shared/src/constants.ts | 9 +- 9 files changed, 101 insertions(+), 79 deletions(-) create mode 100644 client/public/assets/lpc/dirt.png create mode 100644 client/public/assets/lpc/grass.png create mode 100644 client/public/assets/lpc/treetop.png create mode 100644 client/public/assets/lpc/watergrass.png delete mode 100644 client/public/assets/tileset_16x16.png diff --git a/client/public/assets/lpc/dirt.png b/client/public/assets/lpc/dirt.png new file mode 100644 index 0000000000000000000000000000000000000000..614326426909f78b02e39aaaff62524a597f146e GIT binary patch literal 8607 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 literal 0 HcmV?d00001 diff --git a/client/public/assets/lpc/grass.png b/client/public/assets/lpc/grass.png new file mode 100644 index 0000000000000000000000000000000000000000..bf7098b9d033cd52c1caa09e7a184f66ea51ecf2 GIT binary patch literal 8500 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

Bl#wAR+_+2u9a8_^xffG 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 literal 0 HcmV?d00001 diff --git a/client/public/assets/lpc/watergrass.png b/client/public/assets/lpc/watergrass.png new file mode 100644 index 0000000000000000000000000000000000000000..93fee6bff9a85d03574022d04091d0d770772be0 GIT binary patch literal 9980 zcmVKLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=00004XF*Lt006O$eEU(80000WV@Og>004R=004l4008;_004mL004C` z008P>0026e000+nl3&F}000~pNkl zRB9RZouDFV%OZeNeWjMct@~Mg^Zgzaa}88xQn+}T>+UEdp%XyuYg;bN#W+nLC5Flb#Z)6af3pZ5KG$#uoWi( z#0B)3lndwpaP#D#b&aj5!hTHlzHnSq+)&u7?!T=QS}RSIKXPbAAfc&%dH7%+0MzRT z4;KOZ+Rc-Ls4uUzuG?#}_XV!b?80R43miU}$3*opD#)OiYq(6;Esp>~LVjS?7Do+K zkilW3@!;Vi9z0ycQtgrBi?iZ20PM?IqK6Q|x#8x?L7ZK-MBT0XSxZFa8rulqFC<{H zeJKU#@`X=;v0-3#-um#^u#Jg%_5ITHB?oc{Auf@GCW_;0+vE=*B|TxTFiTGtEWops zz59db4eQ4bC`1uL0AOtNg!+2|uN0EEx+k3GR?y;;9t$uz>&$74xspr&S9$5GRUU>A=Z!7j~}r9n7`%%{&p5O znIaRke*8cSh!K|J9^0%X4|&@cU`lxLNe^z_&!U)XSl%x(m_iz}bKl~(sUPA~|JX1v z_Bn8U0;iAERU~!2SAFe9Yz~i&fJ!Z+L_=jJ<*-o3Mo$2pk z2T+>3hjMiY#qo^+eBJ9#B4h`N2JX$0=*jk_6cYC32C*+U=&)?Ua6x_T1~7jO<(n}9bM(-@RTOg#MHHly&M=N|yA_0get&JsRs{s;C5@NMMNm+mKt6Q2f5_#4 zb;1hbRv2F&zPkt>iUEM@U+0~~(`Ip$F6J7TsAW)^yXOWndAln9Fdqu={K1LJDz(mq zAY6d2HgWocmnuTLu+-x?!6T#K^pU#tnVA&o=bZOQ8X;*4!d-_gn?Iatg%?6NU|tIN z%-lVc`-gD)gO^5sqaBNWzh1RMAC+nfi%)t~;E@iG2>6RndK6dO`u8`i2(AryIv2sw zHdsN|KkEa~1kPPXcKXX?t&HK1fZ0~8shDf1pkKQpqGZhwSC{*TY!TBs7$T9wlL+YA z!cq@V*o$JWp{})yVA9vW&Z9VPo1pX8P#^v%7S%gewF!V(KGi0WYwtM#*ENpc1++)5 zGKqjVfdhYG$r4A|qa~N=8doHxmHlrA;j(d@F1ERnEp~|F7oYT?f((F0TY*0|dIII@ zW2chM?NRcc_M#&KPUX6@Y-y?{A(GM@_{H%xRBD!I7{)14%I*v69{GV)lx>|-nP~#! zExDWYVT{8hp0zBwsX`tTGmnuU=uxMAT;5BH*QL^MBvon|6vrDFIn=V6Dl;kI++`r9 zwAlIczZv??nG;KR=dUcv`0>sQtPK7E#ashFF887@b<9BlEBMZJ4L=)2Y5EfWsrcu( ze&TSfowp8x>Qp6|5&UwJ1I&{uMAVkP&c z*DqhI-y1o!f}wp*-J|wl|Ib%`U=@X-7kK^hwL={J z=a*?qLD%N6g72_0{I^)iy@|fs|AprO&T5sJ6j0c!%rI1&s27~El47pm;*ydbYM#I= zhg~g$ZAmFIla3;5CqJ-?p?6mSEW0cn6SeD>G*QWXJ^eu)K+9B(Ber+;{q>*yhBold zU#{Ypf6>JK#aO9Z{;>QRJ)N%x>pI6%h{=YRVziUa$8W<^-~cmJe-`0V*kJbS(qi%)uxA6V5=yrlmA z-9IU!q0gT=v4sBJKPebxkCqaM1=$vYBSL9sF#te$^q7j9kRl`C6P457TuBkYb(wZa z$$zc`D2!5>vFv?Hvyq4oqJ!xB93k8!t<0oQdb$uROz%JdXS0z*E6Rc(;8NU#$51#x z{eb(;_j?i#KYN+W6i`fRafDWC8KAJ&GIQszq5fSto)x5%&-7XXS~@K17!&XXa69b( z?A;%5X7-9Y?xa0)$|W(BgayWR8^NejO~prm2&MV~cRiD=%KbyihcVglahI%xpaU#AIjkQ)5IK6VBS~O%I@z{< z`~XT%7aWI3t>m&~<-fxKk$JOY!>C_)KhoKGIt&F!PT&DG`b@jILHB?Ycx4~*06@cG z(Z$&he?H0_9NM>v;&=}#GfhkO7vM-vlY8{zjC4>6;4VGMKXT3KeVy(|I_jCV&z9+| zqC9pRm^|+gK}qT(u5fuYw}Ll-tDggt=Ye4)D}u=8<*e)~*svpvT+yjibaoF@$x;|Q zU;eY=KJ$w5N>3Mj&CV!diTeU7aoP4U)E>@Vjuk!L;V1K4n_(&IoEwyVTy4TD(JL&q z(?8>yowqXZ>~m&L0AUG1r$5NTTUhF8oo7=ZE`hbf&v8t@IR?I9u>B04{ z^Xhyx2@jYfLm^~r*!p*ULRlpwA_(AN2!V@Q9uFEhwBit>Q-%Fjc8Dzo<9Ne6{5GT< zEk^kY3EUc}w(1E~cw0DeNjqTK=`SrYF#M6)Tcwt9P&;|ALB$h^TIp<2=~gkgx{kb{HE zbs-MoK*6Q4%uw3U$e|T{liQ=rt*Js9IGD%m+_#S6j1qv^xrG*I*lFlQC1g3Y!y;09 zxOfWX(PJp)8j5SJXl_FrV&;3`z}KA*w}8G!DSXV?Y5Osg7PJVU2Ox!1DP%GEu!h;W zZ!NQr3N_%ie*pk?=G@fi2~60<7|6A!R#?aGib4x}LC2p|6f*K|s|1UOEr`Mi8I(Ls zgjlKNt&=@8TPgSU^V1%pA|kD0MQ-x~R-#t<)7!1QAdxx26L8C8_69GWvXFpR$Pd&L zvCka<=Q&H$me{j6b-#lHD>K%$3HzLwj0UQKkiHAOe+yZaL`;r78x ztXG=5r`XMOW0`=lrEl9RX7hGE&|VYIS}I13r%(4!~<*j zfmKy@d-l#F+^W6-6ta%=MTLAF_iGRm$`j`D696WAYgh`2Q3?-Jc7h7k+Icofp92sw z%Aei_E}nAeCTs1tQ!aNY>x?*pL=jzI%vs2&FR!Uu=d*Vn+0W4Q1$tQOR|t?XbBx;_ z?ZaBA8@9Yu*a);NBPvUh=Lkt!LBt74M2roibnz5s=e}(f3);Y^yLR*WnFdGMAK5AWjZiPB&1CJf*hW26eKVYRcCo5i2z?EZJVl&bA(T=Af7TU(JHGY zBq+;ISU!nm4w?|a!wOXCK0EiV%9{4tfCC6$e60R7)ddGdKxB7cW_XJ@690@ANg*@B zVnhb7aORGy|OKo^w*yu^+Rz+MQEpYi*CyL5obAE?waK*WSy zvW6zAk6lP0U67Oriklu18c_)$!&?VX?by}N!xv|WEMfp{*8y=5V$8Nn=stn`08XJJ zhgPs~#I}Ye&j&jB=Xv@2a)Y?~d>2lC@G|ibL>#~e)?aM^wr?oH<&xX3d=TJMdWgeo ztTt7mSC~$UNjYgcpn9FxwoB253Po^AwKBl`ih?N*lUT8`XM zc@BK~NL?Mqm}EP>rmQp`Kj(R*ru_V^z8u|BxR)x!$6Unl^mGzAV|)}9SKrh%K>t6PM{WM+)5&b<*NGq#u!A6IdnL#L zek%#!=d;s}P)Mf`x*kqpXb$M~l4*fqfa&!;Su!h)2b0d*)Ch=T`N&My??5)f!BUP?4?09Fv;_7wBZN>`zLW9vrA# zgvn>niA5d9M2+|+riA&%dOdlociV9Al-vfnH0T8-F~^4lC^7&`&OGu zeDYKrjzIowI-L;4I*f$?PRS;=B}GVc$npcLDgl-Nu4>KLHOfRL0Ngw|s5<#_3a8KT z;Xy>@lf5tOo^ktKx`3|n>}O6Cgsht<2OV`_vewLx+BuO1=^PMA1nC+faS_AkkU2KM zhP$~a9jx$=Q8EFJi=vw+2l3VK7u=j+FOCGhIPi%8BsWS9s?4O+iJ#8;l2k4$H2qd8 z>NM3Li&GL6Jk*!h9L>Oa$~eD9uW1Ap2Vk}@!eUx+(p)H{ZU7>}p8~RistpHYEUQ_MxIk0r&ux4wIToagN;e-zGjx=(6 zl`fvb(o^68Lo7!W{r;q8;uEi=Q59vM%~u3T50onwX(5=3@Ej#RUch3&;fN|- zJmnBovmBW|S=){oHXaK!P`WWaH zz)uqBKKJrW$Q8BBL4J>PkTL|AucD9vXJT5=kaa8_AmcWClaA^_1K?csz9Cn;GM{Co z=i!5SWy$fyM>0lTv3ka-sS?aNdhl=&hY#kBrJW|g`5~j-Y35p8F>SWMu0G#o5n(kI zs|Y=G&p2K~jA|3NfBhEj-Tjl+$uWtFDAXRN5nj~$dhS_JKX)wotYkmKC6);Ca=>o( zS+BqP{X$^HyOE10sMeYHpy0$s93ZJbY^UB(p0F;YOtSy1O%;a^=36G?CIh-o*~=aj zWErWhEYuG}H9K!~E)rfG3Ip>{L)2k!8+x&ZAWOAJEm33xpTj0h16!>Q2qMS032Jn@0@(hW0YN&Wp)`F- z6`|{NK`ar(vm7Kg2{}AL>MC+pW2XRdnawJWT&C)Dt7Wn&3=@QqeXStVsh6&`4L+Pw zl;16)$IE2qy)e9hpO_hH3QQ?Vi8)VYBLmwMrYK!J)#^Kh@N+UlSwSwW+CRFU6RFz{ zbT40KY}he8B1%WFbeQmiZ0x5dC2D^aVYjNu2F-Owd^AQ13PQ& z=g)MbNUDEVj%@Fnkdcn^CCLed`AW?KKF(c6eUo#7);~CY8TjI3R|7&XOVLz`<12!^ zw76CbkyjjYw#sHflCB@BsS{)vQ{Fc%g&Z)GSW+e_>#W!4B%D>f*dki>2^8bxfm+VE}&d>W<|(hpNSzr7Dscc zpDOIP8hdv;#dF}>hcUmhv%SyWd4viwpw41CxS7_DAYw?3{wLiPOYCH`K(tITCNBLfs5&h^yEdz`mv#f)2mtzmM+32g>KZNq~s>>fR zSv+2x;K>1wsTy$hgmV?^F(usXia2|;qz2XTnlK4`Sz?=5Fpis6t$8yquvB{#c*w)1 zbj0`?8&(4#$RF@BHxsdfXmJaOr|9X*jk*HZ67aOHer_2gljl(>WRuH^@bZd@#frHG zkOR)vtm{+l>3q{M1sfPS+}WJJrZ_-aKtY3X=_tT=SwprW?#2@VW95zAw%N~Vjh!1R zi!{7~Q038MK#T$Rn?_vCUo&Px>y)t93Z;a7OOv>j(5*_C4JJ}c9LR+6hJB-fZ4 z3o95`$I!c6F*mHxY?ph$4&c*)e2!mjX#J(cvm&^xyLCU?Iu9_IYu$C)&p?)qEIH4wz zp6+Re^6cmU!0$GW;2Cno@wL#WVWB-?-lVBg%b@i1p0*NxD=1;|chtwoFRRe$p1SL%&wE`D^1jN3W_h5L5l+v^ z=jNEQpuGlOg!ThCrR%Wo3QXDQ>!>z?qauQ6I>51`iyTN4bFmyAJyqA&ZYbpsKu!Fv z)G`iBhQ8;A9Qm0_ErZiX>X7HYUN*j0-=$C-pqmJ>u+(E5Uc-??NKp^NBZvan{Jr|x z4To<*qtpo@^|c$QA3vZzLu1y*Mo&1#t;>6JpcZotM_h;AQ@>4=Kfb0s|DaQoII+^e zi%25KG!4mwdHQ^%mT9$mw`Hhw){41COFW6tuAE!XABt9K`jYw#y?5;RZujR6TxAL~ z5C={6zG$8L74|v`u>F>9o@FEi5cYz2cl^hsrJw_-d}z}&Jjn(8e)7Fjcb}=xkUh@R z2z3ZOGkZl*KXpVb<{G$qFb5R&V&u?@Yu|idvPOW5WxoM$v6QfB=AxX@rKL7zSrB66 zX8AQ!o~0Lu==2f+lYmtmUsL6#3h3;+UWe{n8t9ZUDQPb**bxW#I_&ZdN}zF3A+PJ$ zTFxfp_v6&8(>bPl=m7M;aF;5@EV){2_x5 zRO8>3laS=TOdMrOH}MkJVNS(ji6Flji+*Eay=FL?C{34ZX>$2>!$akeXD{yblHWlT zY}*hJbatX{44|&R5!Zs8(s}=B>31>f=S_=b|tQZIDnlMBwVXlz(?*vjhF;p}Z0wQgiAtLBQ z_+_Yd6!?Y#&_VVPglG~+KwAJn4==`&cSP@uk=LViY3Tv23dyGEVILP~%svb5g~YXxl> zN{?YS2O)@bryio+6dKo5^x|@QF-f01fyw1aUE*R@D7gNS`J& zZ$mW*plY09|H*LH*EUuG0De8)@`Gdnq5(oeLh9V|rrZ!l1%7~XhBV{_6biLdl6+<% z>8h<@ss950Tv6mL^o4zjl5lX8@^ZQSd4UtizM0IdR~rfG%7r_7qT-2QL5KG{`E zt*xz7!#yo)o`W-IX9r*XsnALOi@?WF*9f4v^ULu+!%j;L3P55psy`Wc9_kj}0005` ze*+DWl}+=sh~uN7qk^-5g+Yytjp2hX^t43lqhju(?EdBr%*_X&>;<#+fjNMDoqe1@ zY8pEFW?{tC000P}0aY^gTiCWDvM(R5+FsbG$5H(yyo}6||MvK(*5Sa8ff0-TZFlAQ zWmzhTT#icZxzG@bt(JEFd?};0=su}2do|6gq*v%)+Lu}0?dh${hSk&kztvI<;&>KcKm+XcQK5tGJC_ z)=QO50^tZyts2BiW%vo30a$zyB)*+7mF{|k(w~wu)cflRxGpeShBkDrznNp1&2`rU z3iHyQyF^L^hG5V*xr+b3F=Rui6iAW1gMG^CA%pF)B_S3`58_{@glDAz1{m<@-k0iF4?&2+HF(H&8VF*P9x;{Ykeq}fY?NAsKg@%CZ zhx2Z39t=+f#nSC>IJgyYcRm%5l@H&AA)##6dcMkQJYc^yzCwCjCX2ce6 zy^5D;kD1?EH@*D?ug+2gBS_9I_aRtnT&i1W)p(lh&|>5342xk6c=hvBll^@$Y{a7- z_SQ@&83QIEztuO+?N7XkzCz!!h8GEHdHwf!%b*4G&zB!BIHnZG2evbxNr7RrBwnGB#*%`&KVJt|W%U<|bsxFihA3M@ z#8E)>&1xLJwh4wF9?S~vswgkqQ^Dxo5RE_g8_}g!^GB(!ICnay4P~>F@*R zSWgE(y37QyplJ6d3mR8n6YJC^OkkiYMqS<|L(ub1QSM%&r zJRnhdx_ar)ir9pO#LveKr=UrNA<;srDO?kMU?FmKv2&JQ`U6kgJMalP>a2neA-CjF z5V_vr_u?tS0Px2yke#!{x%84i>wVHoEZ}uXncoH@s5y>~lL+y>z9R;Rrx87kZv}F@ zf0H@|vSX6N9tf8LR~i&L z)ZKNPq$3{*Y}YkKlU<2Ioe=Tz!jwyT2E(H8YQSC|52drkjSx&03+yzzXF4JI%6z2O zJ-Qae>*FCAzDpYZ5M{-6%l&c1KOPo`0=y3;Z}W`V(zGQ{MQKZ!+AEkQi37&nBiqo` zKgA$x@m_G>J$>-K_QKxYZWxR`B&1#+zc_ytbbWZC(_E6i7ZqR8=%L0qTIjbO%M;djTFM(g%PR>K>$P&5Hjn)R8$z{>8R3oPayT)fjN9bkt!HgKg8aQK(Ngo)qhH z=XpbL8|#OSZ@VdjyL8MioVUXFV5!%7j+XC6Ws^8Uf`3&$v~@n-TtuggeWgSY1L@H2 zU!;?@h?9*#oV9WAf?MvCMOdd8HfWOHf8`J1Z7s-BV1wTD58d;&y^$71Kod~E2*7tx`ZxQ5PCBzHWb4B=b%6OMD}UZSzMTCy6eS)Gg3 z<1|aE4xtN#<9Syzfe3XMh#={8 zi=at_fAez0ZT^u#m!IqkJ$Ic3N&lESxC;cPqNae#Tp`g}8>)4YQIDp#sV#ilI>#Rj zLhK}VkO?c;MaDcPKh-4}?)aWzXCM5m6h>%Q3kOnB*9iA8%m16~j%Ne>GQo(h7OaN) z5aS?IiZR%<3cVZ>3p&jKH>{OG_`+m{_E|HNZ0c3CCTuA7CJYe&h#@thXBD1fyG{6K zy1`G*{w7D-WeqfN4~Ja}pfKZjoz_J6DNoGx<_ucvSos)*Tbl}BZ+QiUC~76?kN!NV+S28`Ym^4xFpz-u-%VLb8;_yq#340v~(+QleR z^+dKA(z;3z4)(jSjM-kM4$VP2rD4*j*+J`nYX4e(RirCPG!KVO&8qV_gUNe3M%lMq z90u8Uz=zp~44il6M)#;eBIgfueS7pvIx(lvVUmwjB-7b!$dIPrsDk!>$L^i*3BR>B zlFE~K)*cQRcwJqiSZb7})Z(Q>i}~Z2KdpMTrdhX&lQcAIjX%qEi!?jWX!vxCDs26# zKXDnfz33q2#kkq=AN>|md7;dY5x(D*+JnYiL|R9m(oYkVcT^LcSnAMz^8QcW2V?Kw z&la-vtN5GyucZl+9ZTZl)*4)U4D@@klG%$cM%WMrW?Sai_?A~{OjzFfJgL!I)ItUL zoLI`r@M`hWx6WT^yH`iaLJiPFfw{)6kgXr(19LsyK_&DY<^~9P!!_G$b z_LdUZu&vUCbz(2V| z;l7wTG#N+S$;*uw^xA33A-}*D@6*NamB}9vd?E%RtPVfoO;ZJBkNJ;F%{e*lo4Db~VFX_Jc)UB>(A)6g!O^DMH_Z-I=O~RE9#HnG zdEFQbLL05WZbmQjq^IL zze!>e7k0<3H%5~7Ff*{Lx`vELF6uVA<`$>})iOZfYd0_e8!)_^l!Zr*YSd8LJ4qEN zhk(%HHCD+6gRsGB`J!1Q$x1dLd{o_S$xx9Y`^~Z}!iKr39^M<95R@pIJFHE=+l{)TOh!xX8B7w$<i(YebvsaENd!ih+`X*yl67K=(+!}kd zrjB6Wqlp78>^t8zvP6_V-86QKZIU6U`?snp9jaK_%(YIZk`-;tr)1O_ck?^8dLF2o zq0Q(Q#xRPT5eG}N)n~=fl8Q{FNqQE>vY3I)nqkN?uXT!@43PPqF({!`b9M|7kQfp?xS+G0h}2pDM$=7Gt*JI~D7XkG*LP7s6qZapQWrXhk{6La!^vlmX$f+C(SxIeDZ5EbeaT zcG9i0TRWtHp<3e;;RNf=;NP0_A_}^g&=M~ubYSi)ybJeiGK!B{xG}As^uV005z-rZ zbWk>Xv5=C!SG;xcLsAc=_ebM7k&%Rfb0L61dW1&A<4jVm{#NkCjN!(xE^TKprebgN z^no(@231aDjtvZQMS5s{%LPYd+m7pl^k?udKNjI%S?#>t6PZ^AOta%gnzd%to;S?T zQL*IQhF~hzM@g|E&#Qc~4ZSZmH(GZ=%ojlT*7IJzG3DnN$x#`P;_O<|+^2uLA73k` zV8=}bn54)TEg<|BhdoZO44$9WMgyRbpxMhPN93fWaawXE;rSW4>vAY&nK-)oydz%m zV6AfrdSO*Ofkm1{m5-@$np%qDcq^h<$(+~N{17t%7 zpK-uN@0pGw5F^c&GIBBZEVS<}4w{37xhR`^{Y>jn{0`9~zmEO+S(e1D)_cv-A`U24 zb4qB*zn;}+wwJ!@>gq93&qi7_VIKU9!X68B&RnkAi|F}IVgbK(6eYc&qVXk3+nY*w z=m%1#{4frmp-Fe{1>L$)#9PNAD=DH>m@_Y%6J1ih$RN#^Ome_}3-@R|NBax7`aMj9 z8$0I^xhG9q5G&_>91C?G&Hxn3{ybTEXF|KHIYa9#Qk-Ow^)=4r*L0$&El&|%r0f+o zG=(EIZ00&Aar#FJTEQ3$&O&*rgJ5G{_VRnrRhnHS3?w+llF*WZ@}7#dt);aGqLY=T z43rJ`;3^i)RKo}fUux&mcNKZfR%Hox4DZM1{r4@H5sXhq|7y3T)OnZ2zSwp=X6uX0dG2$5uK9h+=#hsb~{g zZ(vm-ND_cs76s}FjKfh{Z~9#=rY$KCP9xrW zz`Lfy5shiVe%=(6vY_T6;LG+ME;7Ng;ioOyPZ94x%!ZaKB$*JB*&9qZQ45vH?RJm~ zv$T4A#Ka@5py&C#d-xu6XUWprA>zf(IX(I46&jmRsy7c~TRNUFKd)dA715xIW0Cbv z@~;#DZ5oOIE#cnBVhJD~S<-jUbalrt=5XRTRw^TMp1B_eDbJQPUIDP;Go#=C=+nlG ze7|QS1t<3=1Q5D!IrPgayQF9JY9|531h#ve8jo|`sJSOs{rv@^P2P4gIuaxs$UeVh z>>y1nt0l-|l4#w?Qj(|Y6Mk;`qHq=0WPh)PRPSKX3;pt7{_$`nWb!fu)|v{+%3~fX z<`Nh99*Z?l^317)8BkCc1uwmBbhoa)S5{lxp?^irX~w>^dGo*|XzL-b`n3q>GcDSm&BFM=&Cj^%jPl;hjPg^G@roHGwU}w@w{OMd zoYIHy3;D})uD)G0fR6C#*&L86h#?(Cs%^EnsYt%>!iN4K1GAYh*>ZAs${2Oq_D9K^ z!kv!E^3t~K9@W60$-pBDHnug?3=PQ0xMUF%H5N%gA-q#LD2HrmiL*;OB$H)xSMeuE8r*Ha22UMC=V2X>*?%jq=kS zzuHy%rMyF_N@}rU1Q{&Pm0$1-{lm@%+~KyFM#tKF_f`+4dmQnPK+ZeyA+rc5lAvp(mo>>O#pbF}~l;mM{lvRX-n4N3d&^K#g%BPWRHiU4goBAKN4hth4} z&8uL;Vm&*9_qoWWG!%;2d1prrmqa(zD?db!7)+wACYcg5!!G+ra73-I<32Dhx^AT> zps`dJ1*{@{nZ&$aM2NxSd@hsZvaOe6>7;%cf)~T&TifID`htnkhXGwkBX36?nU(J7 z7Sih+!29qv;mi5ofj}Vfnh^4b4~f}Y{w;gQn$xM=xkcONS%0eq+4=Ur!FFcQxZKx-`Q_88UOvg8r>yD9#E z{=IOCdthyb&o<*(hM|@W$#_q00BZ&Zn0YXo?cG{5q0SY%Vl@z@H5KDGr1!@yYG`sm zgb!yc+?@{(NSS!GnBk+mi#Zh-7u6&pVNXkypxskTu=3-x+EV|y_lqdO$YuthHZnJp zb{wcoEmt!yVIipfvFldg_xp!&V(xg`4o!qjN%nO_M1QtcPVIOeKcG7P*VuvHFp;AXK)L+`n;x|tM`dHZg? z=S=T&f)JG_U`y`uESk@Y7?%fI*fehB`Fa7ZA&xDkDL)W5gau=Y=dX zR&ewyKYb(not)In5zLRC1g4G^EmNs`x`;w$C zuqDm7y$f6x_pZ%S(X;8f9x!(?L+k#pp@{vzNSpq=1rJ{)5X0!->~FT?N9RxzHDXr2 zB;DW4liLGE#w!`cMVg^FF$0s(F`^R|#n_9?*1ZbAgo@tZ5!%V@Ls*d;naYoma^Yeo zUV6IYo{8DaaT8eTzGLge=Xd*8SI}1M9q<@g@`gpp`{A-lx0um))?Go_Q?y}g6nXo? zEFGHT+S6-V9RxrMW-I(JFPdYH_wc}Ty35lwh`IGY7e zYEE98U447eQwWq1^ielzzz}~a;a0!7*yLhox@AG!FmoS1D0@~#)C0SLM~=Y!b{!p* z9Gs6V7ry$3$%%g9^H8~#f}9*Br^W5E<0byP8$b?&rgy_XvB`Fsn=)CTBTW-OdmnAr zSUK_SKEG3WgUO(80F?Syv`JQwFvLBVq3p87d#yTDUbkIqQa(MpT%N2@M*^ebDVroQ z=iiI$(){BbJAY~GGf*!*?|u3Y<+9rwqq-T(oj~wK`=I!vois}j0o}3F?@Z^d=FS`0 zx6U-Cw-bL^U%r^#(jPrrk|7Q2-}AORGmo!$uMvkXT=UTm#PZr&-(-7Qw)&7yw&;C+ z;@_jdsz5P;6n~P;8sDm)DOeWM)x(Vz=!5lcu{6L>W8zM+S}<*Ic0`ag4t3+cz_feC zG9UiFU2E)b)Q3^RWu3MUgRd1ie2xA962}#MJc?Qd|M5LfB|gf|W5=?w?|i*`S9I%n zn^7pljE)qA+e^7tG7D0p_LnJ?A)?dyiJuJ{o{#Is+B~Pt*{41Se=^Ese$~oc;D;`P zWp1SWBCG1FgmAg=f{u_opElSJAFM_=2pAO;If7@%%Duo!`*&J(vfI!Cts!hSq9lJX z_=#nXk4$%q_3!3ygml@v=gc*CxK!mH2u7N>9=LE_c+%yyY(mb?f>`|5exfVRs^ml< z>je)*a6g>SCf{@u-g?|y{8*;E3}!$PsBJcDlMK23OmEkG?MwIw!y^#Osjb}A#$M;c z|LV^*0Xn>&Z}5A(&d3wAPX)`qE=)j6QDHf${j<6o5{ujm;83&5a+fdC4z_q+68GNhcJl~E>Xr0@7N4^5aB)?js9=IYW8Nd%}=6ifDPAu0chhAItus2usGAsGE zN%SrpGf}5^Qr&Dq_Gd6={@8=}MHZX;9q$dWUSUs|@^qDw zyc+G(nB>&;0d5kSMeiQpVOGJt{IT;Os*5r=PJCtIMJYno)lGf?D5=W=PgnU>X?4Vzkl+Y zb)Fw=eIj2zZ)1H~+5NfJ#dv14&@^qwvc&fy2&D|gGcfB2YQg@Ve^$T+QT@L9t_>sl zNCA)F_VoDg!8T&>;ms_>X8Oa-7=JQl#JRBbTC1`qwi*#~1UYvrwa?>DgndRPd` zs64B)hGwk6oi`#$M5N^3(O?#iEi@-fDYOTOOf|Tx-YYgGQB^Q2Sp=bhm8+EJ@SNhl zsG>NcZ#SgQe|hOT+1lD#ExyX(nZH=7EZ&4y_I^eUGmF^veHN}3Lm|x3sJ^JRyj1u3 zdGC9Tpq3bTn_E7i=z>nIj}cQU1Bu1(Vq6Hfz~Kz`#QoOgfScPd({bNppw)5+4(e-* zSIgj~hkJ>v3}BAv!SS=%8p_Nx%1rj>Mv|=@!{rP%8!y###l&dPM9y~MP~EIpt+>@^ zG0Rim+q1!s&L*?bjRqKYVteEN@~<=6YmKUf8Ct!sUIYZY6?>23l7@UBOFnF-hWxk| zL!EwU)?O#peKuxHV>Kc?HWIhU?5|nxt-55Lu%yb%$!Sf!_grocKT3AV1nu`|Prxh> z(?Wfcu4NIOYP$K~(dPp8-#I8hs0dGS~!-7Af4JXdBvfKNX zhHn*1RfSGf(ooKvrV|Tx9bUJrVVhr-Vqbq|q%hPq{yc13zO;59 zSGDo%fQjr(wm=Q3A{YvnrxG@|i3T?){_w90rak;dy-{!H@N=&Tg5EXcxU|F%NYqCo zFFKlNVsx}#>W=fxchfT}2!IS~_-fSW+St&Kle`BAIL(v3gpvdI_J3xP%#1u_Zzmbi ztLkOJOXEWpJrEI!d^q5U0SKuWn&Ak9)C;*{@+b~kDYnL7YX{+rhP2G|=Cmb#?kDSd z|B52$(I1UeT4k4474b8{MshDaOCYQs0BmV0PeZF^C_kEkSwBH^1`?*%H8M5`(dP^A z#CS0tQ5VKHavVQ!`f&u8id; z;qW0`0>XrE`O$y`^Iu7N6ir$4DU?M37yYj}_-5^jke5}Bc6>?3P;QQ&2@`BnnUJHk#ftgeoG|LVQzaVPl1|Je*2^F^N(F` zK4Vbw=@a#o^-0$(wkX1W4YzgtPBz@%p5B*`?>6*Ng69j31oFz(N`BWf+wh>M77cqw z8Fu-A!3%vC@RBCOn&*b^kbw5HN-j^5lk8EVx4mC=T+k5F5Whaqxvxq;uzR{&ys0$e zVr3?gR^Gr`4)m8AK2AEQlirVf3fAvwBBJu!z412A(J&!q_o) zzx0Zny|`AW8J}zpm1??+8vC&kLy95DVv1EXDQSJGP?5UrXErJvicSiq7ShaajIav8 zR5Vx2;E2?xjBarXCTo5?^7GJbcIhhyC|dT>4EnWvzMcCP-s!!b%7Y5SWJ`5IUeg<7 zlWc%~%0avN*jU7_fkymsR}_kV4FUU~2ne4KcaWo41Rb!f(F?oNn&K}iB=L1c@f*ml z%o-*uXf5WpVP)% zfcR91{*oU7v{y9;Q;m#PSP-+MoWjS|E)|~5g#{Cm%n|4#X#SHsm z;mzHEz9F^?zZ|8XnJk~cFn4%6~RUa9pQy}|lRNL@)1ZkS$eT@s%S8HZpmH*a{}a|R9$WEb#;i>VvM_LJAM zKxcKmCidm*E^CTpXSt#P3(XHZI`ljgUWbjlB*X3QX+5Ta-|Y;{1W7cs=kmaw&(*1- zYh!QzW?U61*$H9N)`v5*y!IR~>8Y6^gBr=j)M%;ie(?AI$E0i=|BGM<11T;PZO1>t z1ET(A%u*0Db@G#uH)F?r14SCxovVrrcg?9m43{#?*ciQYISdt2`V+h|pV5x|WRtVS z_j<6a!5>Y7>mBq0fLHj?^nxK)5}yMvT){E95V`w!SWdhze*Z^Ukt^Un$(nR@%F4W0 z;e;xhXwKU9Cw9?a*i6K3qvaVMTtrt@yTfV9M-N`U%$H`(x`9{E;7Rr~E#dh7 z>EDbeYNpqr}rCc)*Ik>Ow3U#u&YhTK$NS_q;M z{#svPrVOzcTp6wuhlP7%9|rctxm&VukYEN}@|U_{N28HyU_r70&tTBLb6MZgwua+( z&qMvgr@|dR=d>r2qjwyrux)uG4q`8%tSuHd?)m~oX?Z`%m1Le-0{PLNPEAv?n1DVTWlax{AM;-b!6K zj#6XbiLBHA-dj=!_HV3|HRyGa@Sw zD$bk}xF7&z{(QO`@A&I>YCAJCp>}tr?uGqt=mD8i0vG=X>@tINJD(!l^d4*r$sFJ` zxmY?)r_DXR8u=F$H0a%F?dTUW`6M9OdwB;N2kc)xDM!na+`^)EaqfjXF;Gp`JKB)j zd*Or$a5ih)|9s}}e|y#EPt&E+QKi-#k61;TrX><#p?Ih&>zy03jO7)~hfHR&Cn<%; z@UzF}RRM2e^;v-nUck^D`SmM!?~|}H?3VmGU3RX)ddIg^yVH6H9c1v7B<`d4;@1o* z9JZ768?2DQy5p-6%W7fIC(oJjQ#{mcPY(YeVt@YKKO_HQ{Z*ZUC@HXb{GOqp@y{&=+Im{+f84p{sP+q)Y;GlhqnCxL-EX`(Jh5WG zaT`ZcDNfqLZ{I!OY!|IZ`B{+4V@>?}K$6+Y#b!&ka&v1j`3vd8n(^`RyM;jR_l-)B zD065=+dn9tt!()-_uBEWD}fi*v;Wq_@elqlRG|k6$E^#Fvq)Rzl5>T!=o_kxZJkCV%rH^6_0<&ic zTl;xFV7cm~Y_y@><1PYCqb*K=5OOvCT1}E+6u;ha5WFaobCU`8Q6?&^jaOk$%P@xw zGVgm1DsF~wfvOIKoJEh+#cw~QDR1Td)ku|(`8<9J-P%QiFlBu3;38kt^4qgbBT11{ z=<}02d{*iE{y>jyZrEL>c@lNBPevwp;t;w1YlmBUuZ=Qk<-q~3Ea?860)gR2SSYsq zol>$iBt}4TAuu+G>Qu7r_lcSou3h7CgTi&i3lAt)k*CIA3Q`_6gym}9GcYmy^;fj; ze5jomDWw5j?43&@P!57A+_kCZh5P>_viDPPHj33d9>F~wQRydm9I}}3Zhe9k``=KA zx@}`Ssdh4odP|v1=1e)NfaKtA>pG7l~PJo4!*f$&>^+c|_HwxJEZ2$(1j@C&mwm6f@ zN$~2l;K*aYfM!fw{LN^otFX>T3^|jZ1ai3?2ZRhlxyUAAg5O3`4iX~=mxN!V=a*k< zl|MjvHyhtH$&dhvcLK&21Ycc>aF*|2`;vnCZbq&Cn80^GOFIhG^(?QI*ADyCE$dMn*Ib8XUO{=y?;2}3Yqp>ggW|u1<%w( zUJYTO_e75TA50jHfe6pEi%OkWC9C~%&x&rxnwm+B9K|?gGJp;Gy-WfQb#}&;60!vI zO9m(!Zj%+H|1WBHg@k+jKPY#Ff>Ve|QHaQ1=|UZyM@hVvEBp&ajRxc7Jll6LG}XU- zQ~_JPHXG~N9AHBpKpLgiG$UoX#~p|byvK|xnVVIs<%u_MW9(>8 zE&sydvsEp0!$AKJy35T)ezJ;|wt4+%%^sq;BSF39{Zx7a0vF_tPpwGN!Lo|wx7=BQ z*&lE)HkbsJ9IWoAD~#GjIsbY&Ut-}E4kQE3%pNM){%VqITTUJvvuditCeUb&i~B_g z7oC`VU(Bm*p?VT1N?+zAFXDqpXqV^%t9yxwfxwC?5pphH<|1;#{&Kh>!3FleiNuTlh{W;_eC!1qh*8Nasvn;caB+VW zolAG=5(l-~dP zy-HU5qfF-N`)AY7AEQoB8;=+-B<)Y_4?XFh Q+RFhND!R}rh)wwa0Aae?k^lez diff --git a/client/src/scenes/BootScene.ts b/client/src/scenes/BootScene.ts index 76f7aa9..722d25a 100644 --- a/client/src/scenes/BootScene.ts +++ b/client/src/scenes/BootScene.ts @@ -10,7 +10,10 @@ export class BootScene extends Phaser.Scene { } preload(): void { - this.load.image('tileset_16x16', 'assets/tileset_16x16.png'); + this.load.image('lpc_grass', 'assets/lpc/grass.png'); + this.load.image('lpc_watergrass', 'assets/lpc/watergrass.png'); + this.load.image('lpc_dirt', 'assets/lpc/dirt.png'); + this.load.image('lpc_treetop', 'assets/lpc/treetop.png'); } create(): void { diff --git a/client/src/scenes/GameScene.ts b/client/src/scenes/GameScene.ts index 6ea4d6d..3de3ea5 100644 --- a/client/src/scenes/GameScene.ts +++ b/client/src/scenes/GameScene.ts @@ -6,7 +6,7 @@ import { NpcInfoPanel } from '../ui/NpcInfoPanel.js'; import { CommandPanel } from '../ui/CommandPanel.js'; import { InteractionEmojiManager } from '../ui/InteractionEmoji.js'; import type { WorldState, StateUpdate, EntityState, Appearance } from '@dflike/shared'; -import { TILE_SIZE, SPRITE_FRAME_WIDTH, SPRITE_FRAME_HEIGHT, SPRITE_COLS, Direction, Terrain, TILESET_TILE_SIZE, TILESET_COLS, TILESET_SCALE } from '@dflike/shared'; +import { TILE_SIZE, SPRITE_FRAME_WIDTH, SPRITE_FRAME_HEIGHT, SPRITE_COLS, Direction, Terrain, TILESET_TILE_SIZE, TILESET_SCALE } from '@dflike/shared'; interface EntitySprite { sprite: Phaser.GameObjects.Sprite; @@ -145,108 +145,127 @@ export class GameScene extends Phaser.Scene { private drawWorld(): void { const { worldWidth, worldHeight, terrain, decorations, pointsOfInterest } = this.worldState; - // --- Tile index mapping --- - // Tileset: 17 cols x 19 rows of 16x16 tiles (272x304px) - // Autotile blocks are 5 cols x 3 rows on the left side: - // Grass: rows 0-2 Water: rows 3-5 Dirt: rows 6-8 - // Layout per block: - // [NW-outer] [N-edge ] [NE-outer] [inner-NW] [inner-NE] - // [W-edge ] [center ] [E-edge ] [inner-SW] [inner-SE] - // [SW-outer] [S-edge ] [SE-outer] [variant ] [variant ] + // --- LPC autotile layout (3 cols x 6 rows per tileset, 32x32 tiles) --- + // Row 0: [inner-SE=0] [inner-SW=1] [??=2] + // Row 1: [inner-NE=3] [inner-NW=4] [??=5] + // Row 2: [outer-NW=6] [N-edge=7] [outer-NE=8] + // Row 3: [W-edge=9] [center=10] [E-edge=11] + // Row 4: [outer-SW=12][S-edge=13] [outer-SE=14] + // Row 5: [fill-1=15] [fill-2=16] [fill-3=17] + // + // "outer" = convex corner of the terrain island + // "inner" = concave notch (diagonal-only neighbor is the other terrain) - const C = TILESET_COLS; // 17 - - interface AutotileSet { - nw: number; n: number; ne: number; - w: number; c: number; e: number; - sw: number; s: number; se: number; - inner_nw: number; inner_ne: number; - inner_sw: number; inner_se: number; - } - - const makeAutotile = (baseRow: number): AutotileSet => ({ - nw: baseRow * C + 0, n: baseRow * C + 1, ne: baseRow * C + 2, - w: (baseRow + 1) * C + 0, c: (baseRow + 1) * C + 1, e: (baseRow + 1) * C + 2, - sw: (baseRow + 2) * C + 0, s: (baseRow + 2) * C + 1, se: (baseRow + 2) * C + 2, - inner_nw: baseRow * C + 3, inner_ne: baseRow * C + 4, - inner_sw: (baseRow + 1) * C + 3, inner_se: (baseRow + 1) * C + 4, - }); - - const GRASS = makeAutotile(0); - const WATER = makeAutotile(3); - const DIRT = makeAutotile(6); + const FILL = 16; // solid fill tile (row 5, col 1) const getTerr = (x: number, y: number): number => { if (x < 0 || y < 0 || x >= worldWidth || y >= worldHeight) return Terrain.GRASS; return terrain[y * worldWidth + x]; }; - // Pick autotile based on 8-neighbor context - const pickOverlayTile = (x: number, y: number, terrainType: number): number => { - const tiles = terrainType === Terrain.WATER ? WATER : DIRT; - const same = (dx: number, dy: number) => getTerr(x + dx, y + dy) === terrainType; - const n = same(0, -1), s = same(0, 1), w = same(-1, 0), e = same(1, 0); - const nw = same(-1, -1), ne = same(1, -1), sw = same(-1, 1), se = same(1, 1); + // For a GRASS tile, pick the watergrass/dirt transition tile based on + // which neighbors are the "other" terrain type. + // The LPC edge tiles are drawn FROM the grass perspective (grass is the terrain, + // water/dirt is the background bleeding through at edges). + const pickEdgeTile = (x: number, y: number, otherTerrain: number): number => { + const isOther = (dx: number, dy: number) => getTerr(x + dx, y + dy) === otherTerrain; + const n = isOther(0, -1), s = isOther(0, 1), w = isOther(-1, 0), e = isOther(1, 0); + const nw = isOther(-1, -1), ne = isOther(1, -1), sw = isOther(-1, 1), se = isOther(1, 1); - // Outer corners - if (!n && !w) return tiles.nw; - if (!n && !e) return tiles.ne; - if (!s && !w) return tiles.sw; - if (!s && !e) return tiles.se; - // Edges - if (!n) return tiles.n; - if (!s) return tiles.s; - if (!w) return tiles.w; - if (!e) return tiles.e; - // Inner corners (cardinal matches but diagonal doesn't) - if (!nw) return tiles.inner_nw; - if (!ne) return tiles.inner_ne; - if (!sw) return tiles.inner_sw; - if (!se) return tiles.inner_se; - // Fully surrounded - return tiles.c; + // Outer corners (two cardinal sides are the other terrain) + if (n && w) return 6; // outer-NW: grass only in SE, other terrain in NW + if (n && e) return 8; // outer-NE + if (s && w) return 12; // outer-SW + if (s && e) return 14; // outer-SE + // Edges (one cardinal side is the other terrain) + if (n) return 7; // N-edge: other terrain bleeds from north + if (s) return 13; // S-edge + if (w) return 9; // W-edge + if (e) return 11; // E-edge + // Inner corners (all cardinal = grass, but a diagonal is the other terrain) + if (se) return 0; // inner-SE: other terrain peeks in SE corner + if (sw) return 1; // inner-SW + if (ne) return 3; // inner-NE + if (nw) return 4; // inner-NW + // No adjacent other-terrain at all + return -1; }; - // Build tile data arrays - const grassData: number[][] = []; // base layer: all grass - const overlayData: number[][] = []; // water/dirt with autotile edges - const decoData: number[][] = []; // tree/bush decorations + // Build tile data arrays for each layer + const grassData: number[][] = []; // base: solid grass everywhere + const waterData: number[][] = []; // watergrass transitions + solid water + const dirtData: number[][] = []; // dirt transitions + solid dirt + const decoData: number[][] = []; // tree decorations for (let y = 0; y < worldHeight; y++) { const grassRow: number[] = []; - const overlayRow: number[] = []; + const waterRow: number[] = []; + const dirtRow: number[] = []; const decoRow: number[] = []; + for (let x = 0; x < worldWidth; x++) { - grassRow.push(GRASS.c); const t = terrain[y * worldWidth + x]; - overlayRow.push(t !== Terrain.GRASS ? pickOverlayTile(x, y, t) : -1); + + // Base: always solid grass + grassRow.push(FILL); + + // Water layer + if (t === Terrain.WATER) { + waterRow.push(FILL); // solid water + } else if (t === Terrain.GRASS) { + waterRow.push(pickEdgeTile(x, y, Terrain.WATER)); + } else { + waterRow.push(-1); + } + + // Dirt layer + if (t === Terrain.DIRT) { + dirtRow.push(FILL); // solid dirt + } else if (t === Terrain.GRASS) { + dirtRow.push(pickEdgeTile(x, y, Terrain.DIRT)); + } else { + dirtRow.push(-1); + } + + // Decorations const deco = decorations[y * worldWidth + x]; decoRow.push(deco >= 0 ? deco : -1); } + grassData.push(grassRow); - overlayData.push(overlayRow); + waterData.push(waterRow); + dirtData.push(dirtRow); decoData.push(decoRow); } - // Helper to create a tilemap layer from a 2D data array - const createTileLayer = (data: number[][], name: string, depth: number) => { + // Helper to create a scaled tilemap layer + const createLayer = ( + data: number[][], + tilesetName: string, + textureKey: string, + depth: number, + ) => { const tm = this.make.tilemap({ data, tileWidth: TILESET_TILE_SIZE, tileHeight: TILESET_TILE_SIZE, }); - const ts = tm.addTilesetImage(name, 'tileset_16x16', TILESET_TILE_SIZE, TILESET_TILE_SIZE, 0, 0)!; + const ts = tm.addTilesetImage( + tilesetName, textureKey, + TILESET_TILE_SIZE, TILESET_TILE_SIZE, 0, 0, + )!; const layer = tm.createLayer(0, ts, 0, 0)!; layer.setScale(TILESET_SCALE); layer.setDepth(depth); return layer; }; - createTileLayer(grassData, 'grass', -3); - createTileLayer(overlayData, 'overlay', -2); - createTileLayer(decoData, 'deco', -1); + createLayer(grassData, 'grass', 'lpc_grass', -4); + createLayer(waterData, 'water', 'lpc_watergrass', -3); + createLayer(dirtData, 'dirt', 'lpc_dirt', -2); + createLayer(decoData, 'trees', 'lpc_treetop', -1); - // Points of interest (rendered as colored markers on top of terrain) + // Points of interest markers const graphics = this.add.graphics(); graphics.setDepth(0); for (const poi of pointsOfInterest) { diff --git a/server/src/map/mapGenerator.ts b/server/src/map/mapGenerator.ts index 4d784e9..9ad00b4 100644 --- a/server/src/map/mapGenerator.ts +++ b/server/src/map/mapGenerator.ts @@ -108,12 +108,11 @@ export function generateMap( } // --- Trees (decorations on grass tiles) --- - // Tree tile indices in the tileset (17 cols wide): - // Deciduous tree top: row 2, col 9 = 2*17+9 = 43 (but multi-tile) - // Small bush: row 7, col 9 = 7*17+9 = 128 - // Pine tree: row 3, col 15 = 3*17+15 = 66 - // We'll use a few different tree/bush decoration tiles - const TREE_TILES = [128, 129, 130, 145, 146]; // small plants/bushes from right side of tileset + // Tree tile indices reference treetop.png (6 cols x 7 rows) + // Pick recognizable canopy center tiles from each of the 4 trees: + // Deciduous 1 center: (1,1) = 7 Deciduous 2 center: (4,1) = 10 + // Conifer 1 center: (1,5) = 31 Conifer 2 center: (4,5) = 34 + const TREE_TILES = [7, 10, 31, 34]; for (let y = 1; y < height - 1; y++) { for (let x = 1; x < width - 1; x++) { diff --git a/shared/src/constants.ts b/shared/src/constants.ts index a5721da..75e7f27 100644 --- a/shared/src/constants.ts +++ b/shared/src/constants.ts @@ -72,7 +72,8 @@ export const Terrain = { } as const; export type Terrain = (typeof Terrain)[keyof typeof Terrain]; -// Tileset constants (16x16 tileset scaled 3x to match TILE_SIZE=48) -export const TILESET_TILE_SIZE = 16; -export const TILESET_COLS = 17; // 272px / 16px -export const TILESET_SCALE = TILE_SIZE / TILESET_TILE_SIZE; // 3 +// LPC tileset constants (32x32 tiles scaled 1.5x to match TILE_SIZE=48) +export const TILESET_TILE_SIZE = 32; +export const LPC_COLS = 3; // terrain tilesets are 3 cols wide (96px / 32px) +export const TILESET_SCALE = TILE_SIZE / TILESET_TILE_SIZE; // 1.5 +export const TREETOP_COLS = 6; // treetop.png is 6 cols wide (192px / 32px)