From e7da9b7ac12eb2fe6429fc127af5c8a45f5c9715 Mon Sep 17 00:00:00 2001 From: BRNSystems <70092437+BRNSystems@users.noreply.github.com> Date: Sun, 28 Mar 2021 20:09:20 +0200 Subject: [PATCH] Initial commit --- Sounds.py | 17 + assets/maps/map0 | 14 + assets/sounds/click.wav | Bin 0 -> 11308 bytes assets/sounds/collision.wav | Bin 0 -> 14748 bytes assets/textures/backround/bg-blue.png | Bin 0 -> 587 bytes assets/textures/backround/bg.png | Bin 0 -> 582 bytes assets/textures/backround/circle_arena.png | Bin 0 -> 43940 bytes assets/textures/game/p1_pointer.png | Bin 0 -> 275 bytes assets/textures/game/p2_pointer.png | Bin 0 -> 274 bytes assets/textures/game/player.png | Bin 0 -> 131 bytes assets/textures/game/solid.png | Bin 0 -> 123 bytes assets/textures/icon.png | Bin 0 -> 209 bytes assets/textures/menu/change_btn.png | Bin 0 -> 548 bytes assets/textures/menu/change_btn_pressed.png | Bin 0 -> 569 bytes assets/textures/menu/dash.png | Bin 0 -> 1853 bytes assets/textures/menu/esc.png | Bin 0 -> 1594 bytes assets/textures/menu/ice.png | Bin 0 -> 1900 bytes assets/textures/menu/main_menu.png | Bin 0 -> 15046 bytes assets/textures/menu/menu_button.png | Bin 0 -> 568 bytes assets/textures/menu/menu_button_pressed.png | Bin 0 -> 548 bytes assets/textures/menu/play_button.png | Bin 0 -> 3061 bytes assets/textures/menu/play_button_pressed.png | Bin 0 -> 3095 bytes assets/textures/menu/settings.png | Bin 0 -> 18408 bytes assets/textures/menu/settings_btn.png | Bin 0 -> 1083 bytes assets/textures/menu/settings_btn_pressed.png | Bin 0 -> 1487 bytes assets/textures/menu/template_for_text.png | Bin 0 -> 771 bytes assets/textures/menu/wave.png | Bin 0 -> 2032 bytes epic_sumo1.py | 638 +++++++++++++++++ epic_sumo2.py | 640 ++++++++++++++++++ ingame_funcs.py | 100 +++ s_engine.py | 479 +++++++++++++ server.py | 54 ++ spark.py | 108 +++ 33 files changed, 2050 insertions(+) create mode 100644 Sounds.py create mode 100644 assets/maps/map0 create mode 100644 assets/sounds/click.wav create mode 100644 assets/sounds/collision.wav create mode 100644 assets/textures/backround/bg-blue.png create mode 100644 assets/textures/backround/bg.png create mode 100644 assets/textures/backround/circle_arena.png create mode 100644 assets/textures/game/p1_pointer.png create mode 100644 assets/textures/game/p2_pointer.png create mode 100644 assets/textures/game/player.png create mode 100644 assets/textures/game/solid.png create mode 100644 assets/textures/icon.png create mode 100644 assets/textures/menu/change_btn.png create mode 100644 assets/textures/menu/change_btn_pressed.png create mode 100644 assets/textures/menu/dash.png create mode 100644 assets/textures/menu/esc.png create mode 100644 assets/textures/menu/ice.png create mode 100644 assets/textures/menu/main_menu.png create mode 100644 assets/textures/menu/menu_button.png create mode 100644 assets/textures/menu/menu_button_pressed.png create mode 100644 assets/textures/menu/play_button.png create mode 100644 assets/textures/menu/play_button_pressed.png create mode 100644 assets/textures/menu/settings.png create mode 100644 assets/textures/menu/settings_btn.png create mode 100644 assets/textures/menu/settings_btn_pressed.png create mode 100644 assets/textures/menu/template_for_text.png create mode 100644 assets/textures/menu/wave.png create mode 100644 epic_sumo1.py create mode 100644 epic_sumo2.py create mode 100644 ingame_funcs.py create mode 100644 s_engine.py create mode 100644 server.py create mode 100644 spark.py diff --git a/Sounds.py b/Sounds.py new file mode 100644 index 0000000..bb26277 --- /dev/null +++ b/Sounds.py @@ -0,0 +1,17 @@ +import pygame +from pygame.locals import * + +# basic config + +pygame.mixer.pre_init(48000, -16, 2, 512) +pygame.init() +pygame.mixer.set_num_channels(16) + + +def get_sounds(): + sounds = { + "click": pygame.mixer.Sound("assets/sounds/click.wav"), + "collision": pygame.mixer.Sound("assets/sounds/collision.wav") + } + + return sounds diff --git a/assets/maps/map0 b/assets/maps/map0 new file mode 100644 index 0000000..ea189fb --- /dev/null +++ b/assets/maps/map0 @@ -0,0 +1,14 @@ +000001111111000000 +000011000001100000 +000110000000110000 +001100000000011000 +001000000000001000 +001000000000001000 +001000000000001000 +001000000000001000 +001000000000001000 +001000000000001000 +001100000000011000 +000110000000110000 +000011000001100000 +000001111111000000 \ No newline at end of file diff --git a/assets/sounds/click.wav b/assets/sounds/click.wav new file mode 100644 index 0000000000000000000000000000000000000000..fb11fcd4804b731c8db73f5b9d9a6fdb13fdbad3 GIT binary patch literal 11308 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 R5|{uOJYD@<);T3K0RZxi_RatR literal 0 HcmV?d00001 diff --git a/assets/textures/backround/bg.png b/assets/textures/backround/bg.png new file mode 100644 index 0000000000000000000000000000000000000000..31a031f9d6d28bae71e0ff37755a1c9fe62910eb GIT binary patch literal 582 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 literal 0 HcmV?d00001 diff --git a/assets/textures/game/p2_pointer.png b/assets/textures/game/p2_pointer.png new file mode 100644 index 0000000000000000000000000000000000000000..ccb062f367657f0306f5d062a5fc21295af227c5 GIT binary patch literal 274 zcmeAS@N?(olHy`uVBq!ia0vp^k|4~%1|*NXY)uAIjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85qP=L734qNaX`iaJi?8V~B_M-D|6bnhgY6AL=&QX>heJTDPii zm6iy<7ta@;YlWWQQVjnX^Bk{bHmvM8@u^;K?WONab0^%ldD(S!eW3XLchf7J+xMRq zwz3u0*Qoq(-+!(4F$YhUsZNm`T8*0ok2tBZ7*3FM4C`>3z`AJSKiQI_hc3Lj<)$dc zFjG*w!H0u+K~4*6fLIXI0+k@H1;I literal 0 HcmV?d00001 diff --git a/assets/textures/game/player.png b/assets/textures/game/player.png new file mode 100644 index 0000000000000000000000000000000000000000..ffa991b2ec8187dc92d6ee3930e8054a2084510a GIT binary patch literal 131 zcmeAS@N?(olHy`uVBq!ia0vp^%plCc1|-8Yw(bW~jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85qP=L734qNaX`iP{Py2F+?IfIVBVM%xNb!1@J z*w6hZkrl}2EbxddW?&Fg1z|?dAe9e5K><$}#}J9|WQL~yK0H9cz{bbOw6RjL7AVKy M>FVdQ&MBb@0GX&6A^-pY literal 0 HcmV?d00001 diff --git a/assets/textures/icon.png b/assets/textures/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..14f3226fb5c497f3955fa2d4306f54e896c58b52 GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1SJ1Ryj={W7>k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O`0h7I;J!Gcbs$f-s|Jkje+3V4A0kV~B_M+p{})4;b*UIEpR`n7Z3a{oTQz zuMEE)WDhvd@+6nzy6yYUm1&L)-33fDPG_=j2z_GNuu$qMLzt8b^NfsQi39)DH!{rA zox=3Pl|(>|Px#1ZP1_K>z@;j|==^1poj532;bRa{vGqB>(^xB>_oNB=7(L0l7&;K~!i%?UGS$ zgfI*Rxn9rN9<nF+YU@zKWE?KYz+g&Mj z!7R3{EpjqQ*mjZ@+0Wb*4UKIiN%ms>V=mcf*cOsx8C#-Uvd3f3mc#|y3rynYVed?m zEpwnUm+TqX+mdAOI9#7gc3o|`<3hG;_Ln##( z#4aj{_fykBXHDYkWA~QCdpK}bM@p%<9rg@Kyn*dUR9Q;J-LY3m;#J-jt6)}&9)>+q z63?+zqwh;n_h9V7lK4MmsxM1YHxBlGN&Ld1bvZL8whOtQnyEP0_rH@I4oYlOOHv)I mV_VCmBG^T2FbIOrFipQB@`TJM0Dq?d0000=G`P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGqB>(^xB>_oNB=7(L0nSN8K~!i%?bgXn z1TheW;f7p@gcCVH8U#TakOLoQPYv~ou`H4oFM9VL|&S@jw^y_ z)DhWhsyL1wf=qLcsH&OL02OvzA7IgnBV{m8F-LJhB;trvH3b}%1d*U4s%oYdLFXL> z4?!kzM@n{{GmfeQEYfpCQkr9qmV!vz5v^->IokY$tJyfBs%EMOwBdLq_}^+$KHl#; zw&tF;V^_^Rw$De$!!hOfoyik$L|&TOj=W(1CwuIFPs$in$#H#vMZ=EBOjF!ZYJf$P zj+8d2pd%wV%}1>|B0bG@M^!#b#*q>SU2(h;6y&3X9g(2sgrm&>i&Pw`b8WCWwMMQaNZ$!QF26H#?3SSoj?}aEVb!00000NkvXX Hu0mjf>*(&+ literal 0 HcmV?d00001 diff --git a/assets/textures/menu/dash.png b/assets/textures/menu/dash.png new file mode 100644 index 0000000000000000000000000000000000000000..90a819f4b39dc6cf21b26096af01ab78ae46ffd5 GIT binary patch literal 1853 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 literal 0 HcmV?d00001 diff --git a/assets/textures/menu/ice.png b/assets/textures/menu/ice.png new file mode 100644 index 0000000000000000000000000000000000000000..9c08033d20e845acbae231a3552ed276144ea139 GIT binary patch literal 1900 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 Z^v-(uLCq|G+x3doVvN#GH(X)NjV)J7XXJ$i7 z>xB1t<;%XimPXeV-d3%=cc(2;V%LXXpT33vvw9Kx?&X zrppHW+;t~?@w3=SPPc=*HwpDLm8YtTUcHv0EwmH|A$s-QDK7)AdsC+-i0skUzPX|@ z_MP>DPog_>njVEe*(6%kl>VvI|BKl7PqD>cH0(d!HsCo7M#pRR)O*!Qe9@cKU$tnv z#f0Xt7o2`i*Kl^lPkGF@q9*p;=D^R>d{`DgXyRGA=oXlmmGgArxlL#A6RwM{Ky|P# zexN(^gxlF@BflJ=9Yl%k&Smu96xp!$@Fj9o}whdDxRVtdQ~h%Lul!=R6YJuAi?7rH|3&ANJXIA zG+w>KPvS`0*7153o;9a*Ve{>tx8 zo2LEI1%dGmHWjVkeG+bMuX~{)%n06%!eRJ64 z*O~i-_ex~C;Eb1*by7KNC!aKR-2Hk9??lxL2XA&}rNktCcThvhe{-aU=mu4xAL3gwG@Pc=1U>-sf! z_s(fIK3XYq_j*?=ng^WV+RC!)`1R#L3z#@rgg8_LKoPG%yZl!*Jc{+W?(2_7JuLT>HlNpKB<#4_cZ?E zmpuFbmS?`#W{#W`&MoWxJhM&gE=;siT_tGVb?5=7m7SexddCcf#3wAhQuBq3T#&r~ zrkO>}LqbO5?TX5nM=Y+P&vrR)V9EMs$`!M4ox|B{ZZq%eCoi}(S@Y-RJpPcn(^KZK eHQY6+W&F$9x_!c?cM`w=VeoYIb6Mw<&;$Tvk=~L3 literal 0 HcmV?d00001 diff --git a/assets/textures/menu/play_button.png b/assets/textures/menu/play_button.png new file mode 100644 index 0000000000000000000000000000000000000000..5cf17d225827802f842689fa798065e125c7fda1 GIT binary patch literal 3061 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGqB>(^xB>_oNB=7(L3yMiZK~#8N?VY`E zR7V%aPf|isSi)Kx$wDaF#v*b^Ea8e`8weC{{s6xPG)a$XL7@fuybToi4@in6rg1?9 z5+PWiG^+?%matcjl8Rx~3SaR|CwTBdLnh{#1tb^caXjrsvU>ah14|72prYLFytx zC{4Q_LP8OuubdDgRLR(J2`QhLqI*;W&~vtmj3`8e#7WtG)93FQi&0&Lh<*_vVeq91 z6Jpfn4$Ekd#7>?2Cvxsakr6vAA@NdW|Mcs7A1y@0Y#fZ@ZA=S{9tmT6kHC1fr7m=pZl)gK$YCo^z*7bsm#K`!%rh2mS z`E^-1-ATSMWPcz7*^!-tZFx0#AzNF0=_h|>Pgi>L-^jHyGtx;puYvl_op(RT1NB?g zq0VvfJGpkMqs}q;Diw8q_C;R5yCthz$yb(i=Wffl=hN?rX0X2@uixC4)xG2kTc(y( zo46=5>UUCqNk8+yewLL#){`&H@ZN?4;-Vq+jEqo1v~<&6h%~yvo?eiJ>8o<%!d2#gX-ul-jy5EMM9*}|E42XF5Fgk+l8)N zI-h+{H2OJQ`ONKCv=BX5x;ktVnZKm}?#x-M``@O>o?>J`Z&3+Ra_kk|DU>j2QR+=4 z-x)BcqK!fh-g}6^EKwcy+H`UZGb3j$?!^&(d4G@`<}v-1gXnc-`SYvUA~eRvyVW4~ zzbPr2rqN>LcU0-h*;C13D3mDOSb8YSMx78lufc(1&f`GuGpxhlv|5aeLfomdY78w46(KExas-{%hPbG{97Cp@XHxSVeUpPv3;8o*kkGxTeus zF*19Y9!=uCb$Rf74U3QpJ7cWobx;0NWbW>+$HFo#E3nO%qcz4I?9fSWV&> z&#QQXUhO7_Ib>Gvz&S-s&)jIG7@3VMRhq;*@;her(ByiuRs`PtP<>P0=)s6C>{<3uF=xWappc5CRjD+!QM|^BR~4I1v?T z_TH=5uK*wAeGOPNnDnTCs-Pm|EbBJG$fy9!B>r7qn0N(qUqN$l@=~n0%xh%XM_N?0 zB|D{*_chpT?D4b^np5O)mUWv`G)?Qo$TZ9iVG{Q`kQB-5?d<<+Oy)I`%A`jRNLA5K zd0zv~#y<3oplwg=7s1-l6u?BM!EPli49hJ=WfOok9m#Ezj57I%vVJXj>Kkx0mJhm*tVx=nnsCH+~&33 z1Nttu+B+wb7!r$ljm*C(xE5%xk*|uH0x9t?oWtizl||E2G)=1_Bhv>8nZ&tsffA;A zvV2+Z0iFE0fTBnu7W29|l>ufXLnU{QK(n#)VR{w@rfE4qCh_iX84a^5T`fY359P_y zO)MhP0O5ZW<~8DdCCff?DYLvk1e=YW#bEP$?|T$6MH@je$^@L4IDK>2m`;A~${j62 z(|~XsqEedTJ#b<$uMzJ{FNQ_phce6iBcR#XX?U7tZAu$bG)-f~NDF{pz=?^z*hgpa zMqpkeI~^iX5sbg`{t&Cwu$)D(ZKgGmk@4sPnZ%yZ5z#Zyhp61VMkY9-QIQ7Q!N6O2 zUjuL9azv;_u>J?p`oc6Vi%(_&^V*%k<|8FU_=sD%c?~W5FzdL;TqA$weGRxb_8}Fe zXPUO8Xc~%92G}fVd-SW7A3t9nzVg_lnOAFGBO8pFFNQ6ZG}ivrFo65U=N4iiW)kh zHE(@jXzC_Jt}snY12l;rtHz=mO#0`RtUObnm-l5=rDFC1G)9HyHTG7F8UcBNz=T%f z4T@13NJA}qZ)rtk<~6#wHz{UbcEdF71o3RoF-aBYg-mcP z5ntu~sY~)j;k^uJUNc2YhhlUbu*zb#=d}l_Ft3qiAB9Ff_PMtS%=+=QU^a5|THlX0 zQfn~^GQvRSwc(!E9w^_u#@?WMVv~JKuy?5WDeqTpUXyeh9U0k-Ff^}6U~f>hc=b>g z(Bf4;6}2kOYo=(~Fio4F-sW}ob|%H22lL}@3^u{hS5!0v+1E(nUQvtNyl!iXrlA;3 zP;c|vh4D%i6ctstc+`oC&1;fPZN*5B=H98bdF=^gUu%WyCi^ErHd*sf-mlQS4$@{D zL}Mc(t8ll@=Cvb-X$dsJQAI_$FAT5(+tt? zg-`ac46pxf;OpP|QJ$*b$z=EpT=t^g8eU`WGkzOpuWM3FEq8h>ii|kQkeEOs`KGj4 z7Y(6jL`cPO@Eie)Q5c`boLJ6-5Hg8t-)vlD#8HOC1P4zXrfGy!2nWw2C`N>kD5#Yf zG2|t6g6-7|BQc8o<}&0Zb)re_)rU4PO(TRv!GstgO3l!dkYd`@PmpUxw8bhis^Ugd z1WA)c;|C`yFj z)H#Yb?e8YnIk2oU){Sp6q;Nl{E800000NkvXXu0mjf D568P5 literal 0 HcmV?d00001 diff --git a/assets/textures/menu/play_button_pressed.png b/assets/textures/menu/play_button_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..0342ef6f45639cd512cf2b25048657ba720cfb40 GIT binary patch literal 3095 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 literal 0 HcmV?d00001 diff --git a/assets/textures/menu/settings.png b/assets/textures/menu/settings.png new file mode 100644 index 0000000000000000000000000000000000000000..327e03e72b63c01d461834d295f9c8adf51ae39e GIT binary patch literal 18408 zcmeIacT|&G*XWBC6@k4)5vd|gr7B$@QBe>PP!TDiN-v?;K)?p*rYQ(WR|7<(Ng$yH z1f+xr7+MGcLWj^o=ph8|!+ziIp7);fjXTc2_nyrd86B9By+I;92k#2Jr0t$uId}($oJ0UW`S5t2d^L)&&&Kv6YqfgvH71#biQJDmhHLW?Nu3x*u!kU_3mW@BH7q(oWzxXP&mbQQ%W=><&4fD zwmEU}?#E4++1RrF5%P~t{!gco zokvLadIvX~ajv!TanoG!|G1WIefYVgoggr6jDB2XWRt7^2rF<8%15RyXNR-GLc)VJ z_DoB;y}H5sdv2MhOJv9EW$Z|?i<2WXRA%$-jx*s8SZk{j;4S&-I1r`c38R}hO@nyU zR=gNVOc0obr$vJgdvoRJu6Cc%@zUQ3>rM`H?yV~xSk~23Y2ygVsCv4$FnbXP!7rbW;wmzc>f?w5m8Fr1}=#BI2=irLTzWp)w@ zH$$Xt`p}O4V7%7$ykfVGap>L}?rN_g49PNv82KCv0$^<4Ufdz1c+(bt`18T*wbQed zyyS{O&v~W#B5NmVL-7S(A9Gj7;tFG-95}h9ngpK;VPttin6k>{sM_DbJ zC7MMV@pUcJ%89_V4Z}*=#*QK;ixptTsLOuwC$l5pI$IW&yzs0D#6_1%4vFu@^BCFJ zKts%7B26q>TX*V`$h{r2uDKkdf24ThSLk)$>0bTG z#SA0S25^{Shc)S!Pr%7qjqB0+ABT##3VmHQiA$O@< zya;I?XiAz7Yo9sm?v)rqdf zG5PauI>Z0&BlZvCZA$s%l+8#-th?U2e30AV$iZ@Q)Y7l^C1K zzi-IMF$jYVYxyYe4lzpkF}oOjY1DITgG$b|A~ugp!d{UC@_R0jgDZm7vNcw2K6m=eS;z*4Qh zVr|JqR*-s4m+J4M>7Hb5Z{AbU$-6t#FFA&l@x6oJs^_=(!}|Mbp{ba12bABVHnuVG z@n8rr)BGu5`4yV9`+$*Xp?dz`+RYC^xBgKsv!E#q=XS}9D*r|bn{NuV&Tf6$Y0|(| zFSp(fv;)@zRkoI=^08$~3VH$liRz`=jx?(iAi}rb-j)lk+t34>(k~%PuDQjDI)w~` z>`M{|4Le1*9{+2F%sc&!*WtENGxr6EOKl|M7AFrKjwr6h}$E{MpEuPf9@ z##sgPS)qPRZ{ZJrx7M6G1>DUA*z7U`GW}DbW>pMY5ePLMU8|H<&hCX;+Ac5$96ReB z`K;cz=7W14ljVxddS>vn)MH~u$KM?&^_Z)UWx%c7GY92}J2aH}pjF(YmHivi#RYL$ z?{%D!XO2mZ!rMg-8mAg&sVAkFkXWmKNX=Yr>R@c%y3XxCVbZ0KA`Cg&Dajzy@AMvY zNbd@2ByziQHV18E(E(!6e>vVrhNKN??gkRZN(*}i6IHdULWd&GX{TJTv>N)NJfy~c zM8V#_4^ZPR-lx3QC+ck>#a8?}V5wi(;RX?(d(`-pL6-ojh=NYIxYo{sJ+6(^CVZ!G zH@|0Gb&3{VJ2$-nm`Y)9)ul(m!#1>L#Ilj&xjn�KYI9w6ClFfD3Hk!t>4+M2P~7 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 literal 0 HcmV?d00001 diff --git a/assets/textures/menu/template_for_text.png b/assets/textures/menu/template_for_text.png new file mode 100644 index 0000000000000000000000000000000000000000..034176778a743615c3fd4a4f93b265fdac292b8e GIT binary patch literal 771 zcmeAS@N?(olHy`uVBq!ia0y~yU`hnCmvb-y$!j}h<^U5jgR z3=A9lx&I`x0{NT;9+AZi3}UJv%;*`U@&RbX3{Mxwkczmsw>JtlJMb_ZY`;-@LFDU2 zk6WxXBZ_yq88>li_qknRA`cvky|b!GRMYp+;Zt>7jkW_ zBt`YzMP{q1p z@H<@kH$bvGwLN00bBAQE;$4mdnulPsJ3>Cn$f%s{nu|{BOu$ z@kWaPfI>DF;Q>qquVE57W_?zINJN1nhol-y83hGYEt$K0zep67F_ zdD1u=7&!M|C@pncc_d6r$Xgkf`gm;c=FrN}gic4{=}s^Y{i0kqll%Md{yTa2OUNk# zUI7dZVdh$dcwb9LGtPFZ)ftW4%fo(RdZL-lw!Y$Hb=$kmKAe5sI~3D{L|fV0YYn`Zk(Hx_g%2Iw33{pUs>h35;@7;bzbbd*I+hb z#o@_iPYIqo81bc85S!D&SW|DmWZ*?hzJ)Feq3NM5qRkCMMSPOqWno{+98=N@(oTWO zBpj;?xZ)3^CnUre!O%aV>%KzWXMM{dJ#-N|F00uX*wsc*U69Mi&)%QBqa9D>7@ow?Uyc@T4QMiWf}& zLYU3KjXqI&Rwq^tI<)(_aZCAMhZ3DM#`8;2i#Cbrv_ge8UOPpy77c1^x1Llf5li0Hh1U zF_TR=!ItS1qe7s3t0rhd%9f|P9$B+6Pw=~p5cc|UEo24C^p|dqdDK{iPhpK=u>Z?> z%?uMow&Zw{%yOV2qPXpy!4^dN6iL-WSJTorc6En*hLaNAyO;B8Yy@$)hpcCUtZ{dG zsiT1WIu-w71yGOE4^>@(I$fmec!erOo)GEBV>9FB?|1CN!6F|CC@Z-^Ki9xA4m8PV zxac%n8g1_{GeWq8xR!}XFRAa;8GzZH&a?0>m7UeuTJ{Y<@*~1c_B?V4G91Bw2n#R|#S8#e zTOSf;)*ju2T++^6lAUUY1Q|?9`s{^%+)~^N%I_+!*N#mwkK*TEJw1Jw5OY z&2VbHtt7(0eHA@5#{k2O9T*Hc5xeI-9dS*SFJaH2RZ3$1xjCo9&IPSn75t`SMOiw$ zy}zZqp!JVa2hr7_v4w1lg<(0mxq(&Lto}FHMr?g)YjB_48w97YzAL{l9(usfir^}N zm~;R;hC7A`6D9iTs!?X9R`J0P-4%i|0SGUVnMG{1!57Yn>kP;QmTL z6`Sw#p#x$$A-vEi^;8=?lbF;7*)h9Gz}n)Z{G_qca#rp@+_3AwLT0~xcf8Dy!ewVl z^x)tKk7kn@-UQLvH4Xii?_t2RX|f|s55&o12NGDhrsuRPyk|_$73(_3nGH9!{R#+i zdqacX6ldycu9Oa&4lkO1_Y;kDs)S(PAiZIYVNS%^aSo0Lj`yBJ9>tByZV~62x4hDB zHiq@Z-0g7~ZsE4Tn6siyT zaz3If2Z}T;KNod6CT{EW*a6qi&9O)|R)!NLyP|wJ^|0PnNQycv85}}MAjs*a;0*~R zAN|rvxjQLrSsez>}Z6;Z;fwB{qP&a8R+>dcKpLs7|rro2Mynhymir)Fs0PIOGO!M*3 G%>MzRy1~`} literal 0 HcmV?d00001 diff --git a/epic_sumo1.py b/epic_sumo1.py new file mode 100644 index 0000000..350b421 --- /dev/null +++ b/epic_sumo1.py @@ -0,0 +1,638 @@ +from s_engine import * +from spark import * +from ingame_funcs import * +import pygame +import sys +import time +import random +import math +from pygame.locals import * +import json +import threading +import asyncio +import websockets + +# basic config +work = True + +pygame.mixer.pre_init(48000, -16, 2, 512) +pygame.init() +pygame.mixer.set_num_channels(16) + +font = pygame.font.SysFont('Comic Sans MS', 80) +small_font = pygame.font.SysFont('Comic Sans MS', 40) +tiny_font = pygame.font.SysFont('Comic Sans MS', 20) + +players_defined = 0 +connected = 0 +global Player1 +global Player2 +uri = "ws://brn.systems:8765" +global websocket + +async def write_players(arrx): + global Player1 + global Player2 + Player2.all_ids = arrx[0] + Player2.dir_movement = arrx[1] + Player2.direction = arrx[2] + Player2.ids_to_remove = arrx[3] + Player2.memory = arrx[4] + Player2.move.angle_speed = arrx[5] + Player2.move.backwards = arrx[6] + Player2.move.collisions = arrx[7] + Player2.move.degree = arrx[8] + Player2.move.force = arrx[9] + Player2.move.forward = arrx[10] + Player2.move.half_pi = arrx[11] + Player2.move.left = arrx[12] + Player2.move.offset = arrx[13] + Player2.move.pi = arrx[14] + Player2.move.right = arrx[15] + Player2.move.speed = arrx[16] + Player2.move.three_halves_pi = arrx[17] + Player2.move.two_pi = arrx[18] + Player2.move.vectors = arrx[19] + Player2.movement = arrx[20] + Player2.moving = arrx[21] + Player2.object_id = arrx[22] + Player2.object_pos = arrx[23] + Player2.rect.bottom = arrx[24] + Player2.rect.bottomleft = arrx[25] + Player2.rect.bottomright = arrx[26] + Player2.rect.center = arrx[27] + Player2.rect.centerx = arrx[28] + Player2.rect.centery = arrx[29] + Player2.rect.h = arrx[30] + Player2.rect.height = arrx[31] + Player2.rect.left = arrx[32] + Player2.rect.midbottom = arrx[33] + Player2.rect.midleft = arrx[34] + Player2.rect.midright = arrx[35] + Player2.rect.midtop = arrx[36] + Player2.rect.right = arrx[37] + Player2.rect.size = arrx[38] + Player2.rect.top = arrx[39] + Player2.rect.topleft = arrx[40] + Player2.rect.topright = arrx[41] + Player2.rect.w = arrx[42] + Player2.rect.width = arrx[43] + Player2.rect.x = arrx[44] + Player2.rect.y = arrx[45] + Player2.size = arrx[46] + Player2.special = arrx[47] + Player2.specific.attribute = arrx[48] + Player2.specific.attribute_0 = arrx[49] + Player2.specific.attribute_1 = arrx[50] + Player2.specific.attribute_2 = arrx[51] + Player2.specific.boolean_attribute = arrx[52] + Player2.specific.color_r = arrx[53] + Player2.specific.fixed = arrx[54] + Player2.specific.flip = arrx[55] + Player2.specific.height = arrx[56] + Player2.specific.object_id = arrx[57] + Player2.specific.power = arrx[58] + Player2.specific.scroll = arrx[59] + Player2.specific.stage = arrx[60] + Player2.type = arrx[61] + +async def hello(): + global websocket + global connected + websocket = await websockets.connect(uri) + connected = 1 + while True: + greeting = await websocket.recv() + try: + if players_defined == 1: + data = json.loads(greeting)[1]["data"] + if len(data) == 62: + await write_players(data) + except Exception as e: + print(str(e)) + + +loop = asyncio.get_event_loop() + + +def helloa(): + loop.run_until_complete(hello()) + loop.run_forever() + + +t = threading.Thread(target=helloa, args=tuple()) +t.start() + +while connected == 0: + pass + +Window_size = [900, 600] +screen = pygame.display.set_mode(Window_size) +display = pygame.Surface((1350, 900)) +pygame.display.set_caption("Epic_sumo") +pygame.display.set_icon(pygame.image.load("assets/textures/icon.png").convert()) +clock = pygame.time.Clock() + + +class Bg: + active = [] + timer = 0 + + bgs = { + "first": pygame.image.load("assets/textures/backround/bg.png").convert(), + "second": pygame.image.load("assets/textures/backround/bg-blue.png").convert() + } + bgs["first"].set_colorkey((255, 255, 255)) + bgs["second"].set_colorkey((255, 255, 255)) + + def __init__(self, pos, speed, typeX): + self.object_pos = pos + self.speed = speed + self.type = typeX + + @classmethod + def generate(cls, amount, cord_lim=None): + if cord_lim is None: + cord_lim = [0, 1350] + for i in range(amount): + cls.active.append(Bg([random.randint(cord_lim[0], cord_lim[1]), random.randint(0, 860)], + random.randint(2, 10), random.choice(("first", "second")))) + + @classmethod + def blit_them(cls, display): + for circle in cls.active: + display.blit(cls.bgs[circle.type], circle.object_pos) + + @classmethod + def remove_circle(cls, which): + cls.active.remove(which) + + @classmethod + def central(cls, display): + for circle in cls.active: + circle.move() + + cls.blit_them(display) + + if cls.timer == 0: + cls.generate(12, [1350, 1500]) + cls.timer += 60 + else: + cls.timer -= 1 + + def move(self): + self.object_pos[0] -= self.speed + if self.object_pos[0] < -80: + self.remove_circle(self) + + +class Solids: + def __init__(self): + self.stage = 0 + self.colors = [ + (73, 122, 67), + (127, 182, 120), + (181, 230, 29) + ] + + def draw(self, solid, display, scroll): + cc = (self.stage // 40) % 3 + current_stage = self.stage % 40 + mid_point = [ + solid.object_pos[0] + (solid.size[0] / 2), + solid.object_pos[1] + (solid.size[1] / 2) + ] + + pygame.draw.rect(display, self.colors[cc], pygame.Rect(mid_point[0] - current_stage - scroll.scroll[0], + mid_point[1] - current_stage - scroll.scroll[1], + current_stage * 2, current_stage * 2)) + + def draw_solids(self, objects, display, scroll): + for obj in objects.game_objects: + if obj.type == "solid": + self.draw(obj, display, scroll) + self.stage += 1 + + +def menu(screenX, fs): + def mouse_check(mouse_pos, menu_flow): + + new_list = [0, 0, menu_flow[2], menu_flow[3], 0, 0] + + # settings + if 800 < mouse_pos[0] < 872: + if 500 < mouse_pos[1] < 572: + new_list[0] = 1 + + # play + if 300 < mouse_pos[0] < 591: + if 300 < mouse_pos[1] < 396: + new_list[1] = 1 + + # change player 1 + if 250 < mouse_pos[0] < 359: + if 500 < mouse_pos[1] < 548: + new_list[4] = 1 + + # change player 2 + if 400 < mouse_pos[0] < 509: + if 500 < mouse_pos[1] < 548: + new_list[5] = 1 + + return new_list + + # preparations + + game = Game() + game.game_flow["menu"] = [0, 0, 0, 0, 0, 0] + game.game_flow["sounds"] = get_sounds() + settings_on_top = False + display = pygame.Surface((900, 600)) + + abilities = { + "1.player": "dash", + "2.player": "dash", + "1.storage": 5, + "2.storage": 5 + } + + menu_textures = { + "bg": pygame.image.load("assets/textures/menu/main_menu.png").convert(), + "play": pygame.image.load("assets/textures/menu/play_button.png").convert(), + "play_pressed": pygame.image.load("assets/textures/menu/play_button_pressed.png").convert(), + "settings": pygame.image.load("assets/textures/menu/settings_btn.png").convert(), + "settings_pressed": pygame.image.load("assets/textures/menu/settings_btn_pressed.png").convert(), + "change": pygame.image.load("assets/textures/menu/change_btn.png").convert(), + "change_pressed": pygame.image.load("assets/textures/menu/change_btn_pressed.png").convert(), + "dash": pygame.image.load("assets/textures/menu/dash.png").convert(), + "shockwave": pygame.image.load("assets/textures/menu/wave.png").convert(), + "ice": pygame.image.load("assets/textures/menu/ice.png").convert(), + "settings_menu": pygame.image.load("assets/textures/menu/settings.png").convert() + } + + # game loop + while game.alive: + display.blit(menu_textures["bg"], [0, 0]) + + # event loop + + for event in pygame.event.get(): + if event.type == QUIT: + pygame.quit() + sys.exit() + + if event.type == pygame.MOUSEBUTTONDOWN: + mousepos = pygame.mouse.get_pos() + game.game_flow["menu"] = mouse_check(mousepos, game.game_flow["menu"]) + + # setting actions for buttons + if settings_on_top is False: + if game.game_flow["menu"][1]: + game.game_flow["sounds"]["click"].play(0) + arena(screenX, fs, abilities) + + elif game.game_flow["menu"][4]: + game.game_flow["menu"][2] += 1 + if game.game_flow["menu"][2] > 2: + game.game_flow["menu"][2] = 0 + + game.game_flow["sounds"]["click"].play(0) + + elif game.game_flow["menu"][5]: + game.game_flow["menu"][3] += 1 + if game.game_flow["menu"][3] > 2: + game.game_flow["menu"][3] = 0 + + game.game_flow["sounds"]["click"].play(0) + + # settings menu + + if game.game_flow["menu"][0]: + settings_on_top = not settings_on_top + game.game_flow["sounds"]["click"].play(0) + + if event.type == pygame.MOUSEMOTION: + # if mouse moving get mouse pos + mousepos = pygame.mouse.get_pos() + # function that checks if mouse is above any button and changes image, color of that image + game.game_flow["menu"] = mouse_check(mousepos, game.game_flow["menu"]) + + if event.type == KEYDOWN: + if event.key == K_f: + fs = not fs + if fs is False: + screenX = pygame.display.set_mode(Window_size) + else: + screenX = pygame.display.set_mode(Window_size, pygame.FULLSCREEN) + + elif event.key == K_ESCAPE: + if settings_on_top is False: + pygame.quit() + sys.exit() + else: + settings_on_top = not settings_on_top + + # making menu + + if game.game_flow["menu"][1]: + display.blit(menu_textures["play_pressed"], [300, 300]) + else: + display.blit(menu_textures["play"], [300, 300]) + + # showing ability of 1.player + if game.game_flow["menu"][2] == 0: + display.blit(menu_textures["dash"], [100, 400]) + abilities["1.player"] = "dash" + abilities["1.storage"] = 10 + elif game.game_flow["menu"][2] == 1: + display.blit(menu_textures["shockwave"], [100, 400]) + abilities["1.player"] = "wave" + abilities["1.storage"] = 8 + elif game.game_flow["menu"][2] == 2: + display.blit(menu_textures["ice"], [100, 400]) + abilities["1.player"] = "ice" + abilities["1.storage"] = 10 + + # showing ability of 2.player + if game.game_flow["menu"][3] == 0: + display.blit(menu_textures["dash"], [500, 400]) + abilities["2.player"] = "dash" + abilities["2.storage"] = 10 + elif game.game_flow["menu"][3] == 1: + display.blit(menu_textures["shockwave"], [500, 400]) + abilities["2.player"] = "wave" + abilities["2.storage"] = 8 + elif game.game_flow["menu"][3] == 2: + display.blit(menu_textures["ice"], [500, 400]) + abilities["2.player"] = "ice" + abilities["2.storage"] = 10 + + if game.game_flow["menu"][4] == 0: + display.blit(menu_textures["change"], [250, 500]) + elif game.game_flow["menu"][4] == 1: + display.blit(menu_textures["change_pressed"], [250, 500]) + + if game.game_flow["menu"][5] == 0: + display.blit(menu_textures["change"], [400, 500]) + elif game.game_flow["menu"][5] == 1: + display.blit(menu_textures["change_pressed"], [400, 500]) + + if settings_on_top: + display.blit(menu_textures["settings_menu"], [0, 0]) + + if game.game_flow["menu"][0]: + display.blit(menu_textures["settings_pressed"], [800, 500]) + else: + display.blit(menu_textures["settings"], [800, 500]) + + # basic loop config + + screenX.blit(display, (0, 0)) + pygame.display.update() + clock.tick(60) + + +def arena(screenX, fs, abilities): + global Player1 + global Player2 + global players_defined + ids = Id() + images_dictionary = {"solid": pygame.image.load("assets/textures/game/solid.png").convert(), + "circle": pygame.image.load("assets/textures/backround/circle_arena.png").convert()} + images_dictionary["circle"].set_colorkey((0, 0, 0)) + images_dictionary["solid"].set_colorkey((0, 0, 0)) + game = Game() + game.game_flow["collision_timer"] = 0 + game.game_flow["boost"] = 0.9 + game.game_flow["speed_timer"] = 0 + game.game_flow["winner"] = "na" + game.game_flow["inputs"] = True + game.game_flow["sounds"] = get_sounds() + + new_parameters = [1350, 900] + display = pygame.Surface((1350, 900)) + + # background + + bg = Bg + bg.generate(100) + + # solids + + solids = Solids() + + # loading map + + mapX = load_map("assets/maps/map0") + + # loading objects + + objects = Objects() + + # loading bg circle + + midpoint = [816, 672] + circle = Object("circle", game.custom_id_giver, [192, 0], [0, 0], 0, False, [1248, 1344]) + sort(circle, objects) + game.custom_id_giver += 1 + + # loading from map + + load_objects(mapX, 96, 96, objects, game) + + # players + + # never set direction to 0 + Player1 = Object("player", game.custom_id_giver, [800, 800], [0, 0], + round(math.tau * 0.75, 2), True, [10, 10], True) + Player1.specific.images.append(pygame.image.load("assets/textures/game/player.png").convert()) + Player1.specific.images[0].set_colorkey((0, 0, 0)) + Player1.move.collisions = True # enables collisions for player + Player1.move.speed = 0.5 # increasing speed so ur not super slow + Player1.move.angle_speed = 0.1 + + # simulating movement so u dont start at speed 0 + Player1.dir_movement = Player1.move.set_start_dir_movement(Player1.direction, Player1.dir_movement) + + # sorts player + sort(Player1, objects) + # moves to next id + game.custom_id_giver += 1 + + # player 2 + + # never set direction to 0 + Player2 = Object("player", game.custom_id_giver, [800, 400], [0, 0], round(math.pi/2, 2), True, [10, 10], True) + Player2.specific.images.append(pygame.image.load("assets/textures/game/player.png").convert()) + Player2.specific.images[0].set_colorkey((0, 0, 0)) + Player2.move.collisions = True # enables collisions for player + Player2.move.speed = 0.5 # increasing speed so ur not super slow + Player2.move.angle_speed = 0.1 + + # simulating movement so u dont start at speed 0 + Player2.dir_movement = Player2.move.set_start_dir_movement(Player2.direction, Player2.dir_movement) + + # sorts player + sort(Player2, objects) + # moves to next id + game.custom_id_giver += 1 + players_defined = 1 + # sparks + + sparks = Spark + sparks.sparks["a"] = [] + sparks.sparks["b"] = [] + pointers = [pygame.image.load("assets/textures/game/p1_pointer.png").convert(), + pygame.image.load("assets/textures/game/p2_pointer.png").convert()] + for point in pointers: + point.set_colorkey((0, 0, 0)) + + # scroll + + scroll = Scroll([0, 0]) + + # ending + + winner_text = pygame.image.load("assets/textures/menu/template_for_text.png").convert() + esc = pygame.image.load("assets/textures/menu/esc.png").convert() + + # game loop + + while game.alive: + # checking if end + + check_loser(midpoint, [Player1, Player2], game) + + # setting up bg + + display.fill((20, 20, 20)) + bg.central(display) + + # checking for removed objects + + objects.destroy_trash(ids) + + ids.remove_by_id(objects) + + # doing player movement + + Player1.movement = Player1.move.move(Player1.dir_movement) + Player1.direction, Player1.dir_movement = Player1.move.change_dir(Player1.direction, + Player1.move.angle_speed) + Player2.movement = Player2.move.move(Player2.dir_movement) + Player2.direction, Player2.dir_movement = Player2.move.change_dir(Player2.direction, + Player2.move.angle_speed) + + # second parameter is speed of rotation + + # collisions + + objects.do_collisions(objects) + + players_collisions(Player1, Player2, game) + + # new sparks + sparks.scroll = scroll.scroll + + sparks.create("a", Player1.object_pos, [3, 5], [[10, 255], [0, 200], [0, 0]], 3, 1) + sparks.create("b", Player2.object_pos, [3, 5], [[0, 0], [0, 200], [10, 255]], 3, 1) + + # sounds + + # displaying objects + + scroll.move_scroll(Player1, [900, 600], "both", 30) + scroll.move_scroll(Player2, [900, 600], "both", 30) + + load_textures(objects, images_dictionary, display, scroll) + + solids.draw_solids(objects, display, scroll) + + display_pointers(display, [Player1, Player2], pointers, scroll) + + sparks.central("a", display) + sparks.central("b", display) + + # event loop + + if game.game_flow["inputs"]: + for event in pygame.event.get(): + if event.type == QUIT: + pygame.quit() + sys.exit() + + if event.type == KEYDOWN: + if event.key == K_f: + fs = not fs + if fs is False: + screenX = pygame.display.set_mode(Window_size) + else: + screenX = pygame.display.set_mode(new_parameters, pygame.FULLSCREEN) + + elif event.key == K_ESCAPE: + game.game_flow["sounds"]["click"].play(0) + game.alive = False + + elif event.key == K_d: + Player1.move.right = True + elif event.key == K_a: + Player1.move.left = True + elif event.key == K_w: + Player1.move.forward = True + elif event.key == K_e: + if abilities["1.storage"] > 1: + if abilities["1.player"] == "ice": + Player1.move.vectors = [] + elif abilities["1.player"] == "dash": + Player1.move.vectors.append([Player1.dir_movement[0] * game.game_flow["boost"], + Player1.dir_movement[1] * game.game_flow["boost"]]) + elif abilities["1.player"] == "wave": + Player2.move.vectors.append( + get_shockwave_vector(Player1.object_pos, Player2.object_pos)) + abilities["1.storage"] -= 1 + + + # key_up + + elif event.type == KEYUP: + if event.key == K_d: + Player1.move.right = False + elif event.key == K_a: + Player1.move.left = False + elif event.key == K_w: + Player1.move.forward = False + + else: + stop_inputs([Player1, Player2]) + winner = font.render(f"Winner is : {game.game_flow['winner']}", + False, (255, 255, 255)) + display.blit(winner_text, [50, 50]) + display.blit(winner, [90, 80]) + display.blit(esc, [500, 450]) + + for event in pygame.event.get(): + if event.type == QUIT: + pygame.quit() + sys.exit() + + if event.type == KEYDOWN: + if event.key == K_f: + fs = not fs + if fs is False: + screenX = pygame.display.set_mode(Window_size) + else: + screenX = pygame.display.set_mode(new_parameters, pygame.FULLSCREEN) + + elif event.key == K_ESCAPE: + game.game_flow["sounds"]["click"].play(0) + game.alive = False + # basic loop config + outarr = [Player1.all_ids, Player1.dir_movement, Player1.direction, Player1.ids_to_remove, Player1.memory, Player1.move.angle_speed, Player1.move.backwards, Player1.move.collisions, Player1.move.degree, Player1.move.force, Player1.move.forward, Player1.move.half_pi, Player1.move.left, Player1.move.offset, Player1.move.pi, Player1.move.right, Player1.move.speed, Player1.move.three_halves_pi, Player1.move.two_pi, Player1.move.vectors, Player1.movement, Player1.moving, Player1.object_id, Player1.object_pos, Player1.rect.bottom, Player1.rect.bottomleft, Player1.rect.bottomright, Player1.rect.center, Player1.rect.centerx, Player1.rect.centery, Player1.rect.h, Player1.rect.height, Player1.rect.left, Player1.rect.midbottom, Player1.rect.midleft, Player1.rect.midright, Player1.rect.midtop, Player1.rect.right, Player1.rect.size, Player1.rect.top, Player1.rect.topleft, Player1.rect.topright, Player1.rect.w, Player1.rect.width, Player1.rect.x, Player1.rect.y, Player1.size, Player1.special, Player1.specific.attribute, Player1.specific.attribute_0, Player1.specific.attribute_1, Player1.specific.attribute_2, Player1.specific.boolean_attribute, Player1.specific.color_r, Player1.specific.fixed, Player1.specific.flip, Player1.specific.height, Player1.specific.object_id, Player1.specific.power, Player1.specific.scroll, Player1.specific.stage, Player1.type] + datasend = json.dumps({"player": 1, "data": outarr}) + asyncio.run(websocket.send(datasend)) + screenX.blit(pygame.transform.scale(display, new_parameters), (0, 0)) + pygame.display.update() + clock.tick(60) + + +menu(screen, False) diff --git a/epic_sumo2.py b/epic_sumo2.py new file mode 100644 index 0000000..2464650 --- /dev/null +++ b/epic_sumo2.py @@ -0,0 +1,640 @@ +from s_engine import * +from spark import * +from ingame_funcs import * +import pygame +import sys +import time +import random +import math +from pygame.locals import * +import json +import threading +import asyncio +import websockets + +# basic config +work = True + +pygame.mixer.pre_init(48000, -16, 2, 512) +pygame.init() +pygame.mixer.set_num_channels(16) + +font = pygame.font.SysFont('Comic Sans MS', 80) +small_font = pygame.font.SysFont('Comic Sans MS', 40) +tiny_font = pygame.font.SysFont('Comic Sans MS', 20) + +players_defined = 0 +connected = 0 +global Player1 +global Player2 +uri = "ws://brn.systems:8765" +global websocket + +async def write_players(arrx): + global Player1 + global Player2 + Player1.all_ids = arrx[0] + Player1.dir_movement = arrx[1] + Player1.direction = arrx[2] + Player1.ids_to_remove = arrx[3] + Player1.memory = arrx[4] + Player1.move.angle_speed = arrx[5] + Player1.move.backwards = arrx[6] + Player1.move.collisions = arrx[7] + Player1.move.degree = arrx[8] + Player1.move.force = arrx[9] + Player1.move.forward = arrx[10] + Player1.move.half_pi = arrx[11] + Player1.move.left = arrx[12] + Player1.move.offset = arrx[13] + Player1.move.pi = arrx[14] + Player1.move.right = arrx[15] + Player1.move.speed = arrx[16] + Player1.move.three_halves_pi = arrx[17] + Player1.move.two_pi = arrx[18] + Player1.move.vectors = arrx[19] + Player1.movement = arrx[20] + Player1.moving = arrx[21] + Player1.object_id = arrx[22] + Player1.object_pos = arrx[23] + Player1.rect.bottom = arrx[24] + Player1.rect.bottomleft = arrx[25] + Player1.rect.bottomright = arrx[26] + Player1.rect.center = arrx[27] + Player1.rect.centerx = arrx[28] + Player1.rect.centery = arrx[29] + Player1.rect.h = arrx[30] + Player1.rect.height = arrx[31] + Player1.rect.left = arrx[32] + Player1.rect.midbottom = arrx[33] + Player1.rect.midleft = arrx[34] + Player1.rect.midright = arrx[35] + Player1.rect.midtop = arrx[36] + Player1.rect.right = arrx[37] + Player1.rect.size = arrx[38] + Player1.rect.top = arrx[39] + Player1.rect.topleft = arrx[40] + Player1.rect.topright = arrx[41] + Player1.rect.w = arrx[42] + Player1.rect.width = arrx[43] + Player1.rect.x = arrx[44] + Player1.rect.y = arrx[45] + Player1.size = arrx[46] + Player1.special = arrx[47] + Player1.specific.attribute = arrx[48] + Player1.specific.attribute_0 = arrx[49] + Player1.specific.attribute_1 = arrx[50] + Player1.specific.attribute_2 = arrx[51] + Player1.specific.boolean_attribute = arrx[52] + Player1.specific.color_r = arrx[53] + Player1.specific.fixed = arrx[54] + Player1.specific.flip = arrx[55] + Player1.specific.height = arrx[56] + Player1.specific.object_id = arrx[57] + Player1.specific.power = arrx[58] + Player1.specific.scroll = arrx[59] + Player1.specific.stage = arrx[60] + Player1.type = arrx[61] + +async def hello(): + global websocket + global connected + websocket = await websockets.connect(uri) + connected = 1 + while True: + greeting = await websocket.recv() + try: + if players_defined == 1: + data = json.loads(greeting)[0]["data"] + if len(data) == 62: + await write_players(data) + except Exception as e: + print(str(e)) + + +loop = asyncio.get_event_loop() + + +def helloa(): + loop.run_until_complete(hello()) + loop.run_forever() + + +t = threading.Thread(target=helloa, args=tuple()) +t.start() + +while connected == 0: + pass + +Window_size = [900, 600] +screen = pygame.display.set_mode(Window_size) +display = pygame.Surface((1350, 900)) +pygame.display.set_caption("Epic_sumo") +pygame.display.set_icon(pygame.image.load("assets/textures/icon.png").convert()) +clock = pygame.time.Clock() + + +class Bg: + active = [] + timer = 0 + + bgs = { + "first": pygame.image.load("assets/textures/backround/bg.png").convert(), + "second": pygame.image.load("assets/textures/backround/bg-blue.png").convert() + } + bgs["first"].set_colorkey((255, 255, 255)) + bgs["second"].set_colorkey((255, 255, 255)) + + def __init__(self, pos, speed, typeX): + self.object_pos = pos + self.speed = speed + self.type = typeX + + @classmethod + def generate(cls, amount, cord_lim=None): + if cord_lim is None: + cord_lim = [0, 1350] + for i in range(amount): + cls.active.append(Bg([random.randint(cord_lim[0], cord_lim[1]), random.randint(0, 860)], + random.randint(2, 10), random.choice(("first", "second")))) + + @classmethod + def blit_them(cls, display): + for circle in cls.active: + display.blit(cls.bgs[circle.type], circle.object_pos) + + @classmethod + def remove_circle(cls, which): + cls.active.remove(which) + + @classmethod + def central(cls, display): + for circle in cls.active: + circle.move() + + cls.blit_them(display) + + if cls.timer == 0: + cls.generate(12, [1350, 1500]) + cls.timer += 60 + else: + cls.timer -= 1 + + def move(self): + self.object_pos[0] -= self.speed + if self.object_pos[0] < -80: + self.remove_circle(self) + + +class Solids: + def __init__(self): + self.stage = 0 + self.colors = [ + (73, 122, 67), + (127, 182, 120), + (181, 230, 29) + ] + + def draw(self, solid, display, scroll): + cc = (self.stage // 40) % 3 + current_stage = self.stage % 40 + mid_point = [ + solid.object_pos[0] + (solid.size[0] / 2), + solid.object_pos[1] + (solid.size[1] / 2) + ] + + pygame.draw.rect(display, self.colors[cc], pygame.Rect(mid_point[0] - current_stage - scroll.scroll[0], + mid_point[1] - current_stage - scroll.scroll[1], + current_stage * 2, current_stage * 2)) + + def draw_solids(self, objects, display, scroll): + for obj in objects.game_objects: + if obj.type == "solid": + self.draw(obj, display, scroll) + self.stage += 1 + + +def menu(screenX, fs): + def mouse_check(mouse_pos, menu_flow): + + new_list = [0, 0, menu_flow[2], menu_flow[3], 0, 0] + + # settings + if 800 < mouse_pos[0] < 872: + if 500 < mouse_pos[1] < 572: + new_list[0] = 1 + + # play + if 300 < mouse_pos[0] < 591: + if 300 < mouse_pos[1] < 396: + new_list[1] = 1 + + # change player 1 + if 250 < mouse_pos[0] < 359: + if 500 < mouse_pos[1] < 548: + new_list[4] = 1 + + # change player 2 + if 400 < mouse_pos[0] < 509: + if 500 < mouse_pos[1] < 548: + new_list[5] = 1 + + return new_list + + # preparations + + game = Game() + game.game_flow["menu"] = [0, 0, 0, 0, 0, 0] + game.game_flow["sounds"] = get_sounds() + settings_on_top = False + display = pygame.Surface((900, 600)) + + abilities = { + "1.player": "dash", + "2.player": "dash", + "1.storage": 5, + "2.storage": 5 + } + + menu_textures = { + "bg": pygame.image.load("assets/textures/menu/main_menu.png").convert(), + "play": pygame.image.load("assets/textures/menu/play_button.png").convert(), + "play_pressed": pygame.image.load("assets/textures/menu/play_button_pressed.png").convert(), + "settings": pygame.image.load("assets/textures/menu/settings_btn.png").convert(), + "settings_pressed": pygame.image.load("assets/textures/menu/settings_btn_pressed.png").convert(), + "change": pygame.image.load("assets/textures/menu/change_btn.png").convert(), + "change_pressed": pygame.image.load("assets/textures/menu/change_btn_pressed.png").convert(), + "dash": pygame.image.load("assets/textures/menu/dash.png").convert(), + "shockwave": pygame.image.load("assets/textures/menu/wave.png").convert(), + "ice": pygame.image.load("assets/textures/menu/ice.png").convert(), + "settings_menu": pygame.image.load("assets/textures/menu/settings.png").convert() + } + + # game loop + while game.alive: + display.blit(menu_textures["bg"], [0, 0]) + + # event loop + + for event in pygame.event.get(): + if event.type == QUIT: + pygame.quit() + sys.exit() + + if event.type == pygame.MOUSEBUTTONDOWN: + mousepos = pygame.mouse.get_pos() + game.game_flow["menu"] = mouse_check(mousepos, game.game_flow["menu"]) + + # setting actions for buttons + if settings_on_top is False: + if game.game_flow["menu"][1]: + game.game_flow["sounds"]["click"].play(0) + arena(screenX, fs, abilities) + + elif game.game_flow["menu"][4]: + game.game_flow["menu"][2] += 1 + if game.game_flow["menu"][2] > 2: + game.game_flow["menu"][2] = 0 + + game.game_flow["sounds"]["click"].play(0) + + elif game.game_flow["menu"][5]: + game.game_flow["menu"][3] += 1 + if game.game_flow["menu"][3] > 2: + game.game_flow["menu"][3] = 0 + + game.game_flow["sounds"]["click"].play(0) + + # settings menu + + if game.game_flow["menu"][0]: + settings_on_top = not settings_on_top + game.game_flow["sounds"]["click"].play(0) + + if event.type == pygame.MOUSEMOTION: + # if mouse moving get mouse pos + mousepos = pygame.mouse.get_pos() + # function that checks if mouse is above any button and changes image, color of that image + game.game_flow["menu"] = mouse_check(mousepos, game.game_flow["menu"]) + + if event.type == KEYDOWN: + if event.key == K_f: + fs = not fs + if fs is False: + screenX = pygame.display.set_mode(Window_size) + else: + screenX = pygame.display.set_mode(Window_size, pygame.FULLSCREEN) + + elif event.key == K_ESCAPE: + if settings_on_top is False: + pygame.quit() + sys.exit() + else: + settings_on_top = not settings_on_top + + # making menu + + if game.game_flow["menu"][1]: + display.blit(menu_textures["play_pressed"], [300, 300]) + else: + display.blit(menu_textures["play"], [300, 300]) + + # showing ability of 1.player + if game.game_flow["menu"][2] == 0: + display.blit(menu_textures["dash"], [100, 400]) + abilities["1.player"] = "dash" + abilities["1.storage"] = 10 + elif game.game_flow["menu"][2] == 1: + display.blit(menu_textures["shockwave"], [100, 400]) + abilities["1.player"] = "wave" + abilities["1.storage"] = 8 + elif game.game_flow["menu"][2] == 2: + display.blit(menu_textures["ice"], [100, 400]) + abilities["1.player"] = "ice" + abilities["1.storage"] = 10 + + # showing ability of 2.player + if game.game_flow["menu"][3] == 0: + display.blit(menu_textures["dash"], [500, 400]) + abilities["2.player"] = "dash" + abilities["2.storage"] = 10 + elif game.game_flow["menu"][3] == 1: + display.blit(menu_textures["shockwave"], [500, 400]) + abilities["2.player"] = "wave" + abilities["2.storage"] = 8 + elif game.game_flow["menu"][3] == 2: + display.blit(menu_textures["ice"], [500, 400]) + abilities["2.player"] = "ice" + abilities["2.storage"] = 10 + + if game.game_flow["menu"][4] == 0: + display.blit(menu_textures["change"], [250, 500]) + elif game.game_flow["menu"][4] == 1: + display.blit(menu_textures["change_pressed"], [250, 500]) + + if game.game_flow["menu"][5] == 0: + display.blit(menu_textures["change"], [400, 500]) + elif game.game_flow["menu"][5] == 1: + display.blit(menu_textures["change_pressed"], [400, 500]) + + if settings_on_top: + display.blit(menu_textures["settings_menu"], [0, 0]) + + if game.game_flow["menu"][0]: + display.blit(menu_textures["settings_pressed"], [800, 500]) + else: + display.blit(menu_textures["settings"], [800, 500]) + + # basic loop config + + screenX.blit(display, (0, 0)) + pygame.display.update() + clock.tick(60) + + +def arena(screenX, fs, abilities): + global Player1 + global Player2 + global players_defined + ids = Id() + images_dictionary = {"solid": pygame.image.load("assets/textures/game/solid.png").convert(), + "circle": pygame.image.load("assets/textures/backround/circle_arena.png").convert()} + images_dictionary["circle"].set_colorkey((0, 0, 0)) + images_dictionary["solid"].set_colorkey((0, 0, 0)) + game = Game() + game.game_flow["collision_timer"] = 0 + game.game_flow["boost"] = 0.9 + game.game_flow["speed_timer"] = 0 + game.game_flow["winner"] = "na" + game.game_flow["inputs"] = True + game.game_flow["sounds"] = get_sounds() + + new_parameters = [1350, 900] + display = pygame.Surface((1350, 900)) + + # background + + bg = Bg + bg.generate(100) + + # solids + + solids = Solids() + + # loading map + + mapX = load_map("assets/maps/map0") + + # loading objects + + objects = Objects() + + # loading bg circle + + midpoint = [816, 672] + circle = Object("circle", game.custom_id_giver, [192, 0], [0, 0], 0, False, [1248, 1344]) + sort(circle, objects) + game.custom_id_giver += 1 + + # loading from map + + load_objects(mapX, 96, 96, objects, game) + + # players + + # never set direction to 0 + Player1 = Object("player", game.custom_id_giver, [800, 800], [0, 0], + round(math.tau * 0.75, 2), True, [10, 10], True) + Player1.specific.images.append(pygame.image.load("assets/textures/game/player.png").convert()) + Player1.specific.images[0].set_colorkey((0, 0, 0)) + Player1.move.collisions = True # enables collisions for player + Player1.move.speed = 0.5 # increasing speed so ur not super slow + Player1.move.angle_speed = 0.1 + + # simulating movement so u dont start at speed 0 + Player1.dir_movement = Player1.move.set_start_dir_movement(Player1.direction, Player1.dir_movement) + + # sorts player + sort(Player1, objects) + # moves to next id + game.custom_id_giver += 1 + + # player 2 + + # never set direction to 0 + Player2 = Object("player", game.custom_id_giver, [800, 400], [0, 0], round(math.pi/2, 2), True, [10, 10], True) + Player2.specific.images.append(pygame.image.load("assets/textures/game/player.png").convert()) + Player2.specific.images[0].set_colorkey((0, 0, 0)) + Player2.move.collisions = True # enables collisions for player + Player2.move.speed = 0.5 # increasing speed so ur not super slow + Player2.move.angle_speed = 0.1 + + # simulating movement so u dont start at speed 0 + Player2.dir_movement = Player2.move.set_start_dir_movement(Player2.direction, Player2.dir_movement) + + # sorts player + sort(Player2, objects) + # moves to next id + game.custom_id_giver += 1 + players_defined = 1 + # sparks + + sparks = Spark + sparks.sparks["a"] = [] + sparks.sparks["b"] = [] + pointers = [pygame.image.load("assets/textures/game/p1_pointer.png").convert(), + pygame.image.load("assets/textures/game/p2_pointer.png").convert()] + for point in pointers: + point.set_colorkey((0, 0, 0)) + + # scroll + + scroll = Scroll([0, 0]) + + # ending + + winner_text = pygame.image.load("assets/textures/menu/template_for_text.png").convert() + esc = pygame.image.load("assets/textures/menu/esc.png").convert() + + # game loop + + while game.alive: + # checking if end + + check_loser(midpoint, [Player1, Player2], game) + + # setting up bg + + display.fill((20, 20, 20)) + bg.central(display) + + # checking for removed objects + + objects.destroy_trash(ids) + + ids.remove_by_id(objects) + + # doing player movement + + Player1.movement = Player1.move.move(Player1.dir_movement) + Player1.direction, Player1.dir_movement = Player1.move.change_dir(Player1.direction, + Player1.move.angle_speed) + Player2.movement = Player2.move.move(Player2.dir_movement) + Player2.direction, Player2.dir_movement = Player2.move.change_dir(Player2.direction, + Player2.move.angle_speed) + + # second parameter is speed of rotation + + # collisions + + objects.do_collisions(objects) + + players_collisions(Player1, Player2, game) + + # new sparks + sparks.scroll = scroll.scroll + + sparks.create("a", Player1.object_pos, [3, 5], [[10, 255], [0, 200], [0, 0]], 3, 1) + sparks.create("b", Player2.object_pos, [3, 5], [[0, 0], [0, 200], [10, 255]], 3, 1) + + # sounds + + # displaying objects + + scroll.move_scroll(Player1, [900, 600], "both", 30) + scroll.move_scroll(Player2, [900, 600], "both", 30) + + load_textures(objects, images_dictionary, display, scroll) + + solids.draw_solids(objects, display, scroll) + + display_pointers(display, [Player1, Player2], pointers, scroll) + + sparks.central("a", display) + sparks.central("b", display) + + # event loop + + if game.game_flow["inputs"]: + for event in pygame.event.get(): + if event.type == QUIT: + pygame.quit() + sys.exit() + + if event.type == KEYDOWN: + if event.key == K_f: + fs = not fs + if fs is False: + screenX = pygame.display.set_mode(Window_size) + else: + screenX = pygame.display.set_mode(new_parameters, pygame.FULLSCREEN) + + elif event.key == K_ESCAPE: + game.game_flow["sounds"]["click"].play(0) + game.alive = False + + elif event.key == K_d: + Player2.move.right = True + elif event.key == K_a: + Player2.move.left = True + elif event.key == K_w: + Player2.move.forward = True + elif event.key == K_e: + if abilities["2.storage"] > 0: + if abilities["2.player"] == "ice": + Player2.move.vectors = [] + elif abilities["2.player"] == "dash": + Player2.move.vectors.append([Player2.dir_movement[0] * game.game_flow["boost"], + Player2.dir_movement[1] * game.game_flow["boost"]]) + elif abilities["2.player"] == "wave": + Player1.move.vectors.append( + get_shockwave_vector(Player2.object_pos, Player1.object_pos)) + abilities["2.storage"] -= 1 + + # key_up + + elif event.type == KEYUP: + + if event.key == K_d: + Player2.move.right = False + elif event.key == K_a: + Player2.move.left = False + elif event.key == K_w: + Player2.move.forward = False + + else: + stop_inputs([Player1, Player2]) + winner = font.render(f"Winner is : {game.game_flow['winner']}", + False, (255, 255, 255)) + display.blit(winner_text, [50, 50]) + display.blit(winner, [90, 80]) + display.blit(esc, [500, 450]) + + for event in pygame.event.get(): + if event.type == QUIT: + pygame.quit() + sys.exit() + + if event.type == KEYDOWN: + if event.key == K_f: + fs = not fs + if fs is False: + screenX = pygame.display.set_mode(Window_size) + else: + screenX = pygame.display.set_mode(new_parameters, pygame.FULLSCREEN) + + elif event.key == K_ESCAPE: + game.game_flow["sounds"]["click"].play(0) + game.alive = False + + # basic loop config + + outarr = [Player2.all_ids, Player2.dir_movement, Player2.direction, Player2.ids_to_remove, Player2.memory, Player2.move.angle_speed, Player2.move.backwards, Player2.move.collisions, Player2.move.degree, Player2.move.force, Player2.move.forward, Player2.move.half_pi, Player2.move.left, Player2.move.offset, Player2.move.pi, Player2.move.right, Player2.move.speed, Player2.move.three_halves_pi, Player2.move.two_pi, Player2.move.vectors, Player2.movement, Player2.moving, Player2.object_id, Player2.object_pos, Player2.rect.bottom, Player2.rect.bottomleft, Player2.rect.bottomright, Player2.rect.center, Player2.rect.centerx, Player2.rect.centery, Player2.rect.h, Player2.rect.height, Player2.rect.left, Player2.rect.midbottom, Player2.rect.midleft, Player2.rect.midright, Player2.rect.midtop, Player2.rect.right, Player2.rect.size, Player2.rect.top, Player2.rect.topleft, Player2.rect.topright, Player2.rect.w, Player2.rect.width, Player2.rect.x, Player2.rect.y, Player2.size, Player2.special, Player2.specific.attribute, Player2.specific.attribute_0, Player2.specific.attribute_1, Player2.specific.attribute_2, Player2.specific.boolean_attribute, Player2.specific.color_r, Player2.specific.fixed, Player2.specific.flip, Player2.specific.height, Player2.specific.object_id, Player2.specific.power, Player2.specific.scroll, Player2.specific.stage, Player2.type] + datasend = json.dumps({"player": 2, "data": outarr}) + asyncio.run(websocket.send(datasend)) + screenX.blit(pygame.transform.scale(display, new_parameters), (0, 0)) + pygame.display.update() + clock.tick(60) + + +menu(screen, False) diff --git a/ingame_funcs.py b/ingame_funcs.py new file mode 100644 index 0000000..9215d9c --- /dev/null +++ b/ingame_funcs.py @@ -0,0 +1,100 @@ +import math +from s_engine import * +import pygame +from pygame.locals import * +from Sounds import get_sounds + +# basic config + +pygame.mixer.pre_init(48000, -16, 2, 512) +pygame.init() +pygame.mixer.set_num_channels(16) + + +def between_player_collisions(player1, player2, game): + if game.game_flow["collision_timer"] == 0: + + dist = distance_indicator(player1.object_pos, player2.object_pos) + + if dist < 75: + game.game_flow["sounds"]["collision"].play(0) + + player1.move.vectors.append([player2.dir_movement[0] * player2.move.force, + player2.dir_movement[1] * player2.move.force]) + player2.move.vectors.append([player1.dir_movement[0] * player1.move.force, + player1.dir_movement[1] * player1.move.force]) + game.game_flow["collision_timer"] += 20 + else: + game.game_flow["collision_timer"] -= 1 + + +def players_collisions(player1, player2, game): + if game.game_flow["collision_timer"] == 0: + + dist = distance_indicator(player1.object_pos, player2.object_pos) + + if dist < 75: + game.game_flow["sounds"]["collision"].play(0) + + ag1 = find_angle_between_points(player1.object_pos, player2.object_pos) + ag2 = ag1 + math.pi + + forces = [average(abs(player1.dir_movement[0]), abs(player1.dir_movement[1])) * player1.move.force, + average(abs(player2.dir_movement[0]), abs(player2.dir_movement[1])) * player2.move.force] + + player1.move.vectors.append([math.cos(ag2) * forces[1], + math.sin(ag2) * forces[1]]) + player2.move.vectors.append([math.cos(ag1) * forces[0], + math.sin(ag1) * forces[0]]) + game.game_flow["collision_timer"] += 20 + else: + game.game_flow["collision_timer"] -= 1 + + +def get_shockwave_vector(pos1, pos2, divider=14): + dist = (100 / (distance_indicator(pos1, pos2) + 0.0001)) + + x_wave = (-(pos1[0] - pos2[0]) / divider) * dist + y_wave = (-(pos1[1] - pos2[1]) / divider) * dist + + # divider is there to make the shockwave less powerfull + + return [x_wave, y_wave] + + +def check_loser(midpoint, players, game): + dists = [ + distance_indicator(midpoint, players[0].object_pos), + distance_indicator(midpoint, players[1].object_pos) + ] + for i in range(2): + if dists[i] > 680: + if game.game_flow["inputs"] is False: + game.game_flow["winner"] = "draw" + game.game_flow["inputs"] = False + if i == 0: + game.game_flow["winner"] = "p2" + else: + game.game_flow["winner"] = "p1" + + +def stop_inputs(players): + for player in players: + player.move.forward = False + player.move.left = False + player.move.right = False + + +def display_pointers(display, players, pointers, scroll): + index = 0 + for player in players: + angle = find_angle_between_points(player.object_pos, [player.object_pos[0] + math.cos(player.direction), + player.object_pos[1] + math.sin(player.direction)]) + if angle is False: + index += 1 + continue + + display.blit(pygame.transform.rotate(pointers[index], math.degrees(-angle)), + [(player.object_pos[0] + math.cos(angle) * 40) - scroll.scroll[0] - 12, + (player.object_pos[1] + math.sin(angle) * 40) - scroll.scroll[1] - 12]) + index += 1 \ No newline at end of file diff --git a/s_engine.py b/s_engine.py new file mode 100644 index 0000000..6e0b416 --- /dev/null +++ b/s_engine.py @@ -0,0 +1,479 @@ +import pygame +import sys +import time +import random +import math +import copy +from pygame.locals import * + +pygame.init() + + +# has attributes for basic thing in game +class Game: + def __init__(self, game_maps=None): + self.alive = True + # fs = fullscreen + self.fs = False + self.custom_id_giver = 0 + + self.game_flow = {} + + self.game_maps = None + # checks if there are any maps if there are puts them in self.game_maps + if game_maps is not None: + self.game_maps = game_maps + + +# stores objects in a sorted way +class Objects: + def __init__(self): + self.game_objects = [] + self.collision_objects = [] + self.moving_objects = [] + + # dunno if next att will be useful + # u add ids of objects u want to delete there is no func to delete for now + + self.objects_to_delete = [] + + self.values = { + "pos_to_del": [] + } + + def do_collisions(self, objects): + for obj in self.collision_objects: + collision(obj, objects) + + def destroy_trash(self, ids): + for trash in self.objects_to_delete: + ids.ids_to_remove.append(trash) + self.objects_to_delete = [] + + def take_out_trash(self, ids): + for obj in self.objects_to_delete: + ids.ids_to_remove.append(obj) + self.objects_to_delete = [] + + +# Id class just stores all ids of all objects +class Id: + all_ids = [] + ids_to_remove = [] + + def remove_by_id(self, objects): + for item in self.ids_to_remove: + for obj in objects.game_objects: + if obj.object_id == item: + g_index = objects.game_objects.index(obj) + if obj.moving: + m_index = objects.moving_objects.index(obj) + if obj.move.collisions: + c_index = objects.collision_objects.index(obj) + + del objects.collision_objects[c_index] + + del objects.moving_objects[m_index] + + del objects.game_objects[g_index] + + self.ids_to_remove = [] + + +class Scroll: + def __init__(self, scroll): + self.scroll = scroll + self.fade = 20 + self.safe_fade = 20 + self.in_progress = False + self.save_scroll = self.scroll + + def move_scroll(self, player, screen, which, space=20): + if which == "y" or which == "both": + self.scroll[1] += (player.rect.y - self.scroll[1] - (screen[1] / 2) + (player.size[1] / 2)) / space + self.scroll[1] = int(self.scroll[1]) + if which == "x" or which == "both": + self.scroll[0] += (player.rect.x - self.scroll[0] - (screen[0] / 2) + (player.size[0] / 2)) / space + self.scroll[0] = int(self.scroll[0]) + + def add_scroll(self, which, how_much, fade=None): + if fade is not None: + self.safe_fade = fade + if self.in_progress is False: + self.load_safe_fade() + self.save_scroll = self.scroll + self.in_progress = True + how_much[0] /= self.fade + how_much[1] /= self.fade + self.fade += 0.01 * self.fade + + if which == "x" or which == "both": + self.scroll[0] += how_much[0] + self.scroll[0] = round(self.scroll[0]) + + if which == "y" or which == "both": + self.scroll[1] += how_much[1] + self.scroll[1] = round(self.scroll[1]) + + def load_safe_fade(self): + self.fade = self.safe_fade + self.in_progress = False + + +class Special: + def __init__(self, object_id): + self.object_id = object_id + self.stage = "" + self.attribute = "" + self.images = [] + self.attribute_0 = 0 + self.attribute_1 = 0 + self.attribute_2 = 0 + self.color_r = [0, 0, 0] + self.boolean_attribute = False + self.height = 0 + self.power = 0 + self.flip = False + self.scroll = False + self.fixed = False + + +# collisions class take care of collision funcs +# !!!!!!!!!! holds init for Object !!!!!!!!!!!!!!!!!!! +# class purely for inheritance +class Collisions(Id): + + def __init__(self, typeX, object_id, x_y, movement, direction, moving, size, special=None): + self.type = typeX + self.object_id = object_id + self.object_pos = x_y + self.movement = movement + self.direction = direction + self.moving = moving + self.size = size + self.dir_movement = [0.0, 0.0] + self.memory = [] + self.special = special + if self.object_id != self.all_ids: + self.all_ids.append(self.object_id) + else: + print("duplicate/ linked object") + + # giving it bonus classes + + if self.moving: + self.move = Moving_Object() + if self.special: + self.specific = Special(self.object_id) + + self.rect = pygame.Rect(self.object_pos[0], self.object_pos[1], self.size[0], self.size[1]) + + # theres a function for every type of collisions + # edit collisions here (I added some basic ones just so u can see) + # self if objects that it hit and obj is the object that hit smt + + # always add both side of collisions (ask who collided with whom) + + def hit_bottom(self, obj, objects): + if self.type == "solid": + if obj.type == "player": + obj.rect.bottom = self.rect.top + obj.object_pos = [obj.rect.x, obj.rect.y] + self.memory[0] -= 1 + if self.memory[0] == 0: + objects.objects_to_delete.append(self.object_id) + + opposite = obj.move.get_final_vector() + opp = [-opposite[0] * 0.4, -opposite[1] * 0.8] + obj.move.vectors.append(opp) + + def hit_top(self, obj, objects): + if self.type == "solid": + if obj.type == "player": + obj.rect.top = self.rect.bottom + obj.object_pos = [obj.rect.x, obj.rect.y] + self.memory[0] -= 1 + if self.memory[0] == 0: + objects.objects_to_delete.append(self.object_id) + + opposite = obj.move.get_final_vector() + opp = [-opposite[0] * 0.4, -opposite[1] * 0.8] + obj.move.vectors.append(opp) + + def hit_left(self, obj, objects): + if self.type == "solid": + if obj.type == "player": + obj.rect.left = self.rect.right + obj.object_pos = [obj.rect.x, obj.rect.y] + self.memory[0] -= 1 + if self.memory[0] == 0: + objects.objects_to_delete.append(self.object_id) + + opposite = obj.move.get_final_vector() + opp = [-opposite[0] * 0.4, -opposite[1] * 0.8] + obj.move.vectors.append(opp) + + def hit_right(self, obj, objects): + if self.type == "solid": + if obj.type == "player": + obj.rect.right = self.rect.left + obj.object_pos = [obj.rect.x, obj.rect.y] + self.memory[0] -= 1 + if self.memory[0] == 0: + objects.objects_to_delete.append(self.object_id) + + opposite = obj.move.get_final_vector() + opp = [-opposite[0] * 0.4, -opposite[1] * 0.8] + obj.move.vectors.append(opp) + + +# next 2 classes are for object class +class Moving_Object: + def __init__(self): + # consts + self.degree = 0.0174533 + self.pi = math.pi + self.half_pi = round(math.pi / 2, 6) + self.two_pi = round(math.pi * 2, 6) + self.three_halves_pi = round(3 * (math.pi / 2), 6) + self.speed = 1 + self.force = 3 + self.offset = 0 + self.vectors = [] + + self.forward = False + self.backwards = False + self.left = False + self.right = False + + self.collisions = False + + def move(self, dir_movement): + + movement = dir_movement + + return movement + + # dir is the angle the player is facing + def change_dir(self, direction, angle): + + new_vector = [0, 0] + + if self.left: + direction -= angle + if direction < 0: + direction += self.two_pi + new_vector[0] = round(math.cos(direction) * self.speed, 2) + new_vector[1] = round(math.sin(direction) * self.speed, 2) + self.vectors.append(new_vector) + elif self.right: + direction += angle + if direction > self.two_pi: + direction -= self.two_pi + new_vector[0] = round(math.cos(direction) * self.speed, 2) + new_vector[1] = round(math.sin(direction) * self.speed, 2) + self.vectors.append(new_vector) + elif self.forward: + new_vector[0] = round(math.cos(direction) * self.speed, 2) + new_vector[1] = round(math.sin(direction) * self.speed, 2) + self.vectors.append(new_vector) + + return direction, self.get_final_vector() + + # used for setting things before game loop + def set_start_dir_movement(self, direction, dir_movement): + dir_movement[0] = round(math.cos(direction + (self.offset * self.degree)) * self.speed, 2) + dir_movement[1] = round(math.sin(direction + (self.offset * self.degree)) * self.speed, 2) + return dir_movement + + def get_final_vector(self): + to_remove = [] + for i in range(len(self.vectors)-1): + self.vectors[i][0] *= 0.96 + self.vectors[i][1] *= 0.96 + if abs(self.vectors[i][0]) < 0.2 and abs(self.vectors[i][1]) < 0.2: + to_remove.append(self.vectors[i]) + + for item in to_remove: + self.vectors.remove(item) + + final_vector = [0, 0] + + for vector in self.vectors: + final_vector[0] += vector[0] + final_vector[1] += vector[1] + + return final_vector + + +class Object(Collisions): + def __init__(self, typeX, object_id, x_y, movement, direction, moving, size, special=None): + super().__init__(typeX, object_id, x_y, movement, direction, moving, size, special) + + def __str__(self): + return self.type + + # changes position along with the rect + def change_pos(self, x_y): + self.object_pos = x_y + self.rect = pygame.Rect(self.object_pos[0], self.object_pos[1], self.size[0], self.size[1]) + + +def distance_indicator(coords1, coords2): + x_distance = abs(coords1[0] - coords2[0]) + y_distance = abs(coords1[1] - coords2[1]) + distance = math.sqrt((x_distance ** 2) + (y_distance ** 2)) + return round(distance, 4) + + +def load_images(path, name, number_of_images, file_type=".png"): + images = [] + for i in range(number_of_images): + images.append(pygame.image.load("{}/{}{}{}".format(path, name, i, file_type)).convert()) + return images + + +def load_map(path): + f = open(path, "r") + data = f.read() + f.close() + data = data.split('\n') + product = [] + for line in data: + product.append(list(line)) + return product + + +# next func sorts object into objects class so the objects is stored where it should be +def sort(obj, objects): + objects.game_objects.append(obj) + + if obj.moving: + objects.moving_objects.append(obj) + + if obj.move.collisions: + objects.collision_objects.append(obj) + + +def find_collisions(obj, objects): + hit_list = [] + for element in objects.game_objects: + if element.object_id != obj.object_id: + if element.rect.colliderect(obj.rect): + hit_list.append(element) + return hit_list + + +def collision(obj, objects): + # collisions for left/right + obj.change_pos([obj.object_pos[0] + obj.movement[0], obj.object_pos[1]]) + hit_list = find_collisions(obj, objects) + for item in hit_list: + if obj.movement[0] > 0: + item.hit_right(obj, objects) + elif obj.movement[0] < 0: + item.hit_left(obj, objects) + + # collisions for top/bottom + obj.change_pos([obj.object_pos[0], obj.object_pos[1] + obj.movement[1]]) + hit_list = find_collisions(obj, objects) + for item in hit_list: + if obj.movement[1] > 0: + item.hit_bottom(obj, objects) + elif obj.movement[1] < 0: + item.hit_top(obj, objects) + + +# !!!!!!!!!!! config this function for every program !!!!!!!!!! +def load_objects(game_map, width, height, objects, game): + x, y = 0, 0 + for line in game_map: + for obj in line: + # this is just to be efficient normaly u can use elif and put another obj to another num + if obj == "1": + obj = Object("solid", game.custom_id_giver, [x, y], [0, 0], 0, False, [width, height]) + obj.memory.append(3) + sort(obj, objects) + game.custom_id_giver += 1 + x += width + y += height + x = 0 + + +def load_textures(objects, dictionary, display, scroll): + for object in objects.game_objects: + if object.special: + display.blit(object.specific.images[object.specific.attribute_0], + [object.object_pos[0] - scroll.scroll[0], object.object_pos[1] - scroll.scroll[1]]) + else: + display.blit(dictionary["{}".format(object.type)], + [object.object_pos[0] - scroll.scroll[0], object.object_pos[1] - scroll.scroll[1]]) + + +def load_sp_texture(objects, type_x, image): + for object in objects.special_objects: + if object.type == type_x: + object.attributes.images.append(image) + + +def load_bg(image, y_x, width, height, display): + pos = [0, 0] + for i in range(y_x[0]): + for j in range(y_x[1]): + display.blit(image, pos) + pos[0] += width + pos[0] = 0 + pos[1] += height + + +def find_angle_between_points(center, point): + dists = distances(center, point) + try: + angle = math.atan(dists[1] / dists[0]) + + if point[0] < center[0]: + if point[1] < center[1]: + return angle + math.pi + else: + return (math.pi / 2 - angle) + (math.pi / 2) + else: + if point[1] < center[1]: + return (math.pi / 2 - angle) + 3 * (math.pi / 2) + else: + return angle + except ZeroDivisionError: + return False + + +def distances(cords1, cords2): + return [abs(cords1[0] - cords2[0]), abs(cords1[1] - cords2[1])] + + +def average(*args): + sumX = 0 + for item in args: + sumX += item + return sumX/len(args) + + +def area_intersection_of_circles(points, radius_list): + try: + dist = distance_indicator(points[0], points[1]) + + alpha_cos = (pow(radius_list[1], 2) + pow(dist, 2) - pow(radius_list[0], 2)) / (2 * radius_list[1] * dist) + + alpha = math.acos(alpha_cos) + + beta_cos = (dist - alpha_cos * radius_list[1]) / radius_list[0] + + beta = math.acos(beta_cos) + + triangles = (alpha_cos * pow(radius_list[1], 2) * math.sin(alpha)) + ( + beta_cos * pow(radius_list[0], 2) * math.sin(beta)) + + arcs = ((math.pi * pow(radius_list[0], 2) * beta * 2) / math.tau) + ( + (math.pi * pow(radius_list[1], 2) * alpha * 2) / math.tau) + + return arcs - triangles + except: + return False diff --git a/server.py b/server.py new file mode 100644 index 0000000..eb35498 --- /dev/null +++ b/server.py @@ -0,0 +1,54 @@ +import asyncio +import websockets +import time +import json +import threading + +connected = set() +outreg = [{"player": "1", "data": []}, {"player": "2", "data": []}] + +async def socket_broadcast(data): + for client in connected: + await client.send(str(data)) + +async def hello(websocket, path): + global outreg + i = 0 + connected.add(websocket) + try: + while i == 0: + try: + await socket_broadcast(json.dumps(outreg)) + x = await websocket.recv() + try: + datareg = json.loads(x) + if datareg['player'] == 1: + outreg[0]["data"] = datareg["data"] + elif datareg['player'] == 2: + outreg[1]["data"] = datareg["data"] + #print(json.dumps(datareg)+"\n\n\n"+json.dumps(outreg)) + await socket_broadcast(json.dumps(outreg)) + except Exception as e: + print(e) + except Exception as e: + print(e) + connected.remove(websocket) + i = 1 + finally: + # Unregister. + connected.remove(websocket) + + +start_server = websockets.serve(hello, "localhost", 8765) + +loop = asyncio.get_event_loop() + +def loop_in_thread(): + loop.run_until_complete(start_server) + loop.run_forever() + +t = threading.Thread(target=loop_in_thread, args=tuple()) +t.start() + + +print("hello") diff --git a/spark.py b/spark.py new file mode 100644 index 0000000..12b29b1 --- /dev/null +++ b/spark.py @@ -0,0 +1,108 @@ +import pygame +import random +import math + +from pygame.locals import * + +pygame.init() + + +# dt it missing (the epic sumo is fps dependent) +class Spark: + sparks = {} + scroll = [0, 0] + two_pi = round(math.pi * 2) * 100 + + def __init__(self, pos, angle, speed, colorS, group, scale=1): + self.object_pos = pos + self.angle = angle + self.speed = speed + + self.scale = scale + self.scales = [self.scale * 3.5, self.scale * 0.3] + + self.color = colorS + self.group = group + + # preparing math + self.cosS = math.cos(self.angle) * self.speed + self.L_cosS = math.cos(self.angle + math.pi / 2) * self.speed + + self.sinS = math.sin(self.angle) * self.speed + self.L_sinS = math.sin(self.angle + math.pi / 2) * self.speed + + def move(self, display): + self.object_pos[0] += self.cosS + self.object_pos[1] += self.sinS + + self.draw(display) + + self.speed -= 0.2 + + # im missing the other 2 funcs here didnt really needed them currently + self.angle += 0.1 + + if self.speed <= 0: + self.delete_self(self) + + self.redo_math() + + def draw(self, display): + scroll = self.get_scroll() + + c1 = self.L_cosS * self.scales[1] + c2 = self.L_sinS * self.scales[1] + + p1 = [self.object_pos[0] + self.cosS * self.scale, + self.object_pos[1] + self.sinS * self.scale] + p2 = [self.object_pos[0] + c1, + self.object_pos[1] + c2] + p3 = [self.object_pos[0] - self.cosS * self.scales[0], + self.object_pos[1] - self.sinS * self.scales[0]] + p4 = [self.object_pos[0] - c1, + self.object_pos[1] - c2] + + pygame.draw.polygon(display, self.color, [[p1[0] - scroll[0], p1[1] - scroll[1]], + [p2[0] - scroll[0], p2[1] - scroll[1]], + [p3[0] - scroll[0], p3[1] - scroll[1]], + [p4[0] - scroll[0], p4[1] - scroll[1]]]) + + def redo_math(self): + self.cosS = math.cos(self.angle) * self.speed + self.L_cosS = math.cos(self.angle + math.pi / 2) * self.speed + + self.sinS = math.sin(self.angle) * self.speed + self.L_sinS = math.sin(self.angle + math.pi / 2) * self.speed + + @classmethod + def delete_self(cls, spark): + cls.sparks[spark.group].remove(spark) + + @classmethod + def central(cls, group, display): + for spark in cls.sparks[group]: + spark.move(display) + + # math.radians(random.randint(0, 360)), + # random.uniform(0, cls.two_pi) + @classmethod + def generate(cls, group, pos, speed_lim, color_lim, scaler): + cls.sparks[group].append(Spark(pos, random.randint(0, cls.two_pi) / 100, + random.randint(speed_lim[0], speed_lim[1]), + (random.randint(color_lim[0][0], color_lim[0][1]), + random.randint(color_lim[1][0], color_lim[1][1]), + random.randint(color_lim[2][0], color_lim[2][1])), group, scaler)) + + @classmethod + def create(cls, group, pos, speed_lim, color_lim, scaler, amount): + for i in range(amount): + cls.generate(group, pos.copy(), speed_lim, color_lim, scaler) + + @classmethod + def create_3d(cls, group, pos, speed_lim, color_lim, scaler, amount): + for i in range(amount): + cls.generate(group, pos, speed_lim, color_lim, scaler) + + @classmethod + def get_scroll(cls): + return cls.scroll