From b4fa5d132f482ddf0ffdb489b8782f472658dffd Mon Sep 17 00:00:00 2001 From: MpakobecEx Date: Thu, 22 Oct 2026 18:59:24 +0500 Subject: [PATCH] Fix card faces, lock camera, add stats overlay and standard sleeve back --- .../Resources/CardArt/vanguard_back.png | Bin 0 -> 64381 bytes .../Resources/CardArt/vanguard_back.png.meta | 132 ++++++++++++++++++ .../Vanguard/Runtime/App/SceneEnvironment.cs | 4 +- .../Board3D/Config/PlaymatLayoutConfig.asset | 24 ++-- .../Board3D/Config/PlaymatLayoutConfig.cs | 29 ++-- .../Runtime/Board3D/PlaymatSandbox.cs | 34 +++++ .../Runtime/Board3D/View/BoardCameraRig.cs | 132 ------------------ .../Board3D/View/BoardCameraRig.cs.meta | 2 - .../Runtime/Board3D/View/BoardSlotView.cs | 2 +- .../Runtime/Board3D/View/BoardTextures.cs | 4 + .../Runtime/Board3D/View/GameBoard3D.cs | 64 +++------ .../Vanguard/Runtime/Board3D/View/Pile3D.cs | 17 ++- .../Assets/Vanguard/Runtime/UI/BattleView.cs | 103 +++++++++++++- client/Assets/Vanguard/Runtime/UI/CardArt.cs | 11 ++ .../Vanguard/Runtime/UI/CardImageService.cs | 31 ++++ .../Vanguard/Runtime/UI/Localization.cs | 2 + .../Vanguard/Tests/Editor/ClientSmokeTests.cs | 17 +++ docs/HANDOFF.md | 22 +-- docs/SESSION-STATE.md | 20 +-- 19 files changed, 410 insertions(+), 240 deletions(-) create mode 100644 client/Assets/Vanguard/Resources/CardArt/vanguard_back.png create mode 100644 client/Assets/Vanguard/Resources/CardArt/vanguard_back.png.meta delete mode 100644 client/Assets/Vanguard/Runtime/Board3D/View/BoardCameraRig.cs delete mode 100644 client/Assets/Vanguard/Runtime/Board3D/View/BoardCameraRig.cs.meta diff --git a/client/Assets/Vanguard/Resources/CardArt/vanguard_back.png b/client/Assets/Vanguard/Resources/CardArt/vanguard_back.png new file mode 100644 index 0000000000000000000000000000000000000000..9d0442c691135784677dc07a53dcbdd908725af7 GIT binary patch literal 64381 zcmV)!K#;$QP)004R= z004l4008;_004mL004C`008P>0026e000+nl3&F}00009a7bBm000XU000XU0RWnu z7ytnK14%?dRCwC#y#;ub=h8kNci+v%-8}(92=4Cg?(XjH?rts67TVHMN`(s4D8;=< z3l&OB^;FLH`@S>(x#xM`%_iA|Kqck;%XK|h$Y%H5SLU9Xd+f0xBAb8KKkJ`mef@J2 z{#pO5e*p5&`e*$Ekbl-c>mPvpv;JBC0OX(b&-w=-|Ez!3KLGh>{j>gi0dnuF%d0=R zb@9iG=T3Zk{_Okr&!2s-@H+F}{d4)&yRy#e>$JY!$+ym&KAyKu6<8k~%ePK{^tM_j zE!SJJPU-7ItT*p}q^}eDdL!RD`N2`E>qD&fv0l%&PQ3q`TJPmwADGvxdF$O*@4x@< zD+SgOwcb(dJGU-++G zZ@+Qy{)^9U{qeoyo37bt{~ie-S1ujf`Pz{~w0qlD+O~1MtgRc?@mfn;)~}__>(dDkO4GuaDN&(sGnK`)fzsak6Qiv(6D~`>Md(1uOWSV(U3kpX|Tl_ z)Vl`_>eZbF_S9E58qlMwdG+t!mHKt>l7DsUOntj{%D4J->G)s2dUR+@mCB@2`_?tT zXKW<%@_HnIynB5AQ#&@V6Tuigco2;l!Vh`KAR0AzAV1InG-6_vofpckO|7>%tGEGoN%P>fN~`_3G3?R?m*@d9{-Z z>E6DLtgdZaQ7MKvv6!^<_1$UzeKKtHZ0dc{QtBi<;D~L5*uwr$#mNR>SI5sX?_Wvg%c>B&%+f zin8id&ZXLwDp0M8IaDjRysVlPvZ+Q+HdQZQj;dvsrK;u1m{*l@SyZKLCRHwzL6x%7 zsbXfDtlW%LSvhIRYNaMq`IIDC*~y8r$|WaI*`#K?l@J#EU%g_3OcWL9Pn9a9{F}is6Cimc zfV_Eh?}2Tb*06>gDPYh6p@U%vz`$!T17eU422Fzvuml2YtG*0|J{lM-0Rb@d=+KTq z&{kHrc5QgIW@*Lk2?wS*;oY2=%CCgL>4$ z42C)kg4)!y4uDXTfuO*k08xz^)?gr1uR`^!Rb~*VRksR*p)v!Z5(A;41_WL;83;8P z2-R~K1m(*z5X#7^$^fV;Ajo16WHJac7y#+Aay1}SNKX+Eluu1Euk4gO00;;Y;>;^6 zJ`V&L41#n9KpFs`tyBR(xU7^&2z{umBo=giC5Gh*eSByT#fJpSiVF@fF9;1*3=7Wx zA66u<3fW2jVQ?JeRq@dQvT?Nlq@blJ3LF524i4Rv|Nj9TIzWm8hc$oz99TLy$|lC= z1BVU}9UPVb5pZY#0XTGk6aF4RMS zqaZN;8^BSV^{@txhq4}tg#n_2qd4nf366iP$6pGNJpz#NBZub$#zTSQZ)7`kn)u)~*nM6cwrZODqRMxEA2}GkAvpL<2`@x>kQQG5?2q z{OJH$PGg1+{@szP-vbUEQU=xK{sgkG~f{Hm+GpqX!Qxd8CSg(N)WMD}irD9b2f?L4>}E{KVhevfx{0 zyIUjUjcj)VCHO5_@LOmZZ)CawfHrt91Eg{78Y1Yruq%PDR5-((FGQQo0uNzlK`&oM zR@H14^m3V0xoieiD#L<~40qOptw5p7c4Dlo%miqE5bG#e>9G**2wADoEZ9+DvXUcN zup^MU4mPiZupmkZg)j%miVHTGwY)CO(E&zTQ2_>uH2KMj@b@*ZaH9`}8@y$O`FY6- z_4T9>ACG)1*xOxJkeAz^x&l31`TM=h*AV9CO(EX+eqLVg`Ioo8Jj^S^$CG0CdPDgq zK4*3D_23$#14;=XqXrGI3Jw8?1sU(zslB}CsXcq>#pj==mtK5=>EW_7*s z+N;H`qp!YF?0Wr`BY(-lcfIxc>!SD!&JI+L70Z$Z^J(L{wX}KtdfKsd3+>vzjdpI` zN;|e}q3v5X)3!~UXzQkpv}NN4`TxQ>vqgb!T)UPwtXV_rR26gIcA*CK>PeR_U#2gge*T$$`srWv+rR%G9p#6N<9vDdE`9gi_x!&5bnol0>8pER)7`sY(U<($ z&%gMR?tJz+-M)Q?KKuN0`Tr~i1uVnZ;X~+WKHkd=Komo6l440!Fu8HfYOP>WUn}K3 z=Auc9wN?r!m(dy&Px4wV1(dv&F3}1o7t=~9pv+qiG^(94@(`lZ*r0`N()2Gs$f@|6o znyoLsSF`kmqD+f5Q(s!4=AX4Dj~z|Vv!eU@-d9vBH-~&3?Pwr#S;)pce%9Z9_Z|K4 z(@*r>_dn3L-+oWu-2ay4;2R|eUwtM2KYi+yxSU50A7**^if-Qegs$JbN!PAlr>oaK zrps5a(zTDT)A8f)h)Wvj@Anr1KB#O}F?$?%cUUU-5g+Zrr#@AAkHY-Mo2=E?>Dq zQ^t*@sue2GLe>=c2VsQUB-}xBscLIQgEcFtWvyt?YSbx%U8(d`SryV!WEB;0DpV-Q zTtP1sv@8-VD#M)!ZeYO+WPuX|F((K#$%O3#h)H5a^0Dee#}A*5PZRkP!!;u z&*;k(qHUos7f%8PGF7KwuF75LlCY_wLd6Km5q<(mo;XpYVIW`0`5& zfT$aEO9Kdw0gwP3H2@CQwBLXGEo<>b0t^uHl0>W?hLr!FknW?FlN3kH|BR&IUrEjZ zZh&R}%o+3@KRa+yR~9=|b>rDXX@2(kXZZobK)8P62HoQS10YF!y-)7iC9exW&gTaR z{{QN$ua*Wto)CZx>))?L$v>2&_wUi2PVq@Yz;E*f!$RoR0|5DvEeJS9XD0GDSxbEW z`4{p&xKy}d&?dL}X2GSpdi5Gj96gGvJ<9-Z@)9F&!7=Z{6A+f03f(Q@G&Qk9YYgFkEHPn8?_7F$Fj4M+yGke+%nT z5G4L?PEz>#+poV#9}qx-=Yr6FJLI~WHl~iPn$zJ!huHnPCsyR#xpP#Np8@3M6L!I2 zLBx8TIm5s>Edcqbv;cBc0J2aD6|FTj70hp-p$S5LhEE>;<7ezT!D@W_-M37{zNa79 zy;{m-7H-&ecAY@N0G>CPwBzQWk!k*{=|XftYC&Y5WZx532V@lj{YT_Feh)YvCR_fO zxmE}bhli2##v2sSaUvxe-2YbKump+G#Zii1zh{CzcltEutUV+NjZ!Aa6+*iZbSO+% zmrvQ6y!Y`M9U>sPbm_9VS!d6l6QIDVy#D&@e?3V*`r2+YKrF#gRAwBx4RDpS zjBvO~U-AXQYW(=qzv$k%85Ku#NPQdqSXl*kt3?+6fm0VKUx zo)8K?^!#(Oo`2?P`jolnxihCJ%-36j6R$Jzh9!Z!{m!vtd_NOu?1*6ulG}9Y$`!hB zk@?7l3v}_)B|3WaXz2iC&9Vh%bQiQ51vBHF*gOItFpF2OU1Oi|hFB3qvX(7eAjIs( z^&3poe~|SCgQJ~RMuHo2p0xpfhfp`DUX_Ks3e{slhv5HN;3!Sr@keFM6N6bhr5@+^i2yoS^sKd!J75&o|$Ev-ALhLd6Gx10^G!*q1~&814}?gdX+6`-b%G zBN3@@*>YgLbNrZO&9Oea{V9F);Ry)?0t6@_u`D0?tHFU)RK&_!DaoUhvHzZ8#Deu! z2?2f-S-vK@EIUncQBf2ZXngGIt#FRWhC{$FU%WtPPJJZdX!O#*^70XhXd=w}23rc; zZ}ive;db1|VFUZiJ^#xAvU=%!@evEVRE2A*P*wt99AI;KRUvo@Xoaxe)g^-*{7H+Ba{e zt(!N=LRS5+C+V;5KCo)3BGttKLoYb&(4r{=qyrPEbK*DNy?d9w{q|e>@n8RvNEL|s z@weZWB18!Nr3>fjBEJ{HFP5W02`mQ#p>D@M)Sz)QYQ+ElBf(LSlw*|?9Dg2v@LSCbHQ-TFS&jSYwS%Bg3012Nj+%H7tuCtpCcMC2UEX4~44@w68;>F8!-89n{v`{`3>6 zcY@Whv>Zi&LvNRDQYD9~jao!iM=qj9xn)WOj)#p{VHFjzdJymUD_twSls(blK|Uk5 zk)i8MO7L^DYB{1qL;2_9V@bl%z$mUv9R#~)hxT;x=p03zp;PtFMaXK-Dga3@@HPFIBxw zS@26_Idr~(1Yn)ol(YB+s@tG3HK?5XNS33x^7WFC@`ufLl(Y%z;kyI_n1lF|+l(U= z)Sx?C5RZHSi8XptczO=GP1sM-A;FK2B>|CVP?YC;d*R$!iF8H!`^tTL?!WYt zl9e%l@=9ssK>&~y0+6mnS`7e0@8Li$17sehCWu#~eBl25Z>4+yd;@(PH<+j+QXzz# z0Z@>TKd5{}R>g8uY20ecnZAP>(C06CDwA5eI94T|^o z$!9&{{M;#!`H9=40~G7$@mTe2#A@yqc*w_BuSg{}K!axlPyi%n&z+<57cS7zqot4s z5r8b3BSnfufy1(I8~_2C2eMH|1Aw4n^9uWlP3zQ@5v8ykXm$bstTj88CFNxsq-oBNd-@l(~vs+YDq^hK~Rj?dY`c9-u!xvKh@>!4UR+R)Ce^$Pu zDC<#DaL6)xQE25x}luL%~D1m z8x$ZlTIU%Us+#vq=@cshAj=od5`YvrZN#EA7UUabJ`W(DDu6K3A^1DDZjt7wx>YM# z8~+BmMxqq zg=LmpqaZNQGmeGMv93(!KVlNDqFA4bi*@blRVLTfXv>E63Lsj+q4h{r$!n|X=VVdt zpjlLQ`fjRIF8y~|jz2nLRU+PD5w$8YIIIA~x8HJdnezt4fqz)~@cestYBsr#-9xb^ zUls0si~+K5_b!>Pj}rQK-+h-|tjp$d_t#)SVoM1isKYACYFG|bKvodZc9FBZhPf zma!vhudi1jG7 zYTnmg*>zy)f|-)rCv+3lC59rfdH^mAe7gAD} z>OtirupAY8j-fJBwo{$5X~lx0q}92P8nJrVI;-D3_>H+nJiAS>9)?a+n1s9J2MGV} z-G2r7cAs77Z-4(~%xCe?L5XK}@2k7Ce$`5HX3_1*iu=sDbFz-S{BkJ(e8@_t@FnxUOn(Xs|0>q|lIjp%<*7%0ClJ$IqoWW4D zY86Ud`4&}e*ph0N%X}no{8K)0aCzfSesMTqJAA|nnFLwj7gKI zQg$}Ia`+|s`rbWxZ+#Z>W+ep2!xSFEa^!X!MP-LArdpXvzZ)D6tg-ro!0~%rD_MBh z;o;=8j)WNd=QK^_Nim?+NMiA;_Akx%zI`66!siHTh; zbd>(|SfZ4w%crfn>r4(2W z03s|X-%7OD38`3cU@-}gNG(T>43Mbk*nA*B20bjRGPzH9M!g>Jco1}0x{&OeWVhuG z1=i_UC^W5G5_B1U!7lvvO&f)iVCOJAhre{}j}DL??b}(Mi(7EQAy(76wM1w!?&bdd zZ^W(A2P~8n97UCm6qo0ynVC#w2hOI{8GEUEMpB7NNdAn7l>$d3rALKPdPE3iga=T1 zh>_BR43r*hq|}fAN@XC3<%o)+#F!XLjE$v)_(Y12iOshK+JlBK#If)MS7}C0^Ny(! z5(^N-v7iOjY)d{p7d$=*LgaAxnw%HCNABbHY3FUUnqdcNN3aK-i5QiHJV{Bx@dpEB z8g*~i)+#WpjsI*?r>2y*fBxAWsqTf4KMEOtP|;zbXqDztCC@!bm1@Q*zl{imTC_qMG-kke;(CV8ll9AGezflb#{N z#HYzH?nyF?*-3^`+sQC&1NlsSp2BOjp`-xc2U-sZ38GfU)+5P%{8NRZR1hxTE;A^g zZWk#xc^m)|=k3gZo=?sT-l6D_pnM#}8c5JDf>BQ2-oGz1(ex>deP{ie2U4QHSBXaVATs4OU^V&lT2vrPWt1F< z$H*NNo>pG||F;JR102@SX7_g#$}U!%Z^^74W^c7?)|hTw|5#kuznp_CoIO>Ne-8qO z4iMC0p^m>bzpru4>P1?Ol7gc|oq#$a*Z4;Kier@1pcPeNSLFgrRZ*xC}_&lD1iE)%2A4%EK z!BmzlMoNvw6w_-ag-(2e0#=?NpC|8;_x@kW`!}~elfmHm)Q=1bUQga9kEi}c z?)=kz+a2W)Ke$q3a+úPyZ&=HO{dXvYPC&_jCVg5f` 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 new Vector3(0f, 6.9f, -9.8f), + SceneTheme.Battle => new Vector3(1.4f, 9f, -5.2f), SceneTheme.Login => new Vector3(0f, 2.4f, -9.5f), _ => new Vector3(0f, 3.2f, -10f), }; camera.transform.rotation = theme == SceneTheme.Battle - ? Quaternion.Euler(35.2f, 0f, 0f) + ? Quaternion.Euler(60.5f, 0f, 0f) : Quaternion.Euler(8f, 0f, 0f); } diff --git a/client/Assets/Vanguard/Runtime/Board3D/Config/PlaymatLayoutConfig.asset b/client/Assets/Vanguard/Runtime/Board3D/Config/PlaymatLayoutConfig.asset index f19a043..256ec59 100644 --- a/client/Assets/Vanguard/Runtime/Board3D/Config/PlaymatLayoutConfig.asset +++ b/client/Assets/Vanguard/Runtime/Board3D/Config/PlaymatLayoutConfig.asset @@ -36,27 +36,21 @@ MonoBehaviour: handSpacing: 0.42 handMaxWidth: 7.4 handArc: 0.035 - handViewportY: 0.16 - handViewDistance: 3.6 - handViewMaxWidth: 2 - handViewScale: 0.9 + handViewportX: 0.44 + handViewportY: 0.18 + handViewDistance: 3.8 + handViewMaxWidth: 1.8 + handViewScale: 0.62 handViewRoll: 3.2 handViewArc: 0.02 guardianRowGap: 0.55 guardianSpacing: 0.44 guardianMaxWidth: 3.6 - damageX: 3.5 - pileX: 3.55 - cameraPosition: {x: 0, y: 6.9, z: -9.8} - cameraTarget: {x: 0, y: 0, z: -0.15} + damageX: 3 + pileX: 2.95 + cameraPosition: {x: 1.4, y: 9, z: -5.2} + cameraTarget: {x: 1.4, y: 0, z: -0.1} cameraFov: 50 - orbitYawLimit: 32 - orbitPitchMin: 20 - orbitPitchMax: 62 - zoomMin: 9.5 - zoomMax: 16 - zoomSpeed: 0.006 - panSpeed: 0.0035 tableColor: {r: 0.045, g: 0.04, b: 0.055, a: 1} matSelfColor: {r: 0.055, g: 0.095, b: 0.16, a: 1} matOpponentColor: {r: 0.13, g: 0.065, b: 0.075, a: 1} diff --git a/client/Assets/Vanguard/Runtime/Board3D/Config/PlaymatLayoutConfig.cs b/client/Assets/Vanguard/Runtime/Board3D/Config/PlaymatLayoutConfig.cs index 7af84eb..1ee6b13 100644 --- a/client/Assets/Vanguard/Runtime/Board3D/Config/PlaymatLayoutConfig.cs +++ b/client/Assets/Vanguard/Runtime/Board3D/Config/PlaymatLayoutConfig.cs @@ -50,12 +50,14 @@ namespace Vanguard.Board3D public float handArc = 0.035f; [Header("Рука в поле зрения")] + [Tooltip("Доля ширины экрана для центра карт: 0 — левый край, 0.5 — середина.")] + [Range(0.05f, 0.95f)] public float handViewportX = 0.44f; [Tooltip("Доля высоты экрана для центра карт: 0 — низ, 0.5 — середина.")] - [Range(0.05f, 0.45f)] public float handViewportY = 0.16f; + [Range(0.05f, 0.45f)] public float handViewportY = 0.18f; [Tooltip("Расстояние от камеры до веера руки, метры.")] - public float handViewDistance = 3.6f; - public float handViewMaxWidth = 2.0f; - public float handViewScale = 0.9f; + public float handViewDistance = 3.8f; + public float handViewMaxWidth = 1.8f; + public float handViewScale = 0.62f; public float handViewRoll = 3.2f; public float handViewArc = 0.02f; @@ -66,21 +68,15 @@ namespace Vanguard.Board3D [Header("Стопки")] [Tooltip("Расстояние от центра стола до зоны урона.")] - public float damageX = 3.5f; + public float damageX = 3.0f; [Tooltip("Расстояние от центра стола до колоды и дропа.")] - public float pileX = 3.55f; + public float pileX = 2.95f; [Header("Камера")] - public Vector3 cameraPosition = new Vector3(0f, 6.9f, -9.8f); - public Vector3 cameraTarget = new Vector3(0f, 0f, -0.15f); + [Tooltip("Фиксированная камера над полем. Не двигается игроком.")] + public Vector3 cameraPosition = new Vector3(1.4f, 9.0f, -5.2f); + public Vector3 cameraTarget = new Vector3(1.4f, 0f, -0.1f); public float cameraFov = 50f; - public float orbitYawLimit = 32f; - public float orbitPitchMin = 20f; - public float orbitPitchMax = 62f; - public float zoomMin = 9.5f; - public float zoomMax = 16f; - public float zoomSpeed = 0.006f; - public float panSpeed = 0.0035f; [Header("Палитра")] public Color tableColor = new Color(0.045f, 0.04f, 0.055f); @@ -142,13 +138,12 @@ namespace Vanguard.Board3D handMaxWidth = Mathf.Max(1f, handMaxWidth); guardianMaxWidth = Mathf.Max(1f, guardianMaxWidth); handViewportY = Mathf.Clamp(handViewportY, 0.05f, 0.45f); + handViewportX = Mathf.Clamp(handViewportX, 0.05f, 0.95f); handViewDistance = Mathf.Max(1f, handViewDistance); handViewMaxWidth = Mathf.Max(0.5f, handViewMaxWidth); handViewScale = Mathf.Clamp(handViewScale, 0.3f, 1.5f); handViewRoll = Mathf.Clamp(handViewRoll, 0f, 20f); handViewArc = Mathf.Max(0f, handViewArc); - orbitPitchMax = Mathf.Clamp(orbitPitchMax, orbitPitchMin + 1f, 85f); - zoomMax = Mathf.Max(zoomMin + 0.5f, zoomMax); } } } diff --git a/client/Assets/Vanguard/Runtime/Board3D/PlaymatSandbox.cs b/client/Assets/Vanguard/Runtime/Board3D/PlaymatSandbox.cs index 668fee1..fe4b616 100644 --- a/client/Assets/Vanguard/Runtime/Board3D/PlaymatSandbox.cs +++ b/client/Assets/Vanguard/Runtime/Board3D/PlaymatSandbox.cs @@ -57,6 +57,10 @@ namespace Vanguard.Board3D private static BoardArt SandboxArt(string printingId) { + var texture = LoadSandboxTexture(printingId); + if (texture != null) + return new BoardArt(texture, Color.white, printingId); + var clan = printingId != null && printingId.Contains("002") ? "Kagero" : "RoyalPaladin"; @@ -67,6 +71,36 @@ namespace Vanguard.Board3D printingId); } + private static Texture2D LoadSandboxTexture(string printingId) + { + if (string.IsNullOrEmpty(printingId)) + return null; + + var slash = printingId.IndexOf('/'); + if (slash <= 0 || slash >= printingId.Length - 1) + return null; + + var set = printingId.Substring(0, slash).ToLowerInvariant(); + var tail = printingId.Substring(slash + 1); + var number = string.Empty; + for (var i = 0; i < tail.Length; i++) + { + var c = tail[i]; + if (char.IsDigit(c) || (i == 0 && (c == 'S' || c == 's'))) + { + number += char.ToLowerInvariant(c); + continue; + } + + break; + } + + if (number.Length == 0) + return null; + + return Resources.Load("CardArt/" + set + "_" + number); + } + private static BoardRenderState BuildState() { var state = new BoardRenderState(); diff --git a/client/Assets/Vanguard/Runtime/Board3D/View/BoardCameraRig.cs b/client/Assets/Vanguard/Runtime/Board3D/View/BoardCameraRig.cs deleted file mode 100644 index 36b8899..0000000 --- a/client/Assets/Vanguard/Runtime/Board3D/View/BoardCameraRig.cs +++ /dev/null @@ -1,132 +0,0 @@ -using UnityEngine; -using UnityEngine.EventSystems; -using UnityEngine.InputSystem; - -namespace Vanguard.Board3D -{ - /// - /// Ограниченная орбита камеры: ПКМ — поворот, СКМ — панорама, - /// колесо — зум. Левая кнопка остаётся картам и UI. - /// - public sealed class BoardCameraRig : MonoBehaviour - { - private PlaymatLayoutConfig _config; - private Vector3 _target; - private float _distance = 15f; - private float _yaw; - private float _pitch = 35f; - private bool _orbiting; - private bool _panning; - private Vector2 _lastPointer; - - public void Configure(PlaymatLayoutConfig config) - { - _config = config != null ? config : PlaymatLayoutConfig.Default; - _target = _config.cameraTarget; - var offset = _config.cameraPosition - _target; - _distance = Mathf.Clamp( - offset.magnitude, - _config.zoomMin, - _config.zoomMax); - _pitch = Mathf.Clamp( - Mathf.Asin(Mathf.Clamp(offset.y / Mathf.Max(0.001f, _distance), -1f, 1f)) - * Mathf.Rad2Deg, - _config.orbitPitchMin, - _config.orbitPitchMax); - _yaw = Mathf.Atan2(-offset.x, -offset.z) * Mathf.Rad2Deg; - _yaw = Mathf.Clamp(_yaw, -_config.orbitYawLimit, _config.orbitYawLimit); - Apply(); - } - - private void Update() - { - if (_config == null) - return; - - var mouse = Mouse.current; - if (mouse == null) - return; - - var pointer = mouse.position.ReadValue(); - var overUi = IsPointerOverUi(); - - if (mouse.rightButton.wasPressedThisFrame && !overUi) - { - _orbiting = true; - _lastPointer = pointer; - } - - if (mouse.rightButton.wasReleasedThisFrame) - _orbiting = false; - - if (_orbiting && mouse.rightButton.isPressed) - { - var delta = pointer - _lastPointer; - _lastPointer = pointer; - _yaw = Mathf.Clamp( - _yaw + (delta.x * 0.18f), - -_config.orbitYawLimit, - _config.orbitYawLimit); - _pitch = Mathf.Clamp( - _pitch - (delta.y * 0.16f), - _config.orbitPitchMin, - _config.orbitPitchMax); - Apply(); - } - - if (mouse.middleButton.wasPressedThisFrame && !overUi) - { - _panning = true; - _lastPointer = pointer; - } - - if (mouse.middleButton.wasReleasedThisFrame) - _panning = false; - - if (_panning && mouse.middleButton.isPressed) - { - var delta = pointer - _lastPointer; - _lastPointer = pointer; - var rotation = Quaternion.Euler(_pitch, _yaw, 0f); - var right = rotation * Vector3.right; - var forward = rotation * Vector3.forward; - right.y = 0f; - forward.y = 0f; - right.Normalize(); - forward.Normalize(); - - var scale = _config.panSpeed * _distance; - _target -= (right * (delta.x * scale)) + (forward * (delta.y * scale)); - _target.x = Mathf.Clamp(_target.x, -2.5f, 2.5f); - _target.z = Mathf.Clamp(_target.z, -2f, 2f); - Apply(); - } - - var scroll = mouse.scroll.ReadValue().y; - if (!overUi && Mathf.Abs(scroll) > 0.01f) - { - _distance = Mathf.Clamp( - _distance - (scroll * _config.zoomSpeed), - _config.zoomMin, - _config.zoomMax); - Apply(); - } - } - - private void Apply() - { - var rotation = Quaternion.Euler(_pitch, _yaw, 0f); - transform.rotation = rotation; - transform.position = _target - (rotation * Vector3.forward * _distance); - var camera = GetComponent(); - if (camera != null) - camera.fieldOfView = _config.cameraFov; - } - - private static bool IsPointerOverUi() - { - var eventSystem = EventSystem.current; - return eventSystem != null && eventSystem.IsPointerOverGameObject(); - } - } -} diff --git a/client/Assets/Vanguard/Runtime/Board3D/View/BoardCameraRig.cs.meta b/client/Assets/Vanguard/Runtime/Board3D/View/BoardCameraRig.cs.meta deleted file mode 100644 index 7bfc876..0000000 --- a/client/Assets/Vanguard/Runtime/Board3D/View/BoardCameraRig.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 30bd2e29295c0b241bb1f29e9dc73ca8 \ No newline at end of file diff --git a/client/Assets/Vanguard/Runtime/Board3D/View/BoardSlotView.cs b/client/Assets/Vanguard/Runtime/Board3D/View/BoardSlotView.cs index c7f1504..2e2cdd0 100644 --- a/client/Assets/Vanguard/Runtime/Board3D/View/BoardSlotView.cs +++ b/client/Assets/Vanguard/Runtime/Board3D/View/BoardSlotView.cs @@ -70,7 +70,7 @@ namespace Vanguard.Board3D var text = BoardText.Create( go.transform, label, - 0.14f, + 0.055f, new Color(1f, 1f, 1f, 0.34f), new Vector3(0f, 0.001f, 0f)); text.name = "Slot Label"; diff --git a/client/Assets/Vanguard/Runtime/Board3D/View/BoardTextures.cs b/client/Assets/Vanguard/Runtime/Board3D/View/BoardTextures.cs index f4f11bd..775b126 100644 --- a/client/Assets/Vanguard/Runtime/Board3D/View/BoardTextures.cs +++ b/client/Assets/Vanguard/Runtime/Board3D/View/BoardTextures.cs @@ -36,6 +36,10 @@ namespace Vanguard.Board3D { get { + if (_back != null) + return _back; + + _back = Resources.Load("CardArt/vanguard_back"); if (_back == null) _back = BuildBack(); return _back; diff --git a/client/Assets/Vanguard/Runtime/Board3D/View/GameBoard3D.cs b/client/Assets/Vanguard/Runtime/Board3D/View/GameBoard3D.cs index 79ee3ff..2e9d1b0 100644 --- a/client/Assets/Vanguard/Runtime/Board3D/View/GameBoard3D.cs +++ b/client/Assets/Vanguard/Runtime/Board3D/View/GameBoard3D.cs @@ -43,8 +43,6 @@ namespace Vanguard.Board3D private Transform _pilesRoot; private Transform _zonesRoot; private Camera _camera; - private BoardCameraRig _cameraRig; - private bool _ownsRig; private BoardZoneView _guardianZone; private BoardZoneView _dropIndicator; @@ -159,8 +157,6 @@ namespace Vanguard.Board3D } gameObject.SetActive(visible); - if (_cameraRig != null) - _cameraRig.enabled = visible; } public void Render(MatchView view, BoardRenderState state) @@ -271,7 +267,9 @@ namespace Vanguard.Board3D new Vector3(matWidth, 0.008f, matDepth), _config.matOpponentColor); - var divider = BoardMaterials.CreateLit(_config.lineColor, 1.2f); + var divider = BoardMaterials.CreateUnlit( + null, + new Color(0.34f, 0.24f, 0.10f)); CreateBox( "Center Line", new Vector3(0f, 0.011f, 0f), @@ -339,8 +337,8 @@ namespace Vanguard.Board3D guardianDepth, Mathf.Max(0.022f, _config.cardWidth * 0.04f), _config.guardianColor, - "GUARDIAN", - 0.11f, + null, + 0f, -(guardianDepth * 0.5f) - 0.2f, new Color(0.72f, 0.92f, 1f, 0.75f), _config.highlightColor); @@ -360,8 +358,8 @@ namespace Vanguard.Board3D 2.25f, Mathf.Max(0.018f, _config.cardWidth * 0.03f), _config.damageColor, - "DAMAGE", - 0.1f, + null, + 0f, -zSign * 1.32f, new Color(1f, 0.78f, 0.76f, 0.75f), _config.highlightColor); @@ -433,17 +431,11 @@ namespace Vanguard.Board3D if (_camera == null) return; - if (_cameraRig == null) - { - _cameraRig = _camera.GetComponent(); - if (_cameraRig == null) - { - _cameraRig = _camera.gameObject.AddComponent(); - _ownsRig = true; - } - } - - _cameraRig.Configure(_config); + _camera.transform.position = _config.cameraPosition; + var direction = _config.cameraTarget - _config.cameraPosition; + if (direction.sqrMagnitude > 0.0001f) + _camera.transform.rotation = Quaternion.LookRotation(direction, Vector3.up); + _camera.fieldOfView = _config.cameraFov; } private void BuildSpecs( @@ -496,7 +488,8 @@ namespace Vanguard.Board3D Art = ResolveArt(card.PrintingId), Position = _layout.CirclePosition(localSeat, slot), BaseRotation = Quaternion.Euler(0f, _layout.BaseYaw(localSeat), 0f), - FaceUp = card.FaceUp, + // Карты в кругах V/R всегда открыты, независимо от снимка. + FaceUp = true, Rested = card.Rested, Highlight = state.Highlights.Contains(key) ? _config.highlightColor @@ -669,7 +662,9 @@ namespace Vanguard.Board3D var offset = index - (safeCount - 1) * 0.5f; var halfHeight = Mathf.Tan( _camera.fieldOfView * 0.5f * Mathf.Deg2Rad) * _config.handViewDistance; - var x = offset * step; + var halfWidth = halfHeight * Mathf.Max(0.1f, _camera.aspect); + var x = ((_config.handViewportX - 0.5f) * 2f * halfWidth) + + (offset * step); var y = (_config.handViewportY - 0.5f) * 2f * halfHeight + (1f - Mathf.Abs(offset) / safeCount) * _config.handViewArc; var z = _config.handViewDistance @@ -725,22 +720,11 @@ namespace Vanguard.Board3D UpdatePileSide(self, _deckSelf, _dropSelf, _soulSelf); UpdatePileSide(opponent, _deckOpponent, _dropOpponent, _soulOpponent); - var damageSelf = self != null - ? self.FaceDownDamage + (self.FaceUpDamage?.Count ?? 0) - : 0; - var damageOpponent = opponent != null - ? opponent.FaceDownDamage + (opponent.FaceUpDamage?.Count ?? 0) - : 0; - _damageZones[0]?.SetLabel("DAMAGE " + damageSelf); - _damageZones[1]?.SetLabel("DAMAGE " + damageOpponent); + _damageZones[0]?.SetLabel(string.Empty); + _damageZones[1]?.SetLabel(string.Empty); if (_guardianZone != null) - { - var shield = view.Battle != null ? view.Battle.GuardShield : 0; - var checks = view.Battle != null ? view.Battle.ChecksRemaining : 0; - _guardianZone.SetLabel( - "GUARDIAN SHIELD " + shield + " CHECK " + checks); - } + _guardianZone.SetLabel(string.Empty); } private void UpdatePileSide( @@ -1214,14 +1198,6 @@ namespace Vanguard.Board3D { if (_instance == this) _instance = null; - - if (_cameraRig != null && _ownsRig) - { - if (Application.isPlaying) - Destroy(_cameraRig); - else - DestroyImmediate(_cameraRig); - } } private sealed class HandCardBinding diff --git a/client/Assets/Vanguard/Runtime/Board3D/View/Pile3D.cs b/client/Assets/Vanguard/Runtime/Board3D/View/Pile3D.cs index 8be69f6..2085870 100644 --- a/client/Assets/Vanguard/Runtime/Board3D/View/Pile3D.cs +++ b/client/Assets/Vanguard/Runtime/Board3D/View/Pile3D.cs @@ -73,12 +73,15 @@ namespace Vanguard.Board3D _top.sharedMaterial = BoardMaterials.White; BoardMaterials.SetShadows(_top, false); - _label = BoardText.Create( - transform, - title, - 0.115f, - new Color(0.86f, 0.90f, 1f), - new Vector3(0f, 0.02f, -(height * 0.78f))); + if (Zone != BoardZone.Soul) + { + _label = BoardText.Create( + transform, + title, + 0.05f, + new Color(0.86f, 0.90f, 1f), + new Vector3(0f, 0.02f, -(height * 0.78f))); + } var collider = gameObject.AddComponent(); collider.size = new Vector3(width * 1.06f, 0.16f, height * 1.06f); @@ -128,7 +131,7 @@ namespace Vanguard.Board3D _top.SetPropertyBlock(_block); } - BoardText.SetText(_label, title + " " + safe); + BoardText.SetText(_label, title); } private static void RemoveCollider(GameObject target) diff --git a/client/Assets/Vanguard/Runtime/UI/BattleView.cs b/client/Assets/Vanguard/Runtime/UI/BattleView.cs index 2502b9f..10d0b6e 100644 --- a/client/Assets/Vanguard/Runtime/UI/BattleView.cs +++ b/client/Assets/Vanguard/Runtime/UI/BattleView.cs @@ -80,6 +80,8 @@ namespace Vanguard.UI private RectTransform _soulOverlay; private RectTransform _soulContent; private Text _soulTitle; + private Text _selfStatsText; + private Text _opponentStatsText; public BattleView(Transform parent, MetaService meta, Action onExit) { @@ -129,7 +131,7 @@ namespace Vanguard.UI right.anchorMin = new Vector2(1f, 0f); right.anchorMax = new Vector2(1f, 1f); right.pivot = new Vector2(1f, 0.5f); - right.offsetMin = new Vector2(-528f, 28f); + right.offsetMin = new Vector2(-456f, 28f); right.offsetMax = new Vector2(-36f, -108f); UiKit.AddVerticalLayout(right, 14, 10); @@ -188,6 +190,7 @@ namespace Vanguard.UI _feedback.gameObject.SetActive(false); BuildSoulOverlay(); + BuildStatsOverlays(); _board3D = GameBoard3D.Create(null, PlaymatLayoutConfig.Default); _board3D.ArtProvider = ResolveBoardArt; @@ -234,6 +237,10 @@ namespace Vanguard.UI _topInfo.text = (info.DeckName ?? string.Empty) + " · " + info.MatchId; _soulCounterLabel.text = "Душа: 0"; _soulCounter.interactable = false; + if (_selfStatsText != null) + _selfStatsText.text = string.Empty; + if (_opponentStatsText != null) + _opponentStatsText.text = string.Empty; SetStatus("Подключаемся к матчу…", Muted); _root.gameObject.SetActive(true); _ = LoadCatalogAsync(); @@ -773,6 +780,7 @@ namespace Vanguard.UI _board3D?.SetSelfPlayer(_view.You); _board3D?.Render(_view, BuildBoardRenderState()); UpdateSoulCounter(); + UpdateStatsOverlay(); RebuildIntents(_view); UpdateClock(); @@ -848,9 +856,16 @@ namespace Vanguard.UI _catalog.TryGetValue(printingId, out var meta); var clan = meta != null ? meta.Clan : "None"; var nameId = meta != null ? meta.NameId : printingId; - var sprite = CardImageService.Resolve( - meta != null ? meta.ImageKey : null, - CardArt.ForCard(nameId ?? printingId ?? "card", clan)); + var sprite = CardImageService.Resolve(meta != null ? meta.ImageKey : null, null); + if (sprite == null) + { + sprite = CardImageService.Resolve( + CardImageService.ImageKeyForPrinting(printingId), + null); + } + + if (sprite == null) + sprite = CardArt.ForCard(nameId ?? printingId ?? "card", clan); return new BoardArt( sprite != null ? sprite.texture : null, CardArt.ClanColor(clan), @@ -1023,6 +1038,86 @@ namespace Vanguard.UI } } + private void BuildStatsOverlays() + { + _selfStatsText = CreateStatsPanel( + "SelfStats", + new Vector2(0f, 0f), + new Vector2(0f, 0f), + new Vector2(30f, 24f), + TextAnchor.MiddleLeft); + _opponentStatsText = CreateStatsPanel( + "OpponentStats", + new Vector2(1f, 1f), + new Vector2(1f, 1f), + new Vector2(-488f, -108f), + TextAnchor.MiddleRight); + } + + private Text CreateStatsPanel( + string name, + Vector2 anchor, + Vector2 pivot, + Vector2 position, + TextAnchor alignment) + { + var panel = UiKit.CreatePanel( + _root, + name, + new Color(0.02f, 0.035f, 0.055f, 0.72f)); + panel.anchorMin = anchor; + panel.anchorMax = anchor; + panel.pivot = pivot; + panel.anchoredPosition = position; + panel.sizeDelta = new Vector2(360f, 58f); + + var image = panel.GetComponent(); + if (image != null) + image.raycastTarget = false; + + var text = UiKit.CreateText( + panel, + "Stats", + string.Empty, + 14, + new Color(0.86f, 0.91f, 1f), + alignment); + UiKit.Stretch(text.rectTransform); + text.rectTransform.offsetMin = new Vector2(12f, 5f); + text.rectTransform.offsetMax = new Vector2(-12f, -5f); + text.horizontalOverflow = HorizontalWrapMode.Wrap; + text.verticalOverflow = VerticalWrapMode.Overflow; + UiKit.MakeLiteral(text); + return text; + } + + private void UpdateStatsOverlay() + { + if (_view == null || _selfStatsText == null || _opponentStatsText == null) + return; + + var self = _view.Players.FirstOrDefault(player => player.Index == _view.You); + var opponent = _view.Players.FirstOrDefault(player => player.Index != _view.You); + _selfStatsText.text = FormatStats(self, selfSide: true); + _opponentStatsText.text = FormatStats(opponent, selfSide: false); + } + + private static string FormatStats(PlayerView player, bool selfSide) + { + var title = Loc.Translate(selfSide ? "ВЫ" : "ПРОТИВНИК"); + if (player == null) + return title; + + var damage = player.FaceDownDamage + (player.FaceUpDamage?.Count ?? 0); + var hand = Mathf.Max(player.HandCount, player.Hand?.Count ?? 0); + return title + " · " + player.Name + "\n" + + Loc.Translate("Рука") + " " + hand + + " " + Loc.Translate("Колода") + " " + player.DeckCount + + " " + Loc.Translate("ДРОП") + " " + (player.Drop?.Count ?? 0) + + " " + Loc.Translate("УРОН") + " " + damage + + " " + Loc.Translate("Душа") + " " + (player.Soul?.Count ?? 0); + } + private void BuildSoulOverlay() { _soulOverlay = UiKit.CreatePanel(_root, "SoulOverlay", new Color(0f, 0f, 0f, 0.74f)); diff --git a/client/Assets/Vanguard/Runtime/UI/CardArt.cs b/client/Assets/Vanguard/Runtime/UI/CardArt.cs index 2efac2e..1bf14b4 100644 --- a/client/Assets/Vanguard/Runtime/UI/CardArt.cs +++ b/client/Assets/Vanguard/Runtime/UI/CardArt.cs @@ -85,6 +85,17 @@ namespace Vanguard.UI if (_back != null) return _back; + var texture = Resources.Load("CardArt/vanguard_back"); + if (texture != null) + { + _back = Sprite.Create( + texture, + new Rect(0f, 0f, texture.width, texture.height), + new Vector2(0.5f, 0.5f), + 100f); + return _back; + } + _back = BackTexture(); return _back; } diff --git a/client/Assets/Vanguard/Runtime/UI/CardImageService.cs b/client/Assets/Vanguard/Runtime/UI/CardImageService.cs index cfaba86..5881c4b 100644 --- a/client/Assets/Vanguard/Runtime/UI/CardImageService.cs +++ b/client/Assets/Vanguard/Runtime/UI/CardImageService.cs @@ -51,5 +51,36 @@ namespace Vanguard.UI Cache[imageKey] = sprite; return sprite; } + + /// + /// "BT01/042EN" → "bt01_042". Нужно, когда каталог ещё не загрузился, + /// а арт уже лежит в Resources/CardArt. + /// + public static string ImageKeyForPrinting(string printingId) + { + if (string.IsNullOrEmpty(printingId)) + return null; + + var slash = printingId.IndexOf('/'); + if (slash <= 0 || slash >= printingId.Length - 1) + return null; + + var set = printingId.Substring(0, slash).ToLowerInvariant(); + var tail = printingId.Substring(slash + 1); + var number = string.Empty; + for (var i = 0; i < tail.Length; i++) + { + var c = tail[i]; + if (char.IsDigit(c) || (i == 0 && (c == 'S' || c == 's'))) + { + number += char.ToLowerInvariant(c); + continue; + } + + break; + } + + return number.Length > 0 ? set + "_" + number : null; + } } } diff --git a/client/Assets/Vanguard/Runtime/UI/Localization.cs b/client/Assets/Vanguard/Runtime/UI/Localization.cs index 9ba8c7e..45dc4b5 100644 --- a/client/Assets/Vanguard/Runtime/UI/Localization.cs +++ b/client/Assets/Vanguard/Runtime/UI/Localization.cs @@ -38,6 +38,8 @@ namespace Vanguard.UI ["нет"] = "no", ["Вы: "] = "You: ", ["ДРОП"] = "DROP", + ["Душа"] = "Soul", + ["ДУША"] = "SOUL", ["Кадр"] = "Frame", ["Клан"] = "Clan", ["Пыль"] = "Dust", diff --git a/client/Assets/Vanguard/Tests/Editor/ClientSmokeTests.cs b/client/Assets/Vanguard/Tests/Editor/ClientSmokeTests.cs index 3b72935..59cfaa4 100644 --- a/client/Assets/Vanguard/Tests/Editor/ClientSmokeTests.cs +++ b/client/Assets/Vanguard/Tests/Editor/ClientSmokeTests.cs @@ -66,6 +66,9 @@ namespace Vanguard.Tests Assert.IsNotNull( Resources.Load("CardArt/td01_005"), "TD01 card art is not imported"); + var standardBack = Resources.Load("CardArt/vanguard_back"); + Assert.IsNotNull(standardBack, "Standard Vanguard card back is not imported"); + Assert.AreEqual(standardBack, CardArt.Back.texture); var artGo = new GameObject("ArtProbe", typeof(RectTransform), typeof(Image)); var artImage = artGo.GetComponent(); @@ -234,6 +237,20 @@ namespace Vanguard.Tests card.Ref.Zone == BoardZone.Guardian && card.Ref.InstanceId == 7)); + var selfStats = Resources.FindObjectsOfTypeAll() + .FirstOrDefault(text => text.name == "Stats" + && text.transform.parent != null + && text.transform.parent.name == "SelfStats"); + var opponentStats = Resources.FindObjectsOfTypeAll() + .FirstOrDefault(text => text.name == "Stats" + && text.transform.parent != null + && text.transform.parent.name == "OpponentStats"); + Assert.IsNotNull(selfStats); + Assert.IsNotNull(opponentStats); + StringAssert.Contains("Рука 1", selfStats.text); + StringAssert.Contains("Душа 1", selfStats.text); + StringAssert.Contains("Рука 0", opponentStats.text); + Cleanup(); } diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index 21422db..5765b08 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -840,7 +840,8 @@ Battle; Boot и общие сервисы остаются персистент - Раскладка: локальный игрок всегда внизу; передний ряд `RC–V–RC`, задний `RC–RC–RC`; у противника зеркально. Между половинами — общий круг защиты (карты обоих игроков и текущий Guard). Душа — стопка под V, колода и дроп - сбоку, урон — две колонки по три карты на боку. + сбоку, урон — две колонки по три карты на боку. Карты в V/R всегда + рисуются лицом вверх, даже если снимок пришёл с `FaceUp=false`. - `PlaymatLayoutConfig` (ScriptableObject): размеры карт, позиции рядов, высоты, рука, камера, палитра. Ассет: `Runtime/Board3D/Config/PlaymatLayoutConfig.asset`. @@ -850,16 +851,21 @@ Battle; Boot и общие сервисы остаются персистент - `Card3D` — тонкая коробка: отдельные лицо/рубашка/торец, коллайдер, арт из `CardImageService`, переворот вокруг X, Rest вокруг Y по часовой стрелке, урон — против часовой, плавный снап. Карты пулятся (`GameBoard3D`), - материалы общие, instancing включён. + материалы общие, instancing включён. Рубашка — стандартная VF Vanguard + `Resources/CardArt/vanguard_back.png` (источник: Card Sleeve Gallery, + `Sleeve_06.png`), общая с 2D-UI; при отсутствии файла остаётся + процедурный fallback. - `GameBoard3D` строит стол, круги, зоны, стопки и веер руки; raycast-клики, drag&drop на плоскость стола с подъёмом, подсветкой допустимых кругов и индикатором точки броска. Ошибка интента возвращает карту на место. -- Камера приближена: позиция `(0, 6.9, -9.8)`, цель `(0, 0, -0.15)`, FOV 50. - Рука не лежит на столе, а закреплена в экране снизу по центру - (`handViewportY`, `handViewDistance`) и всегда развёрнута лицом к игроку; - при орбите камеры веер следует за полем зрения, драг из руки уходит на стол. -- `BoardCameraRig` — ПКМ орбита (±32°), СКМ панорама, колесо зум - (9.5–16); ограничения в конфиге. +- Камера фиксирована над полем: позиция `(1.4, 9, -5.2)`, цель + `(1.4, 0, -0.1)`, FOV 50; игрок её не двигает. Рука не лежит на столе, + а закреплена в экране снизу по центру (`handViewportX/Y`, + `handViewDistance`) и всегда развёрнута лицом к игроку; драг из руки + уходит на стол. +- Статистика карт вынесена в отдельные UI-панели: своя — снизу слева, + противника — сверху справа (`HAND/DECK/DROP/DMG/SOUL`); 3D-подписи + стопок и зон больше не дублируют числа. - Душа: клик по стопке или кнопка «Душа: n» в верхней панели открывает оверлей со списком карт. - Песочница: `Assets/Vanguard/Scenes/GameBoard3D.unity` + diff --git a/docs/SESSION-STATE.md b/docs/SESSION-STATE.md index 410ff51..3af10d2 100644 --- a/docs/SESSION-STATE.md +++ b/docs/SESSION-STATE.md @@ -65,15 +65,19 @@ остаются uGUI. Карты — тонкие 3D-объекты с артом, рубашкой, торцом и коллайдером. Rest (атака/поддержка) — поворот по часовой стрелке вокруг Y, урон лежит на боку против часовой; закрытость — переворот вокруг X. - Рука закреплена в поле зрения камеры снизу по центру и всегда смотрит - на игрока, а не лежит на столе. Драг-н-дроп на плоскость стола с - подсветкой целей и плавным снапом; камера приближена. + Рубашка — стандартная VF Vanguard (`Resources/CardArt/vanguard_back.png`), + общая для 2D и 3D. Рука закреплена в поле зрения камеры снизу по центру + и всегда смотрит на игрока, а не лежит на столе. Камера фиксирована над + полем под небольшим углом и не двигается игроком. Драг-н-дроп на + плоскость стола с подсветкой целей и плавным снапом. - Поле: у каждого игрока два ряда `R V R` / `R R R` (V + 5 RC), у противника зеркально; между полями общий круг защиты; душа — стопка под V; колода, дроп и урон — 3D-стопки/карты. Локальный игрок всегда снизу, - даже если он за вторым местом. ПКМ — орбита, СКМ — панорама, колесо — - зум. Кнопка «Душа: n» в верхней панели и клик по стопке души открывают - список карт души. + даже если он за вторым местом. Карты в кругах V/R принудительно + показываются лицом вверх. +- Статистика карт — отдельное UI-наложение: своя панель снизу слева, + противника — сверху справа. Кнопка «Душа: n» в верхней панели и клик по + стопке души открывают список карт души. - Зона урона: карты лежат открытыми и на боку; после Counter Blast выбранная карта переворачивается рубашкой. Heal выбирает карту урона; Counter Blast — открытую карту до активации способности. @@ -95,7 +99,7 @@ открывается из Lobby кнопкой «Коллекция» (сцена `DeckBuilder`). - Не готово: 3D-модели карт/стола (пока процедурные примитивы и арты), звук, настройки (язык уже есть), DOTween, drag&drop и live-валидация - декбилдера. Камера боя — ограниченная орбита; анимации retire/ghost для + декбилдера. Камера боя фиксирована; анимации retire/ghost для 3D-карт ещё не перенесены. ## Запуск @@ -170,8 +174,8 @@ client/Assets/Vanguard/Runtime/Board3D/ Logic/BoardPlacementRules.cs Ride/Call/Move/Guard View/GameBoard3D.cs стол, круги, пул карт, drag&drop View/Card3D.cs карта: лицо/рубашка/торец, Rest, флип - View/BoardCameraRig.cs орбита/панорама/зум PlaymatSandbox.cs демо без сервера +client/Assets/Vanguard/Resources/CardArt/vanguard_back.png рубашка VF client/Assets/Vanguard/Scenes/GameBoard3D.unity песочница поля client/Assets/Vanguard/Runtime/Battle/GameConnection.cs client/Assets/Vanguard/Runtime/Api/ApiClient.cs + ApiContracts.cs