├── .firebase ├── hosting.YnVpbGQvd2Vi.cache └── hosting.YnVpbGRcd2Vi.cache ├── .firebaserc ├── .gitignore ├── .metadata ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── README.md ├── analysis_options.yaml ├── android ├── .gitignore ├── app │ ├── build.gradle │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── roll_the_ball │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── drawable-v21 │ │ │ └── launch_background.xml │ │ │ ├── drawable │ │ │ └── launch_background.xml │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── values-night │ │ │ └── styles.xml │ │ │ └── values │ │ │ └── styles.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle ├── assets ├── audio │ ├── ballTap.mp3 │ ├── ballroll.mp3 │ ├── immutableTile.mp3 │ └── missionPassed.mp3 ├── images │ ├── back.svg │ ├── board-background.svg │ ├── board.svg │ ├── btn_play.svg │ ├── btn_setting.svg │ ├── buttons │ │ ├── levels.svg │ │ └── next.svg │ ├── disabled_back.svg │ ├── disabled_restart.svg │ ├── disabled_setting.svg │ ├── moon.svg │ ├── restart.svg │ ├── setting.svg │ ├── tiles │ │ ├── tile0.svg │ │ ├── tile1.svg │ │ ├── tile10.svg │ │ ├── tile11.svg │ │ ├── tile12.svg │ │ ├── tile13.svg │ │ ├── tile14.svg │ │ ├── tile15.svg │ │ ├── tile16.svg │ │ ├── tile17.svg │ │ ├── tile18.svg │ │ ├── tile19.svg │ │ ├── tile2.svg │ │ ├── tile20.svg │ │ ├── tile21.svg │ │ ├── tile3.svg │ │ ├── tile4.svg │ │ ├── tile5.svg │ │ ├── tile6.svg │ │ ├── tile7.svg │ │ ├── tile8.svg │ │ └── tile9.svg │ └── way_for_ball.svg ├── lottie │ └── snoopd.json └── rive │ └── bird.riv ├── firebase.json ├── fonts ├── Cairo │ └── Cairo-Regular.ttf └── Shizuru │ └── Shizuru-Regular.ttf ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Podfile ├── Podfile.lock ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-1024x1024@1x.png │ │ ├── Icon-App-20x20@1x.png │ │ ├── Icon-App-20x20@2x.png │ │ ├── Icon-App-20x20@3x.png │ │ ├── Icon-App-29x29@1x.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40@1x.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ └── Icon-App-83.5x83.5@2x.png │ └── LaunchImage.imageset │ │ ├── Contents.json │ │ ├── LaunchImage.png │ │ ├── LaunchImage@2x.png │ │ ├── LaunchImage@3x.png │ │ └── README.md │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ └── Runner-Bridging-Header.h ├── lib ├── layout │ ├── breakpoints.dart │ ├── layout.dart │ ├── responsive_gap.dart │ └── responsive_layout_builder.dart ├── main.dart ├── screens │ ├── puzzle │ │ ├── blocs │ │ │ ├── ball │ │ │ │ ├── ball_bloc.dart │ │ │ │ ├── ball_event.dart │ │ │ │ └── ball_state.dart │ │ │ ├── puzzle │ │ │ │ ├── puzzle_bloc.dart │ │ │ │ ├── puzzle_event.dart │ │ │ │ └── puzzle_state.dart │ │ │ └── timer │ │ │ │ ├── timer_bloc.dart │ │ │ │ ├── timer_event.dart │ │ │ │ └── timer_state.dart │ │ ├── puzzle_screen.dart │ │ └── puzzle_widgets │ │ │ ├── background.dart │ │ │ ├── ball.dart │ │ │ ├── ball_view.dart │ │ │ ├── board.dart │ │ │ ├── puzzle_bottom_view.dart │ │ │ ├── puzzle_top_view.dart │ │ │ ├── puzzle_view.dart │ │ │ └── widgets.dart │ └── start │ │ ├── bloc │ │ ├── bird_bloc.dart │ │ ├── bird_event.dart │ │ └── bird_state.dart │ │ ├── start_screen.dart │ │ └── start_widgets │ │ ├── background.dart │ │ ├── bird.dart │ │ ├── bird_container.dart │ │ ├── button_play.dart │ │ ├── button_setting.dart │ │ └── logo.dart ├── utils │ ├── arc_map.dart │ ├── levels_data.dart │ ├── popup │ │ ├── levels │ │ │ ├── levels_popup.dart │ │ │ └── widgets │ │ │ │ └── level_tile.dart │ │ ├── settings │ │ │ └── volume.dart │ │ └── winning │ │ │ ├── widgets │ │ │ └── win_button.dart │ │ │ └── win_popup.dart │ ├── router.dart │ ├── screens.dart │ └── shared_prefs.dart └── widgets │ ├── slide_animation.dart │ └── swipe_detector.dart ├── pubspec.lock ├── pubspec.yaml ├── test └── widget_test.dart └── web ├── favicon.png ├── icons ├── Icon-192.png ├── Icon-512.png ├── Icon-maskable-192.png └── Icon-maskable-512.png ├── index.html ├── main-background.png └── manifest.json /.firebase/hosting.YnVpbGQvd2Vi.cache: -------------------------------------------------------------------------------- 1 | favicon.png,1648469745842,ef6049294bf31362898aeb7918ff6d4580a718fd1d3184a8dd46623b15eae890 2 | main-background.png,1648626482435,06784d2821bd58170edde0fd1eb57b4135b7a22e513ec97bbbf61dc4b540a26b 3 | manifest.json,1648469586604,d3078d02b349302f44db575359bca90564dd9ff4890d766800755ab8137316ba 4 | assets/assets/audio/ballTap.mp3,1645206067241,07e0ac2d328f110124daf441d57900eb8b251080cb3bfb01e035e047b34fbe99 5 | assets/assets/audio/ballroll.mp3,1643209607810,4076f25b7d1d6812dac3f7e93aba418761febc5e1ebe4cf52d7470d85ecda884 6 | assets/assets/audio/immutableTile.mp3,1645206103336,1a7ae07c7731066b12c7987568f00cee0a3f597e5bb050a9d57861e8a8baec30 7 | assets/assets/audio/missionPassed.mp3,1645211263098,22d881b148006839a77ee8a5e1c1188de3785a77f21ef82ba2791141245ab54f 8 | assets/assets/images/back.svg,1648401284532,55df2e9eecf454915e7528cab7bb80849a40cea7f6df5f239a152e58c599b276 9 | assets/assets/images/board-background.svg,1648401284534,70547f7a93b5ad1a1ca2725f43bb66a4545fcd479493b3c72250f9f74f7d50a1 10 | assets/assets/images/board.svg,1648401284535,02f26d5a0acead04b4daa707a9a4e7a94f3c9c72051e5ed2e4a216f5ca314a20 11 | assets/assets/images/btn_play.svg,1648401284536,abdefbeba3ef40cd6be58943062d395d0ea59eb0c308e3d9991955c30883939c 12 | assets/assets/images/btn_setting.svg,1648401284536,65550b15c2f75e20136f42441076c4f3d4dcab399c7395105b3f362493eecd7a 13 | assets/assets/images/moon.svg,1648401284538,533a2d315a3002673f9e680e21eb47827701897697e426a9255efec1678218a5 14 | assets/assets/images/restart.svg,1648401284539,79480d4d0d4eff3d724c4deff28c05082e63c391a69d105bdc06fda9464721fa 15 | assets/assets/images/way_for_ball.svg,1648401284563,93df0dd4113ca55eac63e1ba2702ce66ee9edfde4fbf4485a91270fa53b80245 16 | assets/assets/images/buttons/levels.svg,1648401284537,2439348880d57745a524c3845bf9cbd8e463a4df192321d54b19958045956f7c 17 | assets/assets/images/buttons/next.svg,1648401284538,b6ebca5b52faa92ce92e59ab7cdd31528142455e6939752ceae4b05b4e9cf537 18 | assets/assets/images/tiles/tile0.svg,1648401284541,d6a4b8f0efadeda27d7a0fb701b828ef3bcd53acc5f74c8b93285d2bbc976985 19 | assets/assets/images/tiles/tile1.svg,1648401284541,e6032b03f6eef8052aaf61be61b55b9ee7fab798a1fc2340be7ae34df4d181f6 20 | assets/assets/images/tiles/tile10.svg,1648401284543,6967c2395b439153aa2f3ba32179bc9d6cb624040af6b1f7b636c591229c8feb 21 | assets/assets/images/tiles/tile11.svg,1648401284543,578e37d96721a25224e9bc13c195d2274cbad8b343d8c0c459ec89cdb074b2df 22 | assets/assets/images/tiles/tile12.svg,1648401284544,82b2e374fec178a394b1214fe127fe4dd785d9c513c76cc44692f41aa511311e 23 | assets/assets/images/tiles/tile13.svg,1648401284544,851c5327e5dcb05c5d97ca33da1cdc6f9de651229e3bb0d5e2031c55aa47df64 24 | assets/assets/images/tiles/tile14.svg,1648401284545,c89e9b5442c55fe50644c4a5e060cf75c4f6a4b6b015712f59871bd27120eca9 25 | assets/assets/images/tiles/tile15.svg,1648401284545,8d412bdd5c315a17b60d2377502fa3854b35cc1918db47b8b14e9bc9cb4cf8ed 26 | assets/assets/images/tiles/tile16.svg,1648401284547,3cadeda67f9c165181ef7150f61e39372245bd4e00f0090397cebd3ff3f93fcf 27 | assets/assets/images/tiles/tile17.svg,1648401284547,ce2eff4acda3856cf516b026f168ad23bc048752686944aaeb0b153bb514b06d 28 | assets/assets/images/tiles/tile18.svg,1648401284548,b91c402a73962a868eaca2cba7e6fff58f0c8d3c79392e40d4daf6886274b065 29 | assets/assets/images/tiles/tile19.svg,1648401284548,819ab872635e7d48448b8561fd4d30ef8c3798d184f60fee12e3925f542fd4a3 30 | assets/assets/images/tiles/tile2.svg,1648401284549,278cd921fb18966d7864f3f5bf095f764e8a74a7282fe9b8f36947190c326649 31 | assets/assets/images/tiles/tile20.svg,1648401284550,54f97fa0c4519cab51b5c69e68231fd2e1c4b77e54d31b6bf6b2b9a3fc1b5234 32 | assets/assets/images/tiles/tile21.svg,1648401284550,d9e44e5ac4c07d4345c7783af68b87e0f593ea51d830736f06fb574cb975e145 33 | assets/assets/images/tiles/tile3.svg,1648401284551,d9cce0fa0e25f7a1c206b4d557c36a9d279776d7e5e88dd83141df3f815f6b8c 34 | assets/assets/images/tiles/tile4.svg,1648401284553,02841328be8ccdb3f92ac722bbab57a553fbd0ec067ffa26fc8daed734dc1a26 35 | assets/assets/images/tiles/tile5.svg,1648401284554,0471349cbe580be9597f3e2b46c0311a31da7cb9481259e8d7a1dec0bff52302 36 | assets/assets/images/tiles/tile6.svg,1648401284558,843084cc1d1efb0a71f266b2db1932d77d0f456673458a26d3d0514d4abf66f4 37 | assets/assets/images/tiles/tile7.svg,1648401284559,64dfda5b1ac199ba1af003ba5829926e01666ed87b10183f9b767ec7aa1fc01b 38 | assets/assets/images/tiles/tile8.svg,1648401284559,cd3edabcd5a04a2bf74c790fcbcd3008e865bbe0ec064e6cbc2287dc161c131b 39 | assets/assets/images/tiles/tile9.svg,1648401284560,1e34cd0f8ee020397a5164b717d12bc9bbc070657007c7d6db61d7e524da2b7d 40 | assets/assets/lottie/snoopd.json,1645211157586,7a56a5a8848c3142263be3061c0743bd5280bc1b7df2bc455a28ede5b05fdd8a 41 | assets/assets/rive/bird.riv,1648401284566,48c6a519081d8ea043c3c552241322723e82004344dcc713b950d173a3d873c1 42 | assets/fonts/MaterialIcons-Regular.otf,1615596762000,5f71a8843e4edc9656c39061c2232458a6fc77e1603305960e4efa9c77f8b7a2 43 | assets/fonts/Cairo/Cairo-Regular.ttf,1465929000000,90df577e21414ce00ca0e5742ae80ce75d6770f17dfb237a115dc2dc00b64903 44 | assets/fonts/Shizuru/Shizuru-Regular.ttf,1647195832528,e495faa130fc0c720699538ebfef7a4504f486fbce1e00a8e61cc43915c6c65d 45 | canvaskit/canvaskit.js,315426600000,9ff3503a07b0494aaa30e5afa92a9a083c897951afcc402003699887fb5ac20e 46 | canvaskit/canvaskit.wasm,315426600000,4f057066d417d780f281ecc3c18ea040218529f0cfbb7179c3c8987826709108 47 | canvaskit/profiling/canvaskit.js,315426600000,b0eaf946cc777c85682e64dbe0490f2eb5922e751ea20d64866b8788b5c8f6aa 48 | canvaskit/profiling/canvaskit.wasm,315426600000,5fe6878a8edd1e290b0b7c5a770af45fca1a90d2dc650eafae8d2468ad530502 49 | icons/Icon-192.png,1648626530417,a27c5d1747c8ed7b0e01ad1ad455cae3f333803c3eb330c7ccddc7d6b524f262 50 | icons/Icon-512.png,1648626530420,5ca8c89c295da9ed31e52c8b2a964afc756cda7375df5b9329db85a45e54c9d3 51 | icons/Icon-maskable-192.png,1648626530422,a27c5d1747c8ed7b0e01ad1ad455cae3f333803c3eb330c7ccddc7d6b524f262 52 | icons/Icon-maskable-512.png,1648626530423,5ca8c89c295da9ed31e52c8b2a964afc756cda7375df5b9329db85a45e54c9d3 53 | flutter_service_worker.js,1648822624590,ebbe4c9c337aea540b13df804db820b362bb650cb629183f300af7b748a56458 54 | index.html,1648822624031,ac4192ad219229ee825f5f28c95150b0b0f12c2f04d2d4084c6d8578c1415002 55 | version.json,1648822623703,ccfefb22a16dd9db604ad6ff998dc6cd436dcd0a7b7072a0ec0166c78f93ca68 56 | assets/AssetManifest.json,1648822624010,50342253c1b037f9115f58841067ab747b1642b94848d916a6ed099cbbdd0fa5 57 | assets/FontManifest.json,1648822624010,4fd8ad26587ed53d3dd4cf2bcbb4bf408f2d75cccf9f49bf705c1dde35963a1e 58 | assets/assets/images/disabled_back.svg,1648814061626,70cc2eaf6605ccb75718fdfc98ad1a6aeeffe05091351e26834ebd7022d34ec9 59 | assets/assets/images/disabled_restart.svg,1648812870744,2900cacd1a26d055ddadf57f98d8043c64a8f6304fef3a77a0231afcdc3135dc 60 | assets/NOTICES,1648822624011,3cc5c23edc873344e360b9c56f4c669f38dd429cbaa05ed7f30e734d8928e27a 61 | main.dart.js,1648822622936,542db6eaaa79d8bddc2cc91392193131630885c5d53998cd3af07f1ba012fa83 62 | -------------------------------------------------------------------------------- /.firebase/hosting.YnVpbGRcd2Vi.cache: -------------------------------------------------------------------------------- 1 | favicon.png,1647978363224,2dce38462e2f9124835826e78ada78051f5a44587bff1e1329d2fe1d63db07b6 2 | index.html,1648485191629,5354958a958a50b014d6c639f30ce177e02fc132f937ad8ebfe414931ba76fdb 3 | flutter_service_worker.js,1648485193093,cec048dc786c302a112c9bbee371b0aed96425cbef56057b9d6fb657722e6d06 4 | manifest.json,1647701119756,3697f3bc4bdc76cc3542c89633e8afb5f796c9ddee145654fe31183cc80b2e24 5 | version.json,1648485191258,a58ea00958d84849e9ba93e0377197868451cde2b0da084bf3d0020817c52f8d 6 | assets/AssetManifest.json,1648485191589,11f914fdfca5b5da55d52011d4e6aed5b41489f0e6ebce29c0fa1bfdeb0b526b 7 | assets/FontManifest.json,1648485191589,d14a1026bed49d60a740ef2ae4e353f05458552d8ea086164969297d59eeb7c0 8 | assets/assets/audio/ballTap.mp3,1648050408503,e8c3120a1349c6036fabdc2a0cecb5432d73891aae5147189cfa45176eb45745 9 | assets/assets/images/board-background.svg,1648173400994,c2acc5aa9a01283d0799c5319a00792c4505ce05ca463233b345dafd8030b366 10 | assets/assets/images/back.svg,1648173400993,d47d53da28b61932a34b7b59674c666da71d829fc71c7171c100394d635f7a15 11 | assets/assets/images/board.svg,1648173400995,ad1a9f64da116d7b127a5d656b279fd496aade7aae1bccda25954edc326150f2 12 | assets/assets/images/btn_play.svg,1648173400996,f2a5f78b294b6f92800265a8b7453d0eeda02f5d547ab5a4f8cf30fb7c98860b 13 | assets/assets/images/btn_setting.svg,1648173400997,1f6ffba6c37120686654db143d4306153b382d31f823d143beebead48cd55de6 14 | assets/assets/images/restart.svg,1648173401002,8e3a5fd0f62494a4aea7e497b6154e8449c7dfef00acde3606cb1dc96488ce7b 15 | assets/assets/images/moon.svg,1648173401001,f9e6a18575ce0d27bf8de97ba2d168ae03ce9a1c574976eb3b4391c930142860 16 | assets/assets/images/buttons/levels.svg,1648177508949,d2b07480e015ec1ce32f6aabfd91f4a9470d500759de0af483bd71ce93225cd1 17 | assets/assets/images/buttons/next.svg,1648173401000,60755d1b2dc7883f1cdc01df9bd9b9093a7fb857578d1bec7b8befbfdf990829 18 | assets/assets/images/tiles/tile0.svg,1648173401003,75af5124209f66cbd8ae683755c37c46d01fb71e97db6b94a0c4e5de78bcb649 19 | assets/assets/images/tiles/tile1.svg,1648174013538,ba52d67d75b5db015dd8d299ebe3ea326168cea82b31d0bf4f4e2ee52c1141d8 20 | assets/assets/images/tiles/tile10.svg,1648173401004,601739a4433f38ac4c9da4490a43dd3d0e1ef42225160b0b138410d7565fda67 21 | assets/assets/images/tiles/tile11.svg,1648173401005,fadd84e111d419c602a959a8e79509cc16748687db9f8a94c3c0ef3c3c0d28fb 22 | assets/assets/images/tiles/tile13.svg,1648173401007,ef5b3f61957af3ca942da2d675a46175e7fb3d60a74dc4bc245a80e837f7c2bd 23 | assets/assets/images/tiles/tile12.svg,1648173401006,83f5ca99e8f355db85b7694d4182c666c94df228c93115b768ba767e3f50b39a 24 | assets/assets/images/tiles/tile14.svg,1648173401007,b57791a66d7ebd15789ce4382e8ef68ddc749cfda4357a9cf347eff41ee8728c 25 | assets/assets/images/tiles/tile17.svg,1648173401010,4d2785415ab76cd0cb90fd06606d5a5d289ba1c24b1333a66f3fab56c86857c3 26 | assets/assets/images/tiles/tile16.svg,1648173401009,ac63cfb06faf8da9797a919131333b23e6c2a8bfc605395057cea3b866313dd9 27 | assets/assets/images/tiles/tile18.svg,1648173401011,78a49ea022afeed59bf59b027508673f23398e43b9b98fd1f6fa338c1af0dea4 28 | assets/assets/images/tiles/tile15.svg,1648173401008,653a8c9c55675f7eaa208b5b8536c8c4d3038ca3e5bbd3244514509cd7ad7fda 29 | assets/assets/images/tiles/tile2.svg,1648174040196,c92015a12787426827c807c0d63b0e02f009c5c9bbfb518dcbbd649a84d88551 30 | assets/assets/images/tiles/tile20.svg,1648173401014,f0a7555646e093244a0c30eae3b58ea9e9973e7f145d5247e7b36bea368adc74 31 | assets/assets/images/tiles/tile19.svg,1648173401012,383c8985c89ddcc72789f3146f616b6625ebea1bba4b7161228ad2239a4b2010 32 | assets/assets/images/tiles/tile21.svg,1648173401016,03953fc48a90043b4bb302881d36be989b635a4473474c1220ac99e8bd9fd501 33 | assets/assets/images/tiles/tile6.svg,1648173401020,2254c4724326d024aa72566d6f442cb8874a0eb457c6ab6cf7994290cd2e5506 34 | assets/assets/images/tiles/tile3.svg,1648174065955,6f3aa2e5929d429e4cdecbc62066cbe101e1ad542bc526d2c439028878e4438e 35 | assets/assets/images/way_for_ball.svg,1648173401024,3f8fc8b8a6d74170a2d341bd9e8bc82acc5eacb7a1f70a26b2151879c83cc66c 36 | assets/assets/images/tiles/tile4.svg,1648174091775,00a0ba6f9c61aadcfb2996b525d750d143a547fbaff0ff8d9248f39f428e641c 37 | assets/assets/images/tiles/tile5.svg,1648173401019,628da5dda6fcb9f0eb1545062ddfa0ab150c6358a35f118d970260f615fa30c6 38 | assets/assets/images/tiles/tile7.svg,1648173401021,f6e2b64e8a657523c4a8623e4f1aeb60372919695c3d434e1cd0e1cc8000a492 39 | assets/assets/images/tiles/tile9.svg,1648173401023,201c3d0ccfb58427ea12c2329959700f298f5288f1375e849c1fed4da5eea1cf 40 | assets/assets/images/tiles/tile8.svg,1648173401022,977a0c4006d5a8a5fc16859ffb8b07573f655d8828cd18454591f83c8809dac8 41 | assets/assets/rive/bird.riv,1648049837279,ecb9c31947c9fdfdde380d8c7eb045f323d6cd3a85ce8ddfa33b49a420e74520 42 | assets/assets/audio/immutableTile.mp3,1648050427153,fa6b01afeaf08b6c598b3f88d7bfacdabb1c7890a1b4935b3a5ca660f0a99965 43 | icons/icon.png,1644946574402,eaf2464bfb1d192fdd192a616f7b858dee456d573c6ec619648a1dcf2bdddfa6 44 | main-background.png,1648173401025,cc936d267efebaf15962570355f310d17b7c8ea26a2ee8deeeed2f9e7588dd54 45 | assets/fonts/Cairo/Cairo-Regular.ttf,1648448727461,3315545fd7ebce7d0c6f1973809cf556a09de9516be4f814da8ec6eff28f467b 46 | assets/assets/audio/ballroll.mp3,1648050403889,178332d28a306a19faff5876a97cf69a2fd7cf66eed56b2a715614ef3950cb78 47 | canvaskit/canvaskit.js,1643046523752,7335d1d2b4b78c90079b642b2c1704b4d4c64aa39c9f4b9743eb3ac8b1077e86 48 | assets/assets/lottie/snoopd.json,1647264590732,0f64368554ea4c7176cb08a09c0d666451a9ba8ca2e0d82e1eb2fdf043f14125 49 | canvaskit/profiling/canvaskit.js,1643046524211,d01d6c4c8962e36427f78f2d82c9982a1b321410f5ae14e99de0b6d9fdf9c04b 50 | assets/assets/audio/missionPassed.mp3,1648050431428,afa987f7fd945ec9cfae759a4a9c55ce58ca6d7c5515b9c0fd17c577198e46f8 51 | assets/NOTICES,1648485191589,beca0838a469529215c7e1c0b76d88d9d2483f34e828c73e10e5f37035cd1f4b 52 | assets/fonts/Shizuru/Shizuru-Regular.ttf,1647204788944,fb659cddab46be503ba6ad1ebddcee06b98bbfe6e5266cda5e5de086bf4a377b 53 | assets/fonts/MaterialIcons-Regular.otf,1643041247915,6a33dd7438073c82391fd948bbb9b48c94ef980957cdff54c0f0ac77f4e48d3e 54 | main.dart.js,1648485189598,935f56d4100acdd254e26895d19ab034039750439f467f556038f5b0e27f0c9b 55 | canvaskit/canvaskit.wasm,1643046524202,72f45c0699329fddd2f4a53e9cae8f6a2c8602430a5daddc6778174746089466 56 | canvaskit/profiling/canvaskit.wasm,1643046524490,a3b50911c38d2cd97ad057f2e3293fdc63c6e8f106c91557871da6680840110e 57 | -------------------------------------------------------------------------------- /.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "wayforball" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: cf4400006550b70f28e4b4af815151d1e74846c6 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | . 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # 🌱 Contributing to hacktoberfest 2022 2 | 3 | ![banner](https://user-images.githubusercontent.com/76551267/192131870-a8a3b7d7-cfbf-4e77-9cb5-b0a4e458b02f.png) 4 | 5 | ### Welcome to hacktoberfest 2022 Public Repository. 👨🏻‍💻 6 | 7 |

A month-long celebration from October 1st - 31st sponsored by Digital Ocean and GitHub to get people involved in Open Source. Create your very first pull request to any public repository on GitHub and contribute to the open source developer community. 8 | 9 | https://hacktoberfest.com//

10 | 11 | --- 12 | 13 | ### How to Contribute to this repository 14 | 15 | - Run the project on your system and look for any bug fixes. 16 | - You can make any change, If it works and good for the app, it will be merged. 17 | - Make sure you follow the Hacktoberfest guidelines. 18 | 19 | --- 20 | 21 | ### NOTE 22 | 23 | - Make Sure you commit your changes in a new branch. 24 | - Make Sure you Give proper name to your files describing the addition. 25 | - Also Make Sure to put comments in your code wherever necessary. 26 | - While raising the PR, show the before and after of the changes in the Application. 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Way for Ball 2 | 3 | A slide Flutter Game. 4 | 5 | This engaging puzzle game is really simple, but challenging at the same time. The aim is straightforward – guide your ball through the maze to the exit area. The ball will not roll until you have completed the route. To create the route you must move each individual pattern and solve the puzzle. This is exactly the same as the classic jigsaw sliding games, just digital! 6 | 7 | Some tiles are movable some are not. One with bolts on them is not movable. 8 | 9 | The graphics are smooth, and the puzzles become increasingly difficult. This game tests your skill and logic, and is great fun to play! 10 | 11 | [Play here](https://wayforball.web.app/) 12 | 13 | [![WayForBall](https://wayforball.web.app/main-background.png)](https://wayforball.web.app/) 14 | 15 | 16 | 17 | ## How to contribute: 18 | 19 | - Drop a :star: on the Github repository (optional)
20 | 21 | - Before Contribute Please read [CONTRIBUTING.md](https://github.com/sb-decoder/flutter-puzzle-hack/blob/master/CONTRIBUTING.md) and [CODE_OF_CONDUCT.md](https://github.com/sb-decoder/flutter-puzzle-hack/blob/master/CODE_OF_CONDUCT.md) 22 | 23 | - Create an issue of the project or a feature you would like to add in the project and get the task assigned for youself.(Issue can be any bug fixes or any feature you want to add in this project). 24 | 25 | - Fork the repo to your Github.
26 | 27 | - Clone the Repo by going to your local Git Client in a particular local folder in your local machine by using this command with your forked repository link in place of below given link:
28 | `git clone https://github.com/nehal076/flutter-puzzle-hack` 29 | - Create a branch using below command. 30 | `git branch ` 31 | - Checkout to your branch. 32 | `git checkout ` 33 | - Add your code in your local machine folder. 34 | `git add . ` 35 | - Commit your changes. 36 | `git commit -m""` 37 | - Push your changes. 38 | `git push --set-upstream origin ` 39 | 40 | - Make a pull request! (compare your branch with the owner main branch) 41 | 42 | # Contributors 43 |
44 |

45 | Thanks to these amazing people 46 |

47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | 2 | include: package:flutter_lints/flutter.yaml 3 | 4 | linter: 5 | rules: 6 | avoid_print: false 7 | constant_identifier_names: false 8 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 9 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion flutter.compileSdkVersion 30 | 31 | compileOptions { 32 | sourceCompatibility JavaVersion.VERSION_1_8 33 | targetCompatibility JavaVersion.VERSION_1_8 34 | } 35 | 36 | kotlinOptions { 37 | jvmTarget = '1.8' 38 | } 39 | 40 | sourceSets { 41 | main.java.srcDirs += 'src/main/kotlin' 42 | } 43 | 44 | defaultConfig { 45 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 46 | applicationId "com.example.way_for_ball" 47 | minSdkVersion flutter.minSdkVersion 48 | targetSdkVersion flutter.targetSdkVersion 49 | versionCode flutterVersionCode.toInteger() 50 | versionName flutterVersionName 51 | } 52 | 53 | buildTypes { 54 | release { 55 | // TODO: Add your own signing config for the release build. 56 | // Signing with the debug keys for now, so `flutter run --release` works. 57 | signingConfig signingConfigs.debug 58 | } 59 | } 60 | } 61 | 62 | flutter { 63 | source '../..' 64 | } 65 | 66 | dependencies { 67 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 68 | } 69 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 15 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/example/roll_the_ball/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.way_for_ball 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.6.10' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:4.1.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip 7 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /assets/audio/ballTap.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/assets/audio/ballTap.mp3 -------------------------------------------------------------------------------- /assets/audio/ballroll.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/assets/audio/ballroll.mp3 -------------------------------------------------------------------------------- /assets/audio/immutableTile.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/assets/audio/immutableTile.mp3 -------------------------------------------------------------------------------- /assets/audio/missionPassed.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/assets/audio/missionPassed.mp3 -------------------------------------------------------------------------------- /assets/images/back.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/board-background.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/board.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/btn_play.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/btn_setting.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/buttons/levels.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/buttons/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/disabled_back.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /assets/images/disabled_restart.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/disabled_setting.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /assets/images/moon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/restart.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/setting.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /assets/images/tiles/tile0.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/tiles/tile1.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/tiles/tile10.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/tiles/tile11.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/tiles/tile12.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/tiles/tile13.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/tiles/tile14.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/tiles/tile15.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/tiles/tile16.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/tiles/tile17.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/tiles/tile18.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/tiles/tile19.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/tiles/tile2.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/tiles/tile20.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/tiles/tile21.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/tiles/tile3.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/tiles/tile4.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/tiles/tile5.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/tiles/tile6.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/tiles/tile7.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/tiles/tile8.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/tiles/tile9.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/rive/bird.riv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/assets/rive/bird.riv -------------------------------------------------------------------------------- /firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "build/web", 4 | "ignore": [ 5 | "firebase.json", 6 | "**/.*", 7 | "**/node_modules/**" 8 | ], 9 | "rewrites": [ 10 | { 11 | "source": "**", 12 | "destination": "/index.html" 13 | } 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /fonts/Cairo/Cairo-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/fonts/Cairo/Cairo-Regular.ttf -------------------------------------------------------------------------------- /fonts/Shizuru/Shizuru-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/fonts/Shizuru/Shizuru-Regular.ttf -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 9.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | end 36 | 37 | post_install do |installer| 38 | installer.pods_project.targets.each do |target| 39 | flutter_additional_ios_build_settings(target) 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - audioplayers (0.0.1): 3 | - Flutter 4 | - Flutter (1.0.0) 5 | - path_provider_ios (0.0.1): 6 | - Flutter 7 | - shared_preferences_ios (0.0.1): 8 | - Flutter 9 | - url_launcher_ios (0.0.1): 10 | - Flutter 11 | 12 | DEPENDENCIES: 13 | - audioplayers (from `.symlinks/plugins/audioplayers/ios`) 14 | - Flutter (from `Flutter`) 15 | - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`) 16 | - shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`) 17 | - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) 18 | 19 | EXTERNAL SOURCES: 20 | audioplayers: 21 | :path: ".symlinks/plugins/audioplayers/ios" 22 | Flutter: 23 | :path: Flutter 24 | path_provider_ios: 25 | :path: ".symlinks/plugins/path_provider_ios/ios" 26 | shared_preferences_ios: 27 | :path: ".symlinks/plugins/shared_preferences_ios/ios" 28 | url_launcher_ios: 29 | :path: ".symlinks/plugins/url_launcher_ios/ios" 30 | 31 | SPEC CHECKSUMS: 32 | audioplayers: 455322b54050b30ea4b1af7cd9e9d105f74efa8c 33 | Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a 34 | path_provider_ios: 7d7ce634493af4477d156294792024ec3485acd5 35 | shared_preferences_ios: aef470a42dc4675a1cdd50e3158b42e3d1232b32 36 | url_launcher_ios: 02f1989d4e14e998335b02b67a7590fa34f971af 37 | 38 | PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c 39 | 40 | COCOAPODS: 1.11.2 41 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Roll The Ball 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | way_for_ball 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UIViewControllerBasedStatusBarAppearance 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /lib/layout/breakpoints.dart: -------------------------------------------------------------------------------- 1 | abstract class Breakpoints { 2 | static const double small = 576; 3 | static const double medium = 1200; 4 | static const double large = 1440; 5 | } 6 | -------------------------------------------------------------------------------- /lib/layout/layout.dart: -------------------------------------------------------------------------------- 1 | export 'breakpoints.dart'; 2 | export 'responsive_gap.dart'; 3 | export 'responsive_layout_builder.dart'; 4 | -------------------------------------------------------------------------------- /lib/layout/responsive_gap.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:gap/gap.dart'; 3 | 4 | import 'layout.dart'; 5 | 6 | class ResponsiveGap extends StatelessWidget { 7 | const ResponsiveGap({ 8 | Key? key, 9 | this.small = 0, 10 | this.medium = 0, 11 | this.large = 0, 12 | }) : super(key: key); 13 | 14 | final double small; 15 | final double medium; 16 | final double large; 17 | 18 | @override 19 | Widget build(BuildContext context) { 20 | return ResponsiveLayoutBuilder( 21 | small: (_, __) => Gap(small), 22 | medium: (_, __) => Gap(medium), 23 | large: (_, __) => Gap(large), 24 | child: (_) => const SizedBox.shrink(), 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lib/layout/responsive_layout_builder.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'breakpoints.dart'; 3 | 4 | enum ResponsiveLayoutSize { small, medium, large } 5 | 6 | typedef ResponsiveLayoutWidgetBuilder = Widget Function(BuildContext, Widget); 7 | 8 | class ResponsiveLayoutBuilder extends StatelessWidget { 9 | const ResponsiveLayoutBuilder({ 10 | Key? key, 11 | required this.small, 12 | required this.medium, 13 | required this.large, 14 | required this.child, 15 | }) : super(key: key); 16 | 17 | final ResponsiveLayoutWidgetBuilder small; 18 | final ResponsiveLayoutWidgetBuilder medium; 19 | final ResponsiveLayoutWidgetBuilder large; 20 | final Widget Function(ResponsiveLayoutSize currentSize) child; 21 | 22 | @override 23 | Widget build(BuildContext context) { 24 | return LayoutBuilder( 25 | builder: (context, constraints) { 26 | final screenWidth = MediaQuery.of(context).size.width; 27 | 28 | if (screenWidth <= Breakpoints.small) { 29 | return small(context, child.call(ResponsiveLayoutSize.small)); 30 | } 31 | if (screenWidth <= Breakpoints.medium) { 32 | return medium(context, child.call(ResponsiveLayoutSize.medium)); 33 | } 34 | if (screenWidth <= Breakpoints.large) { 35 | return large(context, child.call(ResponsiveLayoutSize.large)); 36 | } 37 | 38 | return large(context, child.call(ResponsiveLayoutSize.large)); 39 | }, 40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:developer'; 3 | 4 | import 'package:flutter/material.dart'; 5 | import 'package:way_for_ball/utils/router.dart'; 6 | import 'package:url_strategy/url_strategy.dart'; 7 | 8 | import 'utils/shared_prefs.dart'; 9 | 10 | void main() async { 11 | WidgetsFlutterBinding.ensureInitialized(); 12 | await SharedPrefUtils.init(); 13 | setPathUrlStrategy(); 14 | runApp(const MyApp()); 15 | } 16 | 17 | class MyApp extends StatefulWidget { 18 | const MyApp({Key? key}) : super(key: key); 19 | 20 | @override 21 | State createState() => _MyAppState(); 22 | } 23 | 24 | final navigatorKey = GlobalKey(); 25 | 26 | class _MyAppState extends State { 27 | AppRouter router = AppRouter(); 28 | 29 | @override 30 | void initState() { 31 | super.initState(); 32 | SharedPrefUtils.volume = "66"; 33 | SharedPrefUtils.playerLevel = "0"; 34 | 35 | final userPrefs = SharedPrefUtils.getAllUserPrefs(); 36 | log(jsonEncode(userPrefs)); 37 | } 38 | 39 | @override 40 | Widget build(BuildContext context) { 41 | return MaterialApp( 42 | debugShowCheckedModeBanner: false, 43 | theme: ThemeData(primarySwatch: Colors.blue), 44 | navigatorKey: navigatorKey, 45 | onGenerateRoute: router.generateRoute, 46 | onGenerateTitle: (_) => 'Way For Ball', 47 | initialRoute: '', 48 | ); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib/screens/puzzle/blocs/ball/ball_event.dart: -------------------------------------------------------------------------------- 1 | part of 'ball_bloc.dart'; 2 | 3 | abstract class BallEvent { 4 | const BallEvent(); 5 | } 6 | 7 | class InitalizeBall extends BallEvent { 8 | final BuildContext context; 9 | InitalizeBall(this.context); 10 | } 11 | 12 | class UpdateBall extends BallEvent {} 13 | 14 | class UpdateLinearState extends BallEvent {} 15 | 16 | class UpdateCurveState extends BallEvent {} 17 | 18 | class RollBall extends BallEvent {} 19 | 20 | class BallInitalize extends BallEvent {} 21 | -------------------------------------------------------------------------------- /lib/screens/puzzle/blocs/ball/ball_state.dart: -------------------------------------------------------------------------------- 1 | part of 'ball_bloc.dart'; 2 | 3 | abstract class BallState { 4 | const BallState(); 5 | } 6 | 7 | class BallInitial extends BallState {} 8 | 9 | class BallRolling extends BallState { 10 | final double ballX; 11 | final double ballY; 12 | final double ballSize; 13 | BallRolling(this.ballX, this.ballY, this.ballSize); 14 | } 15 | 16 | class BallRollComplete extends BallState {} 17 | -------------------------------------------------------------------------------- /lib/screens/puzzle/blocs/puzzle/puzzle_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'package:audioplayers/audioplayers.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_bloc/flutter_bloc.dart'; 4 | import 'package:way_for_ball/screens/puzzle/blocs/ball/ball_bloc.dart'; 5 | import 'package:way_for_ball/utils/levels_data.dart'; 6 | import 'package:way_for_ball/utils/shared_prefs.dart'; 7 | 8 | import '../timer/timer_bloc.dart'; 9 | 10 | part 'puzzle_event.dart'; 11 | part 'puzzle_state.dart'; 12 | 13 | class PuzzleBloc extends Bloc { 14 | PuzzleBloc() : super(PuzzleInitial()) { 15 | on(_initPuzzle); 16 | on(_swipe); 17 | } 18 | 19 | List> initialState = []; 20 | List> playingState = []; 21 | List>> winningStates = []; 22 | int numBlocks = 0; 23 | List flow = []; 24 | StagePoint? stageStartPoint; 25 | StagePoint? stageEndPoint; 26 | String level = "1"; 27 | bool isFirstMove = false; 28 | int moveCounter = 0; 29 | double volume = 1; 30 | 31 | final sound = AudioCache(); 32 | 33 | _initPuzzle(InitPuzzle event, Emitter emit) { 34 | level = event.level.toString(); 35 | 36 | volume = double.parse(SharedPrefUtils.volume) / 100; 37 | 38 | Level player = levelData.firstWhere((e) => '${e.levelNum}' == level); 39 | 40 | List> arr = []; 41 | 42 | for (var i = 0; i < player.initialState.length; i++) { 43 | List temp = []; 44 | 45 | for (var j = 0; j < player.initialState[i].length; j++) { 46 | temp.add(player.initialState[i][j]); 47 | } 48 | 49 | arr.add(temp); 50 | } 51 | 52 | initialState = [...player.initialState]; 53 | playingState = arr; 54 | winningStates = player.winningStates; 55 | numBlocks = player.initialState[0].length; 56 | stageStartPoint = player.stageStartPoint; 57 | stageEndPoint = player.stageEndPoint; 58 | flow = [...player.flows[0]]; 59 | 60 | emit(PuzzleInitial()); 61 | } 62 | 63 | _swipe(Swipe event, Emitter emit) { 64 | var ctx = event.context; 65 | if (!isFirstMove) { 66 | isFirstMove = true; 67 | // BlocProvider.of(event.context).add(TimerStarted()); 68 | } 69 | 70 | Direction direction = event.direction; 71 | int i = event.row; 72 | int j = event.column; 73 | if (!(playingState[i][j] > 14)) { 74 | sound.play('audio/immutableTile.mp3', volume: volume); 75 | return false; 76 | } 77 | 78 | bool toMove = false; 79 | 80 | moveCounter++; 81 | switch (direction) { 82 | case Direction.up: 83 | if (playingState[i - 1][j] == 0) { 84 | toMove = true; 85 | playingState[i - 1][j] = playingState[i][j]; 86 | } 87 | break; 88 | case Direction.down: 89 | if (playingState[i + 1][j] == 0) { 90 | toMove = true; 91 | playingState[i + 1][j] = playingState[i][j]; 92 | } 93 | break; 94 | case Direction.left: 95 | if (playingState[i][j - 1] == 0) { 96 | toMove = true; 97 | playingState[i][j - 1] = playingState[i][j]; 98 | } 99 | break; 100 | case Direction.right: 101 | if (playingState[i][j + 1] == 0) { 102 | toMove = true; 103 | playingState[i][j + 1] = playingState[i][j]; 104 | } 105 | break; 106 | } 107 | 108 | if (toMove) { 109 | playingState[i][j] = 0; 110 | } else { 111 | sound.play('audio/immutableTile.mp3', volume: volume); 112 | return false; 113 | } 114 | 115 | sound.play('audio/ballTap.mp3', volume: volume); 116 | emit(TileMoved()); 117 | 118 | bool hasCompleted = false; 119 | int pathWay = 0; 120 | 121 | if (winningStates.length > 1) { 122 | for (int i = 1; i < winningStates.length; i++) { 123 | if (checkWin(i)) { 124 | pathWay = i; 125 | } 126 | } 127 | 128 | bool otherPath = checkWin(pathWay); 129 | if (otherPath) { 130 | Level player = levelData.firstWhere((e) => '${e.levelNum}' == level); 131 | flow = [...player.flows[pathWay]]; 132 | BlocProvider.of(ctx).add(InitalizeBall(ctx)); 133 | } 134 | hasCompleted = checkWin(0) || otherPath; 135 | } else { 136 | hasCompleted = checkWin(0); 137 | } 138 | 139 | if (hasCompleted) { 140 | SharedPrefUtils.playerLevel = level; 141 | BlocProvider.of(event.context).add( 142 | TimerReset(moveCounter: moveCounter), 143 | ); 144 | moveCounter = 0; 145 | BlocProvider.of(event.context).add(RollBall()); 146 | } 147 | } 148 | 149 | checkWin(int index) { 150 | for (int i = 0; i < playingState.length; i++) { 151 | for (int j = 0; j < playingState[i].length; j++) { 152 | if (winningStates[index][i][j] != 0 && 153 | playingState[i][j] != winningStates[index][i][j]) { 154 | return false; 155 | } 156 | } 157 | } 158 | return true; 159 | } 160 | 161 | static getBoardSize(BuildContext context) { 162 | final double _width = MediaQuery.of(context).size.width * 0.90; 163 | final double _height = MediaQuery.of(context).size.height * 0.90; 164 | 165 | final double boardSize = _width > _height ? _height : _width; 166 | 167 | return boardSize; 168 | } 169 | } 170 | 171 | enum Direction { 172 | up, 173 | down, 174 | left, 175 | right, 176 | } 177 | 178 | enum Position { 179 | up, 180 | down, 181 | left, 182 | right, 183 | } 184 | -------------------------------------------------------------------------------- /lib/screens/puzzle/blocs/puzzle/puzzle_event.dart: -------------------------------------------------------------------------------- 1 | part of 'puzzle_bloc.dart'; 2 | 3 | abstract class PuzzleEvent { 4 | const PuzzleEvent(); 5 | } 6 | 7 | class InitPuzzle extends PuzzleEvent { 8 | final int level; 9 | 10 | InitPuzzle(this.level); 11 | } 12 | 13 | class Swipe extends PuzzleEvent { 14 | final BuildContext context; 15 | final Direction direction; 16 | final int row; 17 | final int column; 18 | 19 | Swipe(this.context, this.direction, this.row, this.column); 20 | } 21 | -------------------------------------------------------------------------------- /lib/screens/puzzle/blocs/puzzle/puzzle_state.dart: -------------------------------------------------------------------------------- 1 | part of 'puzzle_bloc.dart'; 2 | 3 | abstract class PuzzleState { 4 | const PuzzleState(); 5 | } 6 | 7 | class PuzzleInitial extends PuzzleState {} 8 | 9 | class TileMoved extends PuzzleState {} 10 | -------------------------------------------------------------------------------- /lib/screens/puzzle/blocs/timer/timer_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:convert'; 3 | import 'package:bloc/bloc.dart'; 4 | import 'package:flutter_bloc/flutter_bloc.dart'; 5 | import 'package:way_for_ball/utils/shared_prefs.dart'; 6 | part 'timer_event.dart'; 7 | part 'timer_state.dart'; 8 | 9 | class TimerBloc extends Bloc { 10 | static var duration = const Duration(seconds: 1); 11 | Timer timer = Timer(duration, () {}); 12 | int playTime = 0; 13 | String time = ""; 14 | 15 | TimerBloc() : super(const TimerInitial()) { 16 | on(_onStarted); 17 | on(_onReset); 18 | on(_onTicked); 19 | on(_onStop); 20 | } 21 | 22 | @override 23 | Future close() { 24 | timer.cancel(); 25 | return super.close(); 26 | } 27 | 28 | void _onStarted(TimerStarted event, Emitter emit) { 29 | add(TimerTicked()); 30 | playTime = 0; 31 | timer = Timer.periodic(duration, (_) { 32 | playTime = playTime + 1; 33 | add(TimerTicked()); 34 | }); 35 | } 36 | 37 | void _onReset(TimerReset event, Emitter emit) { 38 | var dataMap = { 39 | "moves": event.moveCounter, 40 | "time": time, 41 | }; 42 | 43 | String data = jsonEncode(dataMap); 44 | 45 | SharedPrefUtils.setUserStringValue( 46 | "level${SharedPrefUtils.playerLevel}", data); 47 | 48 | timer.cancel(); 49 | 50 | emit(const TimerInitial()); 51 | } 52 | 53 | _onStop(TimerStop event, Emitter emit) { 54 | timer.cancel(); 55 | 56 | emit(const ResetTimer()); 57 | } 58 | 59 | void _onTicked(TimerTicked event, Emitter emit) { 60 | // int hours = playTime ~/ (60 * 60) % 24; 61 | int minutes = (playTime ~/ 60) % 60; 62 | int seconds = playTime % 60; 63 | 64 | // String strHours = hours == 0 ? '' : '${format(hours)}:'; 65 | String strHours = ''; 66 | String strMinutes = format(minutes); 67 | String strSeconds = format(seconds); 68 | 69 | time = "$strHours$strMinutes:$strSeconds"; 70 | 71 | emit(TimerRunInProgress(time: time)); 72 | } 73 | 74 | static format(int str) { 75 | return str.toString().padLeft(2, '0'); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /lib/screens/puzzle/blocs/timer/timer_event.dart: -------------------------------------------------------------------------------- 1 | part of 'timer_bloc.dart'; 2 | 3 | abstract class TimerEvent { 4 | const TimerEvent(); 5 | } 6 | 7 | class TimerStarted extends TimerEvent {} 8 | 9 | class TimerReset extends TimerEvent { 10 | final int moveCounter; 11 | 12 | const TimerReset({required this.moveCounter}); 13 | } 14 | 15 | class TimerStop extends TimerEvent {} 16 | 17 | class TimerTicked extends TimerEvent {} 18 | -------------------------------------------------------------------------------- /lib/screens/puzzle/blocs/timer/timer_state.dart: -------------------------------------------------------------------------------- 1 | part of 'timer_bloc.dart'; 2 | 3 | abstract class TimerState { 4 | const TimerState(); 5 | } 6 | 7 | class TimerInitial extends TimerState { 8 | const TimerInitial() : super(); 9 | } 10 | 11 | class TimerRunInProgress extends TimerState { 12 | final String time; 13 | const TimerRunInProgress({ 14 | required this.time, 15 | }); 16 | } 17 | 18 | class TimerRunComplete extends TimerState { 19 | const TimerRunComplete(); 20 | } 21 | 22 | class ResetTimer extends TimerState { 23 | const ResetTimer(); 24 | } 25 | -------------------------------------------------------------------------------- /lib/screens/puzzle/puzzle_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:animated_text_kit/animated_text_kit.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_bloc/flutter_bloc.dart'; 4 | import 'package:way_for_ball/screens/puzzle/blocs/ball/ball_bloc.dart'; 5 | import 'package:way_for_ball/utils/shared_prefs.dart'; 6 | 7 | import 'blocs/puzzle/puzzle_bloc.dart'; 8 | import 'blocs/timer/timer_bloc.dart'; 9 | import 'puzzle_widgets/widgets.dart'; 10 | 11 | class PuzzleScreen extends StatefulWidget { 12 | final int? level; 13 | const PuzzleScreen({Key? key, this.level}) : super(key: key); 14 | 15 | @override 16 | _PuzzleScreenState createState() => _PuzzleScreenState(); 17 | } 18 | 19 | class _PuzzleScreenState extends State { 20 | int playerLevel = int.parse(SharedPrefUtils.playerLevel); 21 | var disableTiles = true; 22 | 23 | @override 24 | void initState() { 25 | super.initState(); 26 | context.read().add(InitPuzzle(widget.level ?? playerLevel)); 27 | } 28 | 29 | @override 30 | Widget build(BuildContext context) { 31 | final double _width = MediaQuery.of(context).size.width; 32 | final double _height = MediaQuery.of(context).size.height; 33 | 34 | final bool widthLarger = _width > _height; 35 | final double _boardSize = PuzzleBloc.getBoardSize(context); 36 | 37 | return Scaffold( 38 | body: Stack( 39 | alignment: Alignment.center, 40 | children: [ 41 | Background( 42 | child: SingleChildScrollView( 43 | child: Column( 44 | mainAxisAlignment: MainAxisAlignment.center, 45 | children: [ 46 | const PuzzleTopView(), 47 | Row( 48 | mainAxisAlignment: MainAxisAlignment.center, 49 | crossAxisAlignment: CrossAxisAlignment.start, 50 | children: [ 51 | Board( 52 | child: Stack( 53 | children: const [ 54 | PuzzleView(), 55 | BallView(), 56 | ], 57 | ), 58 | ), 59 | widthLarger 60 | ? PuzzleBottomView(level: widget.level ?? playerLevel) 61 | : Container(), 62 | ], 63 | ), 64 | widthLarger 65 | ? Container() 66 | : PuzzleBottomView(level: widget.level ?? playerLevel), 67 | ], 68 | ), 69 | ), 70 | ), 71 | BlocBuilder( 72 | builder: (context, state) { 73 | if (state is BallInitial) { 74 | disableTiles = false; 75 | } 76 | if (state is BallRolling) { 77 | disableTiles = true; 78 | } 79 | if (state is BallRollComplete) { 80 | disableTiles = true; 81 | } 82 | return Stack( 83 | children: [ 84 | AnimatedTextKit( 85 | totalRepeatCount: 1, 86 | onFinished: () { 87 | BlocProvider.of(context).add(TimerStarted()); 88 | setState(() { 89 | disableTiles = false; 90 | }); 91 | }, 92 | pause: const Duration(milliseconds: 4), 93 | animatedTexts: [ 94 | ScaleAnimatedText( 95 | 'Ready?', 96 | textStyle: const TextStyle( 97 | fontSize: 70.0, 98 | color: Colors.white, 99 | ), 100 | duration: const Duration(seconds: 1), 101 | ), 102 | ScaleAnimatedText( 103 | 'GO!!', 104 | textStyle: const TextStyle( 105 | fontSize: 70.0, 106 | color: Colors.white, 107 | ), 108 | duration: const Duration(seconds: 1), 109 | ), 110 | ], 111 | ), 112 | disableTiles 113 | ? Container( 114 | width: _boardSize, 115 | height: _boardSize, 116 | color: Colors.transparent, 117 | ) 118 | : const SizedBox.shrink() 119 | ], 120 | ); 121 | }, 122 | ) 123 | ], 124 | ), 125 | ); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /lib/screens/puzzle/puzzle_widgets/background.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_svg/svg.dart'; 3 | 4 | class Background extends StatelessWidget { 5 | final Widget child; 6 | const Background({Key? key, required this.child}) : super(key: key); 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | double width = MediaQuery.of(context).size.width; 11 | double height = MediaQuery.of(context).size.height; 12 | final bool widthLarger = width > height; 13 | return Center( 14 | child: SizedBox( 15 | height: height, 16 | width: width, 17 | child: Stack( 18 | alignment: Alignment.center, 19 | children: [ 20 | SizedBox( 21 | height: height, 22 | width: width, 23 | child: SvgPicture.asset( 24 | 'assets/images/board-background.svg', 25 | fit: BoxFit.cover, 26 | ), 27 | ), 28 | Positioned( 29 | top: widthLarger ? width * 0.05 : width * 0.12, 30 | left: widthLarger ? width * 0.80 : width * .70, 31 | child: SvgPicture.asset( 32 | 'assets/images/moon.svg', 33 | width: widthLarger ? width * .15 : width * 0.25, 34 | height: widthLarger ? width * .15 : width * 0.25, 35 | ), 36 | ), 37 | Container( 38 | alignment: Alignment.center, 39 | width: double.infinity, 40 | height: double.infinity, 41 | child: child, 42 | ), 43 | ], 44 | ), 45 | ), 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/screens/puzzle/puzzle_widgets/ball.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class Ball extends StatelessWidget { 4 | final double x; 5 | final double y; 6 | final double ballSize; 7 | 8 | const Ball( 9 | {Key? key, required this.x, required this.y, required this.ballSize}) 10 | : super(key: key); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | return Positioned( 15 | top: y, 16 | left: x, 17 | child: Container( 18 | width: ballSize, 19 | height: ballSize, 20 | decoration: const BoxDecoration( 21 | shape: BoxShape.circle, 22 | color: Colors.white, 23 | ), 24 | ), 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lib/screens/puzzle/puzzle_widgets/ball_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bloc/flutter_bloc.dart'; 3 | import 'package:way_for_ball/screens/puzzle/blocs/ball/ball_bloc.dart'; 4 | import 'ball.dart'; 5 | 6 | class BallView extends StatefulWidget { 7 | const BallView({Key? key}) : super(key: key); 8 | 9 | @override 10 | _BallViewState createState() => _BallViewState(); 11 | } 12 | 13 | class _BallViewState extends State { 14 | @override 15 | Widget build(BuildContext context) { 16 | BlocProvider.of(context).add(InitalizeBall(context)); 17 | return BlocBuilder( 18 | builder: (context, state) { 19 | final ballBloc = context.read(); 20 | double ballX = ballBloc.ballX; 21 | double ballY = ballBloc.ballY; 22 | double ballSize = ballBloc.ballSize; 23 | if (state is BallRolling) { 24 | ballX = state.ballX; 25 | ballY = state.ballY; 26 | } 27 | 28 | // else { 29 | // BlocProvider.of(context).add(InitalizeBall(context)); 30 | // } 31 | return Ball(x: ballX, y: ballY, ballSize: ballSize); 32 | }, 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/screens/puzzle/puzzle_widgets/board.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class Board extends StatelessWidget { 4 | final Widget child; 5 | const Board({Key? key, required this.child}) : super(key: key); 6 | 7 | @override 8 | Widget build(BuildContext context) { 9 | final double _width = MediaQuery.of(context).size.width * 0.90; 10 | final double _height = MediaQuery.of(context).size.height * 0.90; 11 | 12 | final double _boardSize = _width > _height ? _height : _width; 13 | 14 | return Center( 15 | child: SizedBox( 16 | height: _boardSize, 17 | width: _boardSize, 18 | child: Stack( 19 | alignment: Alignment.center, 20 | children: [ 21 | Container( 22 | height: MediaQuery.of(context).size.height * 0.90, 23 | width: MediaQuery.of(context).size.width * 0.90, 24 | clipBehavior: Clip.hardEdge, 25 | decoration: BoxDecoration( 26 | color: Colors.blue[300], 27 | borderRadius: BorderRadius.circular(8), 28 | boxShadow: const [ 29 | BoxShadow( 30 | color: Colors.black87, 31 | blurRadius: 10, 32 | spreadRadius: 0, 33 | offset: Offset(0, 2.0), 34 | ) 35 | ], 36 | ), 37 | ), 38 | child, 39 | ], 40 | ), 41 | ), 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /lib/screens/puzzle/puzzle_widgets/puzzle_bottom_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bloc/flutter_bloc.dart'; 3 | import 'package:flutter_svg/svg.dart'; 4 | import 'package:way_for_ball/screens/puzzle/blocs/ball/ball_bloc.dart'; 5 | import 'package:way_for_ball/utils/popup/settings/volume.dart'; 6 | import '../blocs/puzzle/puzzle_bloc.dart'; 7 | import '../blocs/timer/timer_bloc.dart'; 8 | 9 | class PuzzleBottomView extends StatefulWidget { 10 | final int level; 11 | const PuzzleBottomView({ 12 | Key? key, 13 | required this.level, 14 | }) : super(key: key); 15 | 16 | @override 17 | _PuzzleBottomViewState createState() => _PuzzleBottomViewState(); 18 | } 19 | 20 | class _PuzzleBottomViewState extends State { 21 | @override 22 | Widget build(BuildContext context) { 23 | final double _width = MediaQuery.of(context).size.width; 24 | final double _height = MediaQuery.of(context).size.height; 25 | 26 | final bool widthLarger = _width > _height; 27 | 28 | List buttons = [ 29 | GameButton( 30 | "back", 31 | "Back", 32 | widthLarger: widthLarger, 33 | onTap: () { 34 | Navigator.of(context).pop(); 35 | }, 36 | ), 37 | const SizedBox(width: 8), 38 | GameButton( 39 | "restart", 40 | "Restart", 41 | widthLarger: widthLarger, 42 | onTap: () { 43 | context.read().add(InitPuzzle(widget.level)); 44 | context.read().add(BallInitalize()); 45 | context.read().add(InitalizeBall(context)); 46 | context.read().add(TimerStop()); 47 | context.read().add(TimerStarted()); 48 | }, 49 | ), 50 | const SizedBox(width: 8), 51 | GameButton( 52 | "setting", 53 | "Setting", 54 | onTap: () { 55 | Volume.show(context); 56 | }, 57 | widthLarger: widthLarger, 58 | ), 59 | ]; 60 | 61 | return Container( 62 | alignment: Alignment.center, 63 | child: widthLarger 64 | ? Column( 65 | mainAxisAlignment: MainAxisAlignment.center, 66 | children: buttons, 67 | ) 68 | : Row( 69 | mainAxisAlignment: MainAxisAlignment.center, 70 | children: buttons, 71 | ), 72 | ); 73 | } 74 | } 75 | 76 | class GameButton extends StatefulWidget { 77 | final String name; 78 | final String text; 79 | final VoidCallback onTap; 80 | final bool widthLarger; 81 | const GameButton( 82 | this.name, 83 | this.text, { 84 | Key? key, 85 | required this.onTap, 86 | required this.widthLarger, 87 | }) : super(key: key); 88 | 89 | @override 90 | State createState() => _GameButtonState(); 91 | } 92 | 93 | class _GameButtonState extends State { 94 | bool disableButton = false; 95 | 96 | @override 97 | Widget build(BuildContext context) { 98 | return BlocBuilder( 99 | builder: (context, state) { 100 | if (state is BallRolling) { 101 | disableButton = true; 102 | } else { 103 | disableButton = false; 104 | } 105 | return Material( 106 | color: Colors.transparent, 107 | child: InkWell( 108 | onTap: disableButton ? null : widget.onTap, 109 | child: Column( 110 | children: [ 111 | const SizedBox(height: 20), 112 | SizedBox( 113 | height: MediaQuery.of(context).size.height * 0.1, 114 | width: MediaQuery.of(context).size.width * 0.1, 115 | child: disableButton 116 | ? SvgPicture.asset( 117 | 'assets/images/disabled_${widget.name}.svg', 118 | ) 119 | : SvgPicture.asset('assets/images/${widget.name}.svg'), 120 | ), 121 | ], 122 | ), 123 | ), 124 | ); 125 | }, 126 | ); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /lib/screens/puzzle/puzzle_widgets/puzzle_top_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bloc/flutter_bloc.dart'; 3 | import 'package:way_for_ball/screens/puzzle/blocs/timer/timer_bloc.dart'; 4 | 5 | class PuzzleTopView extends StatefulWidget { 6 | const PuzzleTopView({Key? key}) : super(key: key); 7 | 8 | @override 9 | _PuzzleTopViewState createState() => _PuzzleTopViewState(); 10 | } 11 | 12 | class _PuzzleTopViewState extends State { 13 | String time = '--'; 14 | @override 15 | Widget build(BuildContext context) { 16 | return BlocBuilder( 17 | builder: (context, state) { 18 | if (state is TimerRunInProgress) { 19 | time = state.time; 20 | } 21 | 22 | if (state is ResetTimer) { 23 | time = '00:00'; 24 | } 25 | 26 | return Padding( 27 | padding: const EdgeInsets.symmetric(vertical: 12), 28 | child: Text( 29 | time, 30 | style: const TextStyle( 31 | color: Colors.yellowAccent, 32 | fontWeight: FontWeight.bold, 33 | fontSize: 18, 34 | ), 35 | ), 36 | ); 37 | }, 38 | ); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/screens/puzzle/puzzle_widgets/puzzle_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bloc/flutter_bloc.dart'; 3 | import 'package:flutter_svg/flutter_svg.dart'; 4 | import 'package:way_for_ball/screens/puzzle/blocs/puzzle/puzzle_bloc.dart'; 5 | import 'package:way_for_ball/widgets/slide_animation.dart'; 6 | import 'package:way_for_ball/widgets/swipe_detector.dart'; 7 | 8 | class PuzzleView extends StatefulWidget { 9 | const PuzzleView({ 10 | Key? key, 11 | }) : super(key: key); 12 | 13 | @override 14 | _PuzzleViewState createState() => _PuzzleViewState(); 15 | } 16 | 17 | class _PuzzleViewState extends State { 18 | List> level = []; 19 | 20 | int levelLength = 0; 21 | late PuzzleBloc puzzleBloc; 22 | 23 | @override 24 | void initState() { 25 | super.initState(); 26 | 27 | puzzleBloc = context.read(); 28 | } 29 | 30 | @override 31 | Widget build(BuildContext context) { 32 | final double _boardSize = PuzzleBloc.getBoardSize(context); 33 | return BlocBuilder( 34 | builder: (context, state) { 35 | if (state is PuzzleInitial) { 36 | level = puzzleBloc.playingState; 37 | levelLength = level.length; 38 | } 39 | 40 | return level.isEmpty 41 | ? const SizedBox() 42 | : GridView.builder( 43 | shrinkWrap: true, 44 | padding: EdgeInsets.zero, 45 | physics: const NeverScrollableScrollPhysics(), 46 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( 47 | crossAxisCount: levelLength, 48 | ), 49 | itemCount: levelLength * levelLength, 50 | itemBuilder: (context, index) { 51 | int i, j = 0; 52 | i = (index / levelLength).floor(); 53 | j = (index % levelLength); 54 | return SwipeDetector( 55 | onSwipeUp: () { 56 | puzzleBloc.add(Swipe(context, Direction.up, i, j)); 57 | }, 58 | onSwipeRight: () { 59 | puzzleBloc.add(Swipe(context, Direction.right, i, j)); 60 | }, 61 | onSwipeDown: () { 62 | puzzleBloc.add(Swipe(context, Direction.down, i, j)); 63 | }, 64 | onSwipeLeft: () { 65 | puzzleBloc.add(Swipe(context, Direction.left, i, j)); 66 | }, 67 | child: SlidingAnimation( 68 | index: j, 69 | child: SizedBox( 70 | width: _boardSize / puzzleBloc.numBlocks, 71 | height: _boardSize / puzzleBloc.numBlocks, 72 | child: SvgPicture.asset( 73 | 'assets/images/tiles/tile${level[i][j]}.svg', 74 | ), 75 | ), 76 | ), 77 | ); 78 | }, 79 | ); 80 | }, 81 | ); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /lib/screens/puzzle/puzzle_widgets/widgets.dart: -------------------------------------------------------------------------------- 1 | export 'background.dart'; 2 | export 'ball.dart'; 3 | export 'ball_view.dart'; 4 | export 'board.dart'; 5 | export 'puzzle_bottom_view.dart'; 6 | export 'puzzle_top_view.dart'; 7 | export 'puzzle_view.dart'; 8 | export 'widgets.dart'; 9 | -------------------------------------------------------------------------------- /lib/screens/start/bloc/bird_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:bloc/bloc.dart'; 4 | import 'package:flutter/material.dart'; 5 | 6 | part 'bird_event.dart'; 7 | part 'bird_state.dart'; 8 | 9 | class BirdBloc extends Bloc { 10 | BirdBloc() : super(BirdInitial()) { 11 | on(_initializeBird); 12 | on(_moveBird); 13 | } 14 | 15 | double x = 0; 16 | double y = 0; 17 | 18 | _initializeBird(InitializeBird event, Emitter emit) { 19 | double width = MediaQuery.of(event.context).size.width; 20 | y = width * 0.15; 21 | 22 | Timer.periodic(const Duration(milliseconds: 20), (_) { 23 | if (x > width) { 24 | x = 0; 25 | } else { 26 | x += 4; 27 | } 28 | 29 | add(MoveBird()); 30 | }); 31 | } 32 | 33 | _moveBird(MoveBird event, Emitter emit) { 34 | emit(BirdMoving(x: x, y: y)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/screens/start/bloc/bird_event.dart: -------------------------------------------------------------------------------- 1 | part of 'bird_bloc.dart'; 2 | 3 | abstract class BirdEvent {} 4 | 5 | class InitializeBird extends BirdEvent { 6 | final BuildContext context; 7 | 8 | InitializeBird(this.context); 9 | } 10 | 11 | class MoveBird extends BirdEvent {} 12 | -------------------------------------------------------------------------------- /lib/screens/start/bloc/bird_state.dart: -------------------------------------------------------------------------------- 1 | part of 'bird_bloc.dart'; 2 | 3 | abstract class BirdState {} 4 | 5 | class BirdInitial extends BirdState {} 6 | 7 | class BirdMoving extends BirdState { 8 | final double x; 9 | final double y; 10 | 11 | BirdMoving({ 12 | required this.x, 13 | required this.y, 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /lib/screens/start/start_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:way_for_ball/screens/start/start_widgets/background.dart'; 3 | import 'package:way_for_ball/screens/start/start_widgets/button_play.dart'; 4 | import 'package:way_for_ball/screens/start/start_widgets/logo.dart'; 5 | 6 | import 'start_widgets/button_setting.dart'; 7 | 8 | class StartScreen extends StatefulWidget { 9 | const StartScreen({Key? key}) : super(key: key); 10 | 11 | @override 12 | _StartScreenState createState() => _StartScreenState(); 13 | } 14 | 15 | class _StartScreenState extends State { 16 | bool isSettingHovered = false; 17 | @override 18 | Widget build(BuildContext context) { 19 | return Background( 20 | child: Column( 21 | mainAxisAlignment: MainAxisAlignment.spaceEvenly, 22 | children: const [ 23 | Logo(), 24 | ButtonPlay(), 25 | ButtonSetting(), 26 | ], 27 | ), 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/screens/start/start_widgets/background.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bloc/flutter_bloc.dart'; 3 | import 'package:flutter_svg/svg.dart'; 4 | import 'package:way_for_ball/screens/start/bloc/bird_bloc.dart'; 5 | 6 | import 'bird_container.dart'; 7 | 8 | class Background extends StatefulWidget { 9 | final Widget child; 10 | const Background({Key? key, required this.child}) : super(key: key); 11 | 12 | @override 13 | State createState() => _BackgroundState(); 14 | } 15 | 16 | class _BackgroundState extends State { 17 | double width = 0; 18 | double height = 0; 19 | bool widthLarger = false; 20 | double x = 0; 21 | double y = 0; 22 | 23 | @override 24 | void initState() { 25 | super.initState(); 26 | 27 | WidgetsBinding.instance.addPostFrameCallback((_) { 28 | BlocProvider.of(context).add(InitializeBird(context)); 29 | }); 30 | } 31 | 32 | @override 33 | Widget build(BuildContext context) { 34 | width = MediaQuery.of(context).size.width; 35 | height = MediaQuery.of(context).size.height; 36 | widthLarger = width > height; 37 | return SizedBox( 38 | height: height, 39 | width: width, 40 | child: Stack( 41 | children: [ 42 | SizedBox( 43 | height: height, 44 | width: width, 45 | child: SvgPicture.asset( 46 | 'assets/images/board-background.svg', 47 | height: height, 48 | width: width, 49 | fit: BoxFit.cover, 50 | // alignment: Alignment.center, 51 | ), 52 | ), 53 | Positioned( 54 | top: widthLarger ? width * 0.05 : width * 0.12, 55 | left: widthLarger ? width * 0.80 : width * .70, 56 | child: SvgPicture.asset( 57 | 'assets/images/moon.svg', 58 | width: widthLarger ? width * .15 : width * 0.25, 59 | height: widthLarger ? width * .15 : width * 0.25, 60 | ), 61 | ), 62 | Container( 63 | alignment: Alignment.center, 64 | width: double.infinity, 65 | height: double.infinity, 66 | child: widget.child, 67 | ), 68 | BlocBuilder( 69 | builder: (context, state) { 70 | if (state is BirdMoving) { 71 | x = state.x; 72 | y = state.y; 73 | } 74 | return BirdContainer(x: x, y: y); 75 | }, 76 | ), 77 | ], 78 | ), 79 | ); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /lib/screens/start/start_widgets/bird.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:rive/rive.dart'; 3 | 4 | class Bird extends StatelessWidget { 5 | final double x; 6 | final double y; 7 | 8 | const Bird({ 9 | Key? key, 10 | required this.x, 11 | required this.y, 12 | }) : super(key: key); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | double width = MediaQuery.of(context).size.width; 17 | double height = MediaQuery.of(context).size.height; 18 | final bool widthLarger = width > height; 19 | 20 | return Positioned( 21 | top: y, 22 | left: x, 23 | child: SizedBox( 24 | height: width * (widthLarger ? 0.05 : 0.2), 25 | width: width * (widthLarger ? 0.05 : 0.2), 26 | child: const RiveAnimation.asset('assets/rive/bird.riv'), 27 | ), 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/screens/start/start_widgets/bird_container.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:way_for_ball/screens/start/start_widgets/bird.dart'; 5 | 6 | class BirdContainer extends StatefulWidget { 7 | final double x; 8 | final double y; 9 | const BirdContainer({Key? key, required this.x, required this.y}) 10 | : super(key: key); 11 | 12 | @override 13 | State createState() => _BirdContainerState(); 14 | } 15 | 16 | class _BirdContainerState extends State { 17 | @override 18 | Widget build(BuildContext context) { 19 | return getBirds(context); 20 | } 21 | 22 | getBirds(context) { 23 | double width = MediaQuery.of(context).size.width; 24 | double height = MediaQuery.of(context).size.height; 25 | final bool widthLarger = width > height; 26 | 27 | List birds = []; 28 | for (var i in List.generate(4, (_) => _)) { 29 | final random = Random(i); 30 | 31 | birds.add( 32 | Bird( 33 | x: widget.x * (i + 1), 34 | y: widget.y * ((widthLarger ? 0.2 : 0.5) + random.nextDouble()), 35 | ), 36 | ); 37 | } 38 | 39 | return Stack(children: birds); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/screens/start/start_widgets/button_play.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_svg/flutter_svg.dart'; 3 | import 'package:way_for_ball/utils/popup/levels/levels_popup.dart'; 4 | 5 | class ButtonPlay extends StatefulWidget { 6 | const ButtonPlay({Key? key}) : super(key: key); 7 | 8 | @override 9 | _ButtonPlayState createState() => _ButtonPlayState(); 10 | } 11 | 12 | class _ButtonPlayState extends State { 13 | bool isHovered = false; 14 | 15 | static getRatioSize(BuildContext context) { 16 | final double _width = MediaQuery.of(context).size.width * 0.90; 17 | final double _height = MediaQuery.of(context).size.height * 0.90; 18 | 19 | final double ratioSize = _width > _height ? _height : _width; 20 | 21 | return ratioSize; 22 | } 23 | 24 | @override 25 | Widget build(BuildContext context) { 26 | double ratioSize = getRatioSize(context); 27 | return Material( 28 | color: Colors.transparent, 29 | shape: const CircleBorder(), 30 | clipBehavior: Clip.hardEdge, 31 | child: InkWell( 32 | onTap: () { 33 | LevelPopup.show(context); 34 | }, 35 | onHover: (value) { 36 | setState(() { 37 | isHovered = value; 38 | }); 39 | }, 40 | child: SizedBox( 41 | width: ratioSize * 0.20, 42 | height: ratioSize * 0.20, 43 | child: isHovered 44 | ? SvgPicture.asset( 45 | 'assets/images/btn_play.svg', 46 | fit: BoxFit.cover, 47 | ) 48 | : SvgPicture.asset( 49 | 'assets/images/btn_play.svg', 50 | fit: BoxFit.cover, 51 | ), 52 | ), 53 | ), 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /lib/screens/start/start_widgets/button_setting.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_svg/flutter_svg.dart'; 3 | import 'package:way_for_ball/utils/popup/settings/volume.dart'; 4 | 5 | class ButtonSetting extends StatefulWidget { 6 | const ButtonSetting({Key? key}) : super(key: key); 7 | 8 | @override 9 | _ButtonSettingState createState() => _ButtonSettingState(); 10 | } 11 | 12 | class _ButtonSettingState extends State { 13 | bool isHovered = false; 14 | 15 | static getRatioSize(BuildContext context) { 16 | final double _width = MediaQuery.of(context).size.width * 0.90; 17 | final double _height = MediaQuery.of(context).size.height * 0.90; 18 | 19 | final double ratioSize = _width > _height ? _height : _width; 20 | 21 | return ratioSize; 22 | } 23 | 24 | @override 25 | Widget build(BuildContext context) { 26 | double ratioSize = getRatioSize(context); 27 | return Material( 28 | color: Colors.transparent, 29 | shape: const CircleBorder(), 30 | clipBehavior: Clip.hardEdge, 31 | child: InkWell( 32 | onTap: () { 33 | Volume.show(context); 34 | }, 35 | onHover: (value) { 36 | setState(() { 37 | isHovered = value; 38 | }); 39 | }, 40 | child: SizedBox( 41 | width: ratioSize * 0.20, 42 | height: ratioSize * 0.20, 43 | child: isHovered 44 | ? SvgPicture.asset( 45 | 'assets/images/btn_setting.svg', 46 | fit: BoxFit.cover, 47 | ) 48 | : SvgPicture.asset( 49 | 'assets/images/btn_setting.svg', 50 | fit: BoxFit.cover, 51 | ), 52 | ), 53 | ), 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /lib/screens/start/start_widgets/logo.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_svg/flutter_svg.dart'; 3 | 4 | class Logo extends StatefulWidget { 5 | const Logo({Key? key}) : super(key: key); 6 | 7 | @override 8 | _ButtonPlayState createState() => _ButtonPlayState(); 9 | } 10 | 11 | class _ButtonPlayState extends State { 12 | @override 13 | Widget build(BuildContext context) { 14 | return Material( 15 | color: Colors.transparent, 16 | clipBehavior: Clip.hardEdge, 17 | child: SizedBox( 18 | width: MediaQuery.of(context).size.width * 0.90, 19 | child: SvgPicture.asset( 20 | 'assets/images/way_for_ball.svg', 21 | fit: BoxFit.contain, 22 | ), 23 | ), 24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/utils/arc_map.dart: -------------------------------------------------------------------------------- 1 | class Arc { 2 | static Map arcMap = { 3 | "C_LU": {"direction": -1, "start": 90, "end": 0, "operator": ">"}, 4 | "C_RU": {"direction": 1, "start": 90, "end": 180, "operator": "<"}, 5 | "C_RB": {"direction": -1, "start": 270, "end": 180, "operator": ">"}, 6 | "C_UL": {"direction": 1, "start": 0, "end": 90, "operator": "<"}, 7 | "C_BL": {"direction": -1, "start": 0, "end": -90, "operator": ">"}, 8 | "C_UR": {"direction": -1, "start": 180, "end": 90, "operator": ">"}, 9 | "C_BR": {"direction": 1, "start": 180, "end": 270, "operator": "<"}, 10 | "C_LB": {"direction": 1, "start": 270, "end": 360, "operator": "<"}, 11 | "L_LR": {"direction": 1, "type": "H", "end": null, "operator": "<"}, 12 | "L_RL": {"direction": -1, "type": "H", "end": null, "operator": ">"}, 13 | "L_UD": {"direction": 1, "type": "V", "end": null, "operator": "<"}, 14 | "L_DU": {"direction": -1, "type": "V", "end": null, "operator": ">"}, 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /lib/utils/popup/levels/levels_popup.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; 4 | 5 | import 'widgets/level_tile.dart'; 6 | 7 | class LevelPopup { 8 | static show(BuildContext context) { 9 | var width = MediaQuery.of(context).size.width; 10 | showDialog( 11 | context: context, 12 | barrierDismissible: true, 13 | builder: (BuildContext context) { 14 | return AlertDialog( 15 | backgroundColor: Colors.transparent, 16 | content: Container( 17 | width: kIsWeb 18 | ? width < 576 19 | ? width * 0.90 20 | : 400 21 | : width * 0.90, 22 | padding: const EdgeInsets.all(10), 23 | decoration: BoxDecoration( 24 | color: const Color(0xff1e3266), 25 | borderRadius: BorderRadius.circular(20), 26 | ), 27 | child: Wrap( 28 | alignment: WrapAlignment.center, 29 | children: [ 30 | const Text( 31 | "Select a Level", 32 | style: TextStyle( 33 | color: Colors.white, 34 | fontWeight: FontWeight.bold, 35 | ), 36 | ), 37 | const SizedBox(height: 20), 38 | StaggeredGrid.count( 39 | crossAxisCount: 4, 40 | crossAxisSpacing: width * 0.001, 41 | mainAxisSpacing: width * 0.001, 42 | children: List.generate(12, (index) { 43 | return LevelTile('${index + 1}'); 44 | }), 45 | ), 46 | ], 47 | ), 48 | ), 49 | ); 50 | }, 51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /lib/utils/popup/levels/widgets/level_tile.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutter/foundation.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:way_for_ball/utils/screens.dart'; 6 | import 'package:way_for_ball/utils/shared_prefs.dart'; 7 | 8 | class LevelTile extends StatelessWidget { 9 | final String level; 10 | const LevelTile( 11 | this.level, { 12 | Key? key, 13 | }) : super(key: key); 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | bool isNextLevel = 18 | int.parse(SharedPrefUtils.playerLevel) + 1 == int.parse(level); 19 | bool isUnlocked = 20 | SharedPrefUtils.getUserStringValue("level$level") != "" || isNextLevel; 21 | return InkWell( 22 | onTap: isUnlocked 23 | ? () { 24 | Navigator.pop(context); 25 | Navigator.pushNamed( 26 | context, 27 | Screens.puzzle_screen, 28 | arguments: int.parse(level), 29 | ); 30 | } 31 | : null, 32 | child: Container( 33 | margin: kIsWeb ? const EdgeInsets.all(10) : null, 34 | decoration: BoxDecoration( 35 | color: const Color(0xff356cb1), 36 | borderRadius: BorderRadius.circular(10), 37 | boxShadow: [ 38 | BoxShadow( 39 | color: Colors.black.withOpacity(0.5), 40 | blurRadius: 10, 41 | offset: const Offset(0, 10), 42 | ), 43 | ], 44 | ), 45 | child: Column( 46 | mainAxisAlignment: MainAxisAlignment.center, 47 | children: [ 48 | isUnlocked 49 | ? Column( 50 | children: [ 51 | Text( 52 | level, 53 | style: const TextStyle( 54 | color: Colors.white, 55 | fontWeight: FontWeight.w700, 56 | fontSize: 28, 57 | fontFamily: 'Shizuru', 58 | ), 59 | ), 60 | isNextLevel 61 | ? const Text( 62 | "0", 63 | style: TextStyle( 64 | color: Colors.transparent, 65 | fontWeight: FontWeight.w700, 66 | fontSize: 14, 67 | ), 68 | ) 69 | : Text( 70 | getTime(level), 71 | style: const TextStyle( 72 | color: Colors.white, 73 | fontWeight: FontWeight.w700, 74 | fontSize: 14, 75 | ), 76 | ), 77 | ], 78 | ) 79 | : Stack( 80 | alignment: Alignment.center, 81 | children: [ 82 | Column( 83 | children: [ 84 | Text( 85 | level, 86 | style: const TextStyle( 87 | color: Colors.transparent, 88 | fontWeight: FontWeight.w700, 89 | fontSize: 28, 90 | fontFamily: 'Shizuru', 91 | ), 92 | ), 93 | isNextLevel 94 | ? Container() 95 | : const Text( 96 | "0", 97 | style: TextStyle( 98 | color: Colors.transparent, 99 | fontWeight: FontWeight.w700, 100 | fontSize: 14, 101 | ), 102 | ), 103 | ], 104 | ), 105 | const Icon(Icons.lock, color: Colors.white), 106 | ], 107 | ) 108 | ], 109 | ), 110 | ), 111 | ); 112 | } 113 | 114 | static getData(String level) { 115 | var data = jsonDecode( 116 | SharedPrefUtils.getUserStringValue('level$level'), 117 | ); 118 | return data; 119 | } 120 | 121 | static getTime(String level) { 122 | return getData(level)['time'].toString(); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /lib/utils/popup/settings/volume.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:way_for_ball/utils/shared_prefs.dart'; 3 | 4 | class Volume { 5 | static show(BuildContext context) { 6 | double _currentSliderValue = 100; 7 | return showDialog( 8 | context: context, 9 | builder: (context) => AlertDialog( 10 | backgroundColor: const Color(0xff1e3266), 11 | content: SizedBox( 12 | width: 100, 13 | child: Wrap( 14 | alignment: WrapAlignment.center, 15 | children: [ 16 | const Text( 17 | "Volume", 18 | style: TextStyle( 19 | color: Colors.white, 20 | fontWeight: FontWeight.bold, 21 | ), 22 | ), 23 | SoundSlider( 24 | onChanged: (value) { 25 | _currentSliderValue = value; 26 | }, 27 | ), 28 | const SizedBox(height: 20), 29 | ElevatedButton( 30 | onPressed: () { 31 | SharedPrefUtils.volume = _currentSliderValue.toString(); 32 | Navigator.pop(context); 33 | }, 34 | style: ElevatedButton.styleFrom( 35 | primary: const Color(0xff356cb1), 36 | ), 37 | child: const Text("OK"), 38 | ) 39 | ], 40 | ), 41 | ), 42 | ), 43 | ); 44 | } 45 | } 46 | 47 | class SoundSlider extends StatefulWidget { 48 | final void Function(double) onChanged; 49 | 50 | const SoundSlider({Key? key, required this.onChanged}) : super(key: key); 51 | 52 | @override 53 | State createState() => _SoundSliderState(); 54 | } 55 | 56 | class _SoundSliderState extends State { 57 | double _currentSliderValue = double.parse(SharedPrefUtils.volume); 58 | 59 | @override 60 | Widget build(BuildContext context) { 61 | return Slider( 62 | value: _currentSliderValue, 63 | max: 100, 64 | divisions: 5, 65 | activeColor: const Color(0xff356cb1), 66 | label: _currentSliderValue.round().toString(), 67 | onChanged: (double value) { 68 | setState(() { 69 | _currentSliderValue = value; 70 | widget.onChanged(value); 71 | }); 72 | }, 73 | ); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /lib/utils/popup/winning/widgets/win_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_svg/flutter_svg.dart'; 3 | 4 | class WinButton extends StatelessWidget { 5 | final String name; 6 | final String text; 7 | final VoidCallback onTap; 8 | 9 | const WinButton({ 10 | Key? key, 11 | required this.name, 12 | required this.text, 13 | required this.onTap, 14 | }) : super(key: key); 15 | 16 | @override 17 | Widget build(BuildContext context) { 18 | double width = MediaQuery.of(context).size.width; 19 | double height = MediaQuery.of(context).size.height; 20 | final bool widthLarger = width > height; 21 | 22 | return Material( 23 | color: Colors.transparent, 24 | child: InkWell( 25 | onTap: onTap, 26 | child: Column( 27 | children: [ 28 | Container( 29 | clipBehavior: Clip.hardEdge, 30 | decoration: BoxDecoration( 31 | shape: BoxShape.circle, 32 | boxShadow: [ 33 | BoxShadow( 34 | color: const Color(0xff444542), 35 | blurRadius: height * 0.010, 36 | spreadRadius: 0, 37 | offset: const Offset(0, 0), 38 | ) 39 | ], 40 | ), 41 | child: SizedBox( 42 | height: widthLarger ? width * 0.04 : width * 0.1, 43 | width: widthLarger ? width * 0.04 : width * 0.1, 44 | child: SvgPicture.asset( 45 | 'assets/images/buttons/$name.svg', 46 | fit: BoxFit.cover, 47 | ), 48 | ), 49 | ), 50 | Material( 51 | color: Colors.transparent, 52 | child: Text( 53 | text, 54 | style: TextStyle( 55 | fontSize: height * 0.014, 56 | color: const Color(0xfffff0f5), 57 | fontWeight: FontWeight.w900, 58 | ), 59 | ), 60 | ), 61 | ], 62 | ), 63 | ), 64 | ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /lib/utils/router.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bloc/flutter_bloc.dart'; 3 | import 'package:way_for_ball/screens/puzzle/blocs/ball/ball_bloc.dart'; 4 | import 'package:way_for_ball/screens/puzzle/blocs/puzzle/puzzle_bloc.dart'; 5 | import 'package:way_for_ball/screens/puzzle/blocs/timer/timer_bloc.dart'; 6 | import 'package:way_for_ball/screens/puzzle/puzzle_screen.dart'; 7 | import 'package:way_for_ball/screens/start/bloc/bird_bloc.dart'; 8 | import 'package:way_for_ball/screens/start/start_screen.dart'; 9 | import 'package:way_for_ball/utils/screens.dart'; 10 | 11 | class AppRouter { 12 | Route generateRoute(RouteSettings settings) { 13 | switch (settings.name) { 14 | case '/': 15 | return MaterialPageRoute( 16 | builder: (context) => MultiBlocProvider( 17 | providers: [ 18 | BlocProvider( 19 | create: (context) => PuzzleBloc(), 20 | ), 21 | BlocProvider( 22 | create: (context) => BallBloc(), 23 | ), 24 | BlocProvider( 25 | create: (context) => BirdBloc(), 26 | ), 27 | ], 28 | child: const StartScreen(), 29 | ), 30 | settings: settings, 31 | ); 32 | case Screens.puzzle_screen: 33 | int? level = settings.arguments as int?; 34 | return MaterialPageRoute( 35 | builder: (context) => MultiBlocProvider( 36 | providers: [ 37 | BlocProvider( 38 | create: (context) => PuzzleBloc(), 39 | ), 40 | BlocProvider( 41 | create: (context) => BallBloc(), 42 | ), 43 | BlocProvider( 44 | create: (context) => TimerBloc(), 45 | ), 46 | ], 47 | child: PuzzleScreen(level: level), 48 | ), 49 | settings: settings, 50 | ); 51 | 52 | default: 53 | return MaterialPageRoute( 54 | builder: (context) => MultiBlocProvider( 55 | providers: [ 56 | BlocProvider( 57 | create: (context) => PuzzleBloc(), 58 | ), 59 | BlocProvider( 60 | create: (context) => BallBloc(), 61 | ), 62 | BlocProvider( 63 | create: (context) => BirdBloc(), 64 | ), 65 | ], 66 | child: const StartScreen(), 67 | ), 68 | settings: settings, 69 | ); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /lib/utils/screens.dart: -------------------------------------------------------------------------------- 1 | class Screens { 2 | static const String puzzle_screen = 'puzzle_screen'; 3 | } 4 | -------------------------------------------------------------------------------- /lib/utils/shared_prefs.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'package:shared_preferences/shared_preferences.dart'; 3 | 4 | class SharedPrefUtils { 5 | static const _APP_PREF = "APP_PREF"; 6 | static const _USER_PREF = "USER_PREF"; 7 | 8 | static const _PLAYER_LEVEL = "playerLevel"; 9 | static const _PLAYER_COMPLETED_LEVEL = "playerCompletedLevel"; 10 | static const _VOLUME = "volume"; 11 | 12 | static final SharedPrefUtils _instance = SharedPrefUtils._ctor(); 13 | 14 | factory SharedPrefUtils() { 15 | return _instance; 16 | } 17 | 18 | SharedPrefUtils._ctor(); 19 | 20 | static late SharedPreferences _prefs; 21 | 22 | static init() async { 23 | _prefs = await SharedPreferences.getInstance(); 24 | } 25 | 26 | // APP_DATA functions 27 | 28 | static setAppStringValue(String key, String value) { 29 | final String? storedData = 30 | _prefs.containsKey(_APP_PREF) ? _prefs.getString(_APP_PREF)! : null; 31 | Map newData = {key: value}; 32 | Map newDataMap = {}; 33 | 34 | if (storedData != null) { 35 | newDataMap.addAll(jsonDecode(storedData)); 36 | newDataMap.addAll(newData); 37 | } else { 38 | newDataMap = newData; 39 | } 40 | 41 | _prefs.setString(_APP_PREF, jsonEncode(newDataMap)); 42 | } 43 | 44 | static String getAppStringValue(String key) { 45 | Map allPrefs = 46 | jsonDecode(_prefs.getString(_APP_PREF) ?? ''); 47 | 48 | return allPrefs[key] ?? ""; 49 | } 50 | 51 | static Map getAllAppPrefs() { 52 | Map allPrefs = _prefs.containsKey(_APP_PREF) 53 | ? jsonDecode(_prefs.getString(_APP_PREF)!) 54 | : {}; 55 | return allPrefs; 56 | } 57 | 58 | // USER_DATA functions 59 | 60 | static setUserStringValue(String key, String value) { 61 | final String? storedData = 62 | _prefs.containsKey(_USER_PREF) ? _prefs.getString(_USER_PREF) : null; 63 | Map newData = {key: value}; 64 | Map newDataMap = {}; 65 | 66 | if (storedData != null) { 67 | newDataMap.addAll(jsonDecode(storedData)); 68 | newDataMap.addAll(newData); 69 | } else { 70 | newDataMap = newData; 71 | } 72 | 73 | _prefs.setString(_USER_PREF, jsonEncode(newDataMap)); 74 | } 75 | 76 | static String getUserStringValue(String key) { 77 | Map allPrefs = _prefs.getString(_USER_PREF) != null 78 | ? jsonDecode(_prefs.getString(_USER_PREF) ?? '') 79 | : {}; 80 | return allPrefs[key] ?? ''; 81 | } 82 | 83 | static Map getAllUserPrefs() { 84 | Map allPrefs = _prefs.containsKey(_USER_PREF) 85 | ? jsonDecode(_prefs.getString(_USER_PREF)!) 86 | : {}; 87 | return allPrefs; 88 | } 89 | 90 | static removeValue(String key) { 91 | return _prefs.remove(key); 92 | } 93 | 94 | static String get playerLevel => getUserStringValue(_PLAYER_LEVEL); 95 | static String get playerCompletedLevel => 96 | getUserStringValue(_PLAYER_COMPLETED_LEVEL); 97 | static String get volume => getUserStringValue(_VOLUME); 98 | 99 | static set playerLevel(String value) => 100 | setUserStringValue(_PLAYER_LEVEL, value); 101 | 102 | static set volume(String value) => setUserStringValue(_VOLUME, value); 103 | } 104 | 105 | enum PrefType { APP_PREF, USER_PREF } 106 | 107 | extension PrefExtension on PrefType { 108 | String get value { 109 | switch (this) { 110 | case PrefType.APP_PREF: 111 | return SharedPrefUtils._APP_PREF; 112 | case PrefType.USER_PREF: 113 | return SharedPrefUtils._USER_PREF; 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /lib/widgets/slide_animation.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; 3 | 4 | class SlidingAnimation extends StatelessWidget { 5 | final Widget child; 6 | final int index; 7 | const SlidingAnimation({ 8 | Key? key, 9 | required this.child, 10 | required this.index, 11 | }) : super(key: key); 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return AnimationConfiguration.staggeredList( 16 | position: index, 17 | duration: const Duration(milliseconds: 375), 18 | child: SlideAnimation( 19 | horizontalOffset: -50.0, 20 | child: FadeInAnimation( 21 | child: child, 22 | ), 23 | ), 24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/widgets/swipe_detector.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class SwipeDetector extends StatelessWidget { 4 | static const double minMainDisplacement = 25; 5 | static const double maxCrossRatio = 0.75; 6 | static const double minVelocity = 30; 7 | 8 | final Widget child; 9 | 10 | final VoidCallback? onSwipeUp; 11 | final VoidCallback? onSwipeDown; 12 | final VoidCallback? onSwipeLeft; 13 | final VoidCallback? onSwipeRight; 14 | 15 | const SwipeDetector({ 16 | Key? key, 17 | required this.child, 18 | this.onSwipeUp, 19 | this.onSwipeDown, 20 | this.onSwipeLeft, 21 | this.onSwipeRight, 22 | }) : super(key: key); 23 | 24 | @override 25 | Widget build(BuildContext context) { 26 | DragStartDetails? panStartDetails; 27 | DragUpdateDetails? panUpdateDetails; 28 | 29 | return GestureDetector( 30 | onTapDown: (_) => panUpdateDetails = 31 | null, // This prevents two fingers quick taps from being detected as a swipe 32 | behavior: HitTestBehavior 33 | .opaque, // This allows swipe above other clickable widgets 34 | child: child, 35 | onPanStart: (startDetails) => panStartDetails = startDetails, 36 | onPanUpdate: (updateDetails) => panUpdateDetails = updateDetails, 37 | onPanEnd: (endDetails) { 38 | if (panStartDetails == null || panUpdateDetails == null) return; 39 | 40 | double dx = panUpdateDetails!.globalPosition.dx - 41 | panStartDetails!.globalPosition.dx; 42 | double dy = panUpdateDetails!.globalPosition.dy - 43 | panStartDetails!.globalPosition.dy; 44 | 45 | int panDurationMiliseconds = 46 | panUpdateDetails!.sourceTimeStamp!.inMilliseconds - 47 | panStartDetails!.sourceTimeStamp!.inMilliseconds; 48 | 49 | double mainDis, crossDis, mainVel; 50 | bool isHorizontalMainAxis = dx.abs() > dy.abs(); 51 | 52 | if (isHorizontalMainAxis) { 53 | mainDis = dx.abs(); 54 | crossDis = dy.abs(); 55 | } else { 56 | mainDis = dy.abs(); 57 | crossDis = dx.abs(); 58 | } 59 | 60 | mainVel = 1000 * mainDis / panDurationMiliseconds; 61 | 62 | if (mainDis < minMainDisplacement) { 63 | debugPrint( 64 | "SWIPE DEBUG | Displacement too short. Real: $mainDis - Min: $minMainDisplacement"); 65 | return; 66 | } 67 | if (crossDis > maxCrossRatio * mainDis) { 68 | debugPrint( 69 | "SWIPE DEBUG | Cross axis displacemnt bigger than limit. Real: $crossDis - Limit: ${mainDis * maxCrossRatio}"); 70 | return; 71 | } 72 | if (mainVel < minVelocity) { 73 | debugPrint( 74 | "SWIPE DEBUG | Swipe velocity too slow. Real: $mainVel - Min: $minVelocity"); 75 | return; 76 | } 77 | 78 | // dy < 0 => UP -- dx > 0 => RIGHT 79 | if (isHorizontalMainAxis) { 80 | if (dx > 0) { 81 | onSwipeRight?.call(); 82 | } else { 83 | onSwipeLeft?.call(); 84 | } 85 | } else { 86 | if (dy < 0) { 87 | onSwipeUp?.call(); 88 | } else { 89 | onSwipeDown?.call(); 90 | } 91 | } 92 | }, 93 | ); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: way_for_ball 2 | description: A new Flutter project. 3 | publish_to: none 4 | version: 1.0.0+1 5 | 6 | environment: 7 | sdk: ">=2.15.0 <3.0.0" 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | bloc: ^8.0.2 13 | flutter_bloc: ^8.0.0 14 | url_launcher: ^6.0.17 15 | audioplayers: ^0.20.1 16 | gap: ^2.0.0 17 | flutter_svg: ^1.0.3 18 | shared_preferences: ^2.0.6 19 | lottie: ^1.2.1 20 | flutter_staggered_animations: ^1.0.0 21 | animated_text_kit: ^4.2.1 22 | flutter_staggered_grid_view: ^0.6.1 23 | url_strategy: ^0.2.0 24 | rive: ^0.8.4 25 | 26 | dev_dependencies: 27 | flutter_test: 28 | sdk: flutter 29 | flutter_lints: ^1.0.0 30 | 31 | flutter: 32 | uses-material-design: true 33 | assets: 34 | - assets/audio/ 35 | - assets/lottie/ 36 | - assets/rive/ 37 | - assets/images/ 38 | - assets/images/tiles/ 39 | - assets/images/buttons/ 40 | fonts: 41 | - family: Shizuru 42 | fonts: 43 | - asset: fonts/Shizuru/Shizuru-Regular.ttf 44 | - family: Cairo 45 | fonts: 46 | - asset: fonts/Cairo/Cairo-Regular.ttf 47 | -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:way_for_ball/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(const MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/web/favicon.png -------------------------------------------------------------------------------- /web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/web/icons/Icon-192.png -------------------------------------------------------------------------------- /web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/web/icons/Icon-512.png -------------------------------------------------------------------------------- /web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | Way For Ball 38 | 39 | 40 | 41 | 44 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /web/main-background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nehal076/flutter-puzzle-hack/a8be1fad8576007d05b5d14005ef7e8e32d1c910/web/main-background.png -------------------------------------------------------------------------------- /web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "way_for_ball", 3 | "short_name": "way_for_ball", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "icons/Icon-maskable-192.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/Icon-maskable-512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } 36 | --------------------------------------------------------------------------------