From 87b4aa27e73b34267e388cf1ab8309ac85a081be Mon Sep 17 00:00:00 2001 From: oz Date: Sat, 9 Jan 2021 19:11:03 +0300 Subject: [PATCH] TFlipperEdge v1. --- Doc/FuncStats.xlsx | Bin 38440 -> 38506 bytes SpaceCadetPinball/SpaceCadetPinball.vcxproj | 2 + .../SpaceCadetPinball.vcxproj.filters | 6 + SpaceCadetPinball/TFlipperEdge.cpp | 512 ++++++++++++++++++ SpaceCadetPinball/TFlipperEdge.h | 61 +++ SpaceCadetPinball/maths.cpp | 41 +- SpaceCadetPinball/maths.h | 6 + 7 files changed, 627 insertions(+), 1 deletion(-) create mode 100644 SpaceCadetPinball/TFlipperEdge.cpp create mode 100644 SpaceCadetPinball/TFlipperEdge.h diff --git a/Doc/FuncStats.xlsx b/Doc/FuncStats.xlsx index bd26638bd8cee3183f2a90adf2cac35e947f71e5..5aa3f46db4ea658cc7f4997bccfaf46def394bcc 100644 GIT binary patch delta 29974 zcmY(qb70)v_B|Y1jcq$=Y}+>4#%k<*V%tXJ#r3mVf$Am4~WUkCpuvTjOg`;jO*jXf68M(zYR(9vzH~gM= zD(rAeS*TUDO0kw-w`yvP6^=RHw3#O63*VpKZlhWpem}%fM{bKMc z$%QrEzQK2ya5!k7XZ+6BLK^rd&NMmY4*0XQ7bddnm{|4b?wL?`@%CYFUNc+cTkTb# z*siWB^obMJkgOpbOcAE4;o!VFTB#$JgsvOTM-$alt;60(ym*gj2_tBNaar=ni!*91 z&D7t@<-9IlHa(-$)3ge>*=ic{bqFU#{V$SiqcSAEnl!R_SXP%t8tE}+cVC&+LIGan zRd(h9N%CsUTr~Sgd^OcBxqesA4{10NoW{sj30`VLtte_tCz6*>D~ktd7Q%PKKDoig zRH|sb-xZ0)~X3(O}4h{o1 z=OrTxA+%#jJXJjDo^DCO%2Utp<$xrU5)a?KDSiaY)CsCCIkSZB4=Wk3(IkaW2}Yll z$jcg&&BIUND@UH@kVsZXO*Ln%uV>DuQC?xb3j!lUsBu!z>)EFD%n0n9UV5Fwj@a6JF|-p&_Q>qhT7 z{)?!s@YqcI3uehSmwX~ptf>bLWr#-?+u8Hvqi$+SEzzG^ov07LZ=WDLM{(JBD_S1Y z3*;K_CAAKMmRwLEb0do=K15&VTI_Mf=4aSkM-R-G#Q?#?hP2$5LSv~#irjb_qlw1I zE*J}Dg$_t6xnGpOU`}$oQUUu*W_TfO@$U~*SjPROeU+VPf{8PgvD8}qe}od4G(zL? z0)o>c5bjWw=yWHc$E9@~rT&l`WhXIP?|j0D!Xdq}!K+?F!vrL^ca7pBP`{TND7-I~`4Kl8zj$Iz{MRPgw$=xv5BM4dON&}i5n!!GFV$$AV zRR?YkBR7f2spdYxCC$OM*ro14lBd^o^kT=orK+K4^hOjTPsP>D)f+kU6<9B#FPciN zoO29Nstt;r-`|*Xe_}jyGWKn*8&f%=Ji9SqhgYQ`KN~&ko5O}&z^KqdB^xYvPA(;? zr!a`bFGm!+E!=H_I|98K#`ENC)hD-KrJ8Dc_z|9;3u^%$gl86M({~;O?^KI`2c9->hX0c*c+!e2DfhufCckB<1CaeWB&T1#2Sr~+EcI=2bXZK0 zg;FcU?E^5N4|^VVX`{m!S4%brj=ne4^2lF8bnG2$71RL`MFwy8o#A$Kj$mdQ zH;YAyu3o6LMPB?OjU`Q-H{asU9Z^_CY%mfElzZ{uu(0Cw5m1*ZA*~+ZpVp;Fr-XcM z5`Y(VWNg#gaW2VF5G0?_b|KR0EBn(6b21>C1;8Kn+k9MYvjr@!| zi-tFrLxVuMsqsP0q=0Y?32(&^(t{yB;fuiHfkJm1mc9fdAvA}RM)f{*`RpxRmZv)D zTDVLZ16)w@3pN1+TE1o{*Y*UfzrXztzR&<)F_9bQNef=|=?WgTG6U>yF@M;g^>qbp z#D9GpPc{M$@t;U$=aEkA`4d6fkJSP3 zHR5<@5cB(ymPmOXAH|*HE${5~siaPbTcsDn_jVZ|PVKjToo-YQJ~yZ!K8nDNw}|OjY&fC z>qD|@`Te5l7m>uDlMX}6l*jVPcCCiU$hLX3{&)?ap~rFT^QQ1&W5`i~-94O)vsfFv zc|lwyV>7*yo}Pebd1J;BLH61YS%~jgcnMp&KsUHhEsC9W<~*balZG;cAH5@3O;pT<>&^PE<@VWmzw@9r*5R z)`3!LrS#5|!F^bDoihu^z^PzSH7GGOf0kn%29s&DM{Dq*EF5t`GFs4D3**c@PkFty z*~L}-&rj{aj5b!i8CJCRg(*8?r%$6cl`)9A-^2#ZJ_sS19FQ2W7&H{fx9m>D zryr>0-<`s}A@7w_V)4G2BA=5G#~6gskqZt=XxGW4rj=Dkd{@&yFlsf;g0wD|H0f~` z&{X|3X4Kg)DM8fkgw~#Nhpt^(K{!z-4{>}$JnD{a)6d;KE#_mH z$shB8+knzv`aopa!($ATKIS>gebLP~ zzFfG0$xgKFHkh${2=i2wry!IL@}_;U1ADg|+DT;O1)FINkY`>C?kDU%KhCFU^NO*= z>qvM;$0x%4$ZWkaz{nBC?&4P1qU7LEev@sz61CLB>pZ)C_$}7-6#7YL=E*q-eOUzp>k0B`wr;}gAO=5RfxCl;4Kxp*x2K#h14fM$5 zaJeC(5ahb(@>`qi@tFbMa`}2!!1WbyLlY}w;7v^^-q`Ic%d=DCRP6#4)qXl>^yk5#Xe#Ras z;Q`Tl@^S9j^2fc&Ct`4tjN<~r-Si{O#@Zl0{~&&Jiojx}!sMZ2f#2MVkcobY`y;`| z1ox!et_0R-*Cdd@gJpbJMBxzrm{&~hCp!#Ejo%oX4=%@j_t;W7-n}?wfiu<^C2UH2 z>ZEPTjxLj5U{F7#if#?m-!WR@B|bd!nctD*O=gW4on>AvY!F2zQvSIB@BgAwqE4Ao z*Ff&mJSDW1yw(dHDu&lxuj0{DsRbvv_DN(798s<2hd4tzV9x^1(;*yg@4aM7g6AR; zZS5nZ%0Ce<6s$Z+6CC2sqBqro#nD0N7Z4O<#x+GCMkubd zRFtWBx`}ItxvCIYXrjy3*T{e8W?NLp_%uMw z88XT2c4S-v$S>zwZI^aEKN)IRsg>e+*#uHJ}$a3WiuG&yUhWxtMl=*J!OCGCQyvVM|&WX(!CLsh%^1 zL>Nlil?yLM8oGDjIx_4#XqZxjG`hBunp&$QIcz5B`$b5CZ1O0MBo3=zwC8&- z$`UK`p5}BTVtSs}@e`c=kQnHCb#QZesGvR++>Tqyhslpgv26 zD)?I!xK)Q}SKE0^7E!&=;QlAS{}g}d)P6;H%MYbxRbJo9Y&+muXwV`s^0DokbRWqT zu%mc(ZVqux?_n}AW-i3^c2kjAiQnNqLU5UNlDv?}O`4)+3B+z9X$F zq$O;tr1Xoo={yR4f!}?x^nNyl@6-0_#;d@1!YW^(b%8S>79(M&gTG3=TwOIvr(u>e z|5ta<&yYJ57s!_e@5jywdGAD-E$Q5}6xjF3%)hH!+w*d~c4v>ObjToE9hty6>R?t? zxU*-AyJCF`LXeF{5C*%hr#QGmQ3vgMFoTgW3+Cv5->F##Z3`DmW((&tzdjOfc3J_Z z_I^+Bhd2_DlZ#A}YciwV?NEQCAkKGAvR?s%@`Mb%f57(UK(L>uLV|k4Cak!XW2cTh zNE?M9TS&qCdEyUR7~Fk$)~lbQyoL~o>z8Z!aDJ2-*Ax8i53t-v3UTd!;G%oGlAaW> zoGqhB9Z@BmtE2gU7n|-bvCAcHl>m~%cvW0QLeHawGwdqY{SXFwCE<14h&Q71kF4_M z9O(jC`}5-M#4+)|gKRUGy*;-P-04pt6N#K|VOz|Kjn>FSW^;Uf;>pr{ua(>%V8X0V zgIu5Xq7g>w`hJ*Hc<23M{2j#mm3?~Ew8B+sFF)GbvVK;MIaRz%)bP zc^I8!*e>_DosH*;#*rrdnV+Ryyd=>+Zl84TL!-Yy%QKU%?S2)!1x0(QDp7FyCR&F= z_PeYUq00m;I2*KN>Fyp43k?lR&vZ?99rXa(Dp4hmgab(vYwx4uO-xVPJ0cL{>HAQ*Sl0Q1Nh!haN5)f8zS z4#8k`Jb!E{Z6(r)gxdykic{%OJ0m!=B;ZcRCAspM;I@BkdSC+oSy>okZrc5OeX=kZ;m zOsg4XfB$rFw@~u7#^ilRktfA-jTA;Vw(A*N76ZqJhiqE%=1+nK%NVO>yEcVf>!j%Q zI(E^3`P; zvP3Q@l|ZJoFVde!k|nb8oTF5MN^Sra^w2R1k;Y?1xf-2WN;UO-lR~!^Mcm~ zZ&OwM<$cH$Sc-lwYiGIRUO_!xYvgDkaM389?+QV|&kTXxHy z@J*g#opvJ%`+^2wA-j1R?EE5-{|d9{dKufEIWkhNegp!_gw^jGI}xnka-tRL4bv=@HiZRI*<0}XjtOj4f8zvTgZ!YFkl_W>`36^+F7OA5 zYo);tBl_(|J#A>0G8>!bi@p_3jBrweg2H{f0W*w&6r$g-H7XX?1Z3Fw#2NrSRV&M9 zb1_FjEcIcc|#qX8uU3Y*A>f)~dC~@%L4|_PJ*>7jZ%#Rm~U7M+U>8^JPz# z49!0W9{b;ew<7p8{J3abKsv-__M<2qzFzm2yg{bWwKHEhdyPZ5B~_g{X_fm1`}?u< zqnUL+u-k;#Upmak^J#E;N>3e!7mEW-s28WTumR#LRn(sI8ahi z(${6;AwMUwR`X1ueJh?Y)f$6V#lSevNTS!D1+2uBq~?BSzxIi7!2emTJicn<_`)F~ z&oriaRDUlX<)HJ^gf1C|-CNXoAi4k&gK`VP%J(P%rN4wD2L=38jpONL zSF*DC!#XoBtWBmi+LQ;k3%!WZz zFAy-RXRA1de7;A|EaxK!$Jus>KF*IAbc0Hhc6iFnWr1zx!7?9R2wzB+_SW18iO8}v z&Tm9@{TVhf%+?sg=ZAc&Rzz><4Rmn{9qK@H6&RY!_crAEms!eyHN#N&W7p ztqCWQ%TPFT6i<6(Bj#m4@a}Wvtb;fPbbwl%K}g#l>^h@XHi+=iScuHXsHteJ)1lrM z_58ROK`+OjOf-`EV!uN$yqJZ?NgoX|tql*~6^-~U)}@XSqd{q*NWS16&TVTMrdMMy zxjhGizoyVREY$2mU4;*>q@wp?8advD_;-_U1)AtnCsc;gDn^TL)m!2kCn4?2xB}o- zf+NkX9~VDNWHKOHaU;wR)hiJ*E@J=a27oHbrx z^Hc6=BsFvX^W$0YtNRMk6}fUp|Za zcu;{5zL_4%!Y)YDjr*jfOQW~Yp(GJqq*X15w6Dw)Ep)2gND*l0S*a`+r%r&=3uR-@ zi9@gF6Tb+QE+J>7-&jnl1W_n!p_=ZlY#iqH$@lcdwMvGg;5V@0fR66B|oh2ZvwdMLAoZ!o( z++IP1_^!d0@`f{_{m~8L@_uY+xTmVtJ~z2@i)S(-eJN6IgKZp4C};r$Kfpj)iDzIU z-7HS8#W%Y4)ubUYNvj)MEvkj-c#DC-o4c)GW^=N_i)VfQY02{m3O;4F8D2S`O@Z3~ z=Kc9Lz)=Bw_0eVwfv&Ef@%6}|I~G>Lvp@PGPQuaR6~%$7+aqL>saSt2 zarboa#*g*=Ht%P8@w*B!!=dn;(}f4&l;F$AcObz=)G*P;H`>qb(NsN z>%f}``o{uF(|2UCju=k2nOULy1cRda#9i#DAt5ln8|x3uG$A_rP%9zAzMZ^PbX8%; z^)}CSSRYLtew0K$y(s|y;<;5>S83wy^$LI|)j?u4*i)?_A+Qe#lz=hOTcq^-l4@gXQpHWFRgndKbpRXosgkK-79*;WSzTICK)wHw>FJ9!WzkLn* z=yQ9O$t&dZ{<^|FnTG1{cK7xeHpw$OeBiE}7w}%%)A@RZF$vtg{ogI@yat@_-!V#n_q$)isCl3Z z9_7=|IniS>NsNR$Lo>QxpE_Fd^O>G2;wCo$=RYTV6~jAMTl=>y#`joH#twP!Z?doV z6_d)q)9arO;D9?XuLn|kt@BBkM5y!qHLFz0ekovO=>6SL|JwbFo&D2n7%E^l`-*Mk zfq3y!t~|T`c=YR_MOZK|Zv*_LKCtxN{Q%+}p2G;0_^Bsj)}j6L`@yjGh9K~M)8d}@ z{yMPne*1Wq_kNAH{s4wJzi?7<@#g9Ib^}8Q?eMZE;APp+{dkE|;@?xV-edOx7V-5a z?(Je@!|(o)Wn;Cng9X*Sr2~2s&GX&%$&I__?dIj^kHdQNsDn}0V^S>#CSc!iWRwoE zUa1WJevLWIa)BE5di8cLEN-Rzr>}=&V*n7t?R2()exG5i1-d)+?Md7s=hx;DU5g%5 zcg~I2o}HF9h=2WT5fRC|{n{$v>-Thb5=Zj(hS1FLuss{6Z1;!77`$%vVDmKe)fLiR zI}k(I_YKbR;kAVuc({B#0@k#-g}uGrcWR7YpL<@1FMzk!_hZMluCCV~ER*kd!yB(# zHyglf$2;{o!~K-x>Q|<++13gmv3(iRCzK_M$`M_=IzO=c8~qVdxLu(aN8gZyv_gmg)?SjBt`tPjrG3B((U2;jA*2k z`xSV&7JYZ99I^=q3O^{+Zd9X|z?@$#a`dsk-JE&xmz-U>$&p5dWPgCzVri(vc8ZAa z_@VeG99M5sNvah$;!2sGOminh~5iN~NR zPjm234-5*lg-x#j(KitIpebKH?|p>#r(fN%L&idQ9G~ z-PW5-p77Ko@~nN{;TaIKmt79B-ak zK1dfWm(lm#R-0h4!uC+nm^#0V9X!MqJSF3Lj~<;>f2uaMZA0;nvQk5mCKa7vT|q?E z0>UdkoWg-Tyt7Saf+B~f(p7Fw-=P@+*z$6qrjn(#ON9bmkza-`T69esOP<10sVR3? zN3Wmpwd-dQa|AtxibjUNSg0+|n$sI&BDgFSicQMcct({$tC6`{jzk7L?N0>}vJ^(R zOd=7U@0xPuHoi-dp(m1Ruiyt+eCCFfIjKlkW+)mR1T)MrEHC}OH9e@?IM+l#7X+nPuW#!I@cNxiHO^6;R(Je%9Eno2`ft_hst?_@Wm8+S zwH?~xp-~>(@;)EP%j1V8DTibY78S3sKi#^pz1y^}I~jHDiD7^1K#huGsdd>KY;e)H z?#^Z2drX_G=M?`Tf=|0d`lY{2S1ST85+8q2wL$y3sy;QgMmuy=pTA!pn0PH=S{1x# z8SvI3L*)I`g&Yv%Y^hwi%_QHlH-B=()hJxDt5G_lEHaIZgwB#55?iiPU(Hh)SMI6? zUddEpR0Ho^%Xm@VW5n{ntHbp1t>7l0o7$F%gGKf`=6HtijVqo2!0*doFVcx8tkT0n>p=TYSi8cbW*|d;FNJ`J6fC4z-`BmL2V6W-y?;6z)xF zp2Hu8vdcM^_MlZm_UtUZq1M;rvbR38M&*Czfq=E#Rj8lxY&m}oklwlL#faC`{F&Ji z&l$8w$cR(_H5wo>r1mIs#NY_5bCK6|KKQszr!&##M1}|(Be#k9k*A`7U!I2P)}V)q zP4$TBi0L4w1?0aAYE*WY1dg%kp;Dl!@lQV@yXG&o*+HO0Knd+4G?z&mLSB#lB zez_Bx&k6j;K(w_mZ+9V~nbs2ij;neWD$seQf3A$UB#kT8VGv6HfW^#aF#7O4Taj21 zx)sw)Q&m@D$niQ|{LhWyXbF}Oh4FanNxkOHvJ>SFU-1>V`&8#%kQcV70Zd<%zyUKy zn%m*-DKP5a`DWv@=@3z{~G{?c!pRtrUn+&#t;Z7$(YJsa^P{4 zQ=Afs)hdr@>dzUw(W7IiwqcD0`w^7;btX0XscuD;y2`}1F9+L*TS>$M{4mOWPAI8} zNyY-|%o>9K$p{6U^Um2;cqU#0#x=E1LcxQC|DGMUgv%joo*Fng1Fg82v?+kY8plzA zoRNVl2mj(Pt6^yH?|w3p)iAhWSuMWwqTS4mMm#?Wtx~ipwUULW@I9Y7?Xd zL<8IT55ydXvkZObq$dVsqbFoV9U09IV?#>?Z^y6v>_X+5`S;DzkC?3smdf4MIx9vrm@sp*IbHB3*}=`D=LzI#gS#f{#z6;9?8DS zeljy{ay+RHba^D=La6^Z&=2@rP|Za+C>+A_Ix-rDpNjqFXdLq`fCy&c_EJITKuSy( zMZCEBDzwA;LiG4Tid%S8ojl3E{3XeR7Zz0KyMbmYGZ2O%J7|Yu|5T#p24~|&Ta<0? z+g&LVRt{;|7Bu@+7s|u>)&mLz{J?z+H^2F`tM<#Fz zWaoQ+V#ZaVy12E0K~N_D5bmts`jGF~B^{T<_gcNzcT!kZV29~B);3wj2C98b*&`9v zVD)s`MD#(4XT{LEoWy1ETz_8bWJvu z{`;QUq`QZuDl&;Rr{H7Qlvw>81-A(v?Vw5q_2Yh9habNra1KC`isn^fHa!QOSjc3U z_ivD=Z#Qy1icANz&>Ia`Qx$83`SF+QK{4+7+sSOxzB(iiA^+2O_GmK z1I(tdgw+{0893JX+eq15NaT1M3z66UwMM<2!~ReSeN=o*R=dVtTE9Jgb{A9VZ})d@ z=Lsv|m;Hdsv|^x)htU&7rGFx&fDG2N=WCadI4yVn@oym!nd@SGITFF6PnLmtl9Kpq~tg@#xD z1;E@|fX(kj+d}T5qX(B%MM77#BvU<35Ol&s(N}HgrKcK!RS1jM7;>V@l@n3bfVke6 zYn@t2n0UYfCAHW*k-$l3DqM|lE~}mW;XhC*lJA2AA249|2204rPP4ZJ>5srp;Pp`o zLnV2XG(xp8zJwFgG3SVz+aJH6QCKM!!?H{>A>@+Dkd7WsUbQbE`V;Dq8-!s%N=0|H zg_vs_lbK(zL&Xmblmdx?CXeGv&D%ORAql(8_3~h%4D?D z4a|I9l}qwkk!8T59Ana=)Sp4uAdgX%!_VX)^>yI4j1LE^QWO-~DN2b<+rwtbZ7Blv zCj7!=4vvIIPJ^1OXB(?2FK6t8Dvnk@WabtFFQ81EB4Pxp829FqZ_GfBpgVr8B0%OHlirC1GSYvn*jt(0;Zx45w&qVdrphK$^CRVK@@jkyKQ5UYjrp}7$%MdovI zVkos+))QLvS}0hBol^#4Ui3mEXt5b8#Zq2H)?ONO6nP#G;cK~X^ShUE!^yqzf-KWH z(1V2a10|U!QQ=gE_hb|#us%uus_n@tzFI%7Bt^D?bA>f2Ft_@|Cp{aY=#t?DXH4=1 zjF2d($*XxW_qK~uH-N(&Sn;M3sDW0tzQ=8<9i)IPF%aWA&ioK3kxM|oP3BPZssG4^ zw<|wR4(jq(x`5D^7LndY!Patz-ejSAz)>5m{DF5L&g53H+9+-PwlY8NIGD*7kMU~5 zpU(G-xG(*=4sndWXFbA%FViE=u4+{+6-yA+HH^Y21wmNp?xzK5unGq)();r-(7qZh zwnt+o5#8YGPa{KHN6fy&IOnD2x1*y+FN=vjq9pT3`cLdS-~PF|?p-Qla0@>*bku1sN zDI>4KO?=PNWbVq)6J0CgG}21zLwAKNnM**PFL!XL{bRZMGYg9u=yK2#U8m(VN(C)@ zLYC}i^h^4hrtM9)rqDc2pLJ=$VD84q?U;GuF(!acCSIcD+L;#H(OR#xKZ;pGxURMI z?{QMaBz6jxUVM&lP>E=T!XkFwZ9D9LF>ZqU(&rvlZ|Cf0vY9H#szQK zymng+dpuxvO%-i$&R*bVWc+xFtWvxo_&r!GYjx_XwHGh8{_L8^=34+-a+fE z)#}&O*-1xx_|9IuKV4g=ioHu&{vR{L|0ww;#p2+DXErXY#k!1jK+mL?AX_;=%&bEd zO%H;fJ@*N-_r~WM>fNAxg`Qz8@3A0a$(Ewvb490;Mw%>E!sVELYzsXQO|3M|c`8RZ zh)o&@C;`4l38xkCdQ122JZ}!G{_gMt5x^%%J-*UIylO&sAFJ&FCZHi(AZy?Y&R)D$eQ1^{B% z1d8JGdB28hFX8r+JxA{jyj1A3NI=+cMftwt4TVLCqlMrm*>jt@uPN%%4(z&Y?8 zwnYC(@2nU3L8?A1W$258)^e6VM+($U5{JFAIb0zU3*41f}=fg9X{gUtfoDwd3J zF}swz+RMEY!a^a4FEsI4YtCshf17h$q#XAfW0deD9BenHe>Izx>JKD8^2kn0Ktk;rnPKfsa66TXd+3&mPg zZ0nw|p{5tmIGOqN)B_{_j+!)vnw)5v_p)_M;F+?rWgg@s5?uvCb{G8L(vZS%j#a+? z&>Np>u#eqd+z4Sc?jPF74gNRzEy-uDf{5_Bv(0MsCb}-xZnMi3bN2}q4ye+ZZMVa_ zkq^kbhT^f~DS)*Z6VR+s6bHrp?_Q3W!^_1VvIN~>x`HYv11-VS-ld=#WwTf|@`*&r zndY!x@J#*a9oNy%r+yrCNhm3Cy3wj~&>6!ljzCQpZiIm9d$Zw)vCbHK&Gul&%CkCQ zzjU|Y4(-X-HKZgiztGK6vKXMYZ0m)*hT>t~)eeLmaa&qU59se~?WMI$V)m@auY<2rH;DRRS6>VHRb32;>) zwfY8EyIhiiYLcR3^Yxty5+2@7KTxibP0mUj!)hgDXdSWX4e~c!R?yFHZX~zZo{P^h ze8+vqF>Oil<0`5vA`x8dS79W_IOufL@Fq>8B`(W)YRr}cgx$qVqE!FlgU{^PpXY8T zt&>Jvm-U2LEC+6S{#^wAK@a6_zNcJ-+%t167}<@fnTRv2Ne;5|DiIt~bXJzz@zJip z%<@I;I6}m_PE9@&Hu{nqXpu{b&aNaLPLKfG8q#u&t7H32@d;t3mhiU|$oe8SIoU$% zAbZil3k`K;(F!{^(^dW_tVUDS+W%*jnA$6F%yhv;*fK*2-nO<-?<0!8_<@DS|G&UR zNM`PpdEqZ`(MrCF^@FzCtUVjdxy4s#yaIuuOqnd}$C1C#D{G#z2_+bj6C>E&gUw;U z`x#p1uL0s1B#B$4?vJlkT;)7=GIw15iyd~2cs{E7p^?ila*YWQjld7s0ZY&UDU@A! zCZhNYNKc=lmf<6hI-x+o#z&YOo8ShYhfYdFge1~&rJuK`_yWRa{7&quQKd(O4csOU zV!`s$LQ8#Qqa>V(?xd651-y<)OoS0FgpC8l!a7uCxmfS>&}HL+j-+`E*qB$Ul($1K zgpI;hXcIU1-;anUKW8*yW{%^7r`|G(-Vp~tFQn%n|7SB@6^6~b?};>w&O*cLqBk_Q z&Oqfkwb-FBT%{m_PGQ8hm!@!U(xn0=sp>$upL=NIsg_C1=v3_;waJ+xC`-rrjG`z7 z5eoA9lQOHU7@z@vU@1fIh(cCm;~v6^W_cNJmu9i2rrJ4MJ(Xru})+70xBMUYL=&5CWUSl^1Xj1;x3o7@&5#VqP zE(_mllJYkd>=K;mK*82|rbMXhg8#djtK1DI2^*ZzhBs+d53;g;0r~u*Ad=*{Js=(m z%jOAbPk0r!jR(iLUq;M?WUG}|e^K|tqBkP8PjH4-o{jXoBDG3ZK6(>8y{dd$j(r?0 zK*opzu617dbRr0Y=p=fGHKC{yu?m$kB8kb%ZG=pvh>m)^-+;K6YKCY{;KQE`!Xkem z$%h{Wm3q+i&L6;lVkH&f1GC-grn?BZd*hp)w9nuz_9%#f&goC}pYqPwO&*XZHMI+9 zJxOoe1zev=O4~H}E9YiZuqviqVyS`67)e+Q7)^nXc2K=bg#uI-NuLeB6D_RsP5V&e zEB5luq1ciy6e#UD%6qBtRdzXS&3C|W#WvPpfI4HJTGkAiLD8R9Dki+)Di`_R&@!_kFbAp(2{(i*D<-ha{*JVcN?Dui=DXw7Ck`KS}+CU=uT{Oxv&bPZF5KQ0txK z0CMSn)4a*Dq0-yC^F&vjTkscO`h*Ru;ctn`g3-xvollB2b(I!$CGJZMwJ13AHhH43 z$hCL0CU)qbAIhnTTZ%wy3#AUl)Sl+$zUWZ@KrD__zDkZ*{h4i491k zYcKhibG04^vVF;XKCoUoUy*w#Cs?eRQj@z!=Qj|*Rc53g)i5S+sA?7dau7=j->qkD z8Qi;~6z(y*rfzQr?yi+Y*cAx$`;uo64G~{4_)Ab4C|eto^}>~Y_5%9X=sNpd;Of^? zL)U{$KK`?S5D=@GYWPMwI_&c15yFl&=p+c^J3;MTrUqf9y zh8T&x+(~5~o0!}$>oF+v`S6q0&?^ra$l-U#L$Z4z4_9%B@>(@r2kWii0fV0@#i@)2 z#CH7zlKgbroQXXZWoD0*ceIu(*~>W>^!Wjw6&oGH^nY5jXN(+HGIlr2kb^_9?31&R zjcoVVXceM@q)CB1eVAjfnz?ug!GR#s-0FF}wY zvtrnpOyxgM&9K?ns*wPoDNkT^Oks1-q<1A| zchg*CsM#6amdv5vImjWyQa4kC@^!}g2cqlFO5%{&=$O$z1!@g3+@AtuJ7F{nh?THB-CFI-&T_jOBwy{HPgF zy9kr->1V>wwx)|WH3v>9`R#NUrm8ynV1yXP+p zPCk7OI_QU!j%B`i|0(^vok})}S({Bv!f6;`7B*%u!V|r^KB5Pcy`kMv8eTlcKk)O| zQSF7jEX8hz$DZIQJYETHjOxOVhc``_MwbZM@Z=YV!e4o-=77@4L9_ZS4`wV!%WrE% zG7TU|176x4xmVPLX&gT!*+2IGN++}ZM;x*2g zH)&j~YXASYK6s?51$Kq*Xl3q#;lwljz$xNv?NKECFpUTF8vXZ(Oz*$Np$kTX{I_Vk znLt2n2DiAVAfotDZQrrDBm|70^v3i~z56mGFOkcd7_NeQUnzD339AV?*^&aoD#$pW zFd|AU5ln04G^ukOZe7+|zTg{wNrjr~t_UUa;+X^i;6ku|szI*s%PbO+SO5vGCU;I#r!$acKTkOMa^N z$d6uIu8yd?UuJiv9wV+7{`^0ZM>0+aOU;~IonQi|+ncCw>h4XGkMWfB-au+MQtBZA zYjK=ynFCG~%Xuxd<*lrkQ_@dO2Oy4tJE-w#S1S^Ea^398%XcohPOybHwwm(3xVB8$ z?VLtcXYs<2Q!z|Rmh=Iw>>N4eF^od_#}oij zfaAEvG9wV=oPl*0<048AIcId@uGwD#obhuHcP&km`PjSQ+}0{YjEqORs=(tJ*(tCh zgHn|G{2z+z(kvs{KP|hn;0*!d=usmejy^UTGaldnO&}mbpt+#a7f$J~jN~eRfvy`b zt@$Ih6Df7%pRKeG2LOpnFoiyH(df- zvKY@9jVemrOu#`V&l0R6N;F#6tj&b456Au>3StCH?Zo$^TzcTOP) zj6U6Xq!HrsAcw10TBLlb3fYtUMWI4h+fgheSfal&8PigSxDko#s;ye-$shm{81s51NLCI- zkdC54U!iX?n0BG?_-`sx0#)dA;v&5 zpcBcGit#DX)yKq9CBVxIQVE?{Mh5hHv+v(BCT8VcSvl!3hMno`G^|b7^*=F*eH?%x zq&W~3JlJn+8aJK_4GA>Q5pWYX{K!c^I|TZi?%q zNN&$QNRY@|{U?a;G;NMMUQ?G+xVF!g?Ya=s@)C^>mVOp^ga`8@xTpcv7OiY}>+_M- zzh8xO2S|6q3j|W5P`D1n2nK?kBrIjD>uY1{e6HvC4>KrXjQZt%cYFl_;#32AzPVcq z?Wtzs?&Gug3cdJA#g>r3Lb7l|Q~P^wk>hG&>c_bR`_Y=(IU#L`{|R%Yg->h@|4=eF zy5Ia7|1c|sQsT7w>Rym4!kGzka+&-Aobg0=rlzUipn*EATPJXD*r3gIidBw?Bl%1D zpawVMZwk0t*k2s6dQJ=;MSZUyqY@GMA*WLFw}Gx|kjQWu;u20BS4CsU9M_N+qEDh1 z%V;@}jDWf8uk@0dk8T&OwmdbsJh%4wjsRk_rn6_+!TkNgnu+N{_g)JoRwKN%d60k2;{624ZLF?JHf(Du<=I`l?X3SJE)l)|+S_Oa5dWNjCFq=BoBSA52xELb? zB9hv%WLEzsQ1a{1LPa(JqW3K`Us^iCZFyTrk=1Yhr$A6gj{JX3T?aUo@B6pOmYF>w znaL)yviCR+%E;biuilWoXCWke?@g4fL^?R?aE{D4vdW6${~r4G`@6a>7tcG6=Y5|0 zzCYuB+l`w@4t6$o&NvC24S~{?*l;eSgP-rRK7f4@@nbvDoB_Y_7(C9JiAC)SR6=?1YXD|Bd(*C1KykBqkt}B zKOc-S)WZCdTTrIfm>Uy%SidOsJ1f`@F6cjN;bqB|%JTZApz=Lu0Mt%LRAAY=2c9LH z$?AT^$gW!Crf^5?Kzr*0lT@%KlQ2qMKkHqQ3{E=8`>s)5TY4O^&=IRILKVQ|M-^4e zk(P0s^bPZTx&?n*Qv5b{Teu3DtKkfH)HmwvbKev7uy_X&ofcwcAApPHp-{un9gj1{rrwxS)R8y4nUQsuKlw+ldulNuQ zi*FR46cGeWwA?X+I%`+IrGy}Wzhv4cO<}?~Q*fD&2OAVB%D@Fd3PG~N!sU{i_@q*! z+#LkMD*FL*Sg+seK}qFQsU_N4W(NcNQSoTP5vR%x@#xl*iFVruT20gMU=2g>crVC> zT-XiO1EI`CF%OL~?rbh3%)q8nB;?A#R5GJO{1rewga!;Ff~_Y#&p}#UaKnt&d^4nz zsh4lnExs_%u43iv{c|lt`5dWLHNYAYO~$FVY^guNCRk4Ud$F1Gcp$GILtrXQ`S!s& z4u%C5XJyQlrp~-Z@IW-n%kFOYO;=8F*x)JFm^rzA`!rUyfM4WXaa!=b+{q(ea83bp z^n+s=F64E1RrwzBH6g z<5%$yRYPnV3Op4m*NQV|Csp2)SG@)=0T$r+T06VY$>`A_K9yku3(=c7t6${!W_+lg*D-CrfN_oMx;rvC?UXwr-B zA(KxG%-hG~3(b{B9>jPSazRBeft*J1!$?j;lVRp`@B^$|_w&HT0kua!D%6iMJ78s8 zU%HNU%y-#>G zB8v$U);jlaET@!h`2oO#s=ukA6oz7KY=A#6i=z0)iS@u;d(_#VmI{WiD3z2>6h&D;EZ=5pI!U^`Rx62Z!L3Jp~Xfv4@rqgH6w<805@WB zochjkITTE=rSg6?*bp1!R}Vlm7(;%6E0KJY8}*P2@9R)dFLO!qqZW&8J^_g`ndZ+Z zyq4Z8PQ`ItD(jQpI?LHDE1YUwr6u4^t^eJ0sTC6T?m0-RY?_%&G2wvZSP3Cv;Xl%* zYFH#=2>eVFzTMNkQws+rojxxM?%XuJ4FwGAh_v6+w%K%EEvSgLD%xSH4$~KTd)}eh zBON5zO1omfGoKFXF&JeJ)Ersf39j5h>#na{`7r7#-N2q=xb{D>WkpU}+l)1dX=j{O zaN*!_Bz}b23NqIi;$lREAldi9HSm~X$1QPa! zSH4>@MlzgSY!9hCs#t?NTuZJf%_6u%>ua4m4-S_O?D|gw z9$JLo4C7*#Kb7ivQ58c4)kUuzDK=g0<{j-opJn?{eXofJ5*X(fzGiKGzSf^@Lz6+k zg2I!TR1u1wr4aLYAg1NmDjy*0a=U$%Q@g`qGlY8mWs5c&j|%X$V@71mtM#$JEZVWX z6nCh5HuG-J72lU}?TNQmI^KF$+ve_LLE@?j7Lxf@Z(d$h#((do2@aNa{$R7pXW7>e zfM|nADF9j}5|D00p!pPU%3h6!ZfPP~jkR6IP85-3xp}X>Sk=oy=2i%k@$c)79|m0% z8B4h#oze3=|_$d_vbWAIFuS znr%U%bcIvOCCsJw={MESxg>5Fk|u4{9BBi@Y7=hS!`0* znU%MV9vV&kj6PL1|F5k5ngy1%W^ywj6}0NM5#pHreOVAE(-I`%YAz|WG<%drvt4D2On(4`gZXI87G2Au^rTe{q`9d!?}drSGznoU$|Cd4 z$+lv0cO|MrPG%ETqRT+>Ff36k2@C@?s{WNB^v#>ka&rru!KxaC4+;?~j4~9zu!?3u z9U!6^uH&xOJ3+b`7|yKUkGRh+yeBUPvg8^nV6u|us}U~~9sm$|*0mQE#DL7>eMK-$ z-dTdqUgc_K6|D)Q!@~#@IuD-;$#W=CTAOL@%fbb1XyJ(Ro~h)M#5hWf#D(Bi-IHVC zz?-b0pP@lCdR(dQN0i^e$O;z-fLBTBn+~gFiDQ(}4i)4pX@-ZDoBpzhRH0hB)^;of zKrf_)KEhQ$YYd<+Vz}yb598epNDXtM4rc7oEsL=AKR~D=U zXPkVRpT%NoyCN({)&A^jXXf2Wm9y9dx3aj_yUA5uzA$qKe)RzrURj3Ui#lI18tTh9 zipkvpPtr+p>8c%4D7+W>`Jkp!7Ra$gzvH;V=RKkjr#zxU9;dhWNvfv*GyCwyY-MnJ zV}w|tubwR0lt=!;z_LQ=C$7Tu)IsFz^GD)esH7SN#0@ArSjS;RNsR&Yo;VNqX!dJ5 zYQ*K{qWm2c5astThV2%QS#E(4%5l(s=N<&=Txc17A%FrnFrF(n7Q?}lzEAG-ju4lG z`Q!i17kSLg-Pb;WJpO8wtSuHq>YB2sC_B<&lHLGwJF#3RuA!Y?nAFSZ4UuXASC)_d z8p6%82RdJ0S1S;%X@-S55ONhyzfsp<*ohzfk--BeTz({6iTG7q+N(rqlRaG`>P(eo zp>aVi3dI|D3(Ln-TDR(e;+n0ZMdV!fSWa8)`@h;^LJIcbp<5f_@T(WD^KJD9vdYKV zEu^%iS6tL>sk;T|zuIAeljfcfYz%jH9X)bs-wFX*GS(bf)dQow!r=L@HkftjCA@7I zwjbV7CudcZ$@qGa_)ZB<87cnefvRk-3=X`Hn9z`_`QI!wetNX$1k5b!4j0DVXZ3~ zNC8m+W?YD!FL%R;2apPo4>K!}o{zZNcx7@5jAz zlYsFTqoDPo2NWhoRPS2R$mh)YScz2YRpFIWMAW>he^c*u$!&lZCm4M&&2}e#&diPB z)~VUszHb1s$5F5GvN!(nfWmCcdz}~`kigUdtM%+yakh=%m)A4}7v7Sz;kL?C2J3^- z+t8x}e;fQT=sg9ZxI4f(&9<|i+=v*T5&burlR}ox-TS`T(cQQ1kn6G}LS~MKE8Vjc z6x|Kmue)&Z8IAF-YJ#@8-Gk3^emc!ChieURTKBs$IipQTZdeB=l`#*99CIrzvLj!x zwvcRq+V3xGRA+4#4t~3LBS(#>J5`o5$g4;5JhJF$=fsPDBOi4hHTshbQ^>OJ71_fpYUjCdx|J$W}C8_US?oq){| z+z}rR6=J}wY>Xn79}Wi2pK-Go!OQJ>`#p1raKjMie~^$-$9F5QQ56)^#^osiby_%? z$IiO`tSBg_T?o5o)#Y}9wNzlyW^mRq?Q3VXCLOrTyX zh$vtzxCVP(KlooYT1_bARO&pR3TfO?ZzsiI!U_x~{0j+1oM*14nsI^EasEcDrNb$C zJ7B;9(k7x+PPp()yFI+P_NUI^!e)WD^4On}2b72i6DwnaU2fC2OpMU>$fti$O-l{j zZr`~tw%cWf9E>@MV2dFH4`|k`4M6jyMw=mv)Oug55MmHp5|6z6ikK}-iX7nPuku87 zXL*cPC?LMcLY+OqV2Q~GDkUbSv=?z!;O3#neSDZa^1@1TIW|Bq90-1@)pw|bY6V77 z`dbW^Jr?#ENA|cZR9VJPukl%?QN^RJ?w*b8;O|H=)NTq0&M-!9Rj$rPBk-~+Sa>Ue z(RZc2%(66LVjd;qxsKmmkpq<5@^mT5K#8t(F!pWdQ0Lkb1Iw~{htX0xtpRT?otg7P zvGt_hx)g(Lnz9>x7D#l#;WYtjwNdkr+4E8_zkKx{X}3Dxckl7;Uw&z^o9{Z$kIap|**!Pw?m~4Wubi0T$$e31fO)N<(g4!A ze)1T_->CxDTWr>D?|EL)(#E5{Z`bSjnVQTx{?x?|jg_dA_X*N9U6A*?TQsTzR+YJ1D-Qp4<##SYEy6>Eu7;b>O~Vd3CtpajTFAA-c8A zp5mIo6es}f8|W6E+`QLBNB|9MCPAZOYE$nDuvjNBxh@|=l94xGkWbI+6yNp>709{+ zkbV+>da_OKI^f-luAhEpe;;kmqMxd2Kj2!1D-*gd6FtGa#Q*u8gp5N{4E7vrhJR@R zR2n{xB&n%nn5+pSf}T<~3{f^hj)b0zB@gt)?|*pex`iSyN@LO%&pDgKE(s%2w~bYg z@l^i-ru~EZybXuxs2m)Ur(<9Yl7Zo{eo|ALP1ICW)x?jp0C$jc|9ubwvxQ$6upihD23;!0_1#!9w5p~4oCbI4(x z#PN{Dl#qO&?_nHzixe2{G&8aB3v7;@Syb--67xhfdPqCr-p^ccG6btf8a*J!)>}w& z%q(A?8%AqIa~&MxS%FFl^EIe$;t+GCsQKOK`p85SS5Xqn!du6v$n-ch{_}%le>q$% ziLW)aaB&HEm0ghNm+qk1!QyN{||$rg23r)1^Q)zb?Tg=_~nk zy}K5p%xhJ9jH+l8TRPazy1rxK-jvrhRcjW=;l6&H>*wEvxjK09X!SV{;TmaA3`0{? zIYl7Gk6@ga+ekv`uq^G9+5w1T=*2-ID7g|YP-SrGK6=W(LY9n1!zZ1#Pbiff$qmF? ze=a~fZJtz?859$S+sS1q4TgF;S^TxO}w`a&agl8++UaVumSn*3l#3t^U)%O4jlvwA< zB(;9Q-SzDu{MzD7#muJ_uPbJ+_3JVi#8HuDGEhkt76;3rz*Q&l$}iZc;mC*I$<{X1 z^6%5VmVpGl(~nSKp*>#L9Bk1MAt7dVOk%5J7xeE5VpH|$>F9jN52nZ zN5>viZHwH(NIK2@2y@YHWhW!Tn%)>(S2h3#J_OH5V8wBQn-1UHbSRJNJd7s$7uUuQ z3=BUSVerp);_iSn{?zDV84HTq%?leXX=Cm1vyv;;W@E_U_L@9gdT6nY)+)Bqe|H^f zVs*TxCk|ExhRiasaV(OOPr_u*V8D~dD-n5T#A3C|`2?_+^I1Yo*Y-2k!u~Cb59Z=E z-#RhAu+uNN9pe@`u21t^#G~tM*FS*4W7~fZj7MJ-vQdQFOO>h}TwC?-7qJxNm@T7i z!63T#yA)1IzL?zF*M^T-3|p&pFYG(yF*Sr+h*m8d^IH~Y&j`#KY612Jca4tjcxdQp zrk29V!IN5!6xcBf4DryZX#m6zp(EfqJ5vzo3~E<55Kj;f8bZ?`(ME*yLpqFu(ieNO6iK$3O4i2XzK9PGw*^zrte%~c*nbO1A zacPp|fW{73Vkmu=HVQNG4s=aAe?22{lPudjMEa?xtFjgnhVhsvXLd|RCZG4DNw_}j z+(&suiC!Ty%9w!B8JK~=1>FB7z0dNqk8GJ^0Q-9rU2lYXmFHJs6-D#W7@sM|4a6aj zGEXcRU<}*U+szz9iyBqM}=Z z%$OmGI`Vp-5C9C-azE83EpuIVW^c`0?rU43v+^)!gI>CcOaW<0bToy=j*nZRvFwVPq+GQe`L{vg-o5sF&pcs$P z4hkX<%LW}0h8%WlO5Zj4zP%eIv@pAPQy;&F#aY<)Lt zmOOa(!M;}dks>2w2T#7e;H%phjSaY^Vm3E;BI115X8H%nZ*!Q(cVGW$f#3ucV9diW z(dqsD(RskToAbub6~R^qPof2sTEq28>QoHMS8XMz8xgMq6*$;RrmvZ+xB`bO^tKc1 zOZ;DeNV+G_`Ri-VVn>!lHPn@Ckq*7t#+{@^_61}Lz`JWJ0!>CAADCG{(mrfE9Qu1i zwS@CExF5~ve|aJsHT70!Y5%tadgxQ;oy72%R-8ckuBji5dDOfidGixi!OQIt^46ho ze-R*sZHX{S@!Oi8D$1ix%r$?V&V`{p3$%2MP(L3jW*8;u;~yY(JM@3_7@<>o6yJR( zWImX@3s^H@^+#p%|lnF2GG;dtLaqItd$MG%r82ck{j?D?P1d{`nxSKD|MX z6vlR}V9<-@WL1Q_Ig0$qxFytka38er(0I`%wUmpeXSf6@fj81H0S8Cc?sfjvfG#oloz zuKh;^_`=ij*@Ko_aGpq&O9U(@4u&ERC4O4|dH5s)t_?njG4MhB zZGIzd6#If3BnK>YjOV&J=$ecEi4YUwFL?Iv;;@w*HvR#dYBz}Kp>80)J=AEu>$dFF zRpVEQ2AbER)vxu8Zx;p|F3VTzOsGE-e`3-E|EgcGjx^07@l3tKH+L@j97s9r(Jzz_ ze4ghY#Ik%c>vf3kwuN|kCIkfC?)-`R86j#6a6+xqb(24({81UOeUetr$|M`4(2}a> zG1<;h&oXTD(WUa&p!E{n$7!%IhB5@8uwsy4_?+N69Bff zJiM-l+~9onk|10tL=^YC`!Vs4in`CK&t6_gGzN*QS3I-Tu=09yNDg&F@q>&l+(y6) zV<;Qm=pWP4gJ`GustnEk+HnXa&9p&KW08=eJ;sVu%)q_#!0C3USB7G>UL9fnYlt|_ zzCl`Jk+7ou34!)TF$3BHxGwlYjAj#o^B%t?T>?jiA*LxVpLuiCvFRqyAJHRPZ zTUO2QV)OJdb=B(7Kk83n6jbK!q<&tp%uq>^FHV5V?|GP5B1zX1>imf9?YE3)MGt|} zdm#K|?lh6*-N}Dp&?5Fr6oUM)9~}86qRYTe{S76F+qO%^H+C%)AobkPkuMu*iG1V` z_Vm_?Ltk#gzGW0h4;l7rhUL4Im^UE2a7HR?KS^Z)m19I z?r1Hq8UVxbd_ObTNddLfsJGdF`O#t-yw-cdFFleWxzjEa#O7xDsnI6yvj623Wc=sK z9V#CLrsyO7fYNGwNoM>;qPG-`>KJFoEwL7jjW?LlEALmyth0K=JHqtx5aRDGe#~kS z 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 XIqd3;sw`t1k<|2TPJ-QZ%whirDKY>| delta 29878 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 + @@ -258,6 +259,7 @@ + diff --git a/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters b/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters index 57f0cf1..8a4faae 100644 --- a/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters +++ b/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters @@ -219,6 +219,9 @@ Header Files\TPinballComponent + + Header Files + @@ -404,6 +407,9 @@ Source Files\TPinballComponent + + Source Files + diff --git a/SpaceCadetPinball/TFlipperEdge.cpp b/SpaceCadetPinball/TFlipperEdge.cpp new file mode 100644 index 0000000..a32f9d9 --- /dev/null +++ b/SpaceCadetPinball/TFlipperEdge.cpp @@ -0,0 +1,512 @@ +#include "pch.h" +#include "TFlipperEdge.h" + + +#include "TLine.h" +#include "TPinballTable.h" +#include "TTableLayer.h" + +float TFlipperEdge::flipper_sin_angle, TFlipperEdge::flipper_cos_angle; +vector_type TFlipperEdge::A1, TFlipperEdge::A2, TFlipperEdge::B1, TFlipperEdge::B2, TFlipperEdge::T1; +line_type TFlipperEdge::lineA, TFlipperEdge::lineB; +circle_type TFlipperEdge::circlebase, TFlipperEdge::circleT1; + +TFlipperEdge::TFlipperEdge(TCollisionComponent* collComp, char* someFlag, unsigned int visualFlag, TPinballTable* table, + vector_type* origin, vector_type* vecT, vector_type* vec3, float bmpCoef1, float bmpCoef2, + float a11, float c4F, float c5F): TEdgeSegment(collComp, someFlag, visualFlag) +{ + vector_type crossProd{}, vecDir1{}, vecDir2{}; + + CollisionC4F = c4F; + CollisionC5F = c5F; + BmpCoef1 = bmpCoef1; + BmpCoef2 = bmpCoef2; + Unknown32F = a11; + + T1Src = *vecT; + Unknown36V = *vec3; + RotOrigin.X = origin->X; + RotOrigin.Y = origin->Y; + + CirclebaseRadius = origin->Z + table->CollisionCompOffset; + CirclebaseRadiusMSq = CirclebaseRadius * 1.01f * (CirclebaseRadius * 1.01f); + CirclebaseRadiusSq = CirclebaseRadius * CirclebaseRadius; + + CircleT1Radius = vecT->Z + table->CollisionCompOffset; + CircleT1RadiusMSq = CircleT1Radius * 1.01f * (CircleT1Radius * 1.01f); + CircleT1RadiusSq = CircleT1Radius * CircleT1Radius; + + vecDir1.X = vecT->X - origin->X; + vecDir1.Y = vecT->Y - origin->Y; + vecDir1.Z = 0.0; + maths::normalize_2d(&vecDir1); + + vecDir2.X = vec3->X - origin->X; + vecDir2.Y = vec3->Y - origin->Y; + vecDir2.Z = 0.0; + maths::normalize_2d(&vecDir2); + + AngleMax = acos(maths::DotProduct(&vecDir1, &vecDir2)); + maths::cross(&vecDir1, &vecDir2, &crossProd); + if (crossProd.Z < 0.0) + AngleMax = -AngleMax; + FlipperFlag = 0; + Angle1 = 0.0; + + auto dirX1 = vecDir1.X; + auto dirY1 = -vecDir1.Y; + A2Src.X = dirY1 * CirclebaseRadius + origin->X; + A2Src.Y = dirX1 * CirclebaseRadius + origin->Y; + A1Src.X = dirY1 * CircleT1Radius + vecT->X; + A1Src.Y = dirX1 * CircleT1Radius + vecT->Y; + + dirX1 = -dirX1; + dirY1 = -dirY1; + B1Src.X = dirY1 * CirclebaseRadius + origin->X; + B1Src.Y = dirX1 * CirclebaseRadius + origin->Y; + B2Src.X = dirY1 * CircleT1Radius + vecT->X; + B2Src.Y = dirX1 * CircleT1Radius + vecT->Y; + + if (AngleMax < 0.0) + { + maths::vswap(&A1Src, &B1Src); + maths::vswap(&A2Src, &B2Src); + } + + auto dx = vecT->X - RotOrigin.X; + auto dy = vecT->Y - RotOrigin.Y; + auto distance1 = sqrt(dy * dy + dx * dx) + table->CollisionCompOffset + vecT->Z; + DistanceDivSq = distance1 * distance1; + + float bmpCoef = min(BmpCoef1, BmpCoef2); + auto distance = maths::Distance(vecT, vec3); + Unknown40F = bmpCoef / (distance / CircleT1Radius + distance / CircleT1Radius); + + TFlipperEdge::place_in_grid(); + Unknown44 = 0; + TimeAngle = 0.0; + Unknown15 = 0; + Unknown46F = 0.0; + AngleMult = 0.0; +} + +void TFlipperEdge::port_draw() +{ + set_control_points(TimeAngle); + build_edges_in_motion(); +} + +float TFlipperEdge::FindCollisionDistance(ray_type* ray) +{ + auto ogRay = ray; + + + float* pfVar2; + short uVar3; + int iVar4; + int uVar5; + vector_type* prVar6; + vector_type* plVar6; + vector_type* pvVar7; + float fVar8; + ray_type ray2; + ray_type ray1; + float local_1c; + float local_18; + float local_14; + float local_10; + float local_c; + float local_8; + + if (ogRay->TimeNow > this->Unknown46F) { + this->FlipperFlag = 0; + } + if (this->Unknown44 == 0) { + if (this->FlipperFlag == 0) { + this->Unknown44 = 0; + this->Unknown15 = 0; + this->Unknown16 = 0; + set_control_points( ogRay->TimeNow); + build_edges_in_motion(); + iVar4 = is_ball_inside( (ogRay->Origin).X, (ogRay->Origin).Y); + ray1.MinDistance = ogRay->MinDistance; + if (iVar4 == 0) { + ray1.Direction.X = (ogRay->Direction).X; + ray1.Direction.Y = (ogRay->Direction).Y; + ray1.Direction.Z = (ogRay->Direction).Z; + ray1.MaxDistance = ogRay->MaxDistance; + ray1.Origin.X = (ogRay->Origin).X; + ray1.Origin.Y = (ogRay->Origin).Y; + ray1.Origin.Z = (ogRay->Origin).Z; + fVar8 = maths::distance_to_flipper(&ray1, &ray2); + plVar6 = &ray2.Origin; + if (fVar8 == 0.0) { + pvVar7 = &this->NextBallPosition; + pvVar7->X = ray2.Origin.X; + (this->NextBallPosition).Y = ray2.Origin.Y; + (this->NextBallPosition).Z = ray2.Origin.Z; + pvVar7->X = pvVar7->X - ray1.Direction.X * 1e-05f; + pfVar2 = &(this->NextBallPosition).Y; + *pfVar2 = *pfVar2 - ray1.Direction.Y * 1e-05f; + } + else { + pvVar7 = &this->NextBallPosition; + LAB_0101bab7: + pvVar7->X = (plVar6)->X; + pvVar7->Y = (plVar6)->Y; + pvVar7->Z = (plVar6)->Z; + } + (this->CollisionDirection).X = ray2.Direction.X; + (this->CollisionDirection).Y = ray2.Direction.Y; + (this->CollisionDirection).Z = ray2.Direction.Z; + return fVar8; + } + fVar8 = maths::Distance_Squared(ogRay->Origin, this->RotOrigin); + if (this->CirclebaseRadiusMSq <= fVar8) { + fVar8 = maths::Distance_Squared(ogRay->Origin, T1); + if (this->CircleT1RadiusMSq <= fVar8) { + ray1.Direction.Y = lineB.PerpendicularL.Y; + ray1.Direction.X = lineB.PerpendicularL.X; + if (iVar4 == 4) { + ray1.Direction.Y = lineA.PerpendicularL.Y; + ray1.Direction.X = lineA.PerpendicularL.X; + } + ray1.Direction.X = -ray1.Direction.X; + ray1.Direction.Y = -ray1.Direction.Y; + } + else { + ray1.Direction.X = T1.X - (ogRay->Origin).X; + ray1.Direction.Y = T1.Y - (ogRay->Origin).Y; + maths::normalize_2d(&ray1.Direction); + } + } + else { + ray1.Direction.X = (this->RotOrigin).X - (ogRay->Origin).X; + ray1.Direction.Y = (this->RotOrigin).Y - (ogRay->Origin).Y; + maths::normalize_2d(&ray1.Direction); + } + ray1.Origin.X = (ogRay->Origin).X - ray1.Direction.X * 5.0f; + ray1.Origin.Y = (ogRay->Origin).Y - ray1.Direction.Y * 5.0f; + ray1.MaxDistance = ogRay->MaxDistance + 10.0f; + fVar8 = maths::distance_to_flipper(&ray1, &ray2); + if (1e+09 <= fVar8) { + ray1.Direction.X = (this->RotOrigin).X - (ogRay->Origin).X; + ray1.Direction.Y = (this->RotOrigin).Y - (ogRay->Origin).Y; + maths::normalize_2d(&ray1.Direction); + ray1.Origin.X = (ogRay->Origin).X - ray1.Direction.X * 5.0f; + ray1.Origin.Y = (ogRay->Origin).Y - ray1.Direction.Y * 5.0f; + fVar8 = maths::distance_to_flipper(&ray1, &ray2); + if (1e+09 <= fVar8) { + return 1e+09; + } + } + LAB_0101ba1a: + (this->NextBallPosition).X = ray2.Origin.X; + (this->NextBallPosition).Y = ray2.Origin.Y; + (this->NextBallPosition).Z = ray2.Origin.Z; + pvVar7 = &this->CollisionDirection; + prVar6 = &ray2.Direction; + LAB_0101bc82: + pvVar7->X = prVar6->X; + pvVar7->Y = prVar6->Y; + pvVar7->Z = prVar6->Z; + (this->NextBallPosition).X = (this->NextBallPosition).X - ray1.Direction.X * 1e-05; + pfVar2 = &(this->NextBallPosition).Y; + *pfVar2 = *pfVar2 - ray1.Direction.Y * 1e-05; + return 0.0; + } + local_8 = (ogRay->Origin).X; + local_14 = this->Unknown40F * ogRay->MaxDistance; + local_c = (ogRay->Origin).Y; + local_10 = ogRay->TimeNow; + local_18 = this->Unknown40F * (ogRay->Direction).X; + local_1c = (ogRay->Direction).Y * this->Unknown40F; + fVar8 = ogRay->TimeDelta + ogRay->TimeNow; + uVar3 = fVar8 <= local_10;// fp flag shift + while (uVar3 == 0) { + set_control_points( local_10); + build_edges_in_motion(); + iVar4 = is_ball_inside( local_8, local_c); + if (iVar4 != 0) { + if ((this->FlipperFlag == 1) && (iVar4 != 5)) { + plVar6 = &lineA.PerpendicularL; + ray1.Direction.Y = lineA.PerpendicularL.Y; + ray1.Direction.X = lineA.PerpendicularL.X; + } + else { + if ((this->FlipperFlag != 2) || (iVar4 == 4)) { + ray1.Direction.X = (this->RotOrigin).X - local_8; + this->Unknown15 = 0; + this->Unknown16 = 1; + ray1.Direction.Y = (this->RotOrigin).Y - local_c; + maths::normalize_2d(&ray1.Direction); + ray1.Origin.X = local_8 - ray1.Direction.X * 5.0f; + ray1.Origin.Y = local_c - ray1.Direction.Y * 5.0f; + ray1.MaxDistance = ogRay->MaxDistance + 10.0f; + fVar8 = maths::distance_to_flipper(&ray1, &ray2); + if (1e+09 <= fVar8) { + (this->NextBallPosition).X = local_8; + (this->CollisionDirection).X = -ray1.Direction.X; + (this->NextBallPosition).Y = local_c; + (this->CollisionDirection).Y = -ray1.Direction.Y; + return 0.0; + } + goto LAB_0101ba1a; + } + plVar6 = &lineB.PerpendicularL; + ray1.Direction.Y = lineB.PerpendicularL.Y; + ray1.Direction.X = lineB.PerpendicularL.X; + } + ray1.Direction.X = -ray1.Direction.X; + ray1.Direction.Y = -ray1.Direction.Y; + (this->Unknown17V).X = plVar6->X; + (this->Unknown17V).Y = plVar6->Y; + (this->Unknown17V).Z = plVar6->Z; + this->Unknown16 = 0; + this->Unknown15 = 1; + ray1.MinDistance = 0.002; + ray1.Origin.X = (ogRay->Origin).X - ray1.Direction.X * 5.0f; + ray1.Origin.Y = (ogRay->Origin).Y - ray1.Direction.Y * 5.0f; + ray1.MaxDistance = ogRay->MaxDistance + 10.0f; + fVar8 = maths::distance_to_flipper(&ray1, &ray2); + (this->CollisionDirection).X = ray2.Direction.X; + (this->CollisionDirection).Y = ray2.Direction.Y; + (this->CollisionDirection).Z = ray2.Direction.Z; + if (1e+09 <= fVar8) { + return 1e+09; + } + pvVar7 = &this->NextBallPosition; + prVar6 = &ray2.Origin; + goto LAB_0101bc82; + } + ray1.Direction.X = (ogRay->Direction).X; + ray1.Direction.Y = (ogRay->Direction).Y; + ray1.Direction.Z = (ogRay->Direction).Z; + ray1.MinDistance = ogRay->MinDistance; + ray1.Origin.X = (ogRay->Origin).X; + ray1.Origin.Y = (ogRay->Origin).Y; + ray1.Origin.Z = (ogRay->Origin).Z; + ray1.MaxDistance = local_14; + fVar8 = maths::distance_to_flipper(&ray1, &ray2); + if (fVar8 < 1e+09) { + pvVar7 = &this->NextBallPosition; + pvVar7->X = ray2.Origin.X; + (this->NextBallPosition).Y = ray2.Origin.Y; + (this->NextBallPosition).Z = ray2.Origin.Z; + pvVar7->X = pvVar7->X - ray1.Direction.X * 1e-05f; + pfVar2 = &(this->NextBallPosition).Y; + *pfVar2 = *pfVar2 - ray1.Direction.Y * 1e-05f; + uVar5 = this->AngleMax > 0.0; + pvVar7 = &this->Unknown17V; + if (this->FlipperFlag == 2) { + plVar6 = &lineB.PerpendicularL; + this->Unknown15 = (uVar5 == 0); + } + else { + this->Unknown15 = uVar5; + plVar6 = &lineA.PerpendicularL; + } + goto LAB_0101bab7; + } + local_10 = local_10 + this->Unknown40F; + local_8 = local_8 + local_18; + local_c = local_c + local_1c; + fVar8 = ogRay->TimeDelta + ogRay->TimeNow; + uVar3 = fVar8 <= local_10; + } + } + else { + this->Unknown44 = 0; + } + return 1e+09; +} + +void TFlipperEdge::EdgeCollision(TBall* ball, float coef) +{ + Unknown44 = 1; + if (!FlipperFlag || !Unknown16 || Unknown15) + { + float collMult = 0.0; + if (Unknown15) + { + float dx = NextBallPosition.X - RotOrigin.X; + float dy = NextBallPosition.Y - RotOrigin.Y; + float distance = dy * dy + dx * dx; + if (circlebase.RadiusSq * 1.01 < distance) + { + float v11; + float v20 = sqrt(distance / DistanceDivSq) * (fabs(AngleMax) / AngleMult); + float dot1 = maths::DotProduct(&Unknown17V, &CollisionDirection); + if (dot1 >= 0.0) + v11 = dot1 * v20; + else + v11 = 0.0; + collMult = v11 * Unknown32F; + } + } + + float maxSpeed = collMult <= 0.0 ? 1000000000.0f : -1.0f; + maths::basic_collision( + ball, + &NextBallPosition, + &CollisionDirection, + CollisionC4F, + CollisionC5F, + maxSpeed, + collMult); + return; + } + + float c4F; + float dx = NextBallPosition.X - RotOrigin.X; + float dy = NextBallPosition.Y - RotOrigin.Y; + float distance = dy * dy + dx * dx; + if (circlebase.RadiusSq * 1.01 < distance) + c4F = (1.0f - sqrt(distance / DistanceDivSq)) * CollisionC4F; + else + c4F = CollisionC4F; + maths::basic_collision(ball, &NextBallPosition, &CollisionDirection, c4F, CollisionC5F, 1000000000.0, 0.0); +} + +void TFlipperEdge::place_in_grid() +{ + float x0 = RotOrigin.X - CirclebaseRadius; + float y0 = RotOrigin.Y - CirclebaseRadius; + float x1 = CirclebaseRadius + RotOrigin.X; + + float v1 = RotOrigin.Y + CirclebaseRadius; + float v2 = T1Src.X - CircleT1Radius; + if (v2 < x0) + x0 = v2; + + float v3 = T1Src.Y - CircleT1Radius; + if (v3 < y0) + y0 = v3; + + float v4 = CircleT1Radius + T1Src.X; + if (v4 > x1) + x1 = v4; + + float v5 = T1Src.Y + CircleT1Radius; + if (v5 > v1) + v1 = v5; + + float v6 = Unknown36V.X - CircleT1Radius; + if (v6 < x0) + x0 = v6; + + float v7 = Unknown36V.Y - CircleT1Radius; + if (v7 < y0) + y0 = v7; + + float v8 = Unknown36V.X + CircleT1Radius; + if (v8 > x1) + x1 = v8; + + float v9 = CircleT1Radius + Unknown36V.Y; + if (v9 > v1) + v1 = v9; + + float y1 = v1; + TTableLayer::edges_insert_square(y0, x0, y1, x1, this, nullptr); +} + +void TFlipperEdge::set_control_points(float timeNow) +{ + maths::SinCos(flipper_angle(timeNow), &flipper_sin_angle, &flipper_cos_angle); + A1 = A1Src; + A2 = A2Src; + B1 = B1Src; + B2 = B2Src; + T1 = T1Src; + maths::RotatePt(&A1, flipper_sin_angle, flipper_cos_angle, &RotOrigin); + maths::RotatePt(&A2, flipper_sin_angle, flipper_cos_angle, &RotOrigin); + maths::RotatePt(&T1, flipper_sin_angle, flipper_cos_angle, &RotOrigin); + maths::RotatePt(&B1, flipper_sin_angle, flipper_cos_angle, &RotOrigin); + maths::RotatePt(&B2, flipper_sin_angle, flipper_cos_angle, &RotOrigin); +} + +void TFlipperEdge::build_edges_in_motion() +{ + maths::line_init(&lineA, A1.X, A1.Y, A2.X, A2.Y); + maths::line_init(&lineB, B1.X, B1.Y, B2.X, B2.Y); + circlebase.RadiusSq = CirclebaseRadiusSq; + circlebase.Center.X = RotOrigin.X; + circlebase.Center.Y = RotOrigin.Y; + circleT1.RadiusSq = CircleT1RadiusSq; + circleT1.Center.X = T1.X; + circleT1.Center.Y = T1.Y; +} + +float TFlipperEdge::flipper_angle(float timeNow) +{ + if (!FlipperFlag) + return Angle1; + float angle = (Angle1 - Angle2) / AngleMax * AngleMult; + if (angle < 0.0) + angle = -angle; + + if (angle >= 0.0000001) + angle = (timeNow - TimeAngle) / angle; + else + angle = 1.0; + + angle = min(1, max(angle, 0)); + if (FlipperFlag == 2) + angle = 1.0f - angle; + return angle * AngleMax; +} + +int TFlipperEdge::is_ball_inside(float x, float y) +{ + vector_type ptTest{}; + float dx = RotOrigin.X - x; + float dy = RotOrigin.Y - y; + if ((A2.X - A1.X) * (y - A1.Y) - (A2.Y - A1.Y) * (x - A1.X) >= 0.0 && + (B1.X - A2.X) * (y - A2.Y) - (B1.Y - A2.Y) * (x - A2.X) >= 0.0 && + (B2.X - B1.X) * (y - B1.Y) - (B2.Y - B1.Y) * (x - B1.X) >= 0.0 && + (A1.X - B2.X) * (y - B2.Y) - (A1.Y - B2.Y) * (x - B2.X) >= 0.0 || + dy * dy + dx * dx <= CirclebaseRadiusSq || + (T1.Y - y) * (T1.Y - y) + (T1.X - x) * (T1.X - x) < CircleT1RadiusSq) + { + if (FlipperFlag == 1) + ptTest = AngleMax < 0.0 ? B1 : B2; + else if (FlipperFlag == 2) + ptTest = AngleMax < 0.0 ? A2 : A1; + else + ptTest = T1; + + if ((y - ptTest.Y) * (RotOrigin.X - ptTest.X) - + (x - ptTest.X) * (RotOrigin.Y - ptTest.Y) >= 0.0f) + return 4; + return 5; + } + return 0; +} + +void TFlipperEdge::SetMotion(int code, float value) +{ + switch (code) + { + case 1: + this->Angle2 = flipper_angle(value); + this->Angle1 = this->AngleMax; + this->AngleMult = this->BmpCoef1; + break; + case 2: + this->Angle2 = flipper_angle(value); + this->Angle1 = 0.0; + this->AngleMult = this->BmpCoef2; + break; + case 1024: + this->FlipperFlag = 0; + this->Angle1 = 0.0; + return; + default: break; + } + + if (!this->FlipperFlag) + this->TimeAngle = value; + this->FlipperFlag = code; + this->Unknown46F = this->AngleMult + this->TimeAngle; +} diff --git a/SpaceCadetPinball/TFlipperEdge.h b/SpaceCadetPinball/TFlipperEdge.h new file mode 100644 index 0000000..c19f366 --- /dev/null +++ b/SpaceCadetPinball/TFlipperEdge.h @@ -0,0 +1,61 @@ +#pragma once +#include "maths.h" +#include "TEdgeSegment.h" + +class TPinballTable; + +class TFlipperEdge : public TEdgeSegment +{ +public: + TFlipperEdge(TCollisionComponent* collComp, char* someFlag, unsigned int visualFlag, TPinballTable* table, + vector_type* origin, vector_type* vecT, vector_type* vec3, float bmpCoef1, float bmpCoef2, float a11, + float c4F, float c5F); + void port_draw() override; + float FindCollisionDistance(ray_type* ray) override; + void EdgeCollision(TBall* ball, float coef) override; + void place_in_grid() override; + void set_control_points(float timeNow); + void build_edges_in_motion(); + float flipper_angle(float timeNow); + int is_ball_inside(float x, float y); + void SetMotion(int code, float value); + + int FlipperFlag; + float CollisionC4F; + float CollisionC5F; + vector_type RotOrigin; + float CirclebaseRadius; + float CircleT1Radius; + float CirclebaseRadiusSq; + float CircleT1RadiusSq; + float CirclebaseRadiusMSq; + float CircleT1RadiusMSq; + float AngleMax; + float Angle2; + float Angle1; + int Unknown15; + int Unknown16; + vector_type Unknown17V; + vector_type A1Src; + vector_type A2Src; + vector_type B1Src; + vector_type B2Src; + float Unknown32F; + vector_type T1Src; + vector_type Unknown36V; + float DistanceDivSq; + float Unknown40F; + vector_type CollisionDirection; + int Unknown44; + float TimeAngle; + float Unknown46F; + float AngleMult; + float BmpCoef1; + float BmpCoef2; + vector_type NextBallPosition; + + static float flipper_sin_angle, flipper_cos_angle; + static vector_type A1, A2, B1, B2, T1; + static line_type lineA, lineB; + static circle_type circlebase, circleT1; +}; diff --git a/SpaceCadetPinball/maths.cpp b/SpaceCadetPinball/maths.cpp index 3591832..0623913 100644 --- a/SpaceCadetPinball/maths.cpp +++ b/SpaceCadetPinball/maths.cpp @@ -268,7 +268,8 @@ void maths::vector_add(vector_type* vec1Dst, vector_type* vec2) vec1Dst->Y += vec2->Y; } -float maths::basic_collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float a4, float a5, float maxSpeed, +float maths::basic_collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float a4, float a5, + float maxSpeed, float multiplier) { ball->Position.X = nextPosition->X; @@ -304,3 +305,41 @@ float maths::Distance_Squared(vector_type vec1, vector_type vec2) { return (vec1.Y - vec2.Y) * (vec1.Y - vec2.Y) + (vec1.X - vec2.X) * (vec1.X - vec2.X); } + +float maths::DotProduct(vector_type* vec1, vector_type* vec2) +{ + return vec1->Y * vec2->Y + vec1->X * vec2->X; +} + +void maths::vswap(vector_type* vec1, vector_type* vec2) +{ + vector_type tmp = *vec1; + *vec1 = *vec2; + *vec2 = tmp; +} + +float maths::Distance(vector_type* vec1, vector_type* vec2) +{ + auto dx = vec1->X - vec2->X; + auto dy = vec1->Y - vec2->Y; + return sqrt(dy * dy + dx * dx); +} + +void maths::SinCos(float angle, float* sinOut, float* cosOut) +{ + *sinOut = sin(angle); + *cosOut = cos(angle); +} + +void maths::RotatePt(vector_type* point, float sin, float cos, vector_type* origin) +{ + auto dirX = point->X - origin->X; + auto dirY = point->Y - origin->Y; + point->X = dirX * cos - dirY * sin + origin->X; + point->Y = dirX * sin + dirY * cos + origin->Y; +} + +float maths::distance_to_flipper(ray_type* ray1, ray_type* ray2) +{ + return 0; +} diff --git a/SpaceCadetPinball/maths.h b/SpaceCadetPinball/maths.h index a1fd4a1..092cfdd 100644 --- a/SpaceCadetPinball/maths.h +++ b/SpaceCadetPinball/maths.h @@ -62,4 +62,10 @@ public: static float basic_collision(TBall* ball, vector_type* nextPosition, vector_type* direction, float a4, float a5, float maxSpeed, float multiplier); static float Distance_Squared(vector_type vec1, vector_type vec2); + static float DotProduct(vector_type* vec1, vector_type* vec2); + static void vswap(vector_type* vec1, vector_type* vec2); + static float Distance(vector_type* vec1, vector_type* vec2); + static void SinCos(float angle, float* sinOut, float* cosOut); + static void RotatePt(vector_type* point, float sin, float cos, vector_type* origin); + static float distance_to_flipper(ray_type* ray1, ray_type* ray2); };