From 6ae6d8ef246133f83a67af156ef8210e84384195 Mon Sep 17 00:00:00 2001 From: Miguel Campos Date: Thu, 22 Aug 2024 15:59:18 -0700 Subject: [PATCH] bit-jumper: deploy new game --- apps/games/bit-jumper/.babelrc | 3 + apps/games/bit-jumper/.eslintrc.json | 18 + apps/games/bit-jumper/.swcrc | 8 + apps/games/bit-jumper/index.html | 18 + apps/games/bit-jumper/project.json | 9 + .../public/assets/achievements/1000.png | Bin 0 -> 4229 bytes .../public/assets/achievements/10000.png | Bin 0 -> 4662 bytes .../public/assets/achievements/15000.png | Bin 0 -> 4602 bytes .../public/assets/achievements/20000.png | Bin 0 -> 4884 bytes .../public/assets/achievements/2500.png | Bin 0 -> 4493 bytes .../public/assets/achievements/5000.png | Bin 0 -> 4541 bytes .../public/assets/achievements/7500.png | Bin 0 -> 4445 bytes .../public/assets/achievements/balloon.png | Bin 0 -> 3587 bytes .../public/assets/achievements/chomper.png | Bin 0 -> 3683 bytes .../public/assets/achievements/floater.png | Bin 0 -> 4279 bytes .../public/assets/achievements/helicopter.png | Bin 0 -> 4255 bytes .../public/assets/achievements/rocket.png | Bin 0 -> 5076 bytes .../public/assets/achievements/smasher.png | Bin 0 -> 6332 bytes .../public/assets/achievements/spiker.png | Bin 0 -> 4250 bytes .../public/assets/audio/balloon_end.mp3 | Bin 0 -> 22986 bytes .../public/assets/audio/balloon_start.mp3 | Bin 0 -> 22986 bytes .../bit-jumper/public/assets/audio/break.mp3 | Bin 0 -> 22986 bytes .../bit-jumper/public/assets/audio/death.mp3 | Bin 0 -> 22986 bytes .../public/assets/audio/helicopter_end.mp3 | Bin 0 -> 22986 bytes .../public/assets/audio/helicopter_start.mp3 | Bin 0 -> 22986 bytes .../bit-jumper/public/assets/audio/jump.mp3 | Bin 0 -> 22986 bytes .../bit-jumper/public/assets/audio/menu.mp3 | Bin 0 -> 22986 bytes .../public/assets/audio/rocket_end.mp3 | Bin 0 -> 22986 bytes .../public/assets/audio/rocket_start.mp3 | Bin 0 -> 22986 bytes .../bit-jumper/public/assets/audio/smash.mp3 | Bin 0 -> 22986 bytes .../bit-jumper/public/assets/audio/spring.mp3 | Bin 0 -> 22986 bytes .../public/assets/fonts/frog-block.ttf | Bin 0 -> 35065 bytes .../public/assets/fonts/license.txt | 121 +++++ .../bit-jumper/public/assets/icons/back.png | Bin 0 -> 182 bytes .../bit-jumper/public/assets/icons/heart.png | Bin 0 -> 203 bytes .../public/assets/icons/sound_off.png | Bin 0 -> 161 bytes .../public/assets/icons/sound_on.png | Bin 0 -> 188 bytes .../bit-jumper/public/assets/media/banner.png | Bin 0 -> 10495 bytes .../public/assets/media/thumbnail.png | Bin 0 -> 3344 bytes .../public/assets/particles/dot.png | Bin 0 -> 82 bytes .../public/assets/particles/ring.png | Bin 0 -> 163 bytes .../public/assets/sprites/infinite_jumper.png | Bin 0 -> 3039 bytes apps/games/bit-jumper/public/favicon.ico | Bin 0 -> 15086 bytes apps/games/bit-jumper/public/sources.txt | 3 + apps/games/bit-jumper/src/lib/data.ts | 15 + .../bit-jumper/src/lib/objects/collisions.ts | 123 +++++ .../bit-jumper/src/lib/objects/controller.ts | 75 ++++ .../bit-jumper/src/lib/objects/enemies.ts | 348 +++++++++++++++ .../bit-jumper/src/lib/objects/loading-bar.ts | 52 +++ .../bit-jumper/src/lib/objects/observer.ts | 53 +++ .../bit-jumper/src/lib/objects/particles.ts | 129 ++++++ .../bit-jumper/src/lib/objects/platforms.ts | 347 +++++++++++++++ .../bit-jumper/src/lib/objects/player.ts | 223 ++++++++++ .../bit-jumper/src/lib/objects/power-ups.ts | 93 ++++ .../bit-jumper/src/lib/objects/ui/button.ts | 26 ++ .../bit-jumper/src/lib/objects/ui/icons.ts | 61 +++ .../bit-jumper/src/lib/objects/ui/link.ts | 16 + .../src/lib/objects/ui/typography.ts | 17 + apps/games/bit-jumper/src/lib/scenes/boot.ts | 97 ++++ .../bit-jumper/src/lib/scenes/credits.ts | 33 ++ apps/games/bit-jumper/src/lib/scenes/end.ts | 81 ++++ apps/games/bit-jumper/src/lib/scenes/menu.ts | 86 ++++ apps/games/bit-jumper/src/lib/scenes/play.ts | 117 +++++ .../bit-jumper/src/lib/scenes/score-plane.ts | 60 +++ apps/games/bit-jumper/src/lib/types.ts | 19 + apps/games/bit-jumper/src/main.ts | 50 +++ apps/games/bit-jumper/src/styles.css | 25 ++ apps/games/bit-jumper/tsconfig.app.json | 9 + apps/games/bit-jumper/tsconfig.json | 28 ++ apps/games/bit-jumper/vite.config.ts | 31 ++ apps/prisma/seed/src/insert-achievements.ts | 13 +- libs/data/games/src/index.ts | 420 +++++++++++------- libs/phaser/plugins/src/lib/charity-games.ts | 31 +- libs/util/functions/.eslintrc.json | 25 ++ libs/util/functions/README.md | 11 + libs/util/functions/jest.config.ts | 11 + libs/util/functions/package.json | 11 + libs/util/functions/project.json | 26 ++ libs/util/functions/src/index.ts | 22 + libs/util/functions/tsconfig.json | 22 + libs/util/functions/tsconfig.lib.json | 10 + libs/util/functions/tsconfig.spec.json | 14 + libs/util/types/src/lib/game-schema.ts | 12 +- nx.json | 8 + package-lock.json | 170 ++++++- package.json | 5 +- tsconfig.base.json | 1 + 87 files changed, 3023 insertions(+), 183 deletions(-) create mode 100644 apps/games/bit-jumper/.babelrc create mode 100644 apps/games/bit-jumper/.eslintrc.json create mode 100644 apps/games/bit-jumper/.swcrc create mode 100644 apps/games/bit-jumper/index.html create mode 100644 apps/games/bit-jumper/project.json create mode 100644 apps/games/bit-jumper/public/assets/achievements/1000.png create mode 100644 apps/games/bit-jumper/public/assets/achievements/10000.png create mode 100644 apps/games/bit-jumper/public/assets/achievements/15000.png create mode 100644 apps/games/bit-jumper/public/assets/achievements/20000.png create mode 100644 apps/games/bit-jumper/public/assets/achievements/2500.png create mode 100644 apps/games/bit-jumper/public/assets/achievements/5000.png create mode 100644 apps/games/bit-jumper/public/assets/achievements/7500.png create mode 100644 apps/games/bit-jumper/public/assets/achievements/balloon.png create mode 100644 apps/games/bit-jumper/public/assets/achievements/chomper.png create mode 100644 apps/games/bit-jumper/public/assets/achievements/floater.png create mode 100644 apps/games/bit-jumper/public/assets/achievements/helicopter.png create mode 100644 apps/games/bit-jumper/public/assets/achievements/rocket.png create mode 100644 apps/games/bit-jumper/public/assets/achievements/smasher.png create mode 100644 apps/games/bit-jumper/public/assets/achievements/spiker.png create mode 100644 apps/games/bit-jumper/public/assets/audio/balloon_end.mp3 create mode 100644 apps/games/bit-jumper/public/assets/audio/balloon_start.mp3 create mode 100644 apps/games/bit-jumper/public/assets/audio/break.mp3 create mode 100644 apps/games/bit-jumper/public/assets/audio/death.mp3 create mode 100644 apps/games/bit-jumper/public/assets/audio/helicopter_end.mp3 create mode 100644 apps/games/bit-jumper/public/assets/audio/helicopter_start.mp3 create mode 100644 apps/games/bit-jumper/public/assets/audio/jump.mp3 create mode 100644 apps/games/bit-jumper/public/assets/audio/menu.mp3 create mode 100644 apps/games/bit-jumper/public/assets/audio/rocket_end.mp3 create mode 100644 apps/games/bit-jumper/public/assets/audio/rocket_start.mp3 create mode 100644 apps/games/bit-jumper/public/assets/audio/smash.mp3 create mode 100644 apps/games/bit-jumper/public/assets/audio/spring.mp3 create mode 100644 apps/games/bit-jumper/public/assets/fonts/frog-block.ttf create mode 100644 apps/games/bit-jumper/public/assets/fonts/license.txt create mode 100644 apps/games/bit-jumper/public/assets/icons/back.png create mode 100644 apps/games/bit-jumper/public/assets/icons/heart.png create mode 100644 apps/games/bit-jumper/public/assets/icons/sound_off.png create mode 100644 apps/games/bit-jumper/public/assets/icons/sound_on.png create mode 100644 apps/games/bit-jumper/public/assets/media/banner.png create mode 100644 apps/games/bit-jumper/public/assets/media/thumbnail.png create mode 100644 apps/games/bit-jumper/public/assets/particles/dot.png create mode 100644 apps/games/bit-jumper/public/assets/particles/ring.png create mode 100644 apps/games/bit-jumper/public/assets/sprites/infinite_jumper.png create mode 100644 apps/games/bit-jumper/public/favicon.ico create mode 100644 apps/games/bit-jumper/public/sources.txt create mode 100644 apps/games/bit-jumper/src/lib/data.ts create mode 100644 apps/games/bit-jumper/src/lib/objects/collisions.ts create mode 100644 apps/games/bit-jumper/src/lib/objects/controller.ts create mode 100644 apps/games/bit-jumper/src/lib/objects/enemies.ts create mode 100644 apps/games/bit-jumper/src/lib/objects/loading-bar.ts create mode 100644 apps/games/bit-jumper/src/lib/objects/observer.ts create mode 100644 apps/games/bit-jumper/src/lib/objects/particles.ts create mode 100644 apps/games/bit-jumper/src/lib/objects/platforms.ts create mode 100644 apps/games/bit-jumper/src/lib/objects/player.ts create mode 100644 apps/games/bit-jumper/src/lib/objects/power-ups.ts create mode 100644 apps/games/bit-jumper/src/lib/objects/ui/button.ts create mode 100644 apps/games/bit-jumper/src/lib/objects/ui/icons.ts create mode 100644 apps/games/bit-jumper/src/lib/objects/ui/link.ts create mode 100644 apps/games/bit-jumper/src/lib/objects/ui/typography.ts create mode 100644 apps/games/bit-jumper/src/lib/scenes/boot.ts create mode 100644 apps/games/bit-jumper/src/lib/scenes/credits.ts create mode 100644 apps/games/bit-jumper/src/lib/scenes/end.ts create mode 100644 apps/games/bit-jumper/src/lib/scenes/menu.ts create mode 100644 apps/games/bit-jumper/src/lib/scenes/play.ts create mode 100644 apps/games/bit-jumper/src/lib/scenes/score-plane.ts create mode 100644 apps/games/bit-jumper/src/lib/types.ts create mode 100644 apps/games/bit-jumper/src/main.ts create mode 100644 apps/games/bit-jumper/src/styles.css create mode 100644 apps/games/bit-jumper/tsconfig.app.json create mode 100644 apps/games/bit-jumper/tsconfig.json create mode 100644 apps/games/bit-jumper/vite.config.ts create mode 100644 libs/util/functions/.eslintrc.json create mode 100644 libs/util/functions/README.md create mode 100644 libs/util/functions/jest.config.ts create mode 100644 libs/util/functions/package.json create mode 100644 libs/util/functions/project.json create mode 100644 libs/util/functions/src/index.ts create mode 100644 libs/util/functions/tsconfig.json create mode 100644 libs/util/functions/tsconfig.lib.json create mode 100644 libs/util/functions/tsconfig.spec.json diff --git a/apps/games/bit-jumper/.babelrc b/apps/games/bit-jumper/.babelrc new file mode 100644 index 000000000..f2f380674 --- /dev/null +++ b/apps/games/bit-jumper/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["@nx/js/babel"] +} diff --git a/apps/games/bit-jumper/.eslintrc.json b/apps/games/bit-jumper/.eslintrc.json new file mode 100644 index 000000000..3456be9b9 --- /dev/null +++ b/apps/games/bit-jumper/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/apps/games/bit-jumper/.swcrc b/apps/games/bit-jumper/.swcrc new file mode 100644 index 000000000..a2d5b04f4 --- /dev/null +++ b/apps/games/bit-jumper/.swcrc @@ -0,0 +1,8 @@ +{ + "jsc": { + "parser": { + "syntax": "typescript" + }, + "target": "es2016" + } +} diff --git a/apps/games/bit-jumper/index.html b/apps/games/bit-jumper/index.html new file mode 100644 index 000000000..64ed1f1c9 --- /dev/null +++ b/apps/games/bit-jumper/index.html @@ -0,0 +1,18 @@ + + + + + Bit Jumper + + + + + + + +
.
+ + + + \ No newline at end of file diff --git a/apps/games/bit-jumper/project.json b/apps/games/bit-jumper/project.json new file mode 100644 index 000000000..840f44346 --- /dev/null +++ b/apps/games/bit-jumper/project.json @@ -0,0 +1,9 @@ +{ + "name": "games-bit-jumper", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "apps/games/bit-jumper/src", + "tags": [], + "// targets": "to see all targets run: nx show project games-bit-jumper --web", + "targets": {} +} diff --git a/apps/games/bit-jumper/public/assets/achievements/1000.png b/apps/games/bit-jumper/public/assets/achievements/1000.png new file mode 100644 index 0000000000000000000000000000000000000000..90fcf64d851ca634e955185f4bf3d73f0138f37f GIT binary patch literal 4229 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 BjC}wA literal 0 HcmV?d00001 diff --git a/apps/games/bit-jumper/public/assets/achievements/20000.png b/apps/games/bit-jumper/public/assets/achievements/20000.png new file mode 100644 index 0000000000000000000000000000000000000000..d74ccdca8fd456e64e3b6d6898e194d6491167a3 GIT binary patch literal 4884 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 literal 0 HcmV?d00001 diff --git a/apps/games/bit-jumper/public/assets/achievements/5000.png b/apps/games/bit-jumper/public/assets/achievements/5000.png new file mode 100644 index 0000000000000000000000000000000000000000..17dfa1e60c877591f2f4d6c1cbe5105989ece1db GIT binary patch literal 4541 zcmcgw3p|u-w|_~DNQwp#Lvuo5n1*I%8@Y!HTjUZl%*14F&5VqD?lrkonB1klNvT{5 z<({OrHcGi?>}S8t)Tol=SbAo7vq=)!V2upjF~ zqv+rXG;g8~n?eVz0l<)r1z#yd79Pf?kf}^88>jxo0t>#ciV^BY>tKI;3>k!@SO;^< zKTN@2ICVc3i;hJg0s{ke0(a@q7`_NS3l8_-N}QiTc_olmS}X8%ZE)dlPgCcodq5M;Yw; z>g)F*fAeJN4LZ_C>LU&GF?uMy-57ne?$gtP5)+9t)l#8xvt_1DnNX9eTOe7!%7A{l0er_gCk!&U1) zH9utc?{g9C7~c``Ylv(-{cjWmjj>rPqs4z0 z@1L#c2OF>{eM4u&*QRC^qxee&07z1-%}pHH+3&IskY!)1wA8mho@}ez%)Nr@E2=ta zant^Wxdoc7XQLY@e}4Ph#)pyHm8}vVm|vI9va&+Or6@~UCUW9~b+cjcV;x@lH{%bT z=H87w#JSZ$ohKd*JaII4B|oF3e~SE5Gi4$oZ!G0(NlveCURZAXY>20?IIvEr(#k(a zsPToG$dHmMFa{Aq?}apAOo6tI!t^BRlgt<(d)xn!O2a=V^0x8MvQ`ef#Ve$H74P&P zK6%lY1DuBszaMU@S`jRoXs%U_@mT!OX*WHRyr&31bx5U11Quh=B~JELZV;1F(x|r7 zY;I@(L`6k={FR5Ol3uP*tyV_uAuXsgX1D(aA+dUy@!19Xc!%obV7*GJ!{k7%qPDg+ zFnT$v^F@4I9DVMsQ~H(D^Mes8dzRjt_3w?kJ0%QJJqs5v)ADIa+RA==t-u(fIWfPl z_qM+r_NSlD{d)BH=wpS4Ws-dr6Tx0C-NG@Zs^A3*T)9Fg69xPJgT7c_Sa{0vGH}vy z$J$Pm^Ul8OHXeaOdy|wJ8>7X901Ab2s%6CKaQzyd>=lwXizU08HXy>2#o=)B%F3RJ zTE*CatwK{(BT|$7)pBK8z8_h-M;%9U6u)KDk;NUG> zV&m9s{+&At4NFf;6!YyNio2=i@J*3L6Y06RqP$yg2TXAG-4Z4sFn(03sH#XiZeA&u z{Zbrg82vS?l-iF4UWW+D$jDR$Oh7r!YPLDp*u3!1;;9Zx3uAdsVo59fX8|Hr;mcU+ zZ&gC|gB$7xli&4KmP_*un$NV1_)#bp23Z!{QyOXY%c3?U4?D35H{c@Ub+UBSwQHKM z7T_*IrjxXOgQzWqaTfi&~dM_KfZkbv<#a4-pgadXXw2&prJ-&*REYw z+fz1ovt5@oc~fiYZp*J;!7VKcGg$Q}Vlof#;PG7eefCjcGuX&D(HImlE{vi?EGz zV9f<)>Ms*XhqaS@Z{GLqZ%Z1sDd4ANuCoswH+6FA7Srv&n0m=xqlDOf?8pgxX6w0p z)?svBI|3sE5shvwgn4x1oX^9pAtJ&%xdO)33~+_vo8s2z?hI2Mrpq@hUC7DGV&+7T z%?5p3@k6-<9PUnJVG~XBhZe$Jxf>xOhJ$vH>6-K7r#$cSOJq5hU@4EDxkqI}j3Fjk zP_u}LJt42&o+zOxf}BCreNqz@6O&66$qW0aP(d4<()6&=^bB7hW@DH~9|^-_U`kRW zH!BD3b=vKDcP-708{58TMJX&SEO*8XViFj*J4p$1&l3?x=|e{d3_XKhr)BPq%CrD1 zel8((Ug5+evIVXFCYEX&uNJz^DUXQ{c6A*h57a0$?9o0pJjSg{GFQum2EnbP;MP4= z$G2@dEdsY@EKBiBdKnsDR8JeiPnWMt}2^#|c|{@W8T0@Oc6xVZ2sr&)tBXeZ3)z?<)1M zShudIP$Lyj_V8LIG<~&K@-BFqIy=j0wcZm`2|dXiYjZl))!7-nS0zjqC}ED-atEsU zb!Q?YBRPe(~AS4BuQ6(1`}GYH_OCbwcp=dNKX; zhc}#=9Fi!b7jiE4^q8T?%FI9y zCG5J+{xlq4>f5diT}SD&%(rgheNGZdb07J z60qra&xIGL?aGk6^kkeuX)Y|}fXJS`sgj!X(cfb4Ua_faz7aTSXMtV!EhI#>r;I2u zRWsXG_P)-|PV@PGprF2;fGp~Us#!a@60a3<;^IUBV}q5PmHf^5x5yJ5V>h^S7U~Dj5?>R>pB=$J))#!{I5``|a$UUriKMPl4WL zWGx!~i)-W5^FlYpNW0gCDwLO(Z{EneeS7mXTPfAy!~FaRNKjbJ(2Lvt>Dk#g{H}p= z@VY{J37){lr=~=K{kFE=3`W_dgs$Qv$rTj_(x&gI0qkdwS%<7hcN&Q^^#CxX67MbV}Qwq7rZFf#(-QCWwr4k$YoDhyC*p zLa>beFMmnf35jn?&&eU?zimY;Ty2ro`fz^(EPYUd*nu zwgoue`iql>P2OmqbnpO0HjwBZ6jRiexf)%49L{6o1G#O`Gpf)tLFeP7qwd_nBqS$y shsME@Vwp*3* literal 0 HcmV?d00001 diff --git a/apps/games/bit-jumper/public/assets/achievements/7500.png b/apps/games/bit-jumper/public/assets/achievements/7500.png new file mode 100644 index 0000000000000000000000000000000000000000..3afa0f48c24c031169e00a35fb1e3040022f9de9 GIT binary patch literal 4445 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 H`$YW%lJrO~ literal 0 HcmV?d00001 diff --git a/apps/games/bit-jumper/public/assets/achievements/balloon.png b/apps/games/bit-jumper/public/assets/achievements/balloon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a3da9c6e89477520eb92846190103f8b72b1d42 GIT binary patch literal 3587 zcmb_f2|SeR8vn>LQJF%itD2FJGBd^qV=ObaWKCl~G~X}Z zt%#6)Nh+12oSaM&iWDkKsQZn|iSE6>-?{hBZ@&57d7l6Ky#HtYX5!pk9p)=7Qvv{B zzT*a459l5#y6((rx18(Efu46EtL>oUj#lq2=8HQ{}l>-v(OC@ z3VC=mIy5vC6>5ay@`KTaW@ct+3>J;W8bAmG!A_146dP~^s~}4=P1!O8G(M9jWO6wO zscDeP6$veLb*E8ZDA8%t$M8ga*3=<%8k)gkuo)bo0BwjeoWYV#!wZ>07GoB1B1-de;EX#P{?Oervt$epuj1KNE$s9lvp%Kmxcl}BNShD;fZv?cf_ThY-VhqC4qt= zRq#N*fI;5LV_4{VFa%r?pT_vU0=^ow;WI!XgKmk%U~vW*Qv)oPfS#qAP9ou}!cHu7 zq+3!MSW^>IBbtGck#P{1MnuURe(s$*Io*rtJVina# z006t@XiFrEPxYtXP6kTEqj@}Ff?sIMX_ zDh|YGz~><@Tovlk){r9QNLhY)hV_*~qM8}mU`UI03H8hiHaIhh;@kNyd@f460Mt=si?6pu)o{R_a|yEWs_ z33q3K8oy}IE#yk-&O02UoX}}5kP*njNog7S!*3FB zC8k{ZW7B49c`!M0=P2Sfo5m&w$Pva)ATD(Uh@1j0d8U03TQ?M#K%Lhedb zVCeyC1VDn#tFGwn)vv3sH#9MM{Jsn#;ptgJHH6-J@l^HEk++h;fexD^ja}uRK975k zUROwqO?6G*KKW5}>*_&k#IsRNAGCWl#(mx5!J#fEXJ=amM-rbhDEvKRhWmnQtG+DOJb5c#BOi6zlQtnIKwWnL%{c3cI^7ol> zmXFGBtfS_CDx_p9gew06kM9G z(2BEZAShFu&FwtgPe@Tq^I7-2v;NR;Wc{{DJ@XaaR3JWNq;0RSj9h=Ev#NFQF$%c=_hdj?&aQbLJEYdJqm?umkgW9nthK)A5tZGS z3>@7kA7u>{)~!uOP#u!>)sJjk?R3H~tB!0gnI}<<3e-OAI8Q~zJi5YNFD5%1Rns|G z9P^;I)^1|#onpnVQbZ&6QhNGeN3~)f!3*>NOdxAq^&>sdbe3F?yObT=A@ zllUr{Bd1EFr014COy69jZhc4nO7%q`dj71|9Iz7iFTk3q{W&*Do9O9jtF^FxyGwJ? zEv;@psCJ7>N(M&% z^oX?8ifTND_UB$>o`CJIHWd$08XXaiNojgY4`1QpYqiLp1vL#p*HThaC>v$Fhh$(# z)9?w?_M2fn8(?`6?at9bEfaU{%)6IrzMph9m(f)66k`UbYba#2=tq7GuxhJZVRb(& z_k_l6x++EG89sHqFb954%uu=}t164TJ;c7Qc4c8;$-$zx&H9%7pC6LI7!gLaZ6Y!uS3@LG=bT#?CdZU z{%PVB9I^Q4j)xbWG&D7@_yb!V9*bTUC-yX*>FjSSOl+#^z$7(Xplx|xP+)v8Apr~z zZ$D-n#oY!tCPCwC-@bjk&bs*y<)0_VM@&V%M_K|7YtL<&@%Fv(zENYFUETvIMM=0)WxC#x1kMr)HbC-+Q?N zDVL;uw!D0$;sVVOv5FVO0PlG1kLaszir2ha1EF~1eQ6S%#XKD$O9y%30ZL2w+R`Lrx+T(IeY^=QGk!+b8Or|%pk5-=uZrysj_d5G1uzB-l)3D)n z@wMlAdctFFL?K8AdLGwv<%M?vr_t+kb30upIq&Uve7v-)MKfIGMjC<~vA_s$6*t9^*8USeOEjt{Ac(Od-X3mCWsHcfxx#m^K5aqx5RG&3) dzWq$N7txTT&X)Ju6f6Ck=4j_?n@yrb{}WI+j^_XX literal 0 HcmV?d00001 diff --git a/apps/games/bit-jumper/public/assets/achievements/chomper.png b/apps/games/bit-jumper/public/assets/achievements/chomper.png new file mode 100644 index 0000000000000000000000000000000000000000..4e3221c3e63208b12dec6a0459081b6042f14771 GIT binary patch literal 3683 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 literal 0 HcmV?d00001 diff --git a/apps/games/bit-jumper/public/assets/achievements/floater.png b/apps/games/bit-jumper/public/assets/achievements/floater.png new file mode 100644 index 0000000000000000000000000000000000000000..a588c407f7008ea8bd35b164af5303975667852f GIT binary patch literal 4279 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 O*Mhl;4W`7%E9Rebu=U;m literal 0 HcmV?d00001 diff --git a/apps/games/bit-jumper/public/assets/achievements/helicopter.png b/apps/games/bit-jumper/public/assets/achievements/helicopter.png new file mode 100644 index 0000000000000000000000000000000000000000..7af11b01fc87fc7bc182d08d7127d07c063b3d05 GIT binary patch literal 4255 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 literal 0 HcmV?d00001 diff --git a/apps/games/bit-jumper/public/assets/achievements/rocket.png b/apps/games/bit-jumper/public/assets/achievements/rocket.png new file mode 100644 index 0000000000000000000000000000000000000000..4f6386076f03a771bc034d700db517c9accf98a8 GIT binary patch literal 5076 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 literal 0 HcmV?d00001 diff --git a/apps/games/bit-jumper/public/assets/achievements/spiker.png b/apps/games/bit-jumper/public/assets/achievements/spiker.png new file mode 100644 index 0000000000000000000000000000000000000000..45d8716b72806cf0fecbefa4e9f36c9ae5eff907 GIT binary patch literal 4250 zcmb_g2|QH$9zWLX*LqWtrED>aDTcW-V~B_d*H*HOnZcAO>F#Nd3UO`7Y~9?EwJ6WwMhS)6Mo6ia?`4@kE*r z3CgC>L1_R$vr*tHg~Y_GvMB-7AQT&;wIzW9-+5%17FJC4w+qc6`l1}okNhSI{=;bb zGnsT03>Fd+0u4C`r7`?q`o_k_FgOB+KtMnVNDzn0#IqsPpnagF?WW90K?DYw&Lq>Q zsyx$p9~z5^(bD=P^{Y!n!lz~EEJncAB18g=6hNYosLUXkK2(33mqY@JNoEF+zHr<$ zfcXU_fXs^o6@aJuVYJu~BFPue3SeqsovB;;L{%awi0nsIg{bPIVLS%|$e&r*qHH$` z`zK3piG3F7f0+bRCX+$-`IHE15EQ>fVezsD1q%zq6M3nCZ%f6mS}0Ru&}WYGBKejS z_yq+_29H6=N<5y!NUv^o=GBN5pcvI2;2yQK%ik?us#(L z{TsuA%{)rP8W0T)kVqdNhyekw4>_cdAVQ1{;0TD3KGH{@c*qA%#KS+?`c>smmX7%F z3?U2)B1lZH2t%w z;#GNTTzT~c8DM=6ZmTayLz%Le{xk;Gmh8tO1*jgzQ|PoHG*9|>&KJ@B@4W~j#w*`X0ILfm$y|(h;YVWGLtX-bhX~%M&Mz_{B>a=84Z~ZQ$e9C zG0_V}qo&f)Q{9p3qaA`5M4-c=bj*~gw7G-8UMG9AL+$3={aHlB>5SKNAEfeUW^=o+ zX~$Mvms-T%IyICgl^2(8c-YtgaI4t3i3Z@i0d*m1C7sA&D?UL>F;yc+p!E{J$VGV^ z{U#8-?>}duzlY+WskCHDN~p)a5Cq{L&Tz^a*ykjEU0ZB<_GQB2A|to= z<;$d*zKR>o&0ddtaYlU8)6@3O&X1mB!`?@7Q&sjUN|^O6DP=&BA{qcN)gYD16=+wK zXafkzn_B7*MZMdBSZR2B`y+t@H7^07&%D=-##zgq%_8rw(6)A2WW2-?TFIWuXoxcS+a_tF z%gZ&3E308{HU2U^FX0khSq8edsamquI@UHemBbFvTB~AA-%KqFX4kgB4-k+p4(V6< z0jo1OE}A>GkZjW_XyH%~*s1t4;(&=;*J?#mnkwZ2tJ5+K4O0VWiWl(sp;ua^7G>3mL!r!R!m(Da>B^ALVhaKd*a*Wd|-r$q*gAJ^D&O6P>H)7rsDiXpnVsQcb=6JkX zk!`lH_ZOfDE>t&^CT z2xm?IwVsw7zNH>|>EVp2VWG!IeB-yPVQ(A<9tX5sNfCsYO{e zAuE6&(NKP)uuv!u8(!rc3ePfN2Yp3%l|8T-x#<;a* z&$5P@*kAZ3&SL(uDz?9PSd6bgvc+7y>P`$Cc(%JBC3&DM+wvKtB2B=I%bQ&A3LsCc z;r>45t}S2XoZd4DcBCyQkUKS{9UmY69<1=Cn?26Xe>3DLoNy@~Ve?INXD5945bAj$ zS^t-%rICT}gWj)yM4HTvaZ`9kX}KdSJNu`;KCW(I zb+ue~clR2)T`>dVo>2t=Py725OI<7aPez${8>tC$IGkIzZ=14M2C&05RVY!exVKLo z;H#oC>zj4FnYHPKa!WXyHrrfwFh+CX$7y*66xU>(7{-uuK22=dNtvWIvEo|ZYYk?( zBFr<8nT+D^BI-IaK_HS>P)HGU+YTely5xBfB2T_`;xV^N`fVmi;O z`P|P3&iVU`RQvVRvG`iOpVq-OPG}c`!CWxj^@E~7p}c^AfE+4MCMib*Clb{&**4Oa zPzjD<{qp4ac{)VyNy?kBmJBwg3?o4?$YHM4hdi3iiZPf3a!5Z>eov&+M#B<+MP z)^w;BLvVqCl@!}^O$51-m5&Y%4){h6*jP7i2(-MgU1Fod%JMP|5r}Av zlPNzwJ`RG(+Et=^ft8cPuf)Ss8njv@=YusH6lOVCyqoSZR^r@y;vu&X=#$R#zV!;bax%*VZb4 zv!>$#ORMs=wiEPD#J6P5bAk(F*~)3sv3JHq`7)dX+{JI9X6=J2>w6#P(Zz`$!Pq32pI`r)r|2_;Rq}{gs>A zmuCcl$ktX<5RA0O-@bLUuJr54t>*_?ijU{f!EN#CD>1{u&Ym9bMdfeUCp|s)8V0)|*`OC_RmdBHhA1?D>4X2c-_?%w}$LUU#=en(C_oXhqu78Y?V9>n3 zhJWmPtlW?}u`Ba9!lqIEO0GNd=8?`<9Z~sXLU5A@#FV-nJ9bnrJCU;tq0Qj&KtrPs z#L*8QKKQuM>pD>~MxK$qy)FTR4Sx$x1GmtI#>RtGK8ZG*yZfGtDkc|ksx5hMhK7b> zH(es}iuGq#phFMB_pI#x`M``hh`bvc>q!|I8G)~VuFp@_2Tvp;gN-3mQ&Yn?LOLea z-%TFhsI4;Z3p{XfCvY`q&(%4R+%#R}uGo{Zn!8fB9slY_A*$JKmU4r8Tm1y`!5PZG zcdxIGSlZb5(x5a%lb;I{?bM8w);n4Acv-o5WCYJ-GH?C@Y1!0@l?ALeN^caX<^Zza jEJFU3|#R-)yNRhPTqhoML|m?ZfAa#OL95!?AtwLq^P((mHiLOiPC*7DhKCiDGS{Lwwk zmPIoOo(EG!QZjPSA8FZ>VdWuqG*s=fuWpnrtJoen^AP0ql1^jR@VJMYCKE91E7#(+%T5g@OU}J%_d@fAd($tLK?EgHBbVrkqVa3*cPt`P;qqFbsA$x|jNqJMB zDBMxkzL63NCj#mLx<|Mc6YQOGZt@MM=$uFSgDXy9^eG({3+16oW( zF;Oa%kiZ2(mmE|Y_~I^(Ek-o+k!v{Gwot7}3lif}V&bI7;Bj%+R&t84w2)XoIbXV% z!?lnc0~M@u{p2@((v_rOq^SFuB*0#*#&XMzBHjjS+~bx zL56@Xq%n`xLR{xiBL&Jp=m1z~5-U*Eh(oe~aA7R0RQt;Sm&~^tF`3u=hFF50s$X;t zPy%RVat@JrCcfIoZ#}{VKAHG<*Rd&F3l>-35Q;Y_> zMCNwI@XJo^tmb0r1@6p=oMOH}-pLEGi0tHR26!#l00S&r(hM8!e)mg;UVCGgp7Y0xe2(-T9~vg%Dok*Xa2U9(GSQDIkm#ay4+iJY#3ruU)pNi86ZG%8_2a0a5IXM zHlWzMail}#Sb5wSM$$ljA6Z~i40}G5!~vWhQ#2)rrv?)4?&QT)JRqo;jVd+U;{4gq zgS!K96wo!68Cm=rN!C0k$2-kO8H34(+KaYX5NQTToRO(+tA~5=xQV1BxkgLcv~{Z+ zQcM~#{F&SjPu1`FMQNK_Ji4B_JmMZgK?Dbzavf{@#)L)y*b4jdW%DZK8xtr11dPuJ zkICVW9zOGVDd#h!Ann6m)I*+O8a6&ohtXsLH`b*$X2`;o^<`TuRQZC-OS23*@|TF% zhZOt?UK%RZ5~nF}jlH5AHwrrs^{c`i<4xxzE8s++ysVANI2Fh>5XA=P3!P=nC*n3k zXb_~ZFi0(DpgPm>)+BXeHwsDhrcn=9!02GlbGi zuq|FZi%|H!?V!i5WQFyK&@@vLTq@9@(8)Zv{>_$doA`@wYMVYt%|s@Mu_utWZiyWd z437?jc}MPHo1u2V{HdRT8LBmSlH!Amk90w!Bh>{bDGxT6L~3!A%OZM#35ZxX8)GX5 zF2bf$;1HWXlz-gK&zjs=>AB@9sXfe_-PhA*&O?XpPIo1d9=OHbbgOtvw()iK4soZB zlNY_n{s|soT%>RV_YY3wp)`XUl$kU-NF5{Th)y%3V?lHiOO$;CMuU^Cmq~A}LKQ~S z2Q5*W7jmKDto&~NJOt-9in6+Ajh+W8z|}g$tKty(8PY z&{o%pJhE4mYpObF0!9u4A3%z@-SZN5VPo}#bGB(DN(%vv-3D05aSnq*>sodp~~y@@lSSi;%-nsmUVMwqdMA|Tvoe*n%&$!oqRz_8Utwjpth zBKCXDPK!yl_x313JJigllT>6nz^Ijkn;2hcEl**T=p*kBAT5em;+hAX847W* zCWs3>A*!|6Px31itN@OBwfg9YH5`053euln^4Buge*10|;L`0tM^dbXu;C>zylpF3 zggnJ2%|+Yhmcj{z7Nn5lWQsR~UETCH7whV%lU!xmAS@ih1gIEr((Nc06xQfRk_Q(9 zlt|Jo_F@n=jN}f73Xye4*FnW_V2LyaAJa)A-GX|u?GfD41jc0_`RxT;c>-=UfQit8ibaHU9q1BHG&yseps;8OMgtC>NK7WW>c~ z7`*(pp#9cH5QGCjY)C0;_d7aPOb3Oa=;kD{&0#K@?ZB`f8Ab=wgy>vDaQfzaHw*+K zimo1Qq+`edsGWKtbOcE&8Au^5M}Ht|fb-l8IgH39ta>B>Tx5;jVMv@+>8rpU;Tq-m z;Er=(b7TD=hqD3&qPlYw+hp`bNZmMpR(;Ny1pI3$32>?aP6130O z!}l+Cq-X8u#)3Hk#reI5U-i4rDhg)X6ZfyI*(qkuQ!Wq7<)w)Eb2pg_{vAIS?d6T~ z&r{$l6ae^Kk3{Rah_4jbgdGAvT!8Bm;*-QzC{O?Z0{Xn2)KnmC{~}dGvb|W?uJt3A zL30pmU!xr;zp)IQ+ISwwH(~7sy#=?hgt3f*EI8d*oIs->B@hj;28R6D8?mfZ3K*5t zsB5F~)bwIM*9F>LBE|N&dNi7*U>PG)n7rv~mn!iAU;Kh|SC32iK0$lVgbw>ewUdc? zS1dan{A{b+lR7Jl!_M231Q+<(z2#@l?_Xgum+wdMLb_JOZ!ltPG~voRg%1!kc#iyArHm;z&Z0?l#w2xU)eS3*z}l0e5_9s*<2EgF1yE9 z6eBmOSM1xRF}o{shiB2iOF1pOH(;x8blE%4e8FT!ETtofHWr;JmgdPmf9t8T0foQy z_Qm$!g zBnSG*x+}wkvlS&AN8ex5dRj(kzI@)&=9)}gi{KsJS&3qTHw~rtva0jw*A?}932^1` z*^=Ym-tJ%a&$Nzzfl>c}!e5}X8(sXrR^U4nK1Q2Vv#cN+*P#G~36CJA!M{O4TT5hB z#lUHSaF7F!&u@*>&ONVQJ+vd7pmZotK*tLqy!zA;@QiNl~ z8VANAm`f4NCMK2na#>>TXmiBijspjDllWU_dfXKY;(d`h)B(H|-K#?DXv+ znPf5l2cgVwZ)oH1BL9Wt)+eG zru^mSnFj!*5$<}Ah*7v^LO=VfCa{a?GMjr;w8!iEVtZh zs(ROG;ha*t#~S9<*OR>>E_8Cv&PgDyh4d><5VUc3w*y(+tYn1539+3wmbBN*#99FI zwX8<9^7RoFN7K_r|A7zcrw(}o3O`luKU-t#PzZ!pv#dTvu0w&%3DdV0KCDsU+wOyQ zdG2NH3r2pbN(uzkiYi42H<8b}a;MQXnk1V#3<`i{p;_4?-b0D7XG-!^15BN2?rr?; zRjug-;-l3YVK3^mm=Pym%#d7|ZA|MGHXuR;`VMVlO!W0EtT7^s6>DZ13wfVeyFDH0 z&$pD2SZyMFtL69&=4yQ%llh3r6kQ{N^-9C!a_{fS|390If3yBv5c`F5ZY z@d-n_N?SH!wcEEf8!Re#AmD>`PNT2JJTC-$S%7-#eCP$dV1?`3-Uv z1LN+bx<(hz1$xgi$lO~*%Ez3!Ely9AEgWv_n8KvE`+3Tar5(I7rPJqN`Ir{2V#Rmd zB{*Cs!#0eOy^rV=UuC8d2UE<9Y-Zy#G@U!xjC#&--=YVW3Cvr>?C(308nASfwzu9SUK8NQb?C}!j3^C_pSOWq zJb-9KLM6pFTNK@FC|#ZYwpjKv*H+C`=n})~l+h+ud>Q=RB%$tJdt9$T<|YfB%aY5Y zw%g~YSLc3@1RVc$CpT*RWCb>$@RJ4qb2YaPg$K~6NPa4i)xR#p5(j z*-h}VR$hN9rB`2p)&)(Hf{?ER<+hU5vA-m$k7p}f+$UeU+^1df7=8PVg5Ut*(Y|vd zml|s4KfggmtF7!Qcl@X=A3;V#8@y{z^bFUks+cBU!8p+RISblyJ?r&F6J+>-G@EYL z(?sth8S_QUr7xLlM;5G@^GxQmBcGU}tJ9x0wjKU=0ph<=`v(;Mjf*!f`Kv3i?i8w_ zRclURjRM~eG_o-;-G6|>j^$&w)$BkpB^#DeOun*~B1;S>8xes6;+yk*3Lua3^eto_ zuf5@!6)(S^IhtC0&CK+?+Gxi?Q1n9L_jJ6{?rfCKfmb4CA{*D80$#qsTd4vujJKpM;nJEa)MitkdR@~Mgx@w+1SVRVM%k#g62Rtw>FgoN`?2ul+o0Y0#y7b~iPUCy0ihN-u ze6$aj!^g6=9OK*yB@dqPjCd%P7v&BWhJT%w#<$5LziR8N>$Zuf`TM&D&y~3*QF6R_l%-M5)&-K= z%H%5ds%dDfMN%K1k%rlu!=rrOxIJ}pisr#&NL2J%Y!*M)YD+2ax}aJ(J60q$HKggF zw=Bai+R#b_A3f*fT;l%Ww!eM(+4?wGKyQqf$*#Jf_>37=-I=`M{tFW!`?ntB;68ol zZjt_utSj5k<$NqXZi?P!pC=}!v~yry*JolW!ucaRZE3gl+6ezM{Af zeoa8+t6I+E$MW{P*Kqf(UXEEg!t1AJtI=T|U?%4|vs#G_vM4SRUs`w={<`6OXJY7q zdG6=L?Uex>z2+CM#4Hcg@3`SE;U+ie=DAB?nmypmn9#=_xjp+&F29?#zu#6k&^JpM zb?d#pUk!1%Z*uDqbB`9mc}ByF%IXCN`m^}l9PM9Ejt_Ra@-F!>;88r%%(#t*3K@0e{%}bT$PCV-<`saCyOa~A>*^E%AXV)2i3H8LG;Bh zw4!h$ohjLfov#DMjE3YIv{tMzonJ;z?&J%2`Sf-#b071OZeZKNN3Z>0Z8oe%%}^tmk<=OK zyU?A#wNh_?Nt&oJ-8B45vr;P}%p4}DP zcPHze%sqyKRjl!Wc-b2mm*>_`SIkR&{aVV3OKf28(yO_Q%!8c;rK6^i=UQ&PlRwBd zubyp($$8sPh`wql9Pm!?910~6HBu~cSUElJ?7W}hk+6qBGR?O4LK4M{$Re;!KgXub1{D6YRrS-ZR+&Gx zTa_n4NU82E{(Z2bvk`vcA}%Nd2h-nOi0bzd}I{vA8=*j%6iGXB`R>#qg_$ zcTtq}@WHYlRM>2q%@L$pq)(hU&Qfeht_c>C-&Pbg=HsiYtxv2TS8LB`*~WXP-N{a5 zi~C$h+x%8FPA3@#+w0l*Fe^sEj;Fk@)oTxzk;|_u=pE7XMlPvhx9;8^KW=}Quur|F zo3_a*+tqiA__NG<%QE7}Ip30WyTVGo;0{NT%#OA_K{DQ<#H$#tXR^N>Arg!O-Q5Gi zh#HCfel?~>TGq2hvArCoduo0W@G0San6WGN3}!e-rza&S-{a&o%zVq+Ax1@!&sFxJ zR5S6p#hl@*w}MN@+lxX+*k4ceqa%aFnxZn`rcpj{P~;)DlKy6)9(y%aS!r@U6_8kT z=I(DUs2zyY>`sll6|x_FPDt4e5(_mp40@j%Z)?cY>Tlr@f*Ki4K;^fl?X55|lRjlQ zIw#g9(ekmAupp6b9{maCiv6fJj7H}a?2K&gy$HDg>lD|G^e|x!N|mY^S5?5{Vhy-W ztuIV^AX6oUFGYQ!d-5ing1ba>*P2wi%c+UPD(dc@e{~?%&A$evthk2^i`ki;+A;oG z56g^!M4KhLJ-nCY7gC@3E5b+edI67w0qtxyc&6`i{=~fEY^C>y1xxN-z44nc&wSAi zuq35lWMyG`HhB5W`{_JvRd*l!!p|diO58svp}f>gPh*Qp(yfFIDEzc#{by`wJ$xWX zD6lN!*7h5|B^pHoIKJi-?yW;XQTNNQJJOpvw7f<^&SFZ!Xekc;o7V|OtHPNTQ&C6! zUTdlx6o|F(=CklwdE3ix%6}Wr?$})w)VI_Txc_yL*giw?ea+0B1-ILkrT1Rk`Ag7P z!i}@zna5jr#cfVQ&FipX#DzEaCiL@DimxV%a%X0zcSmC!x=LwCgXN?HPoun3JI>&H zUfg-zTkQylxebpfUW~JD~ z+smf<+(Rt0LQKFB5v|Wao>|l|(pbs|AV#UH(0d@E`w6`VT1l_p@Gq-yW#S zpWxe}ZO*5f9<8*!O_7SgCtbk}9mZLxqap1Sf2^TgJiFip^$>8{gbUZpnlnEa6|R$#=je?oH_qviKudz@ z2`mXwh3c@vH(6tGRy;oUWnJ0#SNR_()uGGHS9wSQu5k98EAwBXC)6((h?5StNAh#b z8lxTU?(NZlOBdQ@vwF%9$xfGrr;HxP4;aIy)TA?#KOac&EETG3%Gj=J`$|3iM4qiA zsY0Mfv#RgLcE`a`eo|^K=8Yl$dGO6woJM23hPjwQNtR&CBD-MmGFJ05l^JE>$jQBm zANH4_Ul~-rF;sb`?FiP&E-O*3^5{}Hqzi!g2xA5Z4i%kCIlbzeSX)zLHp%_WalcWY zFNe*%S+U~vM-_y=1~1ds$UU#itB&;Ix6j(|-CAmrur&txgtKR*nBeRaFCpZ0_;gX? z_Q0|ZzOA~C2Iu8t@qDSU)4RFd;}{?~y^h;`90@jrmufs^q#H`~tj>6)C0jUx3ldv8 zT%M#pdaTfKg1Du!*-Yo6i=2m$L&x6BrK$?c4PqX+9|qnzh#4bKlqX`_1~UYpq$( z)POZ0Y(fQu3J4W=uK+YP;12*|g&_t@VgM8XNMX4EOlnCs5;I1d?LthNU64#$ohEk6 zxAb*Vt{LA)x3wijSuRk6o6<{~bgHtQ()}k)eB4o*Mml=Ux1DIRiFEN@af5$S=#+N- z&9Tebga%deS?`da^=xa*mqu$I?aAwlRzGAyZcslw6!*f8uVa28zCWTruYJehRIJ+m z(Ucpmsd*E3^A}i~%Wq-*s^fK&>@%IUzPo8?`^;r&2Jm>&;y zafxwH7-XtmB+R^gu@4uqd@=jRG~uRZ`re)6g?Ui)t%<$f{e)K(iX-LLOMTT#OVgT$ zpU?EFGF73{%>B=fRh^9+zWj2;y+6M>rS2&-tqO_NjY$?N$|Ia)hqlW0`mJzZsxiLi zQMaa#Q5DP#CXkU3T|&0iOBNI_JhR8d?bI0& zgvaC1%h$&t=t3+6y-pi}W?NU)^Ms9A(CdTH#iR69Dakq|MFGuPnoXs1rco^&Y>f5I z&Gk*@Oi02&zMKNk)NOwNHIYPY+?D{&9{*C<0RV={c%r;*IBj;5NCN;Q0KnN(uR8#c zA*LQwiggJYAx1=YP(}g@!SG0{$+n$mTYreScV;xS;&3jgo_yCQNOHng2ObQHz)@ff za1>OBVZkV%2Q+}8KvRGg6JB)cN?35<-sljmKwn2cpFv*meP2KP>b3sUUs_~_`sqCj7-fWknK z>fgY$w)RIfnGt;JnOGGcO8`rg*|b%#;K1X(%cJ^&#M3zs(huCX*M9|T58NC{fQ3ks zJ=XRqVK1VPHb_-+b+hZpf`)6my^9MA3s3tYGT|^9ZMBkE-BT>seD2K=T?@^CgxEA? z+<*aR15nJ7~zA%_xN{D?X&DD*3Sj4r=3<1MhNHOxG zGKb`^?JUT5V!&xBZyL@{&N|cSXH9WZA4QIlr=5vQ!Ou3Wla|vH>g%0AGU|osYJDVr3tQqyzp8n%M}C_OFM!s{X8Lc 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 VA87nIz2-%4Art0>&Ht3-{{kQl@%;b* literal 0 HcmV?d00001 diff --git a/apps/games/bit-jumper/public/assets/audio/break.mp3 b/apps/games/bit-jumper/public/assets/audio/break.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..ac2603131d69e7c4081ae27c273fc43b3651a75d GIT binary patch literal 22986 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 DPZhFJ literal 0 HcmV?d00001 diff --git a/apps/games/bit-jumper/public/assets/audio/death.mp3 b/apps/games/bit-jumper/public/assets/audio/death.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..e5c95f4fe04f1bcd1fac3048ac620f5a7c2a898d GIT binary patch literal 22986 zcmeI4cT`i`x9>yf5Fk`TmC!p01f&}v^w2v3LLi|lML2*hKnN}L7J9D&QY?U|^e!U3 zh|-%4upCsBr}yW1=Z*2+xbOYOyW@B7{r%4RV~>&SHTK+VX3x+1uDNFR>DN^h;IHDkKDUA=Ku1m*1+8P({FLh z2@7pZ%)ElwyL_aUb<|a~u+i`#w|h65kDnuO6UvHM7k0q`%Yu)<tvvovemB-^uS5)DOE4&`UO7|GbjGKn2{F_x9JvnBY5G>U$g+8mT9*T^7pYR^oK1ixbt3hJbt-gS#vD%~Zo+ zYmf3Kr%j3tXTo0XsEvwVu8i)-JXeKuFkdLRFF!Hvs}8^}XWdm|4-|ddb>p04c25p8 z0r%T(<((zhHpY~``qSLJr3cJiFfRhk))?pGg^T;;V=IVXs z3t3}D@oYuiL=iZH5#o}(czpNUKFVm(OEGneXeozvq!~!+9PeFSxb#zX%X60!Io07Z zk0pNNqbp{g*i@O?vP=+BMi|%nv3gM5b84L!zS<#p8JqF~B*^_XoK1mT49+No1%1 z0Ns0&9^LH$a2S}T)9AZKbqHVs&`~wGb^8Mrynz)SfcNPZN^Xp{PAE$Slv_rz_r)tu zIP!05mo%P!$$fSC`)S?9)6=RCH&0LPJ6`@c*njkUb-wcS^r+-iZl8V%z-UVcfGECw zDWL6OQZUu~g~vAM^sJKh#e%9=GkMh;Z@BY%OdxBRWpW0v1TsOP4oMWMAg4g($S9~W z8C80R%qK`9i>+s%lNolx-(n3tvLo%i#@!FNUeYFvp>eoCwc-631h4Efr znIdryv!^_V(sD2&u>{N$=ATf2#(z4N)babaT>48WNcB)Ky!)E|6AE|$fC_=hqrKvu zL^bU0LbDkC3e{)Y6vc9j z9OLAo9?`_chz~ADpXjTxGSU#^kz$&GMMSRnlWoCWBrT5V*rVTY@cb>Vfb&%1_D8^A zi4*;MI+5AvD55LKu{mzKZr04=43)rf7YybK18O2NV5x z>%f-{*QVu&!(PRD`xtA-%tRtkk{rK^6@q4R>USD&1LQDZR<`k{!ybwpBnvuNEukKv zP#W0p8OZA21BkUiQa*CJw<0^vMXMV{&@M+_0W$&ke-A*mznwpQ^?!i^;K@3myO#c-ZtxYetAm7dnBhv@dRP(q(GfB&tk*vEUkEw>WZ=UExLi}tg5%je; zaKTE1sgWMpk3uJNGcAnB%#B0M7p8{Eq5SJIqjnXaf8_J*QC`@I)p#}Ue|+h9X`kcwGaRc@bo10RJ1v51 z_~8|vJIj->x%(n@zERO z*brQEJ2;bRdAsf_G2(Y7_a{~=Woe@KmumcfOneqUp>P2D{>@&O_xqbapr8d$5V{=V z`~wL81_c1srWkcE!F^Ds8X);f8#N7H2OR{Fk})sJrB@HY;Sw%d2Pe7H?M5!#zD_CUqjMD}>|X0; z#z;h9fu33-Vt}&O?nnAK)s1`%NrXl|N*U9tunnNt4bW+cD;0k@P*nWFj}<=ayIrK7 zZ?x%Anx1&3`kh(~c?i(Pw?`GQnm!vTe!rtA8HgQdnXV>oI&tUahlY)mQMl>Q*I0{9 zrx)rghn%S^d_o-d=5cezAX{SD^bL^(ngW<8XpAn-*^xUf*gveUhN9X03Y{lMZgJ3z*?4Z$-+~s4(D}{K`Qd)=#^dcZTbf3{t2)Y!GihGTmUt`@M)t;s%yp7MY(tP{F86ZosNq3*^}Jb*OYG^%#kjDWkofO@cB+Y{)x5eq z-Y-0R4r>{3#Y)^O0!%0#GJ_{YPzC#TCAz@H!oynf4g*f3xzM2(TMH)-(JHI*W|w32 zjPmEVjqJ(ewH(Zp@i>q`12lblP(ThsmxFT~Ng5LKM?e}ZFx{5P<21gEWdbDMlp7I?Mq_eJ_XsmzAcV93u4by$ucmYKKGW6`+G}*4sudEmmPQiO2J*A+tFGa zWXSU-L^jc%hP8!}hEtntLFbLws~oP*(S^Whq?i?IX9lQ*IoO}1Si&a_d#H3o64H#T zO?k+bgR0(7Vm=1$tI_fS5@Aecercg#AFxC^6lZB!h*U%CsJ1cCC?KQDyL(r_?ttJJ z9@5hU1!S3^8$BBzACgXx(%~l*Hfc`7yq^{n&IbNc3aZ#Db+gM_$X`$}Vn_^gy-VfA zs=WGuf8fPNr|*mEH`j}5oE^vFR*pCJpt;Y6R?pl-0od_6+h{Q|N0(c3S&1jD779|^ ziYe31=!vrSDPq0%gWR9ulc^ftD@f&-gT}4OkQaI{--${r z8IrW&DYo+4E*l-#j?Cpt6!dM&yKOFRuEvdQ_n@px8yUPR4&f&FvL?idf#eIV0ttKr zMNb#K-NBr@5stXXa$odz9NyhW%@|xhfu#6)@n9>xXK~SBagX3Qx#9#uxQeU_%ZxA%7UYl562)#ZxkJj;YX5HxDN#(Y})l15wS!%$z2qi zAiB3-k4l4zpUaUg1rd6W0Wfjpgv3dwi<~giHMtQg^*z5yKCl~^lB8hlty2v!I>wc1 zbly=ohseU$0kt93z()vr#TY*t3q9&Q%3PSknE*-?<66dR)F4B07_|#s`^DAhg0N6W z_Y(UT8y5rk#HhxKz29^h*+u)z03P<3yJrDd@|={yTsE?1L<@o?{{#MPx3($e0FjLv+}%!l@!go zaJu(YQyYNp4Ktn!es^J8J0UPIPBzN9BUO0ro49>P{# zOl7p{*AdTkLy{9f{?`>f(&nUv^9ECeJ5^tSPO~#BR+BGhYQoSP4jzr2%vq`GwKltx z6@2{3iNXj+!EvZZbU71Su#&asoNk{*AqWwsV<2MM>;LpD%&h8vQC5JiNZ;Tq)glEKVwZjSgUoG=KY0j8&c z*nkeJj9?s(K&B5$)2$omZwlUZ1hv&@zDRs@+e0~Sfo+fxFb~BeO-&DxvIE8`Fwtsq z+Oz8D-Mh<|GSzO@>_5JL*1KJTb2jS2FwzaI!zdHh{1XZbG~X+|$6u{%O#T6d#tO;X zAsT-`A!>3gyx9b_r&V|Bh5+HtoJdRIl?3-D>95r0h(c$lDTmiLeDjflfI~dQlk5(p zz#oK><*D`v;Ytt_Hpdo+uVfTHkGO!Oh!*L-V~LJWwHaPWC7DtKo^bhPh5nO%a>J#M&?a>9Z?e? zCp4HAJS^h_>NZIm?4JYe#1D^ltC8XWFV$428lG~nri$&?%o8?6vDOf~Qo;NMlmCuRc zvXEop1zqWB72!B)u}~wkkLz90N=uVIT_atNrd^JYGb{QgX1&L7a7q7;9j> zYE{E3#t)pyrlk{^xWciQ5#%-bd0v5D-WzH7Hh0|gro>St#&$%R3=w(&)n^HJ!qK;1 z+J?Bb;W!|IVlI9oG}Q6sSQ4_wYcjdq_f>p}&zGyRFF%JyaB^EclYH zFI+x>QGx13F)WsKOmS+Y1ol$96?PS=jo|&Q@5-k|jST6K-$F;==5TA~)~0hN<+^t@ zrp}dXRiv^vA_Sy_)hWVZpVftpuSh7?DEEP^#k_6QQ*ugu|dYRw1N`FB?PR|^2`S&oxUrIqxMNE(p zLZWlSClG*dy^-PF+MJ`zbXDFE4rg6zJOv)XNlW2W?ng&aRVf50d*yu5{FSyrwM~QB zd#-T%w|gQ7e48|@kDD>>xGH(iOV>M0N+Kv95;~QXq_TCVXCK|Ek6y|1S7PzCU2^i@ zy4ThyIk(sH&>qyby}xGa*XkzGU3!&#Mz96~Lq3j)j)(DRm%@sBSYdNhAh>AERahe4 z7p816*1V8G2?k?Smv3Ou+% zT0nwX_LiKy@iR)Qy81m&&%9aFBG>3NM#rRoAmE`iW z&)Z^CKb({$T*$UI?Q5;2NmNwQHUi z@Vo$7!zY|dh<5MB@0nENK~n$4q3{o*&%dalpHKjRem}21$oqZq52e7~AH2@;6^H*L zr*NjNOA1sMV+Mf0=wfJ5Dj|$llywCx^g2P+Y7;q2~9?RUv1iYvS z6nRg%mIJS#+F-+fgvByaGO^-dzLM`HqA-ZN_I;YHY_yC?YyY;``)P^swb=#@cVr{wnsVA zqecoJZvJxn=r_CIuFWAq4}b61KHD6^3vQj_UI8*I#!$k8^H+lLMWa?M2PktIJLQ$Uyx^+WHp_y#LC>{x>MF9JbK3Q+}HS z|56IfyF4>2zq`@>f&$#T^H41}1*@j+sw9h5n7jk8^ii=$j+{mXjxx~FdS)I!czp5a ze%+6D+x|!X`bNpe$d3iUmm&H5dch?t20Wi`6i+|vs>)Ay&rc;EbRQrk_?xUteObw; zD5i6wpY&rrf=4y3`RT-5Fa0XFz&B#IsG&!Azre!8apH|I(YX#WIg;Zd67S% z@Gm+1|AaxS1XXfsH6j@lo2gph**XZV#UfRH8D+!U2#~UZ3Kz^<1Wq!5X)sXMRF=t3 zD2VHe9!jz;(V8$OCQ&ZqsIGW^jJ-dYUfFG+Ze!EY!SPx`bH^Z#afjf}AktJ)2|VEE zXSd@@$w=7v+>~vQ%a*%xp323+KwAif*Lq|s&7Yl-%~E+!RSvt8i_-M@2?hPsX7dlFFdnM!sos38Et&mJSCcDyR=qHp-k@>{QzlcWRT*XEzd9=w zvc4_DrQ@4sc-|_Vhsk_w%%Ikk3Q@Dq&%>1DM_6A>YDj=(ElKO(y2wIB>wrR8fuW3A z^R1TWSt2S~CLFbfYlfr3>1*^DY!%z$Q^Bh=Ew?nZwB+Jx$4i{E8vFWop3<&Ite|X5af|ygC349+>z5|;#&g z-;dg+f+7T{;k`VIJ7uYYn&OWz-b8SrNv&SSof<)y{eYs@JeH}H`!SAYXacA*0 z!$w~~fNdH2Znd1F;`SV80Ph9MojvbX0~V!doZgeba-YKK<%0gXv{@}dy1usyOR8Ws zR5MNIsMGt-0`#Jm-O_Gk=1eL5f(yfy#^goYXL%uy-}E%qb#8~4SjxB=N~FA*NdKfW z#{}x|jlxR!Ej<{!_X#nihnn^CG7vAz=?G+pT#{XJ0tZznZrbRIh_{ctm|!=HSat~0 z6L(`NZ_XKb6*e7ERjV##CNj`tSvYVm zn3IL*Ur<0ufooab|E%>x`~U;h{=9|p40tyNQt#l@tIeuE{slJ2*Ok>9;iJG6T$;Qx z;NEmgIaWgP3^rpn)^hWnOQ0VqRc~B3Q9*pv?_B7@t!(MWv-qsdK#CCE@ckv?r_(mt z>%kw18flSY91=GA_~g9JVK>E&7zQFEKbcC|ExjdXdr%2Tpme<>E^!rMn>-*sU&anS z41$0-DRj!Vo(lQE)^0Lzv{^oXP+u+x4N9u+0%rtML~`dx5!@k}vQm=~{J96BDWd{f z7Sl|+omL3|C}kf$Z%T8M6?gzw`jA_-dX-RLy=PI)A=B@f^w61GpP|f0KM^aK*^A1c zU!}qHlK3^9@ox%xK-#hWdMLb)lpF<+TM;Wm3t&?cW#{s^NC~BXWmvkV*PspNbc~CK zqz!79M`%;%BvcFW_iow-?!+XsAa$mAf)ET*H@bE0X5GO2b=2dI3)dX7fUp!M&i<^T z`bwocN7PuEG!7aSi0QKlV*tXWayl)ef(9yBOW!jVn8jDC++XBf=$~BGeBU-!ueTgG%%bi6J?s$87#lCsxm40!Kl?)X*^rIPcFvAGqU=DqZ=eYyF2bd|pAt1gaDR2BLF-s}qh8c+R`hM32j*xdjJ0%#_Y@Fd2#TSAvHpr!k z`KHwvY{Ehvk>GBo0~S4=qFc+b5P4R4;+sVm4Kz*5NKSSweI{v8&tYImbv~_+FS?M` z5I_>8ZFqd^DbP0w3LE;Az$z(N-Wf{*ZhvFYgX-l=1~EPC?v{;HR+#`1l((R~~h)(=?k2kc`AaRnJo9@|-Wzp~q<#iMne31%-cUGW{*3@ImSFotUqX-d|8)%;H&K z`HK8QC@4RQukpBxaT`ggpDJh zTYd(qr~5ANrEtE!%=bQLRcX8{NI%W}Zc%*JFkhwQ$t7p0$XjX+V@~d(9xj!el{T2%P`5F#qmUrs$+(l06d-BW#W`zj6gOMZC?xFx$|&!=ZeFrwzL8p1-W zVy#`#Dd+~3awD8^x4h@`QFN4JK<_?3hAsAti~7Z;w^1~AM3&*C3k?o>Po_$yiWtvZ z(AiX^51nltuA3E2QqD#z%?auf9Zqzcx|gQ^xvQ4{-bef|DEz%1`={#vHz*vL(_d!0X^prB`iJrB?y(p>nY_*zdTBl&Y13NjcA!>7@8ZcuC*ehFrD z5qP|)-@hdP?eYa9`vAqWug;v>*qUL;OYC9yEN|Q`A9HzA#+yD9fz6&J35C&0$^w|jCt{k@7lzW(OnUEdG}&w*+|SfSwsy$Q5vCp@a3bJ^11NEn~vhe zy;C3bw=M?-q`8lE*jW@ig*n(gD`d`|dj5uOqk_`+PVs)3_+C{I_ujOAuE0oLCaM*} zlK3<)gP}^e3_45IbJ1V?R%XAO|BW^8de>V?_D4soy+G ztBB+4#xm;C`r(&?pJl4FzfI@Lk-rodZ!-4047}d)we-E~b#&M(Uj6KwxoOwZ%rawk z_pwS5I=pJxk--5@uIU3BEs@5ZU+xapXA~+lGHnd7&X4Xbw`33)bN<`K*nhhl{^t+W zf7}RF`+h=!g5`5aOjFF)2*F=U0aDH|%yKC72NYIWwagjU;NSYua5w-6OF$;T3;^M3 z_Y?yylx#v|#o=!K298jT4~cq+0cvOLI0Xh!nbGBf3RSD&kMRgEb$ z>5gWHty&${rYMgsR=@K)qSDu1OLyLDYP1MlYtR40%dv)=rF^Z<&^Y^Y;74RUTF_x~ zexG{_UvIg>bt}@RQq)SZ`PMR|RC4Q_1E!h1@A>gXPaImx()5UT*WcSqCrAgIfs*af zzTz-!_cGqkR8#&37~z`^1D!l z!=STA0=T5uv+)>~Jb(Nfa>;53|DEW9YFi$E`MeBj$O0Qggohev^)$%gWV1QQUP&eA zh{rH>$oe|_j4P!gox6rBCOYl?Q?yMEX!dq5+ZC#FXSfVzp3+M{vmu(BWqqQU&Z4Iu zlN`$G&zuooymAD|mQ|5v8PM&m{c^40NFmete)#rNSO9}n`3@T?YZLe`uI+{*1-Swc|aa>`C)V5v4-Gb0BljweZ z3l*0uQY7hK#c1E7%jP5$B5XwurK>$m--sLX<2En`8|0cZnB+Ei4iD!L6Xxei3R&)2 z*`E&s_AFv!p2m}-^AmB-!NJbH|G0_br=>rk@Q=0om$iT20}5sj-83gGw&AQapJBNu zDp+*1D9l3JN}V~=4-YF(7v2zJVHT4-BRx8FrpANfOSnZO+E#sFctw%1W3$BSY~nl$ z%OYEU1yiK*;e~m}U1*IO(fW8@%QRN-#j_!}jyf;rR+Ov#Pbes+ei4k3{a=)V5Rtiy z_R(d5~Bl>AQ49|MC0_Ur?Yek|aY;O#A%aJUh4F35?opc9g1+U>x#HzMK z=|{0#9E*W4R;euQ6Q4}>I(_p}QH$-+a+^X<8L!^EW>;lyu`s};U)DqD4|h8|`Mf1_ zGaAOEVxj$)3}Z@LAIZh8QI(%J2hvT98;+jah3zXDv3XD0uBK~re8EB+#TN+?j}(?> zM?>yfRGqh^E8ouKJFrE^(4()^azEJ~a377$rPMR5bP?xGtw}sXnbuN~BdQ5@@2xbg zv6$8-)O)!|k8$@qNj~S8L)Z?(>~HL<%(3|^U%IHWrEm@kS0q&`7&^kQAtXQs$e14+ zFo`k>zP19TtX%R?Ij^CNw46ik0eex-M2R%45i`(OBvy%jzV(Kobc};ZnCe;j?L&4d z!giBE$SA*_`>_$rkY_SGBbX&URa97%iH>p|^I3l{VH<@?v=T=0jn!qBmE=URvdlk< z#sn6iG0vBQi3Dx9v9r6cPHL;aCgamMD~9@eU+c$qz%ugLh78umAGZl{n41~J-6{yx zE<+70_=63cmF^ka6+Lm5t-dIJKD%nFoGoU2 zX;vfohKb0$s7~!oYwSaLmF_%!dM>1iqeEx%(+TdGl!`icAY%ZmNn+WkYSHlXm6`G% zrI8}_!n-RB^QN<$Z_Iv|iK28E3~viu_+Tn$c$|0FrqXI)`;Nnq?Y#jQYKac#@)7HA zU~S^_p%GV(jY)ik3F9`>Lzf{UY(N{viore!wI9q4s2XdOd#}7>wGY*d=eB-*%`U@` z$*OPJwCubgc-_47lhxCjwX5S1;0BOlDaO41i>ku4`K<~yI$h8@xK;#0mXMs`NPW7- ztQvk`r6n+G_#72Z{(eZVI2@@6?lC>;xe~Pfb2+E##LVU}%hQ_C~YHtzS7+4~)_73}}#U6;S0@c$p=Dh`^W=iVk+s(am2ir7)K z6;l8|grly&(scQ$67a}CREf}ctM84@O)lar3kjb*TN@T|As(0gP^~p~Hl+G!{GPf! z{ro|R2zCYQ&AIMdvr4AT)8&%}IY#?ii+qc@;rej|F08Vhl>l4Ltkm>Fdp zofoVtE+6Nip0Tx|_P#Iu%R`kQTc=_ece}xCG$ESAnc?AU#GlGF5JGtC6Oln%R}P;g28?D`|8@GblgD8Sgj4J_}0_+NDj5>t#ZtN9|OQp@RJ z_F;^y;Aq4m#|3kaqYSJsPpxPo9fNGCEs4o!CvlsgG8Ln?B@ zXxUW0^&mGhnOTXV&vaN<-kn)0&r*2HhFun#kxQTV;BZmM9tNM3uI1*L(Y*Fpx=}Od zt6>dlx6 zINv20-aiCSH{QGzBIjZiXY+`uLfTcd)v%vjja{QJ&Vu@+08O$9mYczKN%w+ z!&#O=D^Pkp<0j&Ocy?s|^)`K1SbW*8%K#7Tp=?>~aJxKvt68mvNibN06f(f^TZP@c z$Z`95ik)2HH_pam*1g>2jmGUzqbs!!>di6Trf ziAL9A&$5Ifr@7zC)3yq*9K)3MI6P#XS%kEqe8p{``(GbY6 zh(rwH=ZpuWSDYdAe+PLeh?(JGsT(EOyz5%ft3T_i|yW=F&6lFDO{Qpus# z+yUZ~PuOKOBJ1ZFDD_ay7Yz1y_c}gD`{rwar`_2+ioJazY>LM2Msk#jRvOvi%7{?0 zzRy;-G92n%>sKGE7I}T1yjYSJybu5{8~7}7n{US|G{NR_g(avlagz{?xtNTz3N(2l z(gQbVI{KpWjIBt_aV|LDV6579V$M2##u%f;>HB^~=Hh{|ZPoFC!oXb?ES#igr0&A+ zjcMN0v=OTV%WQo_X-dqs&OC#UTb+<`Cc0dH_lH{ub5>S<#Mw2yNrwx z5bIM)Bb6P(*@V*1s*`;|9YwHOeIJ0SKHRK$kHg2oaJ_7am=Vxp<2hz*TB*z&VSjT()n zXd2eoV@)sisOh~YFFEgb-g$54e`fBz=iRyI-1}QIFvEhyz;~_v+26JH+CRU}(Sg6p zUlI5#0)Iu|&j|edIu`^0BA1gY-Tmi&)rsLN0MI6$-hlj1&aao$n0oD=D#_H9e`hq7ABPZ}NBoUr|eW_@J%hje(PPg^Ypm&RPK-)@XB|m3+_3+j;ySYtD*Z?PZ zbha%3;$$c3rh=K4{rpd$2a2m7;EXqqf?J>uQW{^|Mtq2e7vH*hx$X4bC99d}AO2?^ z3$11j|NLFPZ~Ig|9K7VXD?UL=f5UF`e$A67G|%)N-xvZQfDphIR42wJ^N>OuuNONB zZ}tl$0Lab|2!Mcth^W&Oe3*v8#Iu8MNjRDsNdxetz-%iFo*|(RO-b@RkSC1SoR~d; zZQW$_{Bxo-I0pefNEBLwm4wxxBVb@f{^R{YN3m$U7#a#7ksN~V_ie||Q?ecmPa(h@ zumCa#6+mbrA^4bB zI5J2IX9$?f`_7dK%4p9N1Pc*3y=sI2Oj9VNVM#Dr5{Uu?QH2wslvQhMlAKVTBr25C zbF(MGg|Z|p;7t}wo*?BW9wJFv9Nwceb2wxLj0Z75Bp}UuXjB}d%9MzbvjAiTz#N2h zC~xeYa0ehQ!~sG9Nb1+HwWt6ALc`j-9A^NCf=F+B^z*C8j;LVi0irDw!07;V%G0yk zesx>#=C6-mMS-9Hh)v(6b@O*ee*N3iLeLQoLUxPw-s5w>q9BGB0>BoygigW>4&qM} ze&UK^Vk)^mKdJ#7PLw&MT9jj8bXg)_qV2Wmxn231CZ~;R>8b@G7b%<7tL@mfkOftHvz7b<&xZr6*^6nEnG4TaeMN zvhY^KyFF5!{iQdAZ_5>n8U~h{+f_QqV@EhoXkP{&!-b!l$BYq>p2R&CoKr4ve8WwXzQ{ag#SXEn9D!@<;#SA$=gCC$h>9wD2mc5JMCiwAG&l)#t~6@6nBv&2;R6ks zqZ&KpN`r6t=lGXG;2UKXG3O#JD^IupPjY$LAxuBq;ImMdhI%;fL;zf?yT5lE8Vy{d zw}qH9>L|YDdwWBZiXjN<(-9B|aYxz@SV^4GQ8;Pm+Ns z2fYDBN+b65ICH+Fa3C5Kc|LHjI~hz!ah`jHBMsi5!KJV`9qAFMKVF#2;W&s_I}QqI zWc;YRyLSNM?vzo{vU|aDsoC24%_6Npl>+g8L8M8A>+R2F?I)W(y=TNUr#kbC)4NeY!t=(JxklWisjkEsQuztV7`Qf(PVQ z41wXmamkf1It7qP#^EPP*Oi3QCdCjji$npn_!OctiDp~;4ARZ51fWQZjMZX!H1`x$ zQE;TDG)xN=AOmV7+Wi#7ie%wj!D&(l z&PaF55J|786BVw5t^KHMJg#$+b-}5Q`C2t!&(~@26~P%`(^SSq3)0vXE#RRzADu23 zw>`317&ZJkI$Y^w#7r`8~|Q{*4LhNO2x#RhG_Bt@=wowNt4LV7yrPGU3Ex4nTtw&z$IT$5Z6M@q(WBp4ylLaja#Lh z{AbCwW9_O@_bHpSr%~)Y!!yuig+&-88&vJXb0O_cl-j-+MeZcIx#Cp~_HFEixcE>X zqYaQUQ53XzvPx~30ZcJAY;g_D(MBvh?qa&Z6cYSpZXkXoSXJ&bItV}yJR`Ke$<45ZHP}jK`FR!nPk#vO} zq-~rOa(rq5*+_h!xldsec@KOe1!Q4M5%0cDwoEE87)dN4QH9$mCoFo&?a$w)B`X_@ z?ln+#zrS^#Mxc`1UGqNTG-T*B=?t;gfZ<8HtCMVb?lhIW=w=+%PPu+1Rub!MyamxN zZ~MqJds8evr;U70EqOQfu>ppi9OHbH!rR#nZxUGh%wEjx!L$ zE02E^lUdB`W$XfSK#ur0xPX62*02mSTvN?1Ln{T6Z9V%frWJW;mL+L*bgZWxCS{ka z4n3zrGr7PP5;%}rnt?Wuo)d`@SB7T*n4pU^XG!EqqBP(=`|d}P?UgFw)Lg?o>2sT& zx19hxJXpha1AkqjBLY#{KpoJlz#`#xPrjPd)rXnCWtO9z?jTFgd?(M_7@TInSC zA}lEi`_>oz!`E1LoILfz@GXw66{fUbm=vOc@8nAcB-PlyazmNYK(w;@J^F4tqBp^; zJ*&+!t?r#aK;!AcNBX9#jCNB`%c>IUT7FDfjU^OZzTg=d+%mP}K-2xA@sXD6?K$uD z^rXH^ILzO+zn_eYYkY9La(#E%Wd{dWLxuA@&L?F3(Ug$fOPi2iZU6ZN0DAzWjlxV) z7b41VQ;~^r-sURPpF%5=e|NKSm{0G^hsUV*_qauPu#L&7s->lDbGw9I@psq_yYq3a zw<#ZpQZmysln%AGA-AhG=k;B+z zygU%TM7qf9~+>DHH@?=Kw5Rs7-beb@J&FMb-n$Msmg*^u__w!(Bn9d3Og^^Y}> zQWd`x>ZhRKSl(CJLX|J>B_AxBVrfh4-J+Ny4JoQl^~*qMYAFpoj2PZe~G} zT)eOKbZNx100WSInB!1oRp|x5{ld(Ntw@rn<0RJ6dWQO%}JD1c}l5Nb+#ID@Q7BxV(wQ zP-r=wysThz8PW-L6gl!+%rUyQd;e?XCiRD`bLIL2IjfsaOYT#@a;X8YYKQHK-*}cM z|LIu0{X$r^QpSF~&!~qn{i+jBJfEy}*3kBD&Ui$_Nc6UiR{U$ZBBY;Mu%nUtn=Un- zs-6qiLf$EB$WERZGZ2HuqMSW5ORzPro^5h(4G%p}d{Ay(BYjpir=xh{%(m%>_q?8a z{>{po`LEjajhDWMXY~I@Ay(o`T(S=2Yl7w9*A(Jv204(pYM)hrn%NW z$oJ77O|_^*Msf7$uXg9FnQn;bM7taqs;Jm(JB%^IT)cV0;!>umeGI$a;`*lQzD4g) zLgZL#mtaDduhqV%JM9v>y>ST%?I4YuL#~rb3*b|xY0G*;v2pI?EYv=`K6i!ihF6}S zPh1FWd-EeN{KOZTdG0HeX3|!O^U3f;ZFyHO0Uu{MXPYM(fmg>4+uY zxRZ%gSJjBgYhZg#UDFM^Zz!75oNC(RrGcARC?Tjuo4u<4N z@|Fhag6kOYr-o{;5dXloi|QRT%LsAMu%3NmwaG6-;7 zYd>&IfqV?Ba2f7q99P_jJ2SXgk!|ShH(i*Eq{FhTGpkA?hZ95!6GQ5!UU_DA){`{f zSA4rX2(g381Z;oDzB;_jxw6EFu@}GP3Nls>%d@MV`jD^D^(j;fI?e?-={U!^oNRNL zE7Ypb5zVq4X2V|H9Jx@jw(8Y!)ma41MaxSo844cAt@ADqmUK^H?*|Vx)hpx|4HcfUEWi6%EfIdMYRn*8)-9BZL4%;Y`Q?)3%`zV7y z$g3ulGAT(-rm?$7oNOhNZOp=$0m`!+`*>7!-kZDV3rgMd!U|X zDPp0^NvmUA_sr?W140{7Ba}%vCrxzqm8-zEmn$#@b_rad5rT)kXE&Z?po$T+8RbUz zk{k>9084?lu3+Z|R5HFd=UN80(=oTSwlVZH-ix&8u&aM2JbN9PTf1$ex;jku=w%wS zIO=*jWmQF?trvBm1w-u`3vX@lP`Tozdg)HS;knN6o`E7&zvOd_8}F{wPBYc<-4Egq zg%2p<(?rz+Nk)UkI^?)3Q?p-#!ZRE6fNFNrXF;3SC2V)PzRDN%_G@(xvpRB;YwrAc z|APMAXFbKNc9=OB${e_MN85qvbtvIXOq?!*w)1Y`t0q;*A7$wmJcPo)Xvs+x^8-5@ zMH!teSlRhyHt)9CF5Pz!P0pMz7pZE1CO{TyTkMXm+)+iw-@XEVeEm&TvayN<$xD=n zR~2OrY(4MIwJT}oHihbNaYjlP^P)p^2TSblB<7D^A8w1?y4o{D8@69L3vcJv@H|Hy z9X*hrg3~|L*#|3HMsTVlj%t*QZm(T^RTrULEP4TfDmkBW?6&KSPT>p3pdQA@W45D@ z4nO>NM1j-+k|POv>PaF4H1by;k8LvRZ4@c%3{o!Gg2WKMB3Eu6n}g_yj}{S0ER#u& z1v?JU_Ow-CB1t4khzu5=wZ%V?0s)>PvwR1X*tWb1@8Dz?s=9tiMxvZuf#H6~r|JPC zc%{Bv1g+SiCXYXkJE+ix*%7g;73Si{ex@4ZeHs;$493p8QYmlpkTuEakj~n*5DcdN zF5A6flzVH&zeVBMcIUR7cbS$nag_>v0q9w9PH7VYb%IkSi}hs6pbbK8mvu4e`n~l& zakjjfhNZ^k0_zSCl(4usC?Sr{-d=>0 z1%oDziidM_`?+#e$UGPu!|*UN&q#vsDK#H;5A|Xa{RcSWcLJ=nMCD^Jt8lB9ktsS| z^2;V6GNSkoq?lfTkTdkAUUX}Xu)=dNYDev?k`|OzQBUpK-j)oq^ugE{@3%w$M&bO4 z@3CBB^0)3^3jA%M(Qp7$_5VhJ;T3lQgbGa5xar}Iz-GD5q=)r>cN%aGmh)?e=oLKLEB(VE}UuAyRlz4f1{VlVx8P z+!EIkx{W!|*`SfQk>M@FvrpF`LKrIfjA($Vd=Qd1!US0vDvNdiGH%xMVLY9Q`N}3z zg&W8cfkQ>!V`L&R(;#gZPS^XiG)MoHMBCOnIjWlD_WryH#o4Z3*M?o`#k9HsiyBAi z3JZb&+PJ%_IVAWrLDH#)a)LO8w0LY?spz}_i{W2NS+oFgo}w-}Sjsw^>YmaOG$^nd zElV?O!Ru-P#j=BJ&a<|f*COF}l0>Pv#BMW0*%dV1iThpK{%n0ox>}4^Yyn!RHoM*W zp8DkTt+q{rA`EU#uni|)TFg*x?J$JD^IYXr(-lNsk~4CmK$+?!&WCn;nGDgLz-kxL z;K0=%1~hzAZS4udV-1HA!~Jp~J-M zJXuBafGie^psaiEWoQ8YbZcxOJD}TP7m{zu@R-RItfetq9T&fa*=e4<2Oi;OrZhW# zcAm$1#Vb`<7xL{-~JK=?%cmrCJYO-*&m=-w}oXBB3Wac9)Ps zIh~|EmI358ku%#=_&AD0VkoIr7)3;KR-8w#auv#;+C*)|EwpGnUa^xNUo(qpT@c3m5Z;|HwEhaCwS#)2viiHfO9z z#?w~%x>CxO7aIAW#dUWW_J$7OyX7-AJQo0b3QN`>;8^MP^q%{0Zu3&ap<60DE50}m z=~h8qHO|rk}sH$i}Lvv35N0Eea{`Zq&VpQJU^O)p2D{WB(pOGK*LI zWr8kwt4}^Z+C6uFZ_1_B$QuufSbn^C0TJQ~3C{vyI)8x&BnXMu^x#lapPlXBs8%kD*qMUIs zQldqlsvsq3ubzLNRIEj9jaqRu=d@-X(lI*o2kMmcbHRMWo%*_Z`hyxuM2F>jbs}Fq z*)nk9%9D|2)JB_DXqI(djI-xkOHjTNIgX4y1^;z9KL9imGsr!$xA7Y-Pav7ZVvYjo z%Q`_BI)<7Q9W2p4<4htA;NqcI=jQIry-Vt@u`9u`4w@c<(49JljatHo?a=b;h zbg2nUXkD3QVu*SbwL(hM4p3%8#$%0g8CkS6adpiI7x?KGZBVm8KuVNSZQYWh8bplk+s3^0Z?LYXcUpj4dH9Zch->~0G5{`x*!Mr+WtGdD2)|oZ$%%=gi z_;q=`ReDGrK4WKDs6W-jiF8 z-)57tEpC$X!F&?Ddz0b1YLOom3pqd~MUb9@?-0lb7%m?M3nvP$=4{E;7G6^LqI$-l z#P8DmmQJ~hitTEDI7%PD%Ext&TMfUc*OpKjwIGd5v@3_KFP*MDt_tgoTz_A?$>nJ9 z&5S2|SQ$TbUbAA}a}P>i4f&lYSWA4{{{Jyy0|j+O;&t-x4UNBCfS!>ww^;l1^rZi1 z-{l4ODvEl~vR7iSRsCz(cV>mE*3rr=*y(7C@+YG>`hz1gGTR=$6SWSOJg(q*V0wMj zAK7Y|)gGjN_M|&KcSt0xp#M~h&2#0v%8ie2l{FOFHC3~ccAXnBl5L$TZNJtb|0V`% zreUV&)Rfiaw%KjnqZXM|F>0YZ)j7O#PvU`dBK~SD_uLMcj^Ap~SOu&st-m28{Lo!i z^9j-&G4?&5OWj5Cj~$jwWZLu`TIu#}m{sHS#h=FS%w^T)J zP9yR6OET8JSq3B(&Ei=Z=o-sSoy?T>bMK+L!(Hrp&h#l``-__n`DaSr39s~E9ffJ( zf(A4C0u)|X76AoOueo5Rh%Bp8OR-VV+kaUlvhSU+kzIA#*neMF?~WVZX|{*2e5yI# z@+OSDSo?k8IbSAW9OFux46WFWZyv=YW(UD{Z6V179H#y%I2N})*ZrH+TO z_D(Zq8HLC0MSgzr>LhBt%vw?B_Dw&}D}9sRE}Ms@gV*b{bplbX^Ksq<%u@M*_&ivD za+>4%aB|(~+#YP$YA38>bBfFQCx@mp21f4(Z&BZdyV7H}G@r52)bq|fxhcM^&&c`0 z=>dI}y?rU^nCY_YC*oI*xBhVzX2Vlx%J>Hg|HbL~ud4qg5g@r1#~5ymw=nC(`I1`` zkDI@_Z}7>COiYKO00PreBomql7&z=_c>L;R=UdWm);`zxdMe%4+jru#hKe{t_)qLbP)O_@;hK$T9j>>V$p0w%Y*_E=(WjQ>W#@Wf}Q z@vVO*3K|jO9TKk>{+=j=TaO0+T2u*CLSs})khl4HmfS1C7{xnr%C>cTt;m_vumcDvA` zSrq#V+XRlbpI1)Y|2f4wtKIHP7F{)S2^u>PC)vPU;%#g^D3wrtRd(vO zQh&7_?WaL0d)U_S)6h<-iTUn!xTfQ{JT=jCpc?C3Ox+ORe1W2@#|(aTGt|JQSvG)p z&l$tM;vXEiEkEVj6YqzULEj}<2lq6-cL1YjsQenj&Jd~=#s-Y<)8DgCAa0X7m4Z2* zulDAgz7=M6;aH{pXgX!mO>6rHs5<72`CH$DbvtJB_WEqsPosR7KN<~~Yc|a_vujd$ zu+e^qMU1~q1%h?D1UAHZz4@*S>fq|3wjp{=w9YP7g;=o@h z{5Ku<$W zPF%veWQ*kT9?7EuhHL#DPikYcQ{AI#Ck>4%cwKgj>8;#)ixe?a=!Fu7cY!Z!Y}6+6 zMyiV-LGFXQoH?3&pH#Dl*RleE$8-+-TFH*@($=~AtK6@a&`Mu5v{yPc}^OmExS{7O#lJ3YLBi|HL z2W~yuukvbMIc!<)v?yVVdQ)@Yong7sZ+S< zGubO|6P!}}{WX%mYGn55HL4v^r}Z8w&^Oh`;I*7a8jGbf4w~?!=+p4SACp5~=4{pQ zv`r4RGk~iX@~+5$ATGJRtt1L*_N16D_O6wfKc}Gce!Z$TIY2@LOBz~c% zNp*|$oi1Psn?a^Nl~f4K#0~^FMxQo7R#d2=n?EJqe)~i1{oaUSrP-?G557pYj4Dk= zsVQNkRY`N;5;tYT{wXcV+qlfFsduYST`sSs?%v&OA*sv`bnYeit}7%R%vEv7D9!@q z(blVQ19Ga74HFzx{jr>=ulCLdP%ky4(soLFY>@Irs~olWvi!ulT}tV#s@h$duf}BL zHD@mGU~F9KR|=T)C9tXebei#11vtL+S!d6f5o=*-&WIf&GLO+vm@0-73Nzc~0%MY6D8|3-gPu7^48z!B#Ot2Rj z3$w)DfWWAflAQ^=&pn(;5Eo5n<@`n=QQ{l=*Yx4LFz3%qLC*=(DDe_Z`*ZrRP;<9$ zGhRzp?+$YN*0w_$d96ckWJPb3?64a0QU-IjOipaW%w$tL5$PDnEbNw{P^;fOacBtW z$+qvOR-1!AaSHbx$~^X^`FY2zR$lvTPtN$4(5v?1oCk#z znJFX208QnYR+HHy9rKeQFuhi@?0wO9pAEGw&7$!95v;7QS&r7}@JRU(?K=s%2I=Oo zU8B#{=ZkQ6WPEvNzF3J|r+W=pJ&VNGIn0qnp#>#>ibd%FD4Ql}LpU zt5~V?ATi|kgMMC2ugAerXy^}0&Bfhsk%)VnPxO0yR_WvL(}|~^X^9@1IQ6Cea?P2O z1{bRAMn|;_!==CMEqeW2gmAjKD%_gVFAuR%iFYC=P>! z_%otamldWpb_^L!x%>TbM)RhpN#3)d?3kJuy}5s&@ZWUC{CD~g04~V0y-P0$JpPbT z_C73lqM6YT4hk{?*C`2k>}(hZkTXMEs@OxI?WgUqeiu%vNr-shO#R{*cm}FrAW-S; zcOoMkIz%qvq5zc$4g{eSG(p~zrRIu=wi07!GNr6t(PnUjx-_Up5udHZMh!X7c>+HE zE(6x!Y{!TY7*Dbr>VQVT@CEfsu8g#Nn?;(3tx}i_T{^(-SwD{8S!;zNd7o%q9e!lH z7S0V&P$?{u6_c|8ixS}=ywvj^^5{XEYlg{ANe#=EFtojAyt6fCLsSo1BrHhPO`MC;K%3=>Y><%R`Uf{-_`CrcuhQVd#=BC1R)1m`5T2Q;CnY$`{|vb z)jv_tzlN@tcnkjfE@vg&z)nG^v~oT-R1l^FRo9}qUr6C3=ZHgINwrJdg`sHd&^tHgVhEJc8@-(Kk-95K{;&1*BfX@BN4q* z-%6P8Mz3cT?cvd0+~^6;p;FiT*!A@O7XnroSwZ!9NXcQYo8ScCQZ_mlJWuo&Ky~%M zsMMX&wPC%`&0tkXrigl~1Xp!=74>zsB0~ikQoHKZuBoYyxXGSPxXEqlxW!2U#-%$; z+o`*JSf{n?!bb5X&!qP?fnMkHlunT#3f!7lM(hn8PAo>|$fwX5ja z=a9p{ogCGiWiD}iv!^7+8s2a4&nPz4r7}(}pZ4U+Dw-*3wI2+xCnVl4*>6w)oC!a~ z3b)7JrR_Yx{9-=5p!f0|mfb32o8->jUKnW|*C=>CaV@-lz531jUHk)A?G(&6i?)?F z1?@}NDD#MD>|3@?r>3)^XmD3eiL%)j7(Z$(|I3PN|t`*`3v6X_c^btsvVg>D?!+>G1!Tq)kX-L_U>6{1Uzk-os#u|M9Wu3 zJe;WTy!;2j@x42}C@RHa1+A>mT8k>)^hT#OFlb0GHRzlp)F)nYUV8$S z9eJrKP0bD8-L@jlw_8so2W<*`D$TUTTyhXYRT>+7)0VXg8uVa{ zhrdzaa=r{6Cx5+Ubm&hMsFYtjvf{LieP9X8ag+ zorPtRDi}_NRq`K(r6)q*{m}6 zI^S_o@174W-1|c+@{dk#ucvhqF^^wwy1T0Ko(PdV{D|%bX2Rqt{z>&{(#}wzxS|y5 zq#w`kRo9#7p%G{?u9XWHPmW&Cot3oW2(ck1YVG)>6{muDds>Z6%SsY6Z?CBQb{Sn= zjL?(F9$EROf^@b7D$|dQ&|05@6USgy4x?t=F_EBgL*-E0FSN7Sw6%?|nO&ClbMn$^s=NYd@@YphY&(|L2d=g%^|N`4;4WJp(&gcL!5f*a zp0HY3M=|R%n~JuSegm47b?asmL(rbIqPXd1O=u)66<%^;fN0f&gHP+j;LMIyy?0Gv zmhz|`S(h-FFvPkPP=a^dQ@5w9rtGw~2H|M!P?}~r;Q#DYrA1N&$i{D6MHRuMS@;)1 zm57&OSc(`fJkt9-M`!SyPL2{@U9x^0m0_A*R)Uz~_tQp>F@d*4O6CGaSeb_^>qhX= zy9(kJ;;+&yZ#0XRNK^H2c6sk&^=pV>=Uz0_^QDyDB=I{nX(|$!E8OsselcinKO&nm z3L>bsTFgOaq$Lmg>VVVhXwN|UN%QKSLg1OO7Uy8X&XF~_9SSV;!;J#OdHsPMuUVEL zkODO_r3YjLt-mE5XCN&zmDECwbDHKdiudHr?`x34FItKC^g#Fzrtij2V~){U>6=KT&uZj@CSUKp&>BlP~tpW8iLjU!mdV&AIJo zoUr1Xw~uapvgiKOL&6>KN1>g$hIO;K#Ddz{xBz#KM&sEpi(uQBcKIXE@~!r>q%ajq zQlLRV6_|mj0(_tspaWJw5WuztJ(nk02odRk_fs7=4^Ib8I<9Rq|MS?5BG~B zs{uHzBBcjxQiE`d&*tmKaTL7s9*YEtlKSMD>huBaR{NcD@9e@bFeTCezL*icN@NJt z7xqcC_8G8T=re@cs?}u+D^K+e-t%&J(r4$|TpZ)d<6boftVmqq2|I0X@Ea(%W^q|% zn298w3n?yI(uO!#F2#a8_e{7qN*xvYvN908$vx99PL#Kr;!P`gQ{MNxF5Ed+a#6jwubb_qf8GSmnVCI%y? zpy(O`jM$MR|8PbI3(kK|tG8GKR}Tbm|Cc%>!VsC2XV zZ15(?fk=2YUR6ZOAkoqV8A|pqs#@)??#-*eI@(*>Eq@vt@y=w9&|hqUsOr_q;xW@E zR*lLD&XQ|MnHtU((CS1r+9cS5(l%>nD;>x5o;;30pz6CuqQI3r&P~3>*q0MoEKov}m3rwu6h(kkszA1Ayjl6wU%aRJocCUj{jUqCnm&-k$vw zjQC^!ZOX6UDU@>d3LnBBm|rI zjMOoT1(@gX6=Ad%TZnT%*`dRjs1v0)Qf!M<81=->*CWRqC(d8r^@f`X18+WTl8QH{ z0S_X!f5{_PubD1vF=k5}(#y?8I8y@^*|h#nA|iaz-oo;;p%IZ}c!x#l)O{6uDsh3F zrwRyO5c;knGrG{kW6lUa_07%$tJdn9nb;>f1&3`Xd#b8R!I+{|R(4p>03#_v(&S7c zE8SwV%u@|YtvX-FnkChw5)4=-*TbZd5RifoTPT^BmLA3^v`s^}`iU&Xp>Kf{%uNn3 z6xc*0s>S!+m`8p%&CTMKt~({AUcNL0Rdcrz4I+uvg)R|v+0Ki-R}jbpxkDh)NCsP4 zIfSJIN>kRR)U1h=d?0sp8A49RmtfN&oa^Hzo5McGEr%e3UtJ#8^sH;nr~9l z=%#BiG_)j^a;Wjxkj|wqpC(B)a#i z7H?yONpx}FmP^~jj)4z@3Y0&UXYPWYj%o+6Ej(t7kw&z|m;M_m~+OKhzsLyD!lVfH`Kp#wt){ z6yRAfklizXe-+!b1`+YnpiSs=5Sc+)Ra;xKTYZ;EAvl|}rZ4?fa_SvMlLi8@e?7c4 z3t)BftpvV1d8>>E^DWlm3AsipX0bKQvbVap0Add>WTc7jkB!q^)!>jzol1gB$-0jf zCQN%ZY3y5x72*+l^{h3*4d*uSG6`pqzcgx>E9>>Os7#Ih91fePZZ)-DYD9w#&=aMYMMEPOG1Yl}| zNiM@410I%E_7QxQFhZzlc^4#&(k#U?aJJPw)JkLkCA`b11?RZp66eu zKfd=kT>4GzR^z={dsA3f@%OWpWwqDumKLCIPP3W%z+ z+7^AeI#Y>NF8)mQ16Z=7oMI{=;bgm#2dQ;KkjeJyi0!TFW-;Y;uGg$BOXfXlX$=__ z=~a@qcW1#9iW);~Ep2=YNCVf#lX?$$y*@B`e%pf-g&-F%uCklu2VEJ8{_rk!=Un$` zkZ5rrp$y#QXj&jQQ@~a^%{G;aM39?(UCo9^dlL1x`!DFR23%_wtYtrw(!IxX?zLMw zbmWSHOhvz39^(HI1=i|#zsgaIvsAe`QSm7&au(U>oSjCh5cWA&cPAC7#51}z@fFVk zU<5FtzD|*kc^Gra|MkCrrtnXX-v9150OPcTw0%GC`EZikwIj1h`$(^(J+&60;IeZ| zMRWxq*g-lB-YGytv7wTTNj9FiaV=HW4dkpKUfsSri7mK1>WFeFKAZ_kw6Me|deAA~ zpumK{D_Afx2yTGFdWX?mDh@_(>4W=b!FvKT=px} zK(gp~&;v}JBwGzEVmoI7bGQZq$$H=HFVm?yRP(iq{=h}cou%9mj*{8UP>`6AhU$TV zoM<@7t5-AbGpODQrJvXb`KF^KciLMFirkt+4AeZ@f2w4+qwC280R&i-b&NI*+-@7( z=+yU0gnV3Q5rVGMHHG%FIR!AXm20A!wt<|e(zr&3PaR4PdQy#0u6qR6cUyN9^{8b+ zj*ds0?N^lb5t7|wP@712iv@^X>1kRUtsCvow?C#)GnZ1ho&&A8S|Q0#y9HB^Rv4|( zvoq+KLU?lZ+O=E?uT|}t+}F0ClBP!M_(K#a1<#j+dhUPGU{D*4U4yb8sprV1onU}9 zUVZn{f&i^7>j4ing1jjQm{u57szhZuh*cpaHsou)-OC#PoSPD?jzW5Pi+1B(bP@yG zrDBWi&zx_Q_em#n^*n8`UygVMO-qL6Kqmzim5TlB{dinpyYE`prEv|E$d~bB4h0^jm@73j9{! zmjat#=DYy_zR$mUbI03BOd;ix$UVL zGpy(L7e+N7%;<9l97c@C2iYJ%4;8j;!h#GOyicz#z#HG2Z#Ttj3{`9Tk2fhyUE8&^ zGtcA5slv^;%(-svaVlHNkipm@DY9hEne015p2K0Z4y~Oj#47lrI<+Mp6H=VcTU&b- zpFewg6D3dly1M$M^z@hW)`z+#hgV-sr5H;Kd^sY`x1@t<SF&ThA@U@e=Cf&<)o31!&~MsQCpNi2E{5SPtC)Dfgn+WIJy{7)#Ugq6 zV+lG1yP^J6$OVWV-bw?kPA3)?gwapH$MfWi*%e|00a9V_Sqz3jaM+F#9oTqqvQ?gz zMD!4M$V3!PDv5s+Cglyb6s4mxD+`nhPm0}2c-_8n@Vmr_7JmoCSwcdhb)dn#sJI#t zzw!?AK2<6io`u0d@3C4`N4v8=TLn)+%STQNP)E?|C>sX7ztae1z%pf11yOtqhu&yu z4g`F{iO)ioyzk-G!V}+83ywlE(?32exRhWD-^DRA>>g0E;q2C9v1iaJFra{~#G4|( zp6LY;9By(WyBpc{_1n|ad2IF+mCmJ)1`%VqvY}D{X%DgzHTR8l9VLhc#)!|j)Inv@ z#7-EKYm7s}3M_(J#z|&^_DFtHVlHCmN54l$u5T`@NmWp*wi-*a$7te6Szu0xssR`y zv7S^};K`Rrav7MqAq?ZCdc&cDz&e&F3P@4GNP0#KSdKr`O?C5+bYOM8{qB|5+fTjS z%zt`j*d9bj;UH)LoC9Ri=^!Xj1_uFbl@_BhD<7BG09L`?U+4Yt@#*Q=h}(Z1`M%q? zdIz55a6p4*qc-+f%O_c*$wV_mQ?1)mgI21Q=^{W+Df8lm$MC>*j|Q|Fuoq8mHBbnO zDCz4vfA8&)vydat-x}6?`K}8FZD)4eywFybP1@-5123|ULBhwRJ(}&ih?9wR*}OUE zdN}pd4ARj;Tok2)Q=XKWbFy%nIG-8`FEzSx^uoumLMSPqx=gJ=kDHNSCx}sum5L7+ zJj?VKuaqrZI?FX3(Z;e*p$NvOXHPX7UEPz0gDMCo|u=U z#Ngo|{)m9HZOcyU#r|xczIz?5a$<=^!Gs`uVp7_T4>=fJsQ<^V+u6Q5Fyc8aK9ypO z@wg6Tv5tc4TMIBMuuhY)l%U{gCq*Av)`u4?rBKTU6L4gZr>qLJpc_S{X2$5xjhoH^ z(GIkE9Tu~qcV>v$^KxA~5-BL^&;vw`QCsMMI4?McY)H@9W}(sQDhq{`>u{Gj-yDy> zjA?%odoa04(RrLq$}{i;6hL6W`ipz+E}m{~p#z+byen1)!E>WC?XQfV47-(bP7pxG zCNW}p28Vc_%CK|HzPT3d+O;`IyU+Lhn1@o1)qwn=2j$cEKL`^Wcpj53FwYThg7S&m z_3^}@UTNYuD2f;QgGt<>mqFxkDQjvV;6xTk zizv?EA`%#xL_|*>QH)^@1vk=C^jdrxSdG+u3^Y|8z*6}DGb#YMQSsno)Y2{eUZ@r# zb(srGHKn&v(*ZQ~5@VLi%`l`UGW2O51o1(s$VXHuIzW}7Z=gn9-B zKf>MPw`x>RCGy81=G~|mks2O0nZ_%#tivKxOW!U7Oc!bv7$SwF&2h=%%IBy{_!{mt zd}#L-T+AGv0F(8^(`LDDaIr;vk}y7SA@BKR-*qZh%EB4Kp-Wn*tD=(k-tJejU}|yl z01JhmP{@RRf9%~4`Ti396AAzTlIM?*vO3-W!z26+3P=k%QDnt<{K8N{yqHFYCsDzX zJBjN87{~@0^g$t&YIA*l{fl7oldT}2uDdn`C2T<&i`G6NdpUM{poF{iX$Rb#`QkVTKhwev^v806gn6Mop)4kC}4fS`5 zuA1KAU!jwQu8Kz;ztemnFGQuVBHx0e(8lk6>&o42TU?rs-*c}@esF8^J;=1}vD)3~ zyPKO|Z)?4IJVpi{jYQqlOnktBENYzPlzD1AhxS!_d_{oI=y#E*kTV7xaHM`YGX#TEkrC}Ks4I{w%8N8 zkMu^PQtxIWi2y}+a-m}QnIFY57?6C74YpvmnvqI>UVsMk({1?9jjf|GI0io*%@R8$ zPsuE!6~F+t4b*Oo1+stuLIlVSK~D<{K`DTh+j*`f0b&6%Xz70-0%A8SfIP8qIM`apH&b;fFYof_) zZpAaVUU#-pUByQg6|!s0Z8M#x4=5yH5Hyijr$;;D3o(^=c$;pXPI)0>-Xci#?M=vf-6tLW&cXx9Hu|Mm*}gaQEl2-6$L{yx9{3kt%) zS1_+W$o~li0M=ro8i$5sjbZCsmr6?+-h^u%^2b#ec-u(e^+c$? zpc+1MsL!dPo9ITCcP~U%h^#_Ag^c6DrckwEzDSU<_sRKp%ZwRp-(X7$n{EJPTJCBh zbzz4VZTeRTZduChx^P56OBPtdJ$pbh3QKFVEujo#+Y@bsS2FiZzA-tztG++`Yi}oF=>z9j)?7QV3+L#d=rX%AJfG5N0VevDK<(|40Er^h!p%}x*g z)$9N5f&GuW!M~vJkE_G)lK)`}`~ij6AK+S$uY(!Cps-~LJH_{b`lnM+S3f1ZH#{YZ z^t`{Hco&?#x0L!cBipx*2g}^WM&g1p(B@5>NB3^t-Mqi~e&cl3rr+oN4dvUPf1lWS z?e@x;-{o+%V0qzf>QP`3L9RhycTzp?HV_O97T~$yv3V(I==(smM_byFE0Y_p)+Vvv z(_OD``W!pG;&$WA*1NWOzdPvPzjOT7{O_;%KTC?1%B89CvT?$L*Q#30@{gTI*ap2U)dyA?RU4)}kIKF89KuR)tIT9B zl$dc=YS}q(Jnu57Sexd>URP%uX@CSDGW$Ah)$P>a@Ae(i$sovCO_cZZ@d_E6mSuFT zK~qI~Z&S3_TiUFBiQ{L?_mpOfo4{Eu@xeFE@+|tKV2gVClvm@v+sNoF>BMteDKkkp z?RA-e+^(_Kr?7+L+3WI@gi|7!qr5sT0j(vbi1YcB0^BN#T07V#3KYJO&fx{Q^mn=S zhqoHUJ2)8o-VC|9T&UIL;%sgZv482KQGH~SSD@;v%r|l$5C=|AYfqiVAMUNO-#!do z=%86GhwpZ%cTnpn4!lvFo9>IaBXqvdt=PHw+Oo&gFjHzmr2G_z6L(?iMQ_-MWlfa1 zev*>i;Rc`^2nxV`Er^A628VtI)hJfwVTn)*{7IEC-QwFWhT0GXG(&OGQU-K zJ~)+lYy{L=X#A+gT&nhFQi00-jTc{rWy&sX9VEzK?11h#G_4e(Ak^o@GCsFjRA;9U z`M~j5`5B9#wmo5cL)&{0g=-ze4v~?K+=vr(_Z)}%ziNtoO`|3M1%-cE3;bWMxcZZ? zPFgo_7!grDSBVfh2TH#t1URv|KQt>8gBXlip}j7AquT0yWW!JHPcLxfM{*j8(l-O}te@3V;un_^b+c)@c! z-{TUSxP$ESMdZB(A|G!pq(H+(H$L=*u32uYN*K-+)QHb^i5ZdiPqCWKQW%h(M)tRU z?A)5PT=f|~;8wq=EH>)hmC>ffZ@ieayDmKT0M6k`$+@A5~kcGok9X*X_wdcf6 zs*a~s$J#WwmM&Jx%ag^GK7 z(>5FyBzt&D#YvxESj*2?WwR0U=L&PGnieLQUf;*fa$K z6r|HrEoK~h)7gO0JT6WjyY=9!eh*x|;(31S;Y8kCs;u3`ZEc?Pj2IIvRh~+!aryE5 z8y2YlSmv!s7&=vkcq6L3jk~kImsN%FMg$rOyyZn-GbWEz;9`da9BK64`~!B*Z^lv- zm`}c{u}~OOP<78uAXQPu;Gw+`ZGwGU0+hph6-UPMYY4-gj8~ZRJax1a7V15w&9U5J zJ?0G?ClX_;xDzx!zYKhZUZK%}0#$G_#Mlnr9TWbJ0fgPXTqJVzXbl=V4o6x{Q=IgN za-1F-nZQ%OtFyT2Qath9l(w{flY%l#AO0gA#F)Hlp*P%;Rkm`V-AURI!i)002~b`; zfM8WN1X{TW&`*psylj2}Ep16;=5#}GwA?c1o+ZnjC!iyGN2QqX@Fw05G?CjNKAa!B7-6h#FLaYHPD@ z3xFJDB9s1t!avLS^?$4fQPf3sucRnZGe;u=V+$h=!tJ>-8i}zOd-wWrb#7sG#A`0% zIlc%epaq9Sa;y!YY=nDa{csGtH95_Vs+qyL@T8Foz{MEJhI@2+%jijNdn7WDiO~5> zYY=u^C-^f0ckaf-Y)s7dtwHI63z?H*Q_K_Lpaz?@!Y1ZQT8wvy5NtfX@XB0cs zGeMUHc~r_an!qhA!a;6jGXcrV^fE2)5)DL;lawqoCN|K!Y^}cXg>q|_lq$=>%I>9{ z0AlQu1I*1C?{&(1c%qPdx7wW1?1Y1`Dba{w`(90H5zV+yN6WmB;zq?&k~;3{sx)}x zQLwd2P@m~xwXNq!JP&Gu8_nRE3c-Uj8Fdm<(ObbmpjWu6IpDcj@wqqyg5HzcE(j{maAX&_JPU!SF;!wik6Rhu zyr@w@r_Ihy!4wHwG=}%JF7%k@IXsif0Kn){1_<1mafI6vR8zZhF&21XZsBDHbKYqT zfJ+?F0WCy)Ih-k_DHLaKpWhXis6nQNmNm>oPs%17F_IK;?&gBypfekY}55<7#7m_>m?L4lq?a(?~4FPUgLL;h2%;HuekD(y?dZl?T3xVzo zT5a8e;lg6sHhROzELU%69Js7!vIbs8Zsg46Nwp=(O4VYCL)!$Q{D_nn(s~12Q!rL; zY+X`C;4(L!2agJzHPbkNZjro25$E3mN#Ay_Hi0hUjD`jzOYFydd)~Fv+Ow#m%TZY+ zJo&M2scLuNMq1!i&g$x#vFeS$BN96HZ*GU3YrWsT#;VH2N~lRIQA>bSkZU+%RKf#i!C#1rgLC&OVkHOck77m~<0MV#ABjMN}1MQOQ)scX0rBUN|2 zR%M$8zQdx0+s@%_awSqOWP{$cldFvFCCfGGV(1R6AUXWXJY39MK*V`Y9jBjXafN;Z z7|D_3#gNE{Vdj;o1%#~b_|Pr|Z$elMzfUUB{2ErOG=BK=40o1yLAVeNjzbKFq%bEEyuBe@vG9)yI>P{9FKlCKK_twV&~+l5 zK>{!&%(l|FxT?^Y^aeS~>rg%0TeP+OSuBW*x#_}j zajyld%o$&DTrG@KI-K-%YxvSW5+&;|DEuEs=)YSA;<9k)9ua&9X)e}<$m(ezYSKRv zmDsP5&|1%vSWbA+peJzAe}2ttaF>!ofjEc{pfAn{fgz00E-*A;zKq4SC1G}HsK{(; zi74zTqy#ny;4;hv$D%_hwXCS5Mq~e&L8$2DwM+|=bY_l$4SG`9KN~NkaZOFjr6o}S zMud`~K&YRtKn(9RkGkdq+oc$N@|^hx5iq}1^^I~!!pN<>mU&R92|16xitWwKOSxQ8 znJ9Xa7+>@%d+U+vk1`3zt~-8&8TF`DsTyWM5XwM&Xx8A>Ag~!%kovb}%eV5}{azRl zvdXznzK6odnz5-qe-b3+VR%PR`_nCzIvZs_oMe=%!LDwBkXQCQNHz7H_=FDQf} zfOV(Kb%`hPhTsG{y?mWoaD{S}&8E*s1*kO)ZK^6zPu&4Xdd)I> zPiG`}<1}c)94Zh_#So}yur$EY=FTf}t*X_P=L2yaM0oDQGyUDLoiL%Y+J}ni7jRF7 z!pILgs18-P9YrqdKH*#wH!mpC2X%7w#XGAln+P@9h6<4H>buHE+`^$CmNo@6e&J54 z^eu}DBP8~cDl;8P=H_)+jf~e|I;*Nxs)qaIQBKt$!`Xy4#V@FX+TL^)*1cBayv+zg z!T(}LDse1>Uk`3bHKdbGvvA0wJi)N2c3L@`N8YX8p^3U?dDgs0B0|8t>NZ1K791d- zy;r3>QE@EKko^ijam`@`)1IGUixZS`!Um#PRgff*$7mvtD;=<|8P0DIzG%{RN4^;9 zuW-Wna13kVy=L6Yd3DxNyLZM=O=5CQNz#h<3hNcbuz`E3kuX}b>VLp^N@z=mSml#R z^Hl``#Nq7Aln_Z*B*qfOr8han(de?PW~zANE?Ym-J2m6)hNe2K05)O#&|JKQuhX^U zxmp+d2@xE3=g?>#1Qc3+_lo0RO!zyF|G$g+j|u<);BYwo!|byZPV$KxjpZqFW8|4I zjdYuIjcWQV)2qhPLX@v7Q~pGxdR%dwNwv$!!y~qp%15 zRX0ZU%L8`NFQXti0q^E}A@?)Lnf@c7v3g1QnMfcd?tsm$!bj%_&r9b)UY;_M;IS}Q zosjq>*NYB)eONcfBoifyNmDfPOR*}rN~t)4fxc8ftSWyjF^`*4NMFD+5f*BXi_)av zmC!0l^8PG6JJ<=H_bh%Mq;1(gt_$LxcYOUf4hDE_1w65{RQlhirP*o!* zhL_<`yL#;qpZL<7;QPu-4>^5LUUC)K6lzl{B$LMVN1xdg2^c(y#r4Kw@2TNKdhq_X zt{3d4OchI1HC-sTBW-j#?D3U{aOs(W2Nh*HBY2ubtSEYJvq>;CKO*gZ`mo$MC01C? zI3XtR7`ibBV^}EKpB*xowJ(FB=Tyr)4_hZs8}aw#z_XI@gl2SJrUXYq>#$Y_e-|WL z?>7|w70ZW`5A=Z%YcW8Sxpu4`lK$C=grjyx*I3vuF2c20B-E zCsf27i$y0S00OOH*Yk!~?>9GpL>}z_ym|Ng&aeBwU4QnwEB>=|zuztK&(aeA zkb3+9g*Un|O~|)F^e-r&y3NM;*7bfc;%`o2Pm@jB4xX59T_1VPgfz7WCZuSQy%e1U zO>=NeLE617@{vKwr&p|QJpXjY+CFgX@~h9AGkMqTJ&q*VY%cSkYREq8wR7~CZ@TrN zTUOq*N2qHPYD*3Sri$nAE(6Ml*%X2HsXBJ38-8&ebLYFSt=w-VZ9N#g$<+w}io zlK&SJ{y$vo_a*+-6!-;&gIhG1e>nw#x}`zBcQn&qP*CeX8mBcG{I>T_-peN!opL-Lt~lK|zi>H8?%?Z#Gzr(2{t~O(=;_}Y>JRR& z<;Y#GeCJY>gnfRu)8T6D=hi#mJ#H>;OZkClpWu3Isq{E#*T@uuw?M zBN3B{R5MR?vY#>Ux{(# zqeL>GM8va&cQScqCU=p0;HqC%Jw9x@p1if^U9eC4?A6+{zi891+EG7i249D)G>%=mPmfmDY>oz*-|;U4cyCMe@z#9_FXVJ|f z5_2#(NoZMbMCVJNZ7(O(C8jTN?z&cV#|Kqbe4G8u<1n~tJe#WCkST6>#p6QTw!8rU z3%TL0iuqRrQeH%=U-xsh-|1T6p1#)neZzi-&v94thO0>rXJZYjYVWJ%6uNJH&=inI zxU0n4Pug@^9H;ena8kvRVJDH}wY;Hg?CfK)#vU{eps64g4D4`~Mxgv?KcX zCpF6SeXY2q-MYzIJT4keuhhEpNYNBxFcbMT)-t*#bf#|6isX*;Z}Y#7ga`g)$5nefl@ z)?JddEi=%`^5jnjQR2$58KyDN5Kr3xHLu$D(5y>&cVt3FYPBAW*$Ee&vwMmxlRkP{wlps0~=7YUF%6iw9jrR@_n%rkqo#yGiQCRQGqcnN6 zI(v`Wc&%;jXImGMV)&%n1&cNRp?zjZW6eWV-Oii#cIGctgL-(yV&HY3&8kDyan5Cy zN8VYljLR}^)Ta5^p5M;p-G8RGV<^jQpQTbU??L#M922hT10(mMlu2BgLY&T}rOrG5 z)u#Tx$oCrx{}*EY`(^zF1&tq2_+t8Jm;wfeWb?hi4gQ)w=zRE;vt#h)ec}N76j2K} ztncMC&EQ=2==`HTYun@(zVJ4~jm^rwr;2h`;MGnz-!2*KKWCJ3O&Zg>0Fr z_MANKzZGv%|KWPH`__o4blD!DRv?FZ6!_+*<9 z)v&LrG7Jmfa7%*Jxe-m@`vUFgQ4`CFyG>^M4BcF>smGNU)uyR6*p`|!tWll`rzqV# zZq-Gzw@E@(ceps%I(({p|M61Z)lM8Sk|WWdt^Xt;N@rjDT5S9Kf_q0y!rXFiH#cpr z36wa7^G&bY9kETtSEOD%Y?c#uKz6rmK$4h2QeTGgOu#KssH^s#zpC;KYrXKQ$HZjtRPYR-Aa?i$C` zV>z`#LdA+5En6{JR+u-4@*P75lE!k2-1PYGh{;&lC3HHPIcvFvI_**of2-!~e{}bO zz`Mo){F1r)t-CX4TJ`mO;VJnDMVnkia3VCDHMaG~8*jRl?4DKZbRzGpz*w|sZx`Hp zcGo@?nTa}Jc@N8I(8_A4S&B<5L@I0l7SGuM6+N-KvL*#-jTc!%1}hf5mA$j?Gx$YN za{~MN%Z`Of99rEtb@X0?S;BZ~DRPxH2CQq#gi)P*ZHHw0}QKdELyiUKWh5JyNh|RG=ea#UzkN%sO&+rhcveuKZ$Gw~H^7k*3yE z({vg|!Xoai+A(#B>bFhRPMr*ePpK3`h;fSZHBeL&vYF%O|b$>zOAF}%WyU_n0 z1vHtvP1FUAd3JX3J`#k|dy6qp_bAo@#-yt6-fYjI#Q4C;Z7M2-=$}v!;`@MLsxUvB z5`RHK4vcEydq4kYoI-h)bmxYtc(CGD_u|kuEe9-_w+&yrP!}d+w30J4+>eY^3qX}G zo`_{(8IZf=`NhwMt&8eTUp!B66^QN%{n!?gq0#4*ViSe{feZ`wrv@N7;yAo@=^k=) z>cxegr!8glL~wwIrIWD2OL<)ut58tAATG=`YhFv#inn5bZ=$hmdu5U|Z@uC0kX-{a zOF#e!D7L6USK0EfzwXocp32}y-JDRG^~$M?RkAXuO<{`AG;X&WE$2xHKHy-kE3}Ed zKX|5CL7Y`wxOPZPQoo=ci@`$k3sA^p&`m~4yp;UZYb`5+NAvxRH?e!_ot%T^t?b+u zc`ho{RS1Okl}dZoNuCnzeJDR%Wmg}ZY%pb(0DofJxEw*+d8YbI^o*OC*XIDig?V)uv4AuK|=s%c27Zai^glOgCzBN|cO*SgJA1YZ_s~}`0Y~MhY&e^@#CokJGTI{1KcTl!( z?u@MYbI5#f%2i)0Ar{ZjT3D2`BRsF#c_|=YRvmhSN~J}X?#NFaj~Qih24D*eT&*y)Q3BrCfTv>5l%uadXco{W99-l=&n6SDq7;+;;u;nnc>JR$1B=X9OB zFQ2Jb%dKA;K;n(vp2t%_`$bvxrqM!A=X*V@rDRRE`rJ#oC^{)Q=gNJ>GoUdCLGzfZ@*@JJ^ zLlkF8CTlw)+)HHbj1=6>?|t`3MtHjMI!J9$E@xV(q)$f~D{QGPc1NE-xHr+RJsh)$ z&}S#_NT0~07vd6+7ru-y8+`lCH0n&id)!>U#UVnX^C;z^dzVAJoG|C+mCRF$$qSC! z2VhK61W8WKgg7e&`xIrC9T_&u60iDpM7Ov0wMx95-jbRUvo?J~guIUr+*_;dAb2Ar zWp&B^wRW}1F1^xSmo9DR!1GrY8L4tKj-P7&+jS@N%+G2I8WsG&-gs)G7zLJbh4L%B0AU2|u?`R0zBwa&_J=dk~KpWk`*v-deazRXzx zzrrsCekt%vfu9Qe_%as&0ElnF6W`QGC;$*8@c@X~p$+yW!_3tp)TGtJekI7(3tNAi zdeQR;0Z&iq4S0&^jwpb`04r~(yo_ii4Mp(5VaUM)gLj=gkb`3+JSinZm~yCGNSq0= zlY`KHvd!^BWk6Xaxk^Fzo_CrH9d{lLO*Oma3R)52La0 zP7B{T+Z08Hd9ZLyAVd6?0iIM+k20W5h+^7xd;x8 zgg?pbdXp(HODbXFbojK^T`wzsNih%4t8jaVR&`jxZBBS@nKvC&_5`(?N+QQct|nL8O>E z`KSxR*p7WidrCr8udM*op<(m3Bi_Kpb~iaOfGF1(BtX*+-5p@}+f)XyF!(|9m`oQ| z-_}7aWQ9BXW1{)TYM2K!;g%3yldTp>D;P(s6TO#n)>VCfX@qX(!QWT&znzxRxh_s7 zpn)@IYk{ZUir$%++jH!ouiw$TgCuc;0C^meBt&$__<_x-v|id^j$4{;8&{=?t&vrt)_$dfW^Hj8pFUe+`w6ut#ie(K|%2OhqAhMpE%S8DmqpHf1 z*@+fXWpZOmXAzbx%g!i}Oj9NCA((Igiq$dm>H^A8Zg{VJ7#52J{R{znybL0&oAxAp zz`+eE3x^j-rz1!!$2KSn>Ljk6b^p8xjCV-K;W9A~1>Xd-_u=*y>|D4<)F<7_&@?Dd#JEe)m{Iey z<^|%Oos?WEKaFLBcX#Yg2GBW7KCnTWdqF*BJ&&KoC*MjN-C+D9-Ob#V4Kg^8B%X** zVp~0YFOtZws4d6i!8vB;B_*JZQE4G+55r0LGjL6Hw!EDA5|_t^dWvk}35w3v7$+&T zc$P$lU5S*gF=Jyi>edT!50mrs)a_#JaVXW;{q7m(p|r>VeeJ3oBZGA_gVtPs?M65N zKwW`PR?5^tV9lF%#+wu7Nf#h`sOYwkaNCnPQ z9ugDeT#^=~V{71>MT*!ixm%PNbfapR8@ppNPMZ65EoAGc@!Vn_sc=n_-m1|^s3meoHU@7M=kLy(OieSNo4Q%G zS0qO^RHAbnWvR0{Kw3OK#w-4yO;g#R4ErWHKnS7nlVIjXZ1=drNBU3jW}y=Fjc_=G z<+DV7@tX;piRMI5{5VrG@euddGInN=Ds(1Ni5OWC&GkBHlZC4pw8diGEc{}o&^p@r z-uhxNG@Vy7;A4~?RS>aX2(P4MDyKOKBkoq+8y)Oa^YVim{Hq)4(~_32rB03CiBa7k?TIHyTvhLFkp;04tI;QW_l)37;=_S`MPkC#RuLk)G0& zfj-^QbbUO-S#8cfO+gb5GZKCb3AM=8MncRi{0v)q{6L2dPluKFy9@AH&62w!GEtB~ z;CNzlo3oPVLcL3cFz$fbL{X{)<20^ZL+di7EWyo%uQLlp7qq>TMKbpQ22aEHEH_1X zsX8$Tp09OS#f|&vjW7*YcO57*`vqbh#`4y?u(ppbpMvLw&rJeY;lQ@DC$D;xUDW*% zzq@cyIXo(zdl)rE?5gs0r<*%k>+2aC>lwKJtKjm624JC+p8$Z{_(6Rxcc8D5SA%nM zG0P#-cgdQEE1_g(uDhi06`W9N6@X*poucR40-=n$Vr#Jc_AXB2db>3 zOGQ9=qot2P-#ncJnrg{!q74-fn)>%`JUAi;KJLT#7UBS9dup6yZM*40=6qfV^g>d~XB9=;MMm#4RiAJT(y)%`P$Jsg1 zVUn6|Tu7caLmbFB z9Eu(D%ym~y!@Vk7gTipycLUa7MQLx>Pbe5&79|~jCPVuPh08~c^KP95IK?4xII6v# z_MrXa=(I}v%wd~d)%-Wtv$Va%+)As?rXF>UHa_g>1|93X6RwVhkO0(m2o2N8#CIy0 z^(Knun{?9TiR)!!D&+MLnIhF_7zB6{M`K=on7*|W5N7fdg6^yw5vWSgon+~k^aSZb z0vOz!R(e(yk5>Gul31 zwwV4yw*1M&zI&g}psCNv%?Udokwc&FFfB1Ma5#Crs7bf7>YY+l`QB;f_M8*CU=x)q zBuZZ@x`0j<%u71OQ9|;aP%iRrx6&{N{Q925ZIeL`NK-+Rptu{!vuNqa@}=t$9sgo5z8jkt|A*eKr4T zs{EbBxloDpvf&&wR7lw>TrxnobeAH?$B38K<^IMJ>=@uQu3BaKQsVNq%)62(9r131 zZsS{s0p;|-s$nC93lGn;4YE%4wI0g3A(0$zadYbf$jlePPQ2-rB$^SsghA7N7`083 zHiO=jSdhE;10!LT4grVL;+%G2@EvDF)Xtr^ina`PqwK16U0}7H4?T3H`F6y$bI$Ek zxC1N2uSe|vyp`+zQvfXL;09YW&UdjXbjPTxt*^$oV;al)dJ_#OWCEp_?0we^8 zs(sYWpde@|J&^Ph!;d~2|MB=RUN%=<{t^mJl+hgzkD5PRXh*z}0)>>;?A6k$8Z|e& ze+K2Lvm6frDPMKnA14M_ZYvkJF%vHE2oWmrLKe=j146_J5*4N}x8vEyK@RpsPvm`XiOW%0^csIvO(I>wild>TbZ(O`lb5M_LA%Yv<_q+COh;8p ziP2RO;3(rWWVp}^7qY!&SsWniT9c?4@1+Y#bDg`YOWJrVKn6Z(`Cb4;t*=I&g0^iR zRuUJT?<<=Clp9oA%%o;Cz6jX)^^Fl z$6beRm61k}dxC8%e)9crghLhAA*!R4uaIa^;GXVw^9w81gBs-q0oi1b0f0srBy$M~ zQTM(egqB_^&VERej6NVB1=e|{+l2EGc|@pJN)2os(a`SYOX7Ru*_On-Q9co1zGL6N z;$#K&8JkMsOIr0o=)W!BFB7x?;|s&d&jmI!!ZdqFRTWcCE4)s31t74&9&?PA)x;!b z)+fyE_E@JCLpjDT?#UskFDJ()wIZB85|PMFK(TD+ASL}&nJgr|EHx z9SRH{3-XzW5(HM>C}y7>=+|A-GOkBa zPJecB@=qxItH=A_9Tj2%Kw^VsQ|x+rTs~6OU|aU)H%a)%x6Mp$I<^{WE`_ek+y9!K zC$zr|D&z+;2s8{paKiXOAnc?*4WSGchDwr4W@W+Z?1^@sR-)7+g_Q!VqO4 z^Hp0EtT_S~qPM4l3`Q3d;-oo>!2tkMKok~F6-WSJFutG>uT8irK_!5mM=kw zMkaB3p;6>Ge2|1x(YY>8Zb zd8Vup#GI-HGO13AJ14$F;4IoLl(@+Wt41G@vbp262?sN$_(^~|9F{F)Ztms;PlS`) z(lCI!NwxcaU>7G#q@c>CC`nGQ#t2=ftE9XJh5JnGe4>?g*lIui)z4_+z9N=zZ!P*4 zKVzY}oe)f3!`Jn4{`s#aAG@<#v&hEMX}rf1dKri1;&FB$4hM(O05we~28frYq|?Ex zRmLYb8wekVz?RzB$U|q;(^9KRnL%gUgZ}7PAffu2-wrhu42svlLu2`KJ)og4^KFvG zNYo`V^`1HAg}g+302;|Y8nPI402Nt5tD1W}t}3eTLV25Sq(zR&VYwQ>z%ix7?f^*x zNti6gFy9yVsW4xa5$iMu_zz~C$fXdSP^iazG_z7Y+}@0V%L(-FqezOQc9SGAir@+a zM`%V-NdzMbi7ufNgWU>R;Fe%0v??0w0**=|033oaYNSc(>t^;aavs28AkaIlvT6jR z%wm->8W{Nv%PZ_A=M)sPAhT3nK^KlGX)60!?s=Q*SlXI@1wK1>6 z>bzid&lQO4Uh}Z4H)l7}xeW_JNIc+6y0L=4rQ|z7KG>YLtLwbMnq%*K#w0@)mU!EF zF@*ZEXK$ECdkg)wcD(364u!v)9{<6DtIh_}>iFzYuzNlvW>`76Q=_uK44c!ZYZ!mS zO5dqxi}u6*_fkCm9ONs%S+uDy0NFD@2flW)Me&{TQkZ@i@nhextW*DrjC@a%^ypX! zTojW8cIzNGUUsx$QGnBfrjHDqpgSN*H@W_p%YxDF94CPei*_^apx|O3XOM9P^Oj}R zZ?=tdwnc0iZ&B{)SZItZjx;_#)NO% zNAT_;MKKZ~OW4kx3=2#uhG8oMBmp_l?a)8!sBE%6J_)&e2n-QT!Y)sN`!Nr&IrX3; z&KRh30oy?Vg7f(ZJ>bEGn&R`s!)2oZbo! zhGL4k7uFLXO{xJnKsRK*RXjD!rfO$(mV4E4fmhK@2Q9U@g6X0I>-N^DvCoAv`#iK0 zJJ+|fJHx9RSE@Q3ix(ZQ7#utJYWnPz)aQS6W0r?xf@JrC&ndTe&8%u>rn6(&|GH7*h_rw>^c_lMcSElmjd-ICN0S0S1r`HixrII{&rBHr-% zn~g*gB&Dnr$l+vtna)k%Ji1kllmI$IEK!hf&=VPjl9iRpHP0M)LfFVoNa4E?0BAf9 zo(<^wGDHy&RzxSwh_O$U1yRI65Q(;d4T>#q=qfR)b*c_q6F>6`r@hy!)r@ZuFVTB? z!9X;ct6H}IcbDnF5>t2onY$wwL$uTt_XgfhAGLbma@e#3(M{d+;bOywk_W=M-QvPm zt6U2{1hzEns`ZY4bj<8sZ0V4~(Zk%uXD))~8;5#zXZ2>TIff|&?pfCzAGzzL!nKiu zpDw?Pm|oo6axOA{-}{5nuYP=QId|CSkHvcj*F=30x#`V|$R8V4-TIMh@h4O)K`Yoa z{=aPc@Si#t`E@eGjKjtT0k}oVP_QRB*7d`rrRWXWgSkLq0XpDC_(jkV__{$W@do@^ z8{-QK?INAs&|~t{k)MBSfwB%dzoVu zPOczQkbzaatuhWTt2Jhs1#Iyn-=M@4)f_O+Zfrh2^^{RS+it%bC2h|-2B`s$m7}L; z)XNi}=stGhh4xEYpYxj3SMAqM5WG<@-Inn(!{LO<6KCVC0b;d9Cp!9F_0e0VVwSsdI1)VjuaZx>wORnX#2|Ln3w@$$^1q;ZU|@dHQ4yH58yzEI<) zNE#Q2#ho~+sq~O`-nn}PKEDrrE}ppI1s}6)bE4KwNa`)s)_iI3?&=NQKJv%@SeK_h zfz-mrq1Jmxr>?m^`*5W8E_ZKng#XoO-sH8tH`-dgj;VS7G4kx-#@|ofUm5wZVdmzW zuJ#k|b@yK$UXmO6R(~*U?e2fp`abmKqj^E}ZSuFB-D@c;{qpS}qKAGYxVL`t8Tr#v z_;u&~*DA32Q<)DLmFz${^JG8xxo6wv)|p`PWTy(ax&~+!3uEGA_<)TP=$;DCp;_?N zxtfe#E^JPf3$RXd&1f}T0}_p!FWQmx7$g>_btI!yYe2#C3_xG|m?HA@m8$#^*w^>H&rG2-!n5lI;KM5$gEaP-<`-7wtwF(_ zi9VCrlKQ8mpuX+@fA?(Z@SI z&OY}_<`o))!MV6p63swYRMLNOTWo-wLiQi3nBme=IMfa z=lqYw5_-xPHP*)Q_`JE}eR|*_{p9i&gK&#?S!;=3E%dd|r0plBX&&~lJnh`k5NH*4 zb6s0RCTNhVu_u3#!dyd+3|0i}TNSXMCO6r`=fW=F~6AjMh? zQWvF!RL)su@UWelCPguXi-Yxe03IMv{Ov&6l% zJ|yPlJAaWM-tJ)ko;8*B?)h=3-M+)OzIABxUoEkV`lI;5mTmjvT~B(sSptkzZ)@*DbRF;}DXp`LAFwTK^-n2s|t_DdIlS2W4PRN9Lj+1Wo2M ziS0pRP+IVImuXHE-xGon0-}tB)_GLEU0u)X#vBXSCJ!hBuE4U8OGq6G&`dpLD}ZoD z^frZ#t6gut!1nsm~<hn<)Z?-9znX0rq#JH1_J}IYLtIwxf zHq;t?+61E>)4aFw=wXz!m(7FGKQ7Khn1#OZD%l--#xK+3yu(s?UdHv_9rUGAPNds0pPMXmi?2Hwr=d(@h19~N_XZ8$%in7)6iLtpir!pJU(D{`|D z-_}xp6j@b7C)}|&i+)j)JbO9jU`&Ve%)POa>f<{)r!MYh6;7ecCizU^tTy2pR*tqT z`>A_wavO}r^ncQfus9tybU`b7PrY`xb6q z(5C}!4ksG4&+Res64hH;T1kH3=Wd|4R9*AZqvB%Bx0w;^kSD=9uHM(~?HLgahfxIj zMIL3vuFj9@8zW`+NjwjzBdHjTN_FCdKm(upTW*r}0TwlGIs`cLgClvmJQ~qDo{v8DrE)xK1 zXh5xr=niKJOA~)z6_aaU*1P%p0ne{atcCc1}M&DV5SX z5<#)Dcx_s%GLCIZ0JkC^z~?BS7t$5BtnDxkkkAhKt6mp*z{yE01#mJ#W1#$S5XwOU zsB0Y51>upb;OR^tN65kn1(B89>1rhs>ac*z4zIZ$O08Mj(6}x8OIlJ>+D|B~ZeCI; z$M%W6+ra#}`ap!mhB-p!8P9wDs~!Y@aO|7uy;OzqDlpDGt>OEYStW6p-ua2~LR(99 zqFOHP44Z>pwrIEZztr2DdyiFy7vJ$dPi@QYeRn@0{>U2AJX_U#Nn44tuRoNQ4<50| z(3feLK4hL9X*pH)yv%F5@Lp}uR~v_;`e!t1BOF}^!}}sTO_yXe17pPm)oO=kuMiZq zjO~=0Nkv`w%Z-27n1!9ZW@xRd3Fy$$w@pKjFMa@t){ zbzbIS+H;#{TQx!#cYQ7NYVvz_g?;Q^eR$~n`RP!Fw>>*>8pj}>M(6uBbT$=$dCGEC^D&eWC8Ots0zq~Xubj{!X#~cID)gl`9?#52g-eLgjEp@ zBt&(wtYPB6LC15+;}F$Jzx#}O*=!x_dBoCSwQrEb?w(QcG z=tnt)rxKPE9?4mrY&98#cbe zYknIweU)|M+N(m3y<#n>g>y|d{zC2j?zz9O6pv}&u_o@4{J3QKYBpsk%Q7n?DC?w+ zLYhqG%eyr*XCFFlmMgFO-Wad-Jiy=-k!bX`_kA%T>Cq|A`rUqxmRP>@%WbA|<;gzB z?%G+~sq`bZ&fi#;-#>aP^1=4@tBlVFUVabb9N$2B*?F_OeSNJ&{6b{Ihkc5Loy${? z&rH*=t8k3Iy}x=oFZXj*msLlCoq_Kq7wdJ8t`i?(SGv7!S-;p6_2p9Ull6QTw%b6) z|6V9iKAmmQA2QoV4beWc(J`57sOC+lrgsZdL-1dyaJV<6>()zscXkAMC%r{K{e~X6 z!A?qFRz!xpCwYOA>;NTy;~yapqN~U)vO_vL(-tY%+&<91!p9WkNe`t&}nGN~1wkiwrIhS|f@Y<+HXj*_P5N8zJWT zahK{LfZ(Ji;-2pBT-=L6(zAm=7^0y6*_FZ6+XejAqBPFgy6w)-eMI*)Unf%Eri5S?t60fgUY0+e@-#rXBcr#^qCoOpwPmX+7w%W4U7+ZwGh>kOq|?|pP${IMD!Aa3 zf??49h$Bq}AFs!));PSac;e&xsH1c;}0C{3MMeoLPQ+q+LBURvwBJV4&-xXY13j}f#wB1F#~x5Lu2b+UD{>DegGLs3aV4n4{V zS+#tDwu=TLjn#&LMBfYqW>B?XzE@`$a|6`{Ttf%HwDY@pSj9Y9UWb(oVL~EB7>VqU zdEugtvnFp|s`Wd62@DzWrmox8wqsk|`5o9E@k8(S2EI8tCy!!Wl3{(+f$%pWvP8`8 z&P;7fx~ti;q~KrgGHRK%Mf0oEda3h*cRI1(s4+6#yn161zuY|24DbD0Br_%w(;Mq! zxliL->fc5?Xq}|CCD*y8E|krWvV(m#If4D0au*}z9Mq@L_xmLsysFE+JT@~M6Fhod z=9^b8rD{lfb8qe4xpXjnX?puekPx!O?X|XKW|H7>s^8mlT7&V?UeU5`$_ zl!2}Dh*dA7R6U;uryoPO={<>YxGcU9w_oXI1NrkQV>Vfjntm%r!|L&&%qL?v z%A#`}l`o^)E|sdMmj{&9NyT(vL-Mo>V;W-Us@V@$_L&?npKWk!>5M+QQbKRZvUFdc zU)8&_%fNL4nEs%wSRSza5JC2?gpDdgRp?^S?pCo2z7CToqony-w(<>NoJt z%w&y&t4l^u;Luy8*W=-P)rhwQ$#o$wytGWGXL>f7m##m0(yQcR$w3Ld^TEZH1qqj~ zJv1s#S&83>Wy0|%VD;%8|*m*>}+b6B** zxad7gYOF6}V88PwS;+AEuNp*(SxUTG%@QcFz<--}AkcqJh$V@YxnDs&(6xX5IQ z@QUVqG5FsfZ;6ly&YU@u0)}R1jKYb0+Kk;qQLv)ZD7j4Zabk1r7$v^SZaA>w9gb=rTbk&u$=M3rqX<%GN(QF&$s(pd`PKMYP78 z7~N5-I7~dGN2uE*i#8*a3PB;U=Uh9Yd$5N@N0a@DwIcEu)e&7H#+5mYgEE+vxoxdF z?hqQUxP+-aVkxn3EnSei-NdZoS)lcf=2*R&yP|s_L_7rq?bd$YmCO_}=HVC|^;=XvXrMhV1 z0B`T)r_$m;kBVx^sA8qdrpdI=J0m^m|S!B{rK_u z$GO$xm2V+zt(xk~~1=HE#Fg~N@8(iE@OYAS>`R8FOH1M@%&_sUx zf!VGQKOkTb?bpOTd_USOtj;fW5AuxvzbyRf*Xa9i?*D)L^1r&}-`3@SN$O81Tt}9z zLLuiT6jUi_rr3Pu-=+^nGvik`Cj(=YrxqW{c8M_4dpkGgEE-@^^^MkVQlqbrMdkpa z_y2aY*Z%nNa&?XCN55I;ndiyR>q&84lQ>@ITNJ!=D=eOG12^M$10a7LREO^j1n_ME z=IWj)HXc$zcWKfToTXNd={o~fG#I>~r7ewS0t^KwWuO+EEyFkYPMTP0s^AW4sO`IJ z>K7({z+fPzXV!4B{XGc|DI@m{`Vlrlfha35x|OW66~-L3HA`Rp<$z370^gi4RZI6H z<?CapFY4Ddfr&nK|t^`)Um+;e4FvzQWV=A<6hKfT*lkHNz zkTs!^U?fz?%s08)PhawCR@2Z%JpK=?YlQwV^E`D7KisP?hvf70mvu}Hza;6PX&hS37skpgha z6i|b(EgY9xiUT(Y+k3jDSi8B~7G^ArQLD(dZtm7@y`JX<-P*4BwG1Z@<*%cZD)Q>j)yjSp89Q3( z^QV63P_2^a!NKUich>wT6#m{Czsmg+DezY)ECWEuDg{vgHWYphk$<8N|GS#?p*%|t5%T$ literal 0 HcmV?d00001 diff --git a/apps/games/bit-jumper/public/assets/audio/menu.mp3 b/apps/games/bit-jumper/public/assets/audio/menu.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..31a613efaef47837517751721db08da9d962599b GIT binary patch literal 22986 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 literal 0 HcmV?d00001 diff --git a/apps/games/bit-jumper/public/assets/audio/rocket_end.mp3 b/apps/games/bit-jumper/public/assets/audio/rocket_end.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..24411cbdee9e472789c64931c09033008fd113d0 GIT binary patch literal 22986 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ᦓC5WluD6|#?A7|#-Ae} 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 Gf&T|IZ!}f_ literal 0 HcmV?d00001 diff --git a/apps/games/bit-jumper/public/assets/audio/spring.mp3 b/apps/games/bit-jumper/public/assets/audio/spring.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..f20719d41f2839475de4d9cd868446212b7ff047 GIT binary patch literal 22986 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 If2AG&A1i|wdH?_b literal 0 HcmV?d00001 diff --git a/apps/games/bit-jumper/public/assets/fonts/frog-block.ttf b/apps/games/bit-jumper/public/assets/fonts/frog-block.ttf new file mode 100644 index 0000000000000000000000000000000000000000..0e487a24c9dcc0dbb23af06b9adc765542d5cfa7 GIT binary patch literal 35065 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 j*xnNB20C-sTmkkj e7TgfMU=4egxUpbOf5tF&3rBnCb_E-B7*VztMwPoyS9yKhlD`# zhAY2jbpD&}$-L?`>w-o9_%c((g&C&JPDqbV^sRrQP|SEh;)L{?^~}*;*CSdxMVB96 zBw1irB7a)-(}VK8MIn=SzKVA+Sh!V0ylES3%76}H@O1TaS?83{1OQv? BOjiH^ literal 0 HcmV?d00001 diff --git a/apps/games/bit-jumper/public/assets/icons/sound_off.png b/apps/games/bit-jumper/public/assets/icons/sound_off.png new file mode 100644 index 0000000000000000000000000000000000000000..ed55f95aa74038ff79eb9c54b530e09b64f0a6ea GIT binary patch literal 161 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|qCH(4LoEEC zPWI$uP~c#G`Cq=b@SuxQQ_+=T$qfMkpA;kg_XgUgu=ir2Hx%2~aYVe=0*g~yXh z#OjrVb!4}0oX_xTd$3y8{dw0ioRp$BC{46_8gOop!OjUx3lp^jBV%@htY+|Z^>bP0 Hl+XkKb)qzu literal 0 HcmV?d00001 diff --git a/apps/games/bit-jumper/public/assets/icons/sound_on.png b/apps/games/bit-jumper/public/assets/icons/sound_on.png new file mode 100644 index 0000000000000000000000000000000000000000..886cab7e656b6c2844294333a03a3586e382c7e6 GIT binary patch literal 188 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|$~;{hLoEE4 zPJYPepvcl%`M>>IiM877)fd-CojX2pMq77#)hdP}p(Ta&41zzuoC%MpD=72facGb{ zaydXxQNkg<@!s6e*O&@YdwN3~g@5gxsm;j6dL;Z~%t48O$Qzsw_Fg`6WBWDZWfRUR l%$$8v!~XB)SH@E(uuk*x6YTTRo&$6NgQu&X%Q~loCICu+N9F(k literal 0 HcmV?d00001 diff --git a/apps/games/bit-jumper/public/assets/media/banner.png b/apps/games/bit-jumper/public/assets/media/banner.png new file mode 100644 index 0000000000000000000000000000000000000000..c8e3009db80c5d3953de0041496082855de38f34 GIT binary patch literal 10495 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 literal 0 HcmV?d00001 diff --git a/apps/games/bit-jumper/public/assets/particles/dot.png b/apps/games/bit-jumper/public/assets/particles/dot.png new file mode 100644 index 0000000000000000000000000000000000000000..668fe4fc6ee946dfdc80917884b869fc79a5e4af GIT binary patch literal 82 zcmeAS@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)ga%mF?juK)l4Uw%aT1dz++>Eakt cF()|z$Yx?-^jN>75XfTiboFyt=akR{0KbS6ivR!s literal 0 HcmV?d00001 diff --git a/apps/games/bit-jumper/public/assets/particles/ring.png b/apps/games/bit-jumper/public/assets/particles/ring.png new file mode 100644 index 0000000000000000000000000000000000000000..ed4590ab16cc63f00bc17fff8af413656677ad8e GIT binary patch literal 163 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 width / 2 + Controller.TOUCH_OFFSET + ) { + this.player.moveRight(); + } + + if (this.player.body.velocity.y > 0) { + this.player.fall(); + } + + // if the character goes to far to the left, reset it to the right + if (this.player.x < 0 - this.player.width) { + this.player.x = this.scene.sys.game.canvas.width; + } else if (this.player.x > this.scene.sys.game.canvas.width) { + this.player.x = 0 - this.player.width; + } + + // if the player goes too low, explode them. + const camera = this.scene.cameras.main; + if ( + this.player.y > + this.scene.sys.game.canvas.height + + camera.scrollY + + Controller.DEATH_OFFSET + ) { + if (this.player.explode('fall')) { + this.scene.events.emit( + Particles.FLOOR_DEATH, + Player.FLOOR_DEATH_PARTICLE_QUANTITY, + this.player.x, + this.player.y + ); + } + } + } +} diff --git a/apps/games/bit-jumper/src/lib/objects/enemies.ts b/apps/games/bit-jumper/src/lib/objects/enemies.ts new file mode 100644 index 000000000..003e2ce5d --- /dev/null +++ b/apps/games/bit-jumper/src/lib/objects/enemies.ts @@ -0,0 +1,348 @@ +import { assertNever } from '@worksheets/util/errors'; +import { once } from '@worksheets/util/functions'; + +import { DEPTHS, OUT_OF_BOUNDS } from '../data'; +import { EnemyType } from '../types'; +import { Observer } from './observer'; + +export class Enemies extends Phaser.GameObjects.Group { + static SPAWN_CHANCE = 7; + static RECLAIM_OFFSET = 100; + static PREFILL_QUANTITY = 20; + observer: Observer; + recycled: Record; + constructor(scene: Phaser.Scene) { + super(scene); + this.recycled = { + spiker: [], + chomper: [], + floater: [], + }; + this.createAnimations(); + this.prefill(); + } + + prefill() { + // create 10 of each enemy type + for (let i = 0; i < Enemies.PREFILL_QUANTITY; i++) { + this.recycled.spiker.push(new Spiker(this)); + this.recycled.chomper.push(new Chomper(this)); + this.recycled.floater.push(new Floater(this)); + } + } + + spawn(x: number, y: number) { + this.spawnType(x, y, this.randomKey()); + } + + spawnType(x: number, y: number, type: EnemyType) { + const enemy = this.getOrCreate(type); + this.add(enemy.place(x, y)); + } + + createAnimations() { + if (!this.scene.anims.get('spike')) { + this.scene.anims.create({ + key: 'spike', + frames: this.scene.anims.generateFrameNumbers('jumper_spritesheet', { + start: 60, + end: 62, + }), + frameRate: 4, + }); + } + } + + update() { + this.children.iterate((enemy: Phaser.GameObjects.GameObject) => { + if (enemy instanceof Enemy) { + const camera = this.scene.cameras.main; + if (enemy.y > camera.scrollY + camera.height + Enemies.RECLAIM_OFFSET) { + enemy.terminate(); + } + } + return true; + }); + } + + getOrCreate(key: EnemyType) { + const category = this.recycled[key]; + if (category.length) { + return category.pop() as Enemy; + } else { + const EnemyConstructor = this.pickConstructor(key); + return new EnemyConstructor(this); + } + } + + randomKey() { + const keys = Object.keys(this.recycled) as EnemyType[]; + return Phaser.Math.RND.pick(keys); + } + + pickConstructor(key: EnemyType) { + switch (key) { + case 'spiker': + return Spiker; + case 'chomper': + return Chomper; + case 'floater': + return Floater; + default: + throw assertNever(key); + } + } +} + +export abstract class Enemy extends Phaser.Physics.Arcade.Sprite { + static PARTICLE_QUANTITY = 25; + declare type: EnemyType; + enemies: Enemies; + body: Phaser.Physics.Arcade.Body; + constructor(enemies: Enemies) { + super( + enemies.scene, + OUT_OF_BOUNDS.x, + OUT_OF_BOUNDS.y, + 'jumper_spritesheet', + 0 + ); + this.enemies = enemies; + enemies.scene.add.existing(this); + enemies.scene.physics.add.existing(this); + this.setBodySize(12, 12); + this.setDepth(DEPTHS.ENEMY); + if (!(this.body instanceof Phaser.Physics.Arcade.Body)) { + throw new Error( + 'Expected body to be an instance of Phaser.Physics.Arcade.Body' + ); + } + this.body.setAllowGravity(false); + this.body.setImmovable(true); + } + + place(x: number, y: number) { + this.body.checkCollision.none = false; + this.setVisible(true); + this.x = x; + this.y = y; + this.animate(); + return this; + } + + terminate() { + this.body.checkCollision.none = true; + this.setVisible(false); + this.enemies.remove(this); + this.enemies.recycled[this.type].push(this); + } + + abstract animate(): void; +} + +export class Spiker extends Enemy { + type: EnemyType = 'spiker'; + bouncing?: Phaser.Tweens.Tween; + blinking?: Phaser.Time.TimerEvent; + wandering?: Phaser.Tweens.Tween; + + constructor(enemies: Enemies) { + super(enemies); + this.setTexture('jumper_spritesheet', 60); + } + + animate() { + this.blink(); + this.wander(); + this.bounce(); + } + + terminate() { + super.terminate(); + + this.wandering?.stop(); + this.wandering = undefined; + this.bouncing?.stop(); + this.bouncing = undefined; + this.blinking?.remove(); + this.blinking = undefined; + } + + private bounce() { + this.bouncing = this.scene.tweens.add({ + targets: this, + y: this.y + Phaser.Math.RND.pick([-10, -5, 5, 10]), + duration: 1000, + yoyo: true, + repeat: -1, + }); + } + + private wander() { + let lastX = 1; + this.wandering = this.scene.tweens.add({ + targets: this, + x: this.x + 50, + duration: 3000, + yoyo: true, + repeat: -1, + onUpdate: () => { + if (lastX !== this.x) { + this.flipX = this.x < lastX; + lastX = this.x; + } + }, + }); + } + + private blink(waitFor = 2000) { + this.blinking = this.scene.time.delayedCall( + waitFor, + () => { + this.anims.play({ + key: 'spike', + repeat: 1, + }); + + this.blink(Phaser.Math.Between(1000, 5000)); + }, + [], + this + ); + } +} + +export class Chomper extends Enemy { + type: EnemyType = 'chomper'; + direction: boolean; + tween?: Phaser.Tweens.Tween; + constructor(enemies: Enemies) { + super(enemies); + this.direction = false; + this.pickSprite(); + } + + pickSprite() { + this.setTexture('jumper_spritesheet', this.direction ? 63 : 64); + } + + animate() { + this.wander(); + } + + terminate() { + super.terminate(); + + this.tween?.stop(); + this.tween = undefined; + } + + wander() { + this.pickSprite(); + this.tween = this.scene.tweens.add({ + targets: this, + x: this.x + (this.direction ? -25 : +25), + duration: 3000, + onComplete: () => { + this.direction = !this.direction; + this.chomp(); + }, + }); + } + + chomp() { + this.setTexture('jumper_spritesheet', 65); + + const openMouth = once(() => this.setTexture('jumper_spritesheet', 66)); + + const originalX = this.x; + this.tween = this.scene.tweens.add({ + targets: this, + x: { from: this.x - 1, to: this.x + 1 }, + duration: 50, + yoyo: true, + repeat: 14, + delay: 1000, + onUpdate: (t) => { + const v = t.progress; + if (v > 0.1) { + openMouth(); + } + }, + onComplete: () => { + this.x = originalX; + this.wander(); + }, + }); + } +} + +export class Floater extends Enemy { + type: EnemyType = 'floater'; + tween?: Phaser.Tweens.Tween; + + constructor(enemies: Enemies) { + super(enemies); + this.setTexture('jumper_spritesheet', 67); + } + + animate() { + this.moveRandomly(); + } + + terminate() { + super.terminate(); + + this.tween?.stop(); + this.tween = undefined; + } + + moveRandomly() { + // pick a random point to float to. + const offset = 20; + const x = Phaser.Math.Between( + offset, + this.scene.sys.game.canvas.width - offset + ); + const y = Phaser.Math.Between(this.y - 50, this.y + 50); + this.tween = this.scene.tweens.add({ + targets: this, + x, + y, + duration: 3000, + onComplete: () => { + this.laugh(); + }, + }); + } + + laugh() { + const openMouth = once(() => { + this.setTexture('jumper_spritesheet', 69); + }); + const closeMouth = once(() => { + this.setTexture('jumper_spritesheet', 68); + }); + + this.setTexture('jumper_spritesheet', 68); + // bounce up and down + this.tween = this.scene.tweens.add({ + targets: this, + y: this.y + 3, + duration: 150, + yoyo: true, + repeat: 6, + delay: 50, + onUpdate: (t) => { + if (t.progress > 0.9) { + closeMouth(); + } else if (t.progress > 0.1) { + openMouth(); + } + }, + onComplete: () => { + this.moveRandomly(); + }, + }); + } +} diff --git a/apps/games/bit-jumper/src/lib/objects/loading-bar.ts b/apps/games/bit-jumper/src/lib/objects/loading-bar.ts new file mode 100644 index 000000000..da9b91a1f --- /dev/null +++ b/apps/games/bit-jumper/src/lib/objects/loading-bar.ts @@ -0,0 +1,52 @@ +export type ProgressBarOptions = { + width: number; + height: number; + background?: number; + progress?: number; +}; + +export class ProgressBar extends Phaser.GameObjects.Container { + background: Phaser.GameObjects.Graphics; + progress: Phaser.GameObjects.Graphics; + options: ProgressBarOptions; + + constructor( + scene: Phaser.Scene, + x: number, + y: number, + options: ProgressBarOptions + ) { + super(scene, x, y); + this.options = options; + + this.createBars(); + this.scene.add.existing(this); + } + + createBars() { + this.background = new Phaser.GameObjects.Graphics(this.scene); + this.background.fillStyle(this.options.background ?? 0xffffff, 1); + this.background.fillRect( + -this.options.width / 2 - 1, + -this.options.height / 2 - 1, + this.options.width + 2, + this.options.height + 2 + ); + + this.add(this.background); + + this.progress = new Phaser.GameObjects.Graphics(this.scene); + this.add(this.progress); + } + + updateProgress(value: number) { + this.progress.clear(); + this.progress.fillStyle(this.options.background ?? 0x000000, 1); + this.progress.fillRect( + -this.options.width / 2, + -this.options.height / 2, + this.options.width * value, + this.options.height + ); + } +} diff --git a/apps/games/bit-jumper/src/lib/objects/observer.ts b/apps/games/bit-jumper/src/lib/objects/observer.ts new file mode 100644 index 000000000..d1935c75b --- /dev/null +++ b/apps/games/bit-jumper/src/lib/objects/observer.ts @@ -0,0 +1,53 @@ +import { Player } from './player'; + +export class Observer { + static POWER_UP_SCREEN_OFFSET = 130; + static DEFAULT_SCREEN_OFFSET = 90; + static DEFAULT_STARTING_APEX = 60; + static DEFAULT_SCREEN_INTERPOLATION = 0.05; + static EVENT_APEX_CHANGE = 'apex-change'; + apex: number; + scene: Phaser.Scene; + main: Phaser.Cameras.Scene2D.Camera; + player: Player; + screenOffset: number; + interpolation: number; + events: Phaser.Events.EventEmitter; + + constructor(scene: Phaser.Scene, player: Player) { + this.events = new Phaser.Events.EventEmitter(); + this.scene = scene; + this.main = scene.cameras.main; + this.player = player; + this.apex = Observer.DEFAULT_STARTING_APEX; + this.screenOffset = Observer.DEFAULT_SCREEN_OFFSET; + this.interpolation = Observer.DEFAULT_SCREEN_INTERPOLATION; + + this.player.on(Player.EVENT_POWER_UP_START, () => { + this.screenOffset = Observer.POWER_UP_SCREEN_OFFSET; + }); + + this.player.on(Player.EVENT_POWER_UP_OVER, () => { + this.screenOffset = Observer.DEFAULT_SCREEN_OFFSET; + }); + } + + cleanup() { + this.player.off(Player.EVENT_POWER_UP_START); + this.player.off(Player.EVENT_POWER_UP_OVER); + } + + update() { + if (this.player.y < this.apex) { + this.apex = this.player.y; + + this.main.scrollY = Phaser.Math.Linear( + this.main.scrollY, + this.apex - this.screenOffset, + this.interpolation + ); + + this.events.emit(Observer.EVENT_APEX_CHANGE, this.apex); + } + } +} diff --git a/apps/games/bit-jumper/src/lib/objects/particles.ts b/apps/games/bit-jumper/src/lib/objects/particles.ts new file mode 100644 index 000000000..801938338 --- /dev/null +++ b/apps/games/bit-jumper/src/lib/objects/particles.ts @@ -0,0 +1,129 @@ +export class Particles { + static FLOOR_DEATH = 'floor_death'; + static IMPACT_DEATH = 'impact_death'; + static DOTS = 'explode_dots'; + static RINGS = 'explode_rings'; + static EXHAUST = 'rocket_exhaust'; + constructor(scene: Phaser.Scene, x: number, y: number) { + const exhaust = new Phaser.GameObjects.Particles.ParticleEmitter( + scene, + x, + y, + 'dot', + { + lifespan: 1000, + speedX: { min: -30, max: 30 }, + scale: { min: 0.1, max: 2.5 }, + alpha: 1, + emitting: false, + } + ); + + const dots = new Phaser.GameObjects.Particles.ParticleEmitter( + scene, + x, + y, + 'dot', + { + lifespan: 1000, + speedX: { min: -50, max: 50 }, + speedY: { min: -10, max: -40 }, + scale: { min: 0.5, max: 2 }, + alpha: { start: 1, end: 0 }, + gravityY: 200, + emitting: false, + } + ); + + const rings = new Phaser.GameObjects.Particles.ParticleEmitter( + scene, + x, + y, + 'ring', + { + lifespan: 150, + scale: { start: 0, end: 1.25 }, + alpha: { start: 1, end: 0 }, + emitting: false, + } + ); + + const impact = new Phaser.GameObjects.Particles.ParticleEmitter( + scene, + x, + y, + 'dot', + { + lifespan: 3000, + speedX: { min: -100, max: 100 }, + speedY: { min: -150, max: 50 }, + scale: { min: 0.5, max: 2 }, + alpha: { start: 1, end: 0 }, + gravityY: 100, + emitting: false, + } + ); + const floor = new Phaser.GameObjects.Particles.ParticleEmitter( + scene, + x, + y, + 'dot', + { + lifespan: 3000, + speedX: { min: -100, max: 100 }, + speedY: { min: -300, max: 0 }, + scale: { min: 0.5, max: 2 }, + alpha: { start: 1, end: 0 }, + gravityY: 200, + emitting: false, + } + ); + + scene.add.existing(dots); + scene.add.existing(rings); + scene.add.existing(exhaust); + scene.add.existing(impact); + scene.add.existing(floor); + + scene.events.on( + Particles.DOTS, + (quantity: number, x: number, y: number) => { + dots.explode(quantity, x, y); + } + ); + + scene.events.on(Particles.RINGS, (x: number, y: number) => { + rings.emitParticleAt(x, y); + }); + + scene.events.on( + Particles.EXHAUST, + (quantity: number, x: number, y: number) => { + exhaust.explode(quantity, x, y); + } + ); + + scene.events.on( + Particles.IMPACT_DEATH, + (quantity: number, x: number, y: number) => { + impact.explode(quantity, x, y); + } + ); + + scene.events.on( + Particles.FLOOR_DEATH, + (quantity: number, x: number, y: number) => { + floor.explode(quantity, x, y); + } + ); + + scene.events.on('shutdown', () => { + scene.events.off(Particles.DOTS); + scene.events.off(Particles.RINGS); + scene.events.off(Particles.EXHAUST); + scene.events.off(Particles.IMPACT_DEATH); + scene.events.off(Particles.FLOOR_DEATH); + scene.events.off('shutdown'); + }); + } +} diff --git a/apps/games/bit-jumper/src/lib/objects/platforms.ts b/apps/games/bit-jumper/src/lib/objects/platforms.ts new file mode 100644 index 000000000..b34e412d5 --- /dev/null +++ b/apps/games/bit-jumper/src/lib/objects/platforms.ts @@ -0,0 +1,347 @@ +import { assertNever } from '@worksheets/util/errors'; + +import { DEPTHS, OUT_OF_BOUNDS } from '../data'; +import { PlatformType } from '../types'; +import { Observer } from './observer'; +import { Player } from './player'; + +export class PlatformsPool { + static PREFILL_QUANTITY = { + basic: 100, + spring: 20, + sliding: 20, + breaking: 20, + floor: 1, + }; + scene: Phaser.Scene; + recycled: Record; + constructor(scene: Phaser.Scene) { + this.scene = scene; + this.recycled = { + basic: [], + spring: [], + sliding: [], + breaking: [], + floor: [], + }; + } + + terminate(platform: Platform) { + const type = platform.type as PlatformType; + const exists = this.recycled[type].some((p) => p.id === platform.id); + if (exists) return; + + this.recycled[type].push(platform); + } + + get(type: PlatformType) { + const category = this.recycled[type]; + if (category) { + const platform = category.pop(); + if (platform) { + return platform; + } + } + + return this.create(type); + } + + prefill() { + for (const key in this.recycled) { + const k = key as PlatformType; + for (let i = 0; i < PlatformsPool.PREFILL_QUANTITY[k]; i++) { + this.create(k).terminate(); + } + } + } + + private create(type: PlatformType) { + const PlatformConstructor = this.pickConstructor(type); + return new PlatformConstructor( + this.scene, + this, + OUT_OF_BOUNDS.x, + OUT_OF_BOUNDS.y + ); + } + + private pickConstructor(type: PlatformType) { + switch (type) { + case 'basic': + return Platform; + case 'spring': + return Spring; + case 'sliding': + return SlidingPlatform; + case 'breaking': + return BreakingPlatform; + case 'floor': + return Floor; + default: + throw assertNever(type); + } + } + + group() { + // return the count of each type of platform + return Object.keys(this.recycled).reduce( + (acc, type) => ({ + ...acc, + [type]: this.recycled[type as PlatformType].length, + }), + { basic: 0, spring: 0, sliding: 0, breaking: 0, floor: 0 } + ); + } + + count() { + return Object.keys(this.recycled).reduce( + (acc, type) => acc + this.recycled[type as PlatformType].length, + 0 + ); + } +} + +export class Platforms extends Phaser.GameObjects.Group { + static SPAWN_EVENT = 'spawn'; + static SPAWN_RATE = 2; + static GAP = 12; + static SCREEN_OFFSET = 200; + + observer: Observer; + scene: Phaser.Scene; + height: number; + width: number; + pool: PlatformsPool; + constructor(scene: Phaser.Scene, observer: Observer) { + super(scene); + this.scene = scene; + this.observer = observer; + this.height = 0; + this.pool = new PlatformsPool(scene); + + const { width, height } = scene.sys.game.canvas; + this.width = width; + this.height = height; + + this.initialize(); + + this.spawnPlatforms(height - 100); + } + + private initialize() { + this.pool.prefill(); + const { width, height } = this; + this.add(this.pool.get('floor').place(width / 2, height)); + this.add(this.pool.get('basic').place(width / 2, height / 1.25)); + this.add(this.pool.get('spring').place(width / 2, height / 1.25)); + } + + private spawnPlatforms(height: number) { + for (let i = 0; i < Platforms.SPAWN_RATE; i++) { + const y = + height - + Phaser.Math.Between(Platforms.GAP * 1, Platforms.GAP * 1.5) * i; + const x = Phaser.Math.Between(0, this.width); + this.spawnPlatform(x, y); + this.height = y; + } + } + + private spawnPlatform(x: number, y: number) { + const type = Phaser.Math.Between(0, 100); + const generator = (type: PlatformType) => + this.add(this.pool.get(type).place(x, y)); + if (type < 15) { + generator('sliding'); + } else if (type < 25) { + generator('breaking'); + } else if (type < 30) { + generator('basic'); + generator('spring'); + } else { + generator('basic'); + this.emit(Platforms.SPAWN_EVENT, x, y); + } + } + + update() { + if (this.observer.apex < this.height + Platforms.SCREEN_OFFSET) { + this.spawnPlatforms(this.height - Platforms.GAP); + } + // iterate over all children and check if they are out of bounds + const lowerBound = + this.observer.main.scrollY + this.scene.sys.game.canvas.height; + this.children.iterate((platform) => { + if (platform instanceof Platform) { + if (platform.y - Platforms.SCREEN_OFFSET > lowerBound) { + this.remove(platform); + platform.terminate(); + } + } + return true; + }); + } +} + +export class Platform extends Phaser.Physics.Arcade.Sprite { + type: PlatformType = 'basic'; + pool: PlatformsPool; + body: Phaser.Physics.Arcade.Body; + id: string; + constructor(scene: Phaser.Scene, pool: PlatformsPool, x: number, y: number) { + super(scene, x, y, 'jumper_spritesheet', 27); + this.pool = pool; + this.id = Phaser.Math.RND.uuid(); + scene.add.existing(this); + scene.physics.add.existing(this); + this.setBodySize(8, 2); + this.setDepth(DEPTHS.PLATFORM); + if (!(this.body instanceof Phaser.Physics.Arcade.Body)) { + throw new Error( + 'Expected body to be an instance of Phaser.Physics.Arcade.Body' + ); + } + this.body.setImmovable(true); + this.body.setAllowGravity(false); + + this.body.checkCollision.down = false; + this.body.checkCollision.left = false; + this.body.checkCollision.right = false; + } + + place(x: number, y: number) { + this.x = x; + this.y = y; + return this; + } + + terminate() { + this.pool.terminate(this); + } +} + +export class Floor extends Platform { + type: PlatformType = 'floor'; + constructor(scene: Phaser.Scene, pool: PlatformsPool, x: number, y: number) { + super(scene, pool, x, y); + this.scaleX = 20; + } +} + +export class SlidingPlatform extends Platform { + type: PlatformType = 'sliding'; + tween?: Phaser.Tweens.Tween; + constructor(scene: Phaser.Scene, pool: PlatformsPool, x: number, y: number) { + super(scene, pool, x, y); + this.setTexture('jumper_spritesheet', 29); + } + place(x: number, y: number) { + super.place(x, y); + + this.tween = this.scene.tweens.add({ + targets: this, + x: x + Phaser.Math.RND.pick([-30, 30]), + ease: 'Linear', + duration: 1500, + yoyo: true, + repeat: -1, + }); + + return this; + } + + terminate() { + super.terminate(); + if (this.tween) { + this.tween.stop(); + this.tween = undefined; + } + } +} + +export class BreakingPlatform extends Platform { + static PARTICLE_QUANTITY = 10; + type: PlatformType = 'breaking'; + breaking = false; + constructor(scene: Phaser.Scene, pool: PlatformsPool, x: number, y: number) { + super(scene, pool, x, y); + this.setTexture('jumper_spritesheet', 28); + } + + place(x: number, y: number) { + super.place(x, y); + this.breaking = false; + this.body.checkCollision.none = false; + this.setVisible(true); + this.setActive(true); + return this; + } + + terminate() { + super.terminate(); + if (!this.breaking) { + this.breaking = true; + this.setVisible(false); + this.setActive(false); + this.body.checkCollision.none = true; + } + } + + /** The middle of the square for particle emission */ + center() { + return { x: this.x, y: this.y }; + } +} + +export class Spring extends Platform { + type: PlatformType = 'spring'; + constructor(scene: Phaser.Scene, pool: PlatformsPool, x: number, y: number) { + super(scene, pool, x, y); + this.setBodySize(6, 2); + this.setOffset(5, 3); + this.setTexture('jumper_spritesheet', 19); + this.setDepth(DEPTHS.PLATFORM + 1); + + if (scene.anims.get('spring') === undefined) { + scene.anims.create({ + key: 'spring', + frames: scene.anims.generateFrameNumbers('jumper_spritesheet', { + start: 17, + end: 19, + }), + frameRate: 24, + }); + } + } + + launch(player: Player) { + this.playReverse({ + key: 'spring', + yoyo: true, + }); + + player.jump(1.5); + player.on('jump', () => { + this.body.checkCollision.none = true; + this.body.setAllowGravity(true); + this.setVelocityY(-50); + + this.scene.time.delayedCall(1000, () => { + this.terminate(); + }); + player.off('jump'); + }); + } + + terminate() { + super.terminate(); + this.body.setAllowGravity(false); + this.setVelocity(0); + } + + place(x: number, y: number) { + super.place(x, y); + this.body.checkCollision.none = false; + return this; + } +} diff --git a/apps/games/bit-jumper/src/lib/objects/player.ts b/apps/games/bit-jumper/src/lib/objects/player.ts new file mode 100644 index 000000000..eb7cb74af --- /dev/null +++ b/apps/games/bit-jumper/src/lib/objects/player.ts @@ -0,0 +1,223 @@ +import { DEPTHS } from '../data'; +import { DeathReason, PowerUpType } from '../types'; +import { Particles } from './particles'; +import { Balloon, Helicopter, Rocket } from './power-ups'; + +export class Player extends Phaser.Physics.Arcade.Sprite { + static EVENT_POWER_UP_START = 'power-up-start'; + static EVENT_POWER_UP_OVER = 'power-up-over'; + static EVENT_DEATH = 'death'; + static EVENT_SMASH_ENEMY = 'smash-enemy'; + static IMPACT_DEATH_PARTICLE_QUANTITY = 50; + static FLOOR_DEATH_PARTICLE_QUANTITY = 150; + static FLASH_DURATION = 1000; + static FLASH_REPETITIONS = 5; + jumpLag = 50; + speed = 75; + power = 175; + balloonSpeed = 100; + balloonDuration = 3000; + helicopterSpeed = 125; + helicopterDuration = 3500; + rocketDuration = 4000; + rocketSpeed = 250; + body: Phaser.Physics.Arcade.Body; + jumping = false; + powering?: PowerUpType = undefined; + dead = false; + + constructor(scene: Phaser.Scene, x: number, y: number) { + super(scene, x, y, 'jumper_spritesheet', 0); + scene.add.existing(this); + scene.physics.add.existing(this); + this.setBodySize(8, 8); + this.setDepth(DEPTHS.PLAYER); + if (!(this.body instanceof Phaser.Physics.Arcade.Body)) { + throw new Error( + 'Expected body to be an instance of Phaser.Physics.Arcade.Body' + ); + } + + this.createAnimations(); + } + + createAnimations() { + if (!this.anims.get('balloon')) { + this.anims.create({ + key: 'balloon', + frames: this.anims.generateFrameNumbers('jumper_spritesheet', { + start: 10, + end: 13, + }), + frameRate: 12, + }); + } + + if (!this.anims.get('helicopter')) { + this.anims.create({ + key: 'helicopter', + frames: this.anims.generateFrameNumbers('jumper_spritesheet', { + start: 20, + end: 24, + }), + frameRate: 36, + }); + } + + if (!this.anims.get('rocket')) { + this.anims.create({ + key: 'rocket', + frames: this.anims.generateFrameNumbers('jumper_spritesheet', { + start: 30, + end: 34, + }), + frameRate: 24, + }); + } + } + + fall() { + if (this.jumping) return; + this.setTexture('jumper_spritesheet', 1); + } + + jump(multiplier = 1) { + if (this.body.blocked.down) { + this.jumping = true; + this.setTexture('jumper_spritesheet', 2); + setTimeout(() => { + this.body.setVelocityY(-this.power * multiplier); + this.rotation = 0; + this.setTexture('jumper_spritesheet', 0); + this.jumping = false; + this.emit('jump'); + }, this.jumpLag); + } + } + + moveLeft() { + if (this.jumping) this.body.setVelocityX(0); + else this.body.setVelocityX(-this.speed); + } + + moveRight() { + if (this.jumping) this.body.setVelocityX(0); + else this.body.setVelocityX(this.speed); + } + + balloon() { + this.powerUp({ + key: 'balloon', + duration: this.balloonDuration, + speed: this.balloonSpeed, + onComplete: () => { + const balloon = new Balloon(this.scene, this.x, this.y).release( + this.balloonSpeed * 1.15, + this.body.velocity.x + ); + this.scene.time.delayedCall(5000, () => { + balloon.terminate(); + }); + }, + }); + } + + helicopter() { + this.powerUp({ + key: 'helicopter', + duration: this.helicopterDuration, + speed: this.helicopterSpeed, + onComplete: () => { + const helicopter = new Helicopter(this.scene, this.x, this.y).release( + this.helicopterSpeed * 1.25 + ); + this.scene.time.delayedCall(5000, () => { + helicopter.terminate(); + }); + }, + }); + } + + rocket() { + this.scene.cameras.main.flash(1000, 255, 255, 255); + + const event = this.scene.time.addEvent({ + delay: 50, + callback: () => { + this.scene.events.emit(Particles.EXHAUST, 3, this.x, this.y); + }, + repeat: -1, + }); + + this.powerUp({ + key: 'rocket', + duration: this.rocketDuration, + speed: this.rocketSpeed, + onComplete: () => { + event.remove(); + const rocket = new Rocket(this.scene, this.x, this.y).release(200); + this.scene.time.delayedCall(5000, () => { + rocket.terminate(); + }); + }, + }); + } + + explode(reason: DeathReason) { + if (this.dead) return false; + this.body.setVelocity(0); + this.body.setAllowGravity(false); + this.body.checkCollision.none = true; + this.setVisible(false); + this.dead = true; + this.emit(Player.EVENT_DEATH, reason); + this.scene.sound.play('death'); + return true; + } + + private powerUp({ + key, + duration, + speed, + onComplete, + }: { + key: PowerUpType; + duration: number; + speed: number; + onComplete: () => void; + }) { + if (this.powering || this.dead) return; + + this.powering = key; + this.emit(Player.EVENT_POWER_UP_START, key); + this.scene.sound.play(`${key}_start`, { + loop: true, + }); + this.anims.play({ + key, + repeat: -1, + }); + this.body.setVelocityY(-Math.abs(speed)); + this.body.setAllowGravity(false); + this.scene.time.delayedCall(duration, () => { + this.scene.tweens.add({ + targets: this, + alpha: 0, + duration: Player.FLASH_DURATION / Player.FLASH_REPETITIONS / 2, + yoyo: true, + repeat: Player.FLASH_REPETITIONS, + onComplete: () => { + this.scene.sound.stopByKey(`${key}_start`); + this.scene.sound.play(`${key}_end`); + this.alpha = 1; + this.powering = undefined; + this.anims.stop(); + this.body.setAllowGravity(true); + this.setTexture('jumper_spritesheet', 1); + this.emit(Player.EVENT_POWER_UP_OVER); + onComplete(); + }, + }); + }); + } +} diff --git a/apps/games/bit-jumper/src/lib/objects/power-ups.ts b/apps/games/bit-jumper/src/lib/objects/power-ups.ts new file mode 100644 index 000000000..45fc0f49d --- /dev/null +++ b/apps/games/bit-jumper/src/lib/objects/power-ups.ts @@ -0,0 +1,93 @@ +import { DEPTHS } from '../data'; +import { Particles } from './particles'; + +export class PowerUps extends Phaser.GameObjects.Group { + static SPAWN_CHANCE = 1; + constructor(scene: Phaser.Scene) { + super(scene); + } + + spawn(x: number, y: number) { + const type = Phaser.Math.Between(0, 100); + + if (type < 50) { + this.add(new Balloon(this.scene, x, y - Balloon.HEIGHT_OFFSET)); + } else if (type < 90) { + this.add(new Helicopter(this.scene, x, y - Helicopter.HEIGHT_OFFSET)); + } else { + this.add(new Rocket(this.scene, x, y - Rocket.HEIGHT_OFFSET)); + } + } +} + +export class PowerUp extends Phaser.Physics.Arcade.Sprite { + body: Phaser.Physics.Arcade.Body; + constructor(scene: Phaser.Scene, x: number, y: number, frame: number) { + super(scene, x, y, 'jumper_spritesheet', frame); + scene.add.existing(this); + scene.physics.add.existing(this); + this.setDepth(DEPTHS.POWER_UP); + if (!(this.body instanceof Phaser.Physics.Arcade.Body)) { + throw new Error( + 'Expected body to be an instance of Phaser.Physics.Arcade.Body' + ); + } + + this.body.setAllowGravity(false); + } + + release(speed = 10, variance = 10) { + this.setVelocityY(-Math.abs(speed)); + this.setVelocityX(Phaser.Math.Between(-variance, variance)); + return this; + } + + terminate() { + this.destroy(); + } +} + +export class Balloon extends PowerUp { + static HEIGHT_OFFSET = 6; + event: Phaser.Time.TimerEvent; + constructor(scene: Phaser.Scene, x: number, y: number) { + super(scene, x, y, 6); + + this.setBodySize(5, 8); + } + + terminate() { + this.scene.events.emit(Particles.RINGS, this.x, this.y); + super.terminate(); + } +} + +export class Helicopter extends PowerUp { + static HEIGHT_OFFSET = 5; + constructor(scene: Phaser.Scene, x: number, y: number) { + super(scene, x, y, 7); + this.body.setSize(8, 8); + } + + release(speed: number) { + super.release(speed); + this.body.setAllowGravity(true); + this.body.setAngularVelocity(Phaser.Math.Between(speed, speed * 3)); + return this; + } +} + +export class Rocket extends PowerUp { + static HEIGHT_OFFSET = 5; + constructor(scene: Phaser.Scene, x: number, y: number) { + super(scene, x, y, 8); + this.setBodySize(8, 8); + } + + release(speed: number) { + super.release(speed); + this.setTexture('jumper_spritesheet', 35); + this.setVelocityY(-Math.abs(speed)); + return this; + } +} diff --git a/apps/games/bit-jumper/src/lib/objects/ui/button.ts b/apps/games/bit-jumper/src/lib/objects/ui/button.ts new file mode 100644 index 000000000..d26b7ed17 --- /dev/null +++ b/apps/games/bit-jumper/src/lib/objects/ui/button.ts @@ -0,0 +1,26 @@ +import { DEPTHS } from '../../data'; + +export class Button extends Phaser.GameObjects.Rectangle { + constructor(scene: Phaser.Scene, x: number, y: number, text: string) { + super(scene, x, y, text.length * 8 + 4, 11, 0xffffff); + this.setInteractive({ useHandCursor: true }); + this.on('pointerdown', () => { + this.emit('click'); + this.scene.sound.play('menu'); + }).setDepth(DEPTHS.UI); + + scene.add.existing(this); + + scene.add + .text(x, y, text, { + fontSize: '8px', + align: 'center', + color: '#fff', + fontFamily: 'frog-block', + }) + .setStroke('#000', 4) + .setOrigin(0.5, 0.5) + .setResolution(10) + .setDepth(DEPTHS.UI); + } +} diff --git a/apps/games/bit-jumper/src/lib/objects/ui/icons.ts b/apps/games/bit-jumper/src/lib/objects/ui/icons.ts new file mode 100644 index 000000000..b2569c867 --- /dev/null +++ b/apps/games/bit-jumper/src/lib/objects/ui/icons.ts @@ -0,0 +1,61 @@ +import { DEPTHS } from '../../data'; + +export class Icon extends Phaser.GameObjects.Sprite { + constructor(scene: Phaser.Scene, x: number, y: number, texture: string) { + super(scene, x, y, texture); + this.setDepth(DEPTHS.UI); + this.setInteractive({ useHandCursor: true }); + this.setOrigin(0, 0); + + this.on( + 'pointerdown', + () => { + this.emit('click'); + this.scene.sound.play('menu'); + }, + this + ); + + this.scene.add.existing(this); + } +} + +export class BackIcon extends Icon { + constructor(scene: Phaser.Scene, x: number, y: number) { + super(scene, x, y, 'back'); + } +} + +export class HeartIcon extends Icon { + constructor(scene: Phaser.Scene, x: number, y: number) { + super(scene, x, y, 'heart'); + } +} + +export class SoundIcon extends Icon { + constructor(scene: Phaser.Scene, x: number, y: number) { + super(scene, x, y, 'sound_on'); + + this.on( + 'pointerdown', + () => { + this.toggle(); + }, + this + ); + + this.scene.add.existing(this); + } + + mute(mute: boolean) { + this.scene.sound.mute = mute; + this.setTexture(mute ? 'sound_off' : 'sound_on'); + return this; + } + + toggle() { + const newState = !this.scene.sound.mute; + this.mute(newState); + this.emit('toggle', newState); + } +} diff --git a/apps/games/bit-jumper/src/lib/objects/ui/link.ts b/apps/games/bit-jumper/src/lib/objects/ui/link.ts new file mode 100644 index 000000000..e297e3da6 --- /dev/null +++ b/apps/games/bit-jumper/src/lib/objects/ui/link.ts @@ -0,0 +1,16 @@ +import { Typography } from './typography'; + +export class Link extends Typography { + constructor( + scene: Phaser.Scene, + x: number, + y: number, + text: string, + href: string + ) { + super(scene, x, y, text); + this.setInteractive({ useHandCursor: true }).on('pointerdown', () => { + window.open(href, '_blank'); + }); + } +} diff --git a/apps/games/bit-jumper/src/lib/objects/ui/typography.ts b/apps/games/bit-jumper/src/lib/objects/ui/typography.ts new file mode 100644 index 000000000..6f5343a23 --- /dev/null +++ b/apps/games/bit-jumper/src/lib/objects/ui/typography.ts @@ -0,0 +1,17 @@ +import { DEPTHS } from '../../data'; + +export class Typography extends Phaser.GameObjects.Text { + constructor(scene: Phaser.Scene, x: number, y: number, text: string) { + super(scene, x, y, text, { + fontSize: '8px', + align: 'center', + color: '#fff', + fontFamily: 'frog-block', + }); + this.setStroke('#000', 4); + this.setOrigin(0.5, 0.5); + this.setResolution(10); + this.setDepth(DEPTHS.UI); + scene.add.existing(this); + } +} diff --git a/apps/games/bit-jumper/src/lib/scenes/boot.ts b/apps/games/bit-jumper/src/lib/scenes/boot.ts new file mode 100644 index 000000000..bf5ac231e --- /dev/null +++ b/apps/games/bit-jumper/src/lib/scenes/boot.ts @@ -0,0 +1,97 @@ +import { CharityGamesPlugin } from '@worksheets/phaser/plugins'; +import Phaser from 'phaser'; + +import { ProgressBar } from '../objects/loading-bar'; +import { Typography } from '../objects/ui/typography'; +import { Menu } from './menu'; + +export class Boot extends Phaser.Scene { + static readonly KEY = 'boot'; + server: CharityGamesPlugin; + serverProgress: ProgressBar; + assetProgress: ProgressBar; + constructor() { + super(Boot.KEY); + } + + preload() { + this.server = CharityGamesPlugin.find(this); + this.server.initialize(); + + this.createBars(); + this.setLoadEvents(); + + const { width, height } = this.cameras.main; + + new Typography(this, width / 2, height * 0.65, 'LOADING'); + + this.load.image('dot', './assets/particles/dot.png'); + this.load.image('ring', './assets/particles/ring.png'); + this.load.image('sound_on', './assets/icons/sound_on.png'); + this.load.image('sound_off', './assets/icons/sound_off.png'); + this.load.image('back', './assets/icons/back.png'); + this.load.image('heart', './assets/icons/heart.png'); + + this.load.audio('balloon_end', './assets/audio/balloon_end.mp3'); + this.load.audio('balloon_start', './assets/audio/balloon_start.mp3'); + this.load.audio('break', './assets/audio/break.mp3'); + this.load.audio('death', './assets/audio/death.mp3'); + this.load.audio('helicopter_end', './assets/audio/helicopter_end.mp3'); + this.load.audio('helicopter_start', './assets/audio/helicopter_start.mp3'); + this.load.audio('jump', './assets/audio/jump.mp3'); + this.load.audio('menu', './assets/audio/menu.mp3'); + this.load.audio('rocket_end', './assets/audio/rocket_end.mp3'); + this.load.audio('rocket_start', './assets/audio/rocket_start.mp3'); + this.load.audio('smash', './assets/audio/smash.mp3'); + this.load.audio('spring', './assets/audio/spring.mp3'); + + this.load.spritesheet( + 'jumper_spritesheet', + './assets/sprites/infinite_jumper.png', + { + frameHeight: 16, + frameWidth: 16, + } + ); + } + + createBars() { + const { width, height } = this.cameras.main; + this.assetProgress = new ProgressBar(this, width / 2, height / 2 - 6, { + height: 8, + width: width * 0.5, + }); + this.serverProgress = new ProgressBar(this, width / 2, height / 2 + 6, { + height: 8, + width: width * 0.5, + }); + } + + setLoadEvents() { + this.load.on( + 'progress', + (value: number) => { + this.assetProgress.updateProgress(value); + }, + this + ); + + this.load.on('complete', () => { + this.startGame(); + }); + + this.server.on('initializing', (value: number) => { + this.serverProgress.updateProgress(value); + }); + + this.server.on('initialized', () => { + this.startGame(); + }); + } + + startGame() { + if (this.server.isInitialized && this.load.isReady()) { + this.scene.start(Menu.KEY); + } + } +} diff --git a/apps/games/bit-jumper/src/lib/scenes/credits.ts b/apps/games/bit-jumper/src/lib/scenes/credits.ts new file mode 100644 index 000000000..c749f6eae --- /dev/null +++ b/apps/games/bit-jumper/src/lib/scenes/credits.ts @@ -0,0 +1,33 @@ +import { VERSION } from '../data'; +import { BackIcon } from '../objects/ui/icons'; +import { Link } from '../objects/ui/link'; +import { Typography } from '../objects/ui/typography'; +import { Menu } from './menu'; + +export class Credits extends Phaser.Scene { + static readonly KEY = 'credits'; + constructor() { + super(Credits.KEY); + } + + create() { + new BackIcon(this, 2, 2).on('click', () => { + this.scene.start(Menu.KEY); + }); + new Typography(this, 45, 20, 'CREDITS'); + // draw a line under the title + this.add.rectangle(45, 25, 60, 1, 0xffffff); + + new Typography(this, 45, 40, 'CODE:'); + new Link(this, 45, 50, 'ModestDuck', 'https://modestduck.itch.io'); + + new Typography(this, 45, 70, 'ART:'); + new Link(this, 45, 80, 'i-am-44', 'https://i-am-44.itch.io/'); + new Link(this, 45, 90, 'Polyducks', 'https://polyducks.itch.io/'); + + new Typography(this, 45, 110, 'MUSIC:').setFontSize(8); + new Link(this, 45, 120, 'ColorAlpha', 'https://coloralpha.itch.io/'); + + new Typography(this, 45, 150, VERSION); + } +} diff --git a/apps/games/bit-jumper/src/lib/scenes/end.ts b/apps/games/bit-jumper/src/lib/scenes/end.ts new file mode 100644 index 000000000..19751c1ae --- /dev/null +++ b/apps/games/bit-jumper/src/lib/scenes/end.ts @@ -0,0 +1,81 @@ +import { CharityGamesPlugin } from '@worksheets/phaser/plugins'; + +import { StorageKey } from '../data'; +import { Enemies } from '../objects/enemies'; +import { Button } from '../objects/ui/button'; +import { Typography } from '../objects/ui/typography'; +import { GameOverPayload } from '../types'; +import { Menu } from './menu'; +import { Play } from './play'; + +export class End extends Phaser.Scene { + static readonly KEY = 'end'; + payload: GameOverPayload; + server: CharityGamesPlugin; + + constructor() { + super(End.KEY); + } + + init(payload: GameOverPayload) { + this.payload = payload; + this.server = CharityGamesPlugin.find(this); + } + + create() { + const { width, height } = this.cameras.main; + const highScore = Math.max( + this.payload.score, + this.server.storage.get(StorageKey.HIGH_SCORE, 0) + ); + + this.server.storage.set(StorageKey.HIGH_SCORE, highScore); + + new Typography(this, width * 0.5, 25, 'GAME\nOVER').setFontSize(16); + + new Typography(this, width * 0.5, 65, `SCR: ${this.payload.score}`); + + new Typography(this, width * 0.5, 75, `HI: ${highScore}`); + + new Button(this, width * 0.5, height - 60, 'MENU').on('click', () => { + this.scene.start(Menu.KEY); + }); + new Button(this, width * 0.5, height - 40, 'RESTART').on('click', () => { + this.scene.start(Play.KEY); + }); + + const enemies = new Enemies(this); + enemies.spawn(width * Phaser.Math.FloatBetween(0.2, 0.8), height * 0.9); + + this.server.storage.save(); + this.submitScore(highScore); + this.submitAchievements(highScore); + } + + submitScore(score: number) { + this.server.leaderboard.submit(score); + } + + submitAchievements(score: number) { + const achievements: string[] = []; + const { death, powerUps, smashed } = this.payload; + death === 'spiker' && achievements.push(achievement('spiker')); + death === 'chomper' && achievements.push(achievement('chomper')); + death === 'floater' && achievements.push(achievement('floater')); + smashed >= 5 && achievements.push(achievement('smasher')); + powerUps['balloon'] >= 2 && achievements.push(achievement('balloon')); + powerUps['helicopter'] >= 2 && achievements.push(achievement('helicopter')); + powerUps['rocket'] >= 2 && achievements.push(achievement('rocket')); + score >= 1000 && achievements.push(achievement('1000')); + score >= 2500 && achievements.push(achievement('2500')); + score >= 5000 && achievements.push(achievement('5000')); + score >= 7500 && achievements.push(achievement('7500')); + score >= 10000 && achievements.push(achievement('10000')); + score >= 15000 && achievements.push(achievement('15000')); + score >= 20000 && achievements.push(achievement('20000')); + + this.server.achievements.unlock(achievements); + } +} + +const achievement = (name: string) => `bit-jumper:${name}`; diff --git a/apps/games/bit-jumper/src/lib/scenes/menu.ts b/apps/games/bit-jumper/src/lib/scenes/menu.ts new file mode 100644 index 000000000..cfce41420 --- /dev/null +++ b/apps/games/bit-jumper/src/lib/scenes/menu.ts @@ -0,0 +1,86 @@ +import { CharityGamesPlugin } from '@worksheets/phaser/plugins'; + +import { StorageKey } from '../data'; +import { Enemies } from '../objects/enemies'; +import { PlatformsPool } from '../objects/platforms'; +import { Button } from '../objects/ui/button'; +import { HeartIcon, SoundIcon } from '../objects/ui/icons'; +import { Typography } from '../objects/ui/typography'; +import { EnemyType, PlatformType } from '../types'; +import { Credits } from './credits'; + +export class Menu extends Phaser.Scene { + static readonly KEY = 'menu'; + server: CharityGamesPlugin; + + constructor() { + super(Menu.KEY); + } + + preload() { + this.server = CharityGamesPlugin.find(this); + } + + create() { + const { width, height } = this.cameras.main; + const highScore = this.server.storage.get(StorageKey.HIGH_SCORE, 0); + const muted = this.server.storage.get(StorageKey.MUTE, false); + + new HeartIcon(this, 2, 2).on('click', () => { + this.scene.start(Credits.KEY); + }); + new SoundIcon(this, width - 2, 2) + .setOrigin(1, 0) + .mute(muted) + .on('toggle', (update: boolean) => { + this.server.storage.set(StorageKey.MUTE, update); + this.server.storage.save(); + }); + + new Typography(this, width / 2, 40, 'BIT\nJUMPER') + .setFontSize(16) + .setScale(0.9); + + new Button(this, width / 2, height - 60, 'PLAY').on('click', () => { + this.scene.start('play'); + }); + + new Button(this, width / 2, height - 40, `HI: ${highScore}`); + + this.spawnPlatforms(); + this.spawnEnemies(); + } + + spawnPlatforms() { + const { width, height } = this.cameras.main; + + const pool = new PlatformsPool(this); + const offset = 5; + const options: PlatformType[] = ['basic', 'basic', 'breaking', 'sliding']; + const randomWithinScreen = () => + Phaser.Math.Between(offset, width - offset); + for (let i = 1; i < 8; i++) { + const key = Phaser.Math.RND.pick(options); + this.add.existing( + pool.get(key).place(randomWithinScreen(), height - 21 * i) + ); + } + } + + spawnEnemies() { + const { width, height } = this.cameras.main; + + const pool = new Enemies(this); + const offset = 15; + const options: EnemyType[] = ['spiker', 'chomper', 'floater']; + + const randomWithinScreen = () => + Phaser.Math.Between(width / 2 - offset, width / 2 + offset); + + const key = Phaser.Math.RND.pick(options); + + this.add.existing( + pool.getOrCreate(key).place(randomWithinScreen(), height / 2) + ); + } +} diff --git a/apps/games/bit-jumper/src/lib/scenes/play.ts b/apps/games/bit-jumper/src/lib/scenes/play.ts new file mode 100644 index 000000000..4e408c258 --- /dev/null +++ b/apps/games/bit-jumper/src/lib/scenes/play.ts @@ -0,0 +1,117 @@ +import Phaser from 'phaser'; + +import { Collisions } from '../objects/collisions'; +import { Controller } from '../objects/controller'; +import { Enemies } from '../objects/enemies'; +import { Observer } from '../objects/observer'; +import { Particles } from '../objects/particles'; +import { Platforms } from '../objects/platforms'; +import { Player } from '../objects/player'; +import { PowerUps } from '../objects/power-ups'; +import { DeathReason, GameOverPayload, PowerUpType } from '../types'; +import { End } from './end'; +import { ScorePlane } from './score-plane'; + +export class Play extends Phaser.Scene { + static readonly KEY = 'play'; + static readonly GAME_OVER_DELAY = 3000; + particles: Particles; + player: Player; + controller: Controller; + observer: Observer; + collisions: Collisions; + platforms: Platforms; + powerUps: PowerUps; + enemies: Enemies; + + constructor() { + super(Play.KEY); + } + + create() { + const { width, height } = this.sys.game.canvas; + this.particles = new Particles(this, 0, 0); + this.player = new Player(this, width / 1.25, height / 1.5); + this.observer = new Observer(this, this.player); + this.platforms = new Platforms(this, this.observer); + this.controller = new Controller(this, this.player); + this.powerUps = new PowerUps(this); + this.enemies = new Enemies(this); + this.collisions = new Collisions( + this, + this.player, + this.platforms, + this.powerUps, + this.enemies + ); + + this.scene.launch(ScorePlane.KEY); + this.connect(); + this.cleanup(); + } + + connect() { + const scorePlane = this.scene.get(ScorePlane.KEY) as ScorePlane; + this.time.delayedCall(250, () => { + this.controller.enable(); + }); + + this.platforms.on(Platforms.SPAWN_EVENT, (x: number, y: number) => { + const luck = Phaser.Math.Between(0, 100); + if (luck > PowerUps.SPAWN_CHANCE) return; + + this.powerUps.spawn(x, y); + }); + + this.platforms.on(Platforms.SPAWN_EVENT, (x: number, y: number) => { + const luck = Phaser.Math.Between(0, 100); + if (luck > Enemies.SPAWN_CHANCE) return; + + this.enemies.spawn(x, y); + }); + + this.observer.events.on(Observer.EVENT_APEX_CHANGE, (apex: number) => { + if (apex < 0) { + const score = Math.floor(Math.abs(apex)); + this.scene + .get(ScorePlane.KEY) + .events.emit(ScorePlane.EVENT_UPDATE_SCORE, score); + } + }); + + this.player.on(Player.EVENT_DEATH, (reason: DeathReason) => { + this.time.delayedCall(Play.GAME_OVER_DELAY, () => { + const payload: GameOverPayload = { + death: reason, + score: scorePlane.score, + powerUps: scorePlane.powerUps, + smashed: scorePlane.smashed, + }; + this.scene.stop(ScorePlane.KEY); + this.scene.start(End.KEY, payload); + }); + }); + + this.player.on(Player.EVENT_POWER_UP_START, (key: PowerUpType) => { + scorePlane.events.emit(ScorePlane.EVENT_POWER_UP, key); + }); + + this.player.on(Player.EVENT_SMASH_ENEMY, () => { + scorePlane.events.emit(ScorePlane.EVENT_SMASH_ENEMY); + }); + } + + update() { + this.controller.update(); + this.observer.update(); + this.platforms.update(); + this.enemies.update(); + } + + cleanup() { + this.events.on('shutdown', () => { + this.observer.cleanup(); + this.platforms.off(Platforms.SPAWN_EVENT); + }); + } +} diff --git a/apps/games/bit-jumper/src/lib/scenes/score-plane.ts b/apps/games/bit-jumper/src/lib/scenes/score-plane.ts new file mode 100644 index 000000000..7a7ca2a5d --- /dev/null +++ b/apps/games/bit-jumper/src/lib/scenes/score-plane.ts @@ -0,0 +1,60 @@ +import { Typography } from '../objects/ui/typography'; +import { PowerUpType } from '../types'; + +export class ScorePlane extends Phaser.Scene { + static readonly KEY = 'score-plane'; + static readonly EVENT_UPDATE_SCORE = 'update-score'; + static readonly EVENT_POWER_UP = 'power-up'; + static readonly EVENT_SMASH_ENEMY = 'smash-enemy'; + static readonly SMASH_ENEMY_POINTS = 100; + typography: Typography; + score: number; + smashed: number; + powerUps: Record; + constructor() { + super(ScorePlane.KEY); + this.score = 0; + this.smashed = 0; + this.powerUps = { + balloon: 0, + helicopter: 0, + rocket: 0, + }; + } + + updateScore(score: number) { + this.score = score; + this.typography.setText(`${score}`); + } + + create() { + this.typography = new Typography(this, 4, 4, '0') + .setAlign('left') + .setOrigin(0); + + this.events.on( + ScorePlane.EVENT_UPDATE_SCORE, + (score: number) => { + this.updateScore(score); + }, + this + ); + + this.events.on( + ScorePlane.EVENT_POWER_UP, + (key: PowerUpType) => { + this.powerUps[key]++; + }, + this + ); + + this.events.on( + ScorePlane.EVENT_SMASH_ENEMY, + () => { + this.updateScore(this.score + ScorePlane.SMASH_ENEMY_POINTS); + this.smashed++; + }, + this + ); + } +} diff --git a/apps/games/bit-jumper/src/lib/types.ts b/apps/games/bit-jumper/src/lib/types.ts new file mode 100644 index 000000000..91049ae04 --- /dev/null +++ b/apps/games/bit-jumper/src/lib/types.ts @@ -0,0 +1,19 @@ +export type PlatformType = + | 'basic' + | 'spring' + | 'sliding' + | 'breaking' + | 'floor'; + +export type EnemyType = 'spiker' | 'chomper' | 'floater'; + +export type PowerUpType = 'balloon' | 'helicopter' | 'rocket'; + +export type GameOverPayload = { + score: number; + death: DeathReason; + powerUps: Record; + smashed: number; +}; + +export type DeathReason = EnemyType | 'fall'; diff --git a/apps/games/bit-jumper/src/main.ts b/apps/games/bit-jumper/src/main.ts new file mode 100644 index 000000000..2fb2edaa9 --- /dev/null +++ b/apps/games/bit-jumper/src/main.ts @@ -0,0 +1,50 @@ +import 'phaser'; + +import { CharityGamesPlugin } from '@worksheets/phaser/plugins'; + +import { Boot } from './lib/scenes/boot'; +import { Credits } from './lib/scenes/credits'; +import { End } from './lib/scenes/end'; +import { Menu } from './lib/scenes/menu'; +import { Play } from './lib/scenes/play'; +import { ScorePlane } from './lib/scenes/score-plane'; + +const config: Phaser.Types.Core.GameConfig = { + type: Phaser.AUTO, + backgroundColor: '#000000', + roundPixels: true, + render: { + pixelArt: true, + }, + scale: { + parent: 'game', + mode: Phaser.Scale.FIT, + autoCenter: Phaser.Scale.CENTER_BOTH, + width: 90, + height: 160, + }, + scene: [Boot, Menu, Play, End, ScorePlane, Credits], + plugins: { + global: [ + { + key: CharityGamesPlugin.KEY, + plugin: CharityGamesPlugin, + start: true, + }, + ], + }, + physics: { + default: 'arcade', + arcade: { + gravity: { y: 250, x: 0 }, + debug: false, + }, + }, + dom: { + createContainer: true, + }, +}; + +window.addEventListener('load', () => { + new Phaser.Game(config); +}); diff --git a/apps/games/bit-jumper/src/styles.css b/apps/games/bit-jumper/src/styles.css new file mode 100644 index 000000000..169a5b288 --- /dev/null +++ b/apps/games/bit-jumper/src/styles.css @@ -0,0 +1,25 @@ +body, +html { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + overflow: hidden; + margin: 0px; + position: relative; + touch-action: none; + /* background: linear-gradient(180deg, #fff -10%, #d0eeff 110%); */ + background-color: #000; +} +canvas { + border: 4px solid #fff; + box-sizing: border-box; + margin: auto; +} + +@font-face { + font-family: 'frog-block'; + src: url('/assets/fonts/frog-block.ttf'); + font-weight: 400; + font-weight: normal; +} diff --git a/apps/games/bit-jumper/tsconfig.app.json b/apps/games/bit-jumper/tsconfig.app.json new file mode 100644 index 000000000..357ad0004 --- /dev/null +++ b/apps/games/bit-jumper/tsconfig.app.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": ["node"] + }, + "exclude": ["src/**/*.spec.ts", "src/**/*.test.ts"], + "include": ["src/**/*.ts"] +} diff --git a/apps/games/bit-jumper/tsconfig.json b/apps/games/bit-jumper/tsconfig.json new file mode 100644 index 000000000..149b69e88 --- /dev/null +++ b/apps/games/bit-jumper/tsconfig.json @@ -0,0 +1,28 @@ +{ + "extends": "../../../tsconfig.base.json", + "files": [], + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ESNext", "DOM"], + "moduleResolution": "Node", + "strict": true, + "resolveJsonModule": true, + "isolatedModules": true, + "esModuleInterop": true, + "noEmit": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "skipLibCheck": true, + "strictPropertyInitialization": false, + "types": ["vite/client"] + }, + "include": ["src"], + "references": [ + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/apps/games/bit-jumper/vite.config.ts b/apps/games/bit-jumper/vite.config.ts new file mode 100644 index 000000000..72f042a42 --- /dev/null +++ b/apps/games/bit-jumper/vite.config.ts @@ -0,0 +1,31 @@ +/// +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; +import dotenv from 'dotenv'; +import { defineConfig } from 'vite'; + +dotenv.config({ + path: '.env', +}); +export default defineConfig({ + root: __dirname, + cacheDir: '../../../node_modules/.vite/apps/games/bit-jumper', + base: './', // Use relative paths for all assets + define: { + 'process.env': process.env, + }, + server: { + port: 7013, + host: 'localhost', + }, + + plugins: [nxViteTsPaths()], + + build: { + outDir: '../../../dist/apps/games/bit-jumper', + emptyOutDir: true, + reportCompressedSize: true, + commonjsOptions: { + transformMixedEsModules: true, + }, + }, +}); diff --git a/apps/prisma/seed/src/insert-achievements.ts b/apps/prisma/seed/src/insert-achievements.ts index bb5a8df71..8e49527cb 100644 --- a/apps/prisma/seed/src/insert-achievements.ts +++ b/apps/prisma/seed/src/insert-achievements.ts @@ -3,12 +3,15 @@ import { prisma } from '@worksheets/prisma'; import { getSeedingChanges, seedingProperties } from '@worksheets/util/seeding'; import { SeedableGameAchievementSchema } from '@worksheets/util/types'; +type GameAchievementSchema = SeedableGameAchievementSchema & { gameId: string }; export const insertAchievements = async () => { const storedAchievements = await prisma.gameAchievement.findMany({ select: seedingProperties, }); - const achievements = games.flatMap((g) => g.achievements); + const achievements: GameAchievementSchema[] = games.flatMap((g) => + g.achievements.map((a) => ({ ...a, gameId: g.id })) + ); const { creating, updating } = getSeedingChanges( achievements, @@ -32,9 +35,7 @@ export const insertAchievements = async () => { } }; -const insertAchievement = async ( - achievement: SeedableGameAchievementSchema -) => { +const insertAchievement = async (achievement: GameAchievementSchema) => { await prisma.$transaction(async (tx) => { await tx.gameAchievement.create({ data: { @@ -63,9 +64,7 @@ const insertAchievement = async ( }); }; -const updateAchievement = async ( - achievement: SeedableGameAchievementSchema -) => { +const updateAchievement = async (achievement: GameAchievementSchema) => { await prisma.$transaction(async (tx) => { await tx.gameAchievement.update({ where: { diff --git a/libs/data/games/src/index.ts b/libs/data/games/src/index.ts index db6594b06..388d023d5 100644 --- a/libs/data/games/src/index.ts +++ b/libs/data/games/src/index.ts @@ -11,6 +11,266 @@ import { import { SeedableGameSchema } from '@worksheets/util/types'; const integratedGames: SeedableGameSchema[] = [ + { + version: 2, + id: 'bit-jumper', + name: 'Bit Jumper', + developerId: 'charity-games', + iconUrl: + 'https://cdn.charity.games/_games/bit-jumper/assets/media/thumbnail.png', + bannerUrl: + 'https://cdn.charity.games/_games/bit-jumper/assets/media/banner.png', + viewport: viewports['PORTRAIT-ONLY'], + categories: ['1p', 'arcade', 'endless', 'mobile', 'desktop'], + file: { + type: 'HTML', + url: 'https://cdn.charity.games/_games/bit-jumper/index.html', + }, + markets: {}, + createdAt: new Date('2024-08-24T00:00:00.000Z'), + updatedAt: new Date('2024-08-24T00:00:00.000Z'), + description: + '

Bit Jumper is a fast-paced endless runner where you must jump from platform to platform to reach the highest score possible. How high can you jump?

Move with left/right arrow keys or touching the left/right sides of the screen.

', + multiplier: 0.002, + leaderboard: true, + cloudStorage: true, + loot: [], + achievements: [ + { + id: 'bit-jumper:spiker', + version: 2, + name: 'Die to a Spiker', + description: 'Slam into a Spiker enemy and die in Bit Jumper.', + iconUrl: + 'https://cdn.charity.games/_games/bit-jumper/assets/achievements/spiker.png', + secret: false, + loot: [ + { + itemId: '5', + quantity: 1, + chance: 1, + }, + ], + }, + { + id: 'bit-jumper:chomper', + version: 2, + name: 'Die to a Chomper', + description: 'Slam into a Chomper enemy and die in Bit Jumper.', + iconUrl: + 'https://cdn.charity.games/_games/bit-jumper/assets/achievements/chomper.png', + secret: false, + loot: [ + { + itemId: '5', + quantity: 1, + chance: 1, + }, + ], + }, + { + id: 'bit-jumper:floater', + version: 2, + name: 'Die to a Floater', + description: 'Slam into a Floater enemy and die in Bit Jumper.', + iconUrl: + 'https://cdn.charity.games/_games/bit-jumper/assets/achievements/floater.png', + secret: false, + loot: [ + { + itemId: '5', + quantity: 1, + chance: 1, + }, + ], + }, + { + id: 'bit-jumper:smasher', + version: 2, + name: 'Smash 5 Enemies', + description: + 'Hit an enemy while using a power-up to smash it in Bit Jumper. Enemies include Spikers, Chompers, and Floaters.', + iconUrl: + 'https://cdn.charity.games/_games/bit-jumper/assets/achievements/smasher.png', + secret: false, + loot: [ + { + itemId: '5', + quantity: 1, + chance: 1, + }, + ], + }, + { + id: 'bit-jumper:balloon', + version: 2, + name: 'Balloon Power-Up x2', + description: + 'Collect the Balloon Power-Up twice in a single game of Bit Jumper.', + iconUrl: + 'https://cdn.charity.games/_games/bit-jumper/assets/achievements/balloon.png', + secret: false, + loot: [ + { + itemId: '5', + quantity: 1, + chance: 1, + }, + ], + }, + { + id: 'bit-jumper:helicopter', + version: 2, + name: 'Helicopter Power-Up x2', + description: + 'Collect the Helicopter Power-Up twice in a single game of Bit Jumper.', + iconUrl: + 'https://cdn.charity.games/_games/bit-jumper/assets/achievements/helicopter.png', + secret: false, + loot: [ + { + itemId: '5', + quantity: 1, + chance: 1, + }, + ], + }, + { + id: 'bit-jumper:rocket', + version: 2, + name: 'Rocket Power-Up x2', + description: + 'Collect the Rocket Power-Up twice in a single game of Bit Jumper.', + iconUrl: + 'https://cdn.charity.games/_games/bit-jumper/assets/achievements/rocket.png', + secret: false, + loot: [ + { + itemId: '5', + quantity: 1, + chance: 1, + }, + ], + }, + { + id: 'bit-jumper:1000', + version: 2, + name: 'Score 1000', + description: 'Score 1000 points in a single game of Bit Jumper', + iconUrl: + 'https://cdn.charity.games/_games/bit-jumper/assets/achievements/1000.png', + secret: false, + loot: [ + { + itemId: '5', + quantity: 1, + chance: 1, + }, + ], + }, + { + id: 'bit-jumper:2500', + version: 2, + name: 'Score 2500', + description: 'Score 2500 points in a single game of Bit Jumper', + iconUrl: + 'https://cdn.charity.games/_games/bit-jumper/assets/achievements/2500.png', + secret: false, + loot: [ + { + itemId: '5', + quantity: 1, + chance: 1, + }, + ], + }, + { + id: 'bit-jumper:5000', + version: 2, + name: 'Score 5000', + description: 'Score 5000 points in a single game of Bit Jumper', + iconUrl: + 'https://cdn.charity.games/_games/bit-jumper/assets/achievements/5000.png', + secret: false, + loot: [ + { + itemId: '5', + quantity: 2, + chance: 1, + }, + ], + }, + { + id: 'bit-jumper:7500', + version: 2, + name: 'Score 7500', + description: 'Score 7500 points in a single game of Bit Jumper', + iconUrl: + 'https://cdn.charity.games/_games/bit-jumper/assets/achievements/7500.png', + secret: false, + loot: [ + { + itemId: '5', + quantity: 3, + chance: 1, + }, + ], + }, + { + id: 'bit-jumper:10000', + version: 2, + name: 'Score 10000', + description: 'Score 10000 points in a single game of Bit Jumper', + iconUrl: + 'https://cdn.charity.games/_games/bit-jumper/assets/achievements/10000.png', + secret: false, + loot: [ + { + itemId: '8', + quantity: 1, + chance: 1, + }, + ], + }, + { + id: 'bit-jumper:15000', + version: 2, + name: 'Score 15000', + description: 'Score 15000 points in a single game of Bit Jumper', + iconUrl: + 'https://cdn.charity.games/_games/bit-jumper/assets/achievements/15000.png', + secret: false, + loot: [ + { + itemId: '8', + quantity: 2, + chance: 1, + }, + ], + }, + { + id: 'bit-jumper:20000', + version: 2, + name: 'Score 20000', + description: 'Score 20000 points in a single game of Bit Jumper', + iconUrl: + 'https://cdn.charity.games/_games/bit-jumper/assets/achievements/20000.png', + secret: false, + loot: [ + { + itemId: '8', + quantity: 3, + chance: 1, + }, + ], + }, + ], + tasks: [ + { type: 'score', score: 500 }, + { type: 'score', score: 1000 }, + { type: 'score', score: 2500 }, + ], + }, { version: 1, id: 'hide-and-seek', @@ -39,7 +299,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'hide-and-seek:perfect', version: 1, - gameId: 'hide-and-seek', name: 'Play a Perfect Game', description: 'Find all three hidden characters without making a mistake', @@ -57,7 +316,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'hide-and-seek:found-one', version: 1, - gameId: 'hide-and-seek', name: 'Find One', description: 'Find at least one hidden character during a game', iconUrl: @@ -74,7 +332,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'hide-and-seek:found-two', version: 1, - gameId: 'hide-and-seek', name: 'Find Two', description: 'Find at least two hidden characters during a game', iconUrl: @@ -91,7 +348,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'hide-and-seek:found-three', version: 1, - gameId: 'hide-and-seek', name: 'Find Three', description: 'Find all three hidden characters during a game', iconUrl: @@ -108,21 +364,21 @@ const integratedGames: SeedableGameSchema[] = [ ], tasks: [ { - name: 'Find one hidden character', + name: 'Play Hide & Seek (1)', description: 'Find one hidden character during a single game of Hide and Seek', type: 'score', score: 1, }, { - name: 'Find two hidden characters', + name: 'Play Hide & Seek (2)', description: 'Find two hidden characters during a single game of Hide and Seek', type: 'score', score: 2, }, { - name: 'Find all hidden characters', + name: 'Play Hide & Seek (3)', description: 'Find all three hidden characters during a single game of Hide and Seek', type: 'score', @@ -156,7 +412,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'TALL_TOWER_BONUS_1', version: 1, - gameId: 'tall-tower', name: 'Bonus Prize - 1', description: 'Reach the bonus prize line with a single block', iconUrl: @@ -173,7 +428,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'TALL_TOWER_BONUS_2', version: 1, - gameId: 'tall-tower', name: 'Bonus Prize - 2', description: 'Reach the bonus prize line with two blocks', iconUrl: @@ -190,7 +444,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'TALL_TOWER_BONUS_3', version: 1, - gameId: 'tall-tower', name: 'Bonus Prize - 3', description: 'Reach the bonus prize line with three blocks', iconUrl: @@ -207,7 +460,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'TALL_TOWER_MINOR_1', version: 1, - gameId: 'tall-tower', name: 'Minor Prize - 1', description: 'Reach the minor prize line with one block', iconUrl: @@ -224,7 +476,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'TALL_TOWER_MINOR_2', version: 1, - gameId: 'tall-tower', name: 'Minor Prize - 2', description: 'Reach the minor prize line with two blocks', iconUrl: @@ -241,7 +492,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'TALL_TOWER_MINOR_3', version: 1, - gameId: 'tall-tower', name: 'Minor Prize - 3', description: 'Reach the minor prize line with three blocks', iconUrl: @@ -258,7 +508,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'TALL_TOWER_MAJOR_1', version: 1, - gameId: 'tall-tower', name: 'Major Prize - 1', description: 'Reach the major prize line with one block', iconUrl: @@ -275,7 +524,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'TALL_TOWER_MAJOR_2', version: 1, - gameId: 'tall-tower', name: 'Major Prize - 2', description: 'Reach the major prize line with two blocks', iconUrl: @@ -292,7 +540,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'TALL_TOWER_MAJOR_3', version: 1, - gameId: 'tall-tower', name: 'Major Prize - 3', description: 'Reach the major prize line with three blocks', iconUrl: @@ -312,6 +559,10 @@ const integratedGames: SeedableGameSchema[] = [ type: 'score', score: 50, }, + { + type: 'score', + score: 100, + }, ], }, { @@ -334,28 +585,11 @@ const integratedGames: SeedableGameSchema[] = [ multiplier: 0.015, leaderboard: true, cloudStorage: true, - loot: [ - { - itemId: '4', - quantity: 1, - chance: 1, - }, - { - itemId: '2', - quantity: 1, - chance: 1, - }, - { - itemId: '10044', - quantity: 1, - chance: 1, - }, - ], + loot: [], achievements: [ { id: 'BLOCK_BASH_100_POINTS_GAME', version: 1, - gameId: 'block-bash', name: 'Score 100', description: 'Score 100 points in a single game', iconUrl: @@ -372,7 +606,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'BLOCK_BASH_500_POINTS_GAME', version: 1, - gameId: 'block-bash', name: 'Score 500', description: 'Score 500 points in a single game', iconUrl: @@ -389,7 +622,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'BLOCK_BASH_1000_POINTS_GAME', version: 2, - gameId: 'block-bash', name: 'Score 1,000', description: 'Score 1,000 points in a single game', iconUrl: @@ -411,7 +643,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'BLOCK_BASH_1500_POINTS_GAME', version: 2, - gameId: 'block-bash', name: 'Score 1,500', description: 'Score 1,500 points in a single game', iconUrl: @@ -433,7 +664,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'BLOCK_BASH_2000_POINTS_GAME', version: 2, - gameId: 'block-bash', name: 'Score 2,000', description: 'Score 2,000 points in a single game', iconUrl: @@ -455,7 +685,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'BLOCK_BASH_2500_POINTS_GAME', version: 1, - gameId: 'block-bash', name: 'Score 2,500', description: 'Score 2,500 points in a single game', iconUrl: @@ -477,7 +706,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'BLOCK_BASH_3000_POINTS_GAME', version: 2, - gameId: 'block-bash', name: 'Score 3,000', description: 'Score 3,000 points in a single game', iconUrl: @@ -499,7 +727,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'BLOCK_BASH_3500_POINTS_GAME', version: 1, - gameId: 'block-bash', name: 'Score 3,500', description: 'Score 3,500 points in a single game', iconUrl: @@ -521,7 +748,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'BLOCK_BASH_4000_POINTS_GAME', version: 2, - gameId: 'block-bash', name: 'Score 4,000', description: 'Score 4,000 points in a single game', iconUrl: @@ -543,7 +769,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'BLOCK_BASH_4500_POINTS_GAME', version: 1, - gameId: 'block-bash', name: 'Score 4,500', description: 'Score 4,500 points in a single game', iconUrl: @@ -565,7 +790,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'BLOCK_BASH_5000_POINTS_GAME', version: 2, - gameId: 'block-bash', name: 'Score 5,000', description: 'Score 5,000 points in a single game', iconUrl: @@ -587,7 +811,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'BLOCK_BASH_100_LINES', version: 1, - gameId: 'block-bash', name: 'Complete 100 Lines', description: 'Complete 100 lines across all games', iconUrl: @@ -604,7 +827,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'BLOCK_BASH_500_LINES', version: 1, - gameId: 'block-bash', name: 'Complete 500 Lines', description: 'Complete 500 lines across all games', iconUrl: @@ -621,7 +843,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'BLOCK_BASH_1000_LINES', version: 1, - gameId: 'block-bash', name: 'Complete 1,000 Lines', description: 'Complete 1,000 lines across all games', iconUrl: @@ -638,7 +859,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'BLOCK_BASH_2500_LINES', version: 1, - gameId: 'block-bash', name: 'Complete 2,500 Lines', description: 'Complete 2,500 lines across all games', iconUrl: @@ -655,7 +875,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'BLOCK_BASH_5000_LINES', version: 1, - gameId: 'block-bash', name: 'Complete 5,000 Lines', description: 'Complete 5,000 lines across all games', iconUrl: @@ -672,7 +891,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'BLOCK_BASH_10000_LINES', version: 1, - gameId: 'block-bash', name: 'Complete 10,000 Lines', description: 'Complete 10,000 lines across all games', iconUrl: @@ -689,7 +907,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'BLOCK_BASH_1000_BLOCKS_LIFETIME', version: 1, - gameId: 'block-bash', name: 'Place 1,000 Blocks', description: 'Place 1,000 blocks across all games', iconUrl: @@ -706,7 +923,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'BLOCK_BASH_5000_BLOCKS_LIFETIME', version: 1, - gameId: 'block-bash', name: 'Place 5,000 Blocks', description: 'Place 5,000 blocks across all games', iconUrl: @@ -723,7 +939,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'BLOCK_BASH_10000_BLOCKS_LIFETIME', version: 1, - gameId: 'block-bash', name: 'Place 10,00 Blocks', description: 'Place 10,000 blocks across all games', iconUrl: @@ -740,7 +955,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'BLOCK_BASH_20000_BLOCKS_LIFETIME', version: 1, - gameId: 'block-bash', name: 'Place 20,000 Blocks', description: 'Place 20,000 blocks across all games', iconUrl: @@ -757,7 +971,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'BLOCK_BASH_50000_BLOCKS_LIFETIME', version: 1, - gameId: 'block-bash', name: 'Place 50,000 Blocks', description: 'Place 50,000 blocks across all games', iconUrl: @@ -774,7 +987,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'BLOCK_BASH_100000_BLOCKS_LIFETIME', version: 1, - gameId: 'block-bash', name: 'Place 100,000 Blocks', description: 'Place 100,000 blocks across all games', iconUrl: @@ -822,68 +1034,11 @@ const integratedGames: SeedableGameSchema[] = [ score: 250, }, ], - loot: [ - { - itemId: '10044', - quantity: 1, - chance: 1, - }, - { - itemId: '10055', - quantity: 1, - chance: 1, - }, - { - itemId: '10058', - quantity: 1, - chance: 1, - }, - { - itemId: '10029', - quantity: 1, - chance: 1, - }, - { - itemId: '10047', - quantity: 1, - chance: 1, - }, - { - itemId: '10114', - quantity: 1, - chance: 1, - }, - { - itemId: '10115', - quantity: 1, - chance: 1, - }, - { - itemId: '10116', - quantity: 1, - chance: 1, - }, - { - itemId: '10117', - quantity: 1, - chance: 1, - }, - { - itemId: '10118', - quantity: 1, - chance: 1, - }, - { - itemId: '10119', - quantity: 1, - chance: 1, - }, - ], + loot: [], achievements: [ { id: 'DINO_DASH_SCORE_100', version: 1, - gameId: 'dino-dash', name: 'Score 100', description: 'Score over 100 points in a single game', iconUrl: @@ -900,7 +1055,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'DINO_DASH_SCORE_500', version: 1, - gameId: 'dino-dash', name: 'Score 500', description: 'Score over 500 points in a single game', iconUrl: @@ -917,7 +1071,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'DINO_DASH_SCORE_1000', version: 1, - gameId: 'dino-dash', name: 'Score 1000', description: 'Score over 1000 points in a single game', iconUrl: @@ -939,7 +1092,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'DINO_DASH_SCORE_2500', version: 1, - gameId: 'dino-dash', name: 'Score 2500', description: 'Score over 2500 points in a single game', iconUrl: @@ -961,7 +1113,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'DINO_DASH_SCORE_5000', version: 1, - gameId: 'dino-dash', name: 'Score 5000', description: 'Score over 5000 points in a single game', iconUrl: @@ -993,7 +1144,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'DINO_DASH_COINS_1', version: 1, - gameId: 'dino-dash', name: 'Collect 1 Coin', description: 'Collect 1 coin across all games', iconUrl: @@ -1010,7 +1160,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'DINO_DASH_COINS_10', version: 1, - gameId: 'dino-dash', name: 'Collect 10 Coins', description: 'Collect 10 coins across all games', iconUrl: @@ -1027,7 +1176,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'DINO_DASH_COINS_50', version: 1, - gameId: 'dino-dash', name: 'Collect 50 Coins', description: 'Collect 50 coins across all games', iconUrl: @@ -1044,7 +1192,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'DINO_DASH_COINS_100', version: 1, - gameId: 'dino-dash', name: 'Collect 100 Coins', description: 'Collect 100 coins across all games', iconUrl: @@ -1066,7 +1213,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'DINO_DASH_COINS_250', version: 1, - gameId: 'dino-dash', name: 'Collect 250 Coins', description: 'Collect 250 coins across all games', iconUrl: @@ -1088,7 +1234,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'DINO_DASH_DAMAGE_1', version: 1, - gameId: 'dino-dash', name: 'Take 1 Damage', description: 'Take 1 damage across all games', iconUrl: @@ -1105,7 +1250,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'DINO_DASH_DAMAGE_10', version: 1, - gameId: 'dino-dash', name: 'Take 10 Damage', description: 'Take 10 damage across all games', iconUrl: @@ -1122,7 +1266,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'DINO_DASH_DAMAGE_25', version: 1, - gameId: 'dino-dash', name: 'Take 25 Damage', description: 'Take 25 damage across all games', iconUrl: @@ -1139,7 +1282,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'DINO_DASH_DAMAGE_50', version: 1, - gameId: 'dino-dash', name: 'Take 50 Damage', description: 'Take 50 damage across all games', iconUrl: @@ -1156,7 +1298,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'DINO_DASH_DAMAGE_100', version: 1, - gameId: 'dino-dash', name: 'Take 100 Damage', description: 'Take 100 damage across all games', iconUrl: @@ -1173,7 +1314,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'DINO_DASH_JUMPS_125', version: 2, - gameId: 'dino-dash', name: 'Jump 125 Times', description: 'Jump 125 time across all games', iconUrl: @@ -1190,7 +1330,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'DINO_DASH_JUMPS_250', version: 2, - gameId: 'dino-dash', name: 'Jump 250 Times', description: 'Jump 250 times across all games', iconUrl: @@ -1207,7 +1346,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'DINO_DASH_JUMPS_1250', version: 2, - gameId: 'dino-dash', name: 'Jump 1250 Times', description: 'Jump 1250 times across all games', iconUrl: @@ -1224,7 +1362,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'DINO_DASH_JUMPS_3000', version: 2, - gameId: 'dino-dash', name: 'Jump 3000 Times', description: 'Jump 3000 times across all games', iconUrl: @@ -1241,7 +1378,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'DINO_DASH_JUMPS_5000', version: 2, - gameId: 'dino-dash', name: 'Jump 5000 Times', description: 'Jump 5000 times across all games', iconUrl: @@ -1258,7 +1394,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'DINO_DASH_UNLOCK_BILLY', version: 1, - gameId: 'dino-dash', name: 'Unlock Billy the Brontosaurus', description: 'Visit the shop and purchase the character: Billy the Brontosaurus', @@ -1276,7 +1411,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'DINO_DASH_UNLOCK_TERRY', version: 1, - gameId: 'dino-dash', name: 'Unlock Terry the Triceratops', description: 'Visit the shop and purchase the character: Terry the Triceratops', @@ -1294,7 +1428,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'DINO_DASH_UNLOCK_CARLY', version: 1, - gameId: 'dino-dash', name: 'Unlock Carly the Carnotaurus', description: 'Visit the shop and purchase the character: Carly the Carnotaurus', @@ -1339,18 +1472,11 @@ const integratedGames: SeedableGameSchema[] = [ score: 10, }, ], - loot: [ - { - itemId: '2', - quantity: 2, - chance: 0.1, - }, - ], + loot: [], achievements: [ { id: 'COLOR_RUN_SCORE_1', version: 3, - gameId: 'color-run', name: 'First Score', description: 'Score 1 point in the game', iconUrl: @@ -1367,7 +1493,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'COLOR_RUN_SCORE_5', version: 3, - gameId: 'color-run', name: 'Score 5', description: 'Score 5 points in the game', iconUrl: @@ -1384,7 +1509,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'COLOR_RUN_SCORE_10', version: 3, - gameId: 'color-run', name: 'Score 10', description: 'Score 10 points in the game', iconUrl: @@ -1401,7 +1525,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'COLOR_RUN_SCORE_25', version: 3, - gameId: 'color-run', name: 'Score 25', description: 'Score 25 points in the game', iconUrl: @@ -1423,7 +1546,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'COLOR_RUN_SCORE_50', version: 3, - gameId: 'color-run', name: 'Score 50', description: 'Score 50 points in the game', iconUrl: @@ -1445,7 +1567,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'COLOR_RUN_SCORE_75', version: 3, - gameId: 'color-run', name: 'Score 75', description: 'Score 75 points in the game', iconUrl: @@ -1467,7 +1588,6 @@ const integratedGames: SeedableGameSchema[] = [ { id: 'COLOR_RUN_SCORE_100', version: 3, - gameId: 'color-run', name: 'Score 100', description: 'Score 100 points in the game', iconUrl: diff --git a/libs/phaser/plugins/src/lib/charity-games.ts b/libs/phaser/plugins/src/lib/charity-games.ts index 50bf6eec6..4745c5bd9 100644 --- a/libs/phaser/plugins/src/lib/charity-games.ts +++ b/libs/phaser/plugins/src/lib/charity-games.ts @@ -26,6 +26,7 @@ export const isValidOrigin = (origin: string) => { return origin === '*' || validOrigins.includes(origin); }; +// TODO: Move charity games plugin towards an API-first approach. export class CharityGamesPlugin extends Phaser.Plugins.BasePlugin { static KEY = 'CharityGamesPlugin'; storage: StorageAPI; @@ -37,6 +38,7 @@ export class CharityGamesPlugin extends Phaser.Plugins.BasePlugin { rewards: RewardAPI; events: Phaser.Events.EventEmitter = new Phaser.Events.EventEmitter(); isInitialized = false; + isDisabled = false; storageKey = 'storage'; constructor(pluginManager: Phaser.Plugins.PluginManager) { @@ -54,6 +56,8 @@ export class CharityGamesPlugin extends Phaser.Plugins.BasePlugin { } #preload() { + if (this.isDisabled) return; + if (window.parent === window) { throw new Error('No parent window'); } @@ -85,25 +89,29 @@ export class CharityGamesPlugin extends Phaser.Plugins.BasePlugin { }); } - async initialize() { - // 10 seconds timeout for initialization - const { signal, cancel } = createTimeout(10 * SECONDS); + async initialize(): Promise { + this.isDisabled = process.env['DISABLE_CHARITY_GAMES_SDK'] === 'true'; + if (this.isDisabled) console.info('Charity Games SDK is disabled'); + + const { signal, cancel } = createTimeout(10 * (this.isDisabled ? 0 : 10)); try { this.#preload(); this.#emit('initializing', 0.33); - await this.session.start(signal); + await this.session.initialize(signal); this.#emit('initializing', 0.66); - await this.storage.load(signal); + await this.storage.initialize(signal); this.#emit('initializing', 1); - await this.achievements.load(signal); + await this.achievements.initialize(signal); this.isInitialized = true; this.#emit('initialized', { ok: true }); } catch (error) { - console.error('Failed to initialize', error); + if (!this.isDisabled) { + console.error('Failed to initialize', error); + } this.isInitialized = true; this.#emit('initialized', { ok: false }); } finally { @@ -112,6 +120,7 @@ export class CharityGamesPlugin extends Phaser.Plugins.BasePlugin { } send(event: T, payload: GameEventPayload) { + if (this.isDisabled) return; window.parent.postMessage({ event, payload }, '*'); } @@ -142,7 +151,7 @@ class SessionAPI { this.id = null; } - async start(signal: AbortSignal) { + async initialize(signal: AbortSignal) { const { sessionId } = await cancelableRequest(this.plugin, signal)( 'start-session', 'session-started' @@ -167,7 +176,7 @@ class StorageAPI { this.ignored = keys; } - async load(signal: AbortSignal) { + async initialize(signal: AbortSignal) { const { storage } = await cancelableRequest(this.plugin, signal)( 'load-storage', 'storage-loaded' @@ -221,7 +230,7 @@ class StorageAPI { class LeaderboardsAPI { constructor(private plugin: CharityGamesPlugin) {} - async submit(score: number) { + submit(score: number) { this.plugin.send('submit-score', { sessionId: this.plugin.session.id, score, @@ -233,7 +242,7 @@ class AchievementsAPI { cached: string[] = []; constructor(private plugin: CharityGamesPlugin) {} - async load(signal: AbortSignal) { + async initialize(signal: AbortSignal) { const act = await cancelableRequest(this.plugin, signal)( 'load-achievements', 'achievements-loaded' diff --git a/libs/util/functions/.eslintrc.json b/libs/util/functions/.eslintrc.json new file mode 100644 index 000000000..3230caf3d --- /dev/null +++ b/libs/util/functions/.eslintrc.json @@ -0,0 +1,25 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.json"], + "parser": "jsonc-eslint-parser", + "rules": { + "@nx/dependency-checks": "error" + } + } + ] +} diff --git a/libs/util/functions/README.md b/libs/util/functions/README.md new file mode 100644 index 000000000..e8772ab2e --- /dev/null +++ b/libs/util/functions/README.md @@ -0,0 +1,11 @@ +# util-functions + +This library was generated with [Nx](https://nx.dev). + +## Building + +Run `nx build util-functions` to build the library. + +## Running unit tests + +Run `nx test util-functions` to execute the unit tests via [Jest](https://jestjs.io). diff --git a/libs/util/functions/jest.config.ts b/libs/util/functions/jest.config.ts new file mode 100644 index 000000000..b0ba8c986 --- /dev/null +++ b/libs/util/functions/jest.config.ts @@ -0,0 +1,11 @@ +/* eslint-disable */ +export default { + displayName: 'util-functions', + preset: '../../../jest.preset.js', + testEnvironment: 'node', + transform: { + '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], + }, + moduleFileExtensions: ['ts', 'js', 'html'], + coverageDirectory: '../../../coverage/libs/util/functions', +}; diff --git a/libs/util/functions/package.json b/libs/util/functions/package.json new file mode 100644 index 000000000..a7ec2a460 --- /dev/null +++ b/libs/util/functions/package.json @@ -0,0 +1,11 @@ +{ + "name": "util/functions", + "version": "0.0.1", + "dependencies": { + "tslib": "^2.3.0" + }, + "type": "commonjs", + "main": "./src/index.js", + "typings": "./src/index.d.ts", + "private": true +} diff --git a/libs/util/functions/project.json b/libs/util/functions/project.json new file mode 100644 index 000000000..d82f09dce --- /dev/null +++ b/libs/util/functions/project.json @@ -0,0 +1,26 @@ +{ + "name": "util-functions", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/util/functions/src", + "projectType": "library", + "tags": [], + "targets": { + "build": { + "executor": "@nx/js:tsc", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/libs/util/functions", + "main": "libs/util/functions/src/index.ts", + "tsConfig": "libs/util/functions/tsconfig.lib.json", + "assets": ["libs/util/functions/*.md"] + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "libs/util/functions/jest.config.ts" + } + } + } +} diff --git a/libs/util/functions/src/index.ts b/libs/util/functions/src/index.ts new file mode 100644 index 000000000..83f2d786c --- /dev/null +++ b/libs/util/functions/src/index.ts @@ -0,0 +1,22 @@ +export const once = (fn: () => void) => { + let called = false; + return () => { + if (called) return; + called = true; + fn(); + }; +}; + +// eslint-disable-next-line @typescript-eslint/ban-types +export const lucky = (chance: number, callback: T) => { + if (chance < 1 || chance > 100) { + throw new Error('Chance must be an integer between 1 and 100 inclusive'); + } + return (x: number, y: number) => { + // calculate luck between 1 and 100 inclusive + const luck = Math.ceil(Math.random() * 100); + if (luck > chance) return; + + callback(x, y); + }; +}; diff --git a/libs/util/functions/tsconfig.json b/libs/util/functions/tsconfig.json new file mode 100644 index 000000000..8122543a9 --- /dev/null +++ b/libs/util/functions/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "module": "commonjs", + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/libs/util/functions/tsconfig.lib.json b/libs/util/functions/tsconfig.lib.json new file mode 100644 index 000000000..4befa7f09 --- /dev/null +++ b/libs/util/functions/tsconfig.lib.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "declaration": true, + "types": ["node"] + }, + "include": ["src/**/*.ts"], + "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] +} diff --git a/libs/util/functions/tsconfig.spec.json b/libs/util/functions/tsconfig.spec.json new file mode 100644 index 000000000..69a251f32 --- /dev/null +++ b/libs/util/functions/tsconfig.spec.json @@ -0,0 +1,14 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/libs/util/types/src/lib/game-schema.ts b/libs/util/types/src/lib/game-schema.ts index adbfcdecc..470e8bf9c 100644 --- a/libs/util/types/src/lib/game-schema.ts +++ b/libs/util/types/src/lib/game-schema.ts @@ -22,11 +22,13 @@ export const basicGameAchievementSchema = z.object({ iconUrl: z.string(), }); -export const seedableGameAchievementSchema = basicGameAchievementSchema.extend({ - secret: z.boolean(), - version: z.number(), - loot: seedableLootSchema.array(), -}); +export const seedableGameAchievementSchema = basicGameAchievementSchema + .extend({ + secret: z.boolean(), + version: z.number(), + loot: seedableLootSchema.array(), + }) + .omit({ gameId: true }); export type SeedableGameAchievementSchema = z.infer< typeof seedableGameAchievementSchema diff --git a/nx.json b/nx.json index 1a48357f7..636fe27b0 100644 --- a/nx.json +++ b/nx.json @@ -112,6 +112,14 @@ "options": { "targetName": "eslint:lint" } + }, + { + "plugin": "@nx/webpack/plugin", + "options": { + "buildTargetName": "build", + "serveTargetName": "serve", + "previewTargetName": "preview" + } } ] } diff --git a/package-lock.json b/package-lock.json index 07101101e..10a6317cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -155,7 +155,8 @@ "validate-npm-package-name": "^5.0.0", "verdaccio": "^5.0.4", "vite": "^5.0.0", - "vitest": "^1.3.1" + "vitest": "^1.3.1", + "webpack-cli": "^5.1.4" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -14492,6 +14493,7 @@ "version": "4.36.1", "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.36.1.tgz", "integrity": "sha512-DJSilV5+ytBP1FbFcEJovv4rnnm/CokuVvrBEtW/Va9DvuJ3HksbXUJEpI0aV1KtuL4ZoO9AVE6PyNLzF7tLeA==", + "license": "MIT", "peer": true, "funding": { "type": "github", @@ -14502,6 +14504,7 @@ "version": "4.36.1", "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.36.1.tgz", "integrity": "sha512-y7ySVHFyyQblPl3J3eQBWpXZkliroki3ARnBKsdJchlgt7yJLRDUcf4B8soufgiYt3pEQIkBWBx1N9/ZPIeUWw==", + "license": "MIT", "peer": true, "dependencies": { "@tanstack/query-core": "4.36.1", @@ -14664,6 +14667,7 @@ "funding": [ "https://trpc.io/sponsor" ], + "license": "MIT", "peer": true, "peerDependencies": { "@tanstack/react-query": "^4.18.0", @@ -16439,9 +16443,10 @@ "license": "ISC" }, "node_modules/@videojs/http-streaming": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-3.13.1.tgz", - "integrity": "sha512-G7YrgNEq9ETaUmtkoTnTuwkY9U+xP7Xncedzgxio/Rmz2Gn2zmodEbBIVQinb2UDznk7X8uY5XBr/Ew6OD/LWg==", + "version": "3.13.2", + "resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-3.13.2.tgz", + "integrity": "sha512-eCfQp61w00hg7Y9npmLnsJ6UvDF+SsFYzu7mQJgVXxWpVm9AthYWA3KQEKA7F7Sy6yzlm/Sps8BHs5ItelNZgQ==", + "license": "Apache-2.0", "peer": true, "dependencies": { "@babel/runtime": "^7.12.5", @@ -16465,6 +16470,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-4.0.0.tgz", "integrity": "sha512-xJp7Yd4jMLwje2vHCUmi8MOUU76nxiwII3z4Eg3Ucb+6rrkFVGosrXlMgGnaLjq724j3wzNElRZ71D/CKrTtxg==", + "license": "MIT", "peer": true, "dependencies": { "@babel/runtime": "^7.12.5", @@ -16824,6 +16830,53 @@ "@xtuc/long": "4.2.2" } }, + "node_modules/@webpack-cli/configtest": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, "node_modules/@xmldom/xmldom": { "version": "0.8.10", "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", @@ -16992,6 +17045,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-4.0.1.tgz", "integrity": "sha512-H1nh/P9VZXUf17AA5NQfJML88CFjVBDuGkp5zDHa7oEhYN9TTpNLJknRY1ie0iSKWlDf6JRnJKaZVDSQdPy6Cg==", + "license": "Apache-2.0", "peer": true, "dependencies": { "@babel/runtime": "^7.12.5", @@ -17004,6 +17058,7 @@ "version": "3.0.5", "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-3.0.5.tgz", "integrity": "sha512-PKVgdo8/GReqdx512F+ombhS+Bzogiofy1LgAj4tN8PfdBx3HSS7V5WfJotKTqtOWGwVfSWsrYN/t09/DSryrw==", + "license": "MIT", "peer": true, "dependencies": { "@babel/runtime": "^7.12.5", @@ -23601,6 +23656,16 @@ "fxparser": "src/cli/cli.js" } }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, "node_modules/fastq": { "version": "1.17.0", "dev": true, @@ -26068,6 +26133,16 @@ "node": ">= 0.4" } }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -29832,6 +29907,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-7.1.0.tgz", "integrity": "sha512-7N+pk79EH4oLKPEYdgRXgAsKDyA/VCo0qCHlUwacttQA0WqsjZQYmNfywMvjlY9MpEBVZEt0jKFd73Kv15EBYQ==", + "license": "Apache-2.0", "peer": true, "dependencies": { "@babel/runtime": "^7.12.5", @@ -29843,6 +29919,7 @@ "version": "3.0.5", "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-3.0.5.tgz", "integrity": "sha512-PKVgdo8/GReqdx512F+ombhS+Bzogiofy1LgAj4tN8PfdBx3HSS7V5WfJotKTqtOWGwVfSWsrYN/t09/DSryrw==", + "license": "MIT", "peer": true, "dependencies": { "@babel/runtime": "^7.12.5", @@ -30880,6 +30957,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-1.3.0.tgz", "integrity": "sha512-WgeIwxAqkmb9uTn4ClicXpEQYCEduDqRKfmUdp4X8vmghKfBNXZLYpREn9eqrDx/Tf5LhzRcJLSpi4ohfV742Q==", + "license": "Apache-2.0", "peer": true, "dependencies": { "@babel/runtime": "^7.12.5", @@ -30941,6 +31019,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/mux.js/-/mux.js-7.0.3.tgz", "integrity": "sha512-gzlzJVEGFYPtl2vvEiJneSWAWD4nfYRHD5XgxmB2gWvXraMPOYk+sxfvexmNfjQUFpmk6hwLR5C6iSFmuwCHdQ==", + "license": "Apache-2.0", "peer": true, "dependencies": { "@babel/runtime": "^7.11.2", @@ -35650,6 +35729,19 @@ "node": ">=0.10.0" } }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", @@ -38370,6 +38462,7 @@ "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.63.0.tgz", "integrity": "sha512-OMlgrTCPzE/ibtRMoeLVhOY0RcNuNWh0rhAVqeKnk/QwcuUKQbnqhZ1kg2vzD8VU/6h3FoPTq4RJPHgLBvX6Bw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "@adobe/css-tools": "~4.3.3", @@ -38430,6 +38523,7 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "dev": true, + "license": "BSD-3-Clause", "peer": true, "engines": { "node": ">= 8" @@ -40454,13 +40548,14 @@ } }, "node_modules/video.js": { - "version": "8.16.1", - "resolved": "https://registry.npmjs.org/video.js/-/video.js-8.16.1.tgz", - "integrity": "sha512-yAhxu4Vhyx5DdOgPn2PcRKHx3Vzs9tpvCWA0yX+sv5bIeBkg+IWdEX+MHGZgktgDQ/R8fJDxDbEASyvxXnFn1A==", + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/video.js/-/video.js-8.17.3.tgz", + "integrity": "sha512-zhhmE0LNxJRA603/48oYzF7GYdT+rQRscvcsouYxFE71aKhalHLBP6S9/XjixnyjcrYgwIx8OQo6eSjcbbAW0Q==", + "license": "Apache-2.0", "peer": true, "dependencies": { "@babel/runtime": "^7.12.5", - "@videojs/http-streaming": "3.13.1", + "@videojs/http-streaming": "3.13.2", "@videojs/vhs-utils": "^4.0.0", "@videojs/xhr": "2.7.0", "aes-decrypter": "^4.0.1", @@ -40478,6 +40573,7 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/@videojs/xhr/-/xhr-2.7.0.tgz", "integrity": "sha512-giab+EVRanChIupZK7gXjHy90y3nncA2phIOyG3Ne5fvpiMJzvqYwiTOnEVW2S4CoYcuKJkomat7bMXA/UoUZQ==", + "license": "MIT", "peer": true, "dependencies": { "@babel/runtime": "^7.5.5", @@ -40504,6 +40600,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/videojs-contrib-quality-levels/-/videojs-contrib-quality-levels-4.1.0.tgz", "integrity": "sha512-TfrXJJg1Bv4t6TOCMEVMwF/CoS8iENYsWNKip8zfhB5kTcegiFYezEA0eHAJPU64ZC8NQbxQgOwAsYU8VXbOWA==", + "license": "Apache-2.0", "peer": true, "dependencies": { "global": "^4.4.0" @@ -40520,6 +40617,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/videojs-font/-/videojs-font-4.2.0.tgz", "integrity": "sha512-YPq+wiKoGy2/M7ccjmlvwi58z2xsykkkfNMyIg4xb7EZQQNwB71hcSsB3o75CqQV7/y5lXkXhI/rsGAS7jfEmQ==", + "license": "Apache-2.0", "peer": true }, "node_modules/videojs-ima": { @@ -41545,6 +41643,62 @@ } } }, + "node_modules/webpack-cli": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", + "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^2.1.1", + "@webpack-cli/info": "^2.0.2", + "@webpack-cli/serve": "^2.0.5", + "colorette": "^2.0.14", + "commander": "^10.0.1", + "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/webpack-dev-middleware": { "version": "6.1.2", "license": "MIT", diff --git a/package.json b/package.json index 699ca9606..25de2c2f2 100644 --- a/package.json +++ b/package.json @@ -180,9 +180,10 @@ "validate-npm-package-name": "^5.0.0", "verdaccio": "^5.0.4", "vite": "^5.0.0", - "vitest": "^1.3.1" + "vitest": "^1.3.1", + "webpack-cli": "^5.1.4" }, "nx": { "includedScripts": [] } -} \ No newline at end of file +} diff --git a/tsconfig.base.json b/tsconfig.base.json index 0e5a6697b..850ee7710 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -324,6 +324,7 @@ "@worksheets/util/data": ["libs/util/data/src/index.ts"], "@worksheets/util/enums": ["libs/util/enums/src/index.ts"], "@worksheets/util/errors": ["libs/util/errors/src/index.ts"], + "@worksheets/util/functions": ["libs/util/functions/src/index.ts"], "@worksheets/util/generators": ["libs/util/generators/src/index.ts"], "@worksheets/util/html": ["libs/util/html/src/index.ts"], "@worksheets/util/integrations": ["libs/util/integrations/src/index.ts"],