diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..7abac96 Binary files /dev/null and b/.DS_Store differ diff --git a/README.md b/README.md index 32e4825..58de294 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,70 @@ -# watermelon -Flutter版合成大西瓜 +

+ +

+

+合成大瓜 +

+

+ +

+ +# 简介 + +合成大瓜是使用[Flutter](https://flutter.dev/)+[Flame](https://flame-engine.org/)+[Forge2D](https://github.com/flame-engine/forge2d)开发的一个开源小游戏。 + +我在[微伞小游戏](http://www.wesane.com/)开发的[《合成大西瓜》](http://www.wesane.com/game/654/)的基础上将其移植到 Flutter 平台,并添加了以下新特性: + +- 支持自定义背景图 +- 支持重力感应操控 +- 支持修改图片素材 +- 支持反向合成小瓜 +- 支持只生成小/大瓜 +- 内置多套游戏主题(水果/表情/校徽) + +# 预览 + +| ![](screenshots/play.jpg) | ![](screenshots/win.jpg) | ![](screenshots/inner.jpg) | ![](screenshots/img.jpg) | +| :------------: | :------------: | :------------: | :------------: | + + +# 下载地址 + +网页版:http://v.idoo.top/mix + +安卓/iOS:https://www.pgyer.com/Dagua + +***PS:iOS版安装包需要自签才能使用*** + + +# 开源地址 + +本项目开源地址 https://github.com/idootop/fallDown , 欢迎Star/PR ^^ + +Web端生成 +```shell +flutter build web --release +``` + +Android端生成 +```shell +flutter build apk --split-per-abi +``` + +PS:亦可支持iOS,Mac,Windows,Linux端,请自行打包 + +# 免责声明 + +合成大瓜为免费开源软件,仅供学习交流,你可以非商业性地下载、安装、复制和散发本软件产品。 + +本游戏的创意玩法来自[《合成大西瓜》](http://www.wesane.com/game/654/),应用内的素材收集自互联网,部分图片、音频素材版权归[微伞小游戏](http://www.wesane.com/)所有,侵删。 + +# 鸣谢 + +Flutter https://flutter.dev/ + +Flame https://flame-engine.org/ + +Forge2D https://github.com/flame-engine/forge2d + +合成大西瓜 http://www.wesane.com/game/654/ + diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..108d105 --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1 @@ +include: package:pedantic/analysis_options.yaml diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..0a741cb --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,11 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 0000000..9f55989 --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,62 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 30 + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + applicationId "cat.love.mix" //bundle id + minSdkVersion 16 + targetSdkVersion 30 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro new file mode 100644 index 0000000..bccd023 --- /dev/null +++ b/android/app/proguard-rules.pro @@ -0,0 +1,7 @@ +#Flutter Wrapper +-keep class io.flutter.app.** { *; } +-keep class io.flutter.plugin.** { *; } +-keep class io.flutter.util.** { *; } +-keep class io.flutter.view.** { *; } +-keep class io.flutter.** { *; } +-keep class io.flutter.plugins.** { *; } diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..61e728a --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..635adf5 --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + diff --git a/android/app/src/main/kotlin/com/example/watermelon/MainActivity.kt b/android/app/src/main/kotlin/com/example/watermelon/MainActivity.kt new file mode 100644 index 0000000..ed51515 --- /dev/null +++ b/android/app/src/main/kotlin/com/example/watermelon/MainActivity.kt @@ -0,0 +1,6 @@ +package cat.love.mix + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..304732f --- /dev/null +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..1e4baa3 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..13f0678 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..b518014 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..2d898d9 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..3c992b0 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..449a9f9 --- /dev/null +++ b/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..d74aa35 --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..61e728a --- /dev/null +++ b/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..3100ad2 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,31 @@ +buildscript { + ext.kotlin_version = '1.3.50' + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.5.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..a673820 --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,4 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true +android.enableR8=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..296b146 --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000..44e62bc --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1,11 @@ +include ':app' + +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() + +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/android/watermelon_android.iml b/android/watermelon_android.iml new file mode 100644 index 0000000..1899969 --- /dev/null +++ b/android/watermelon_android.iml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/.DS_Store b/assets/.DS_Store new file mode 100644 index 0000000..feabc32 Binary files /dev/null and b/assets/.DS_Store differ diff --git a/assets/audio/boom.mp3 b/assets/audio/boom.mp3 new file mode 100644 index 0000000..1d92ba7 Binary files /dev/null and b/assets/audio/boom.mp3 differ diff --git a/assets/audio/boom1.mp3 b/assets/audio/boom1.mp3 new file mode 100644 index 0000000..113cce0 Binary files /dev/null and b/assets/audio/boom1.mp3 differ diff --git a/assets/audio/boom2.mp3 b/assets/audio/boom2.mp3 new file mode 100644 index 0000000..021b357 Binary files /dev/null and b/assets/audio/boom2.mp3 differ diff --git a/assets/audio/cheer.mp3 b/assets/audio/cheer.mp3 new file mode 100644 index 0000000..9e98cd9 Binary files /dev/null and b/assets/audio/cheer.mp3 differ diff --git a/assets/audio/coin.wav b/assets/audio/coin.wav new file mode 100644 index 0000000..689ad63 Binary files /dev/null and b/assets/audio/coin.wav differ diff --git a/assets/audio/fall.mp3 b/assets/audio/fall.mp3 new file mode 100644 index 0000000..d3c44bc Binary files /dev/null and b/assets/audio/fall.mp3 differ diff --git a/assets/audio/mix.wav b/assets/audio/mix.wav new file mode 100644 index 0000000..ab30f2f Binary files /dev/null and b/assets/audio/mix.wav differ diff --git a/assets/images/.DS_Store b/assets/images/.DS_Store new file mode 100644 index 0000000..e6f579c Binary files /dev/null and b/assets/images/.DS_Store differ diff --git a/assets/images/985/1.png b/assets/images/985/1.png new file mode 100644 index 0000000..6695969 Binary files /dev/null and b/assets/images/985/1.png differ diff --git a/assets/images/985/10.png b/assets/images/985/10.png new file mode 100644 index 0000000..562d0e3 Binary files /dev/null and b/assets/images/985/10.png differ diff --git a/assets/images/985/11.png b/assets/images/985/11.png new file mode 100644 index 0000000..ee04d4e Binary files /dev/null and b/assets/images/985/11.png differ diff --git a/assets/images/985/2.png b/assets/images/985/2.png new file mode 100644 index 0000000..59ab6a4 Binary files /dev/null and b/assets/images/985/2.png differ diff --git a/assets/images/985/3.png b/assets/images/985/3.png new file mode 100644 index 0000000..6946d3b Binary files /dev/null and b/assets/images/985/3.png differ diff --git a/assets/images/985/4.png b/assets/images/985/4.png new file mode 100644 index 0000000..e032409 Binary files /dev/null and b/assets/images/985/4.png differ diff --git a/assets/images/985/5.png b/assets/images/985/5.png new file mode 100644 index 0000000..28ef61d Binary files /dev/null and b/assets/images/985/5.png differ diff --git a/assets/images/985/6.png b/assets/images/985/6.png new file mode 100644 index 0000000..f086ff3 Binary files /dev/null and b/assets/images/985/6.png differ diff --git a/assets/images/985/7.png b/assets/images/985/7.png new file mode 100644 index 0000000..e26e792 Binary files /dev/null and b/assets/images/985/7.png differ diff --git a/assets/images/985/8.png b/assets/images/985/8.png new file mode 100644 index 0000000..b731ac3 Binary files /dev/null and b/assets/images/985/8.png differ diff --git a/assets/images/985/9.png b/assets/images/985/9.png new file mode 100644 index 0000000..315e637 Binary files /dev/null and b/assets/images/985/9.png differ diff --git a/assets/images/bg.png b/assets/images/bg.png new file mode 100644 index 0000000..6b9b12f Binary files /dev/null and b/assets/images/bg.png differ diff --git a/assets/images/dead_line.png b/assets/images/dead_line.png new file mode 100644 index 0000000..ebf5ddb Binary files /dev/null and b/assets/images/dead_line.png differ diff --git a/assets/images/flame.png b/assets/images/flame.png new file mode 100644 index 0000000..5addaf6 Binary files /dev/null and b/assets/images/flame.png differ diff --git a/assets/images/friuts/1.png b/assets/images/friuts/1.png new file mode 100644 index 0000000..815692f Binary files /dev/null and b/assets/images/friuts/1.png differ diff --git a/assets/images/friuts/10.png b/assets/images/friuts/10.png new file mode 100644 index 0000000..935d711 Binary files /dev/null and b/assets/images/friuts/10.png differ diff --git a/assets/images/friuts/11.png b/assets/images/friuts/11.png new file mode 100644 index 0000000..7596c1d Binary files /dev/null and b/assets/images/friuts/11.png differ diff --git a/assets/images/friuts/2.png b/assets/images/friuts/2.png new file mode 100644 index 0000000..2e1d78d Binary files /dev/null and b/assets/images/friuts/2.png differ diff --git a/assets/images/friuts/3.png b/assets/images/friuts/3.png new file mode 100644 index 0000000..42460a6 Binary files /dev/null and b/assets/images/friuts/3.png differ diff --git a/assets/images/friuts/4.png b/assets/images/friuts/4.png new file mode 100644 index 0000000..3a4536a Binary files /dev/null and b/assets/images/friuts/4.png differ diff --git a/assets/images/friuts/5.png b/assets/images/friuts/5.png new file mode 100644 index 0000000..286f0de Binary files /dev/null and b/assets/images/friuts/5.png differ diff --git a/assets/images/friuts/6.png b/assets/images/friuts/6.png new file mode 100644 index 0000000..357f310 Binary files /dev/null and b/assets/images/friuts/6.png differ diff --git a/assets/images/friuts/7.png b/assets/images/friuts/7.png new file mode 100644 index 0000000..a67f47b Binary files /dev/null and b/assets/images/friuts/7.png differ diff --git a/assets/images/friuts/8.png b/assets/images/friuts/8.png new file mode 100644 index 0000000..5ccc376 Binary files /dev/null and b/assets/images/friuts/8.png differ diff --git a/assets/images/friuts/9.png b/assets/images/friuts/9.png new file mode 100644 index 0000000..83c7582 Binary files /dev/null and b/assets/images/friuts/9.png differ diff --git a/assets/images/qq/1.png b/assets/images/qq/1.png new file mode 100644 index 0000000..1c12215 Binary files /dev/null and b/assets/images/qq/1.png differ diff --git a/assets/images/qq/10.png b/assets/images/qq/10.png new file mode 100644 index 0000000..ed9c3c8 Binary files /dev/null and b/assets/images/qq/10.png differ diff --git a/assets/images/qq/11.png b/assets/images/qq/11.png new file mode 100644 index 0000000..d9ea507 Binary files /dev/null and b/assets/images/qq/11.png differ diff --git a/assets/images/qq/2.png b/assets/images/qq/2.png new file mode 100644 index 0000000..efaee49 Binary files /dev/null and b/assets/images/qq/2.png differ diff --git a/assets/images/qq/3.png b/assets/images/qq/3.png new file mode 100644 index 0000000..4b1e5be Binary files /dev/null and b/assets/images/qq/3.png differ diff --git a/assets/images/qq/4.png b/assets/images/qq/4.png new file mode 100644 index 0000000..7a56fe0 Binary files /dev/null and b/assets/images/qq/4.png differ diff --git a/assets/images/qq/5.png b/assets/images/qq/5.png new file mode 100644 index 0000000..30d8074 Binary files /dev/null and b/assets/images/qq/5.png differ diff --git a/assets/images/qq/6.png b/assets/images/qq/6.png new file mode 100644 index 0000000..ef5f9dc Binary files /dev/null and b/assets/images/qq/6.png differ diff --git a/assets/images/qq/7.png b/assets/images/qq/7.png new file mode 100644 index 0000000..167c686 Binary files /dev/null and b/assets/images/qq/7.png differ diff --git a/assets/images/qq/8.png b/assets/images/qq/8.png new file mode 100644 index 0000000..62b9e76 Binary files /dev/null and b/assets/images/qq/8.png differ diff --git a/assets/images/qq/9.png b/assets/images/qq/9.png new file mode 100644 index 0000000..1b3060c Binary files /dev/null and b/assets/images/qq/9.png differ diff --git a/assets/images/qr.jpg b/assets/images/qr.jpg new file mode 100644 index 0000000..87c3170 Binary files /dev/null and b/assets/images/qr.jpg differ diff --git a/assets/images/setting.png b/assets/images/setting.png new file mode 100644 index 0000000..ddc4462 Binary files /dev/null and b/assets/images/setting.png differ diff --git a/assets/images/shandong/1.png b/assets/images/shandong/1.png new file mode 100644 index 0000000..0ce71da Binary files /dev/null and b/assets/images/shandong/1.png differ diff --git a/assets/images/shandong/10.png b/assets/images/shandong/10.png new file mode 100644 index 0000000..6946d3b Binary files /dev/null and b/assets/images/shandong/10.png differ diff --git a/assets/images/shandong/11.png b/assets/images/shandong/11.png new file mode 100644 index 0000000..f51c28e Binary files /dev/null and b/assets/images/shandong/11.png differ diff --git a/assets/images/shandong/2.png b/assets/images/shandong/2.png new file mode 100644 index 0000000..469bc0e Binary files /dev/null and b/assets/images/shandong/2.png differ diff --git a/assets/images/shandong/3.png b/assets/images/shandong/3.png new file mode 100644 index 0000000..bac0885 Binary files /dev/null and b/assets/images/shandong/3.png differ diff --git a/assets/images/shandong/4.png b/assets/images/shandong/4.png new file mode 100644 index 0000000..9bbb334 Binary files /dev/null and b/assets/images/shandong/4.png differ diff --git a/assets/images/shandong/5.png b/assets/images/shandong/5.png new file mode 100644 index 0000000..4f37185 Binary files /dev/null and b/assets/images/shandong/5.png differ diff --git a/assets/images/shandong/6.png b/assets/images/shandong/6.png new file mode 100644 index 0000000..91b1fb5 Binary files /dev/null and b/assets/images/shandong/6.png differ diff --git a/assets/images/shandong/7.png b/assets/images/shandong/7.png new file mode 100644 index 0000000..ff9112f Binary files /dev/null and b/assets/images/shandong/7.png differ diff --git a/assets/images/shandong/8.png b/assets/images/shandong/8.png new file mode 100644 index 0000000..8515027 Binary files /dev/null and b/assets/images/shandong/8.png differ diff --git a/assets/images/shandong/9.png b/assets/images/shandong/9.png new file mode 100644 index 0000000..6695969 Binary files /dev/null and b/assets/images/shandong/9.png differ diff --git a/assets/images/shine.png b/assets/images/shine.png new file mode 100644 index 0000000..1e63792 Binary files /dev/null and b/assets/images/shine.png differ diff --git a/flutter-plugins b/flutter-plugins new file mode 100644 index 0000000..9d0adaf --- /dev/null +++ b/flutter-plugins @@ -0,0 +1,17 @@ +# This is a generated file; do not edit or check into version control. +audioplayers=/Users/mac/dev/flutter/.pub-cache/hosted/pub.flutter-io.cn/audioplayers-0.15.1/ +flutter_plugin_android_lifecycle=/Users/mac/dev/flutter/.pub-cache/hosted/pub.flutter-io.cn/flutter_plugin_android_lifecycle-1.0.11/ +image_picker=/Users/mac/dev/flutter/.pub-cache/hosted/pub.flutter-io.cn/image_picker-0.6.7+22/ +image_picker_web_redux=/Users/mac/dev/flutter/.pub-cache/hosted/pub.flutter-io.cn/image_picker_web_redux-1.1.3/ +path_provider=/Users/mac/dev/flutter/.pub-cache/hosted/pub.flutter-io.cn/path_provider-1.6.27/ +path_provider_linux=/Users/mac/dev/flutter/.pub-cache/hosted/pub.flutter-io.cn/path_provider_linux-0.0.1+2/ +path_provider_macos=/Users/mac/dev/flutter/.pub-cache/hosted/pub.flutter-io.cn/path_provider_macos-0.0.4+8/ +path_provider_windows=/Users/mac/dev/flutter/.pub-cache/hosted/pub.flutter-io.cn/path_provider_windows-0.0.4+3/ +sensors=/Users/mac/dev/flutter/.pub-cache/hosted/pub.flutter-io.cn/sensors-0.4.2+6/ +share_plus=/Users/mac/dev/flutter/.pub-cache/hosted/pub.flutter-io.cn/share_plus-1.2.0/ +share_plus_web=/Users/mac/dev/flutter/.pub-cache/hosted/pub.flutter-io.cn/share_plus_web-0.1.0/ +url_launcher=/Users/mac/dev/flutter/.pub-cache/hosted/pub.flutter-io.cn/url_launcher-5.7.10/ +url_launcher_linux=/Users/mac/dev/flutter/.pub-cache/hosted/pub.flutter-io.cn/url_launcher_linux-0.0.1+4/ +url_launcher_macos=/Users/mac/dev/flutter/.pub-cache/hosted/pub.flutter-io.cn/url_launcher_macos-0.0.1+9/ +url_launcher_web=/Users/mac/dev/flutter/.pub-cache/hosted/pub.flutter-io.cn/url_launcher_web-0.1.5+3/ +url_launcher_windows=/Users/mac/dev/flutter/.pub-cache/hosted/pub.flutter-io.cn/url_launcher_windows-0.0.1+3/ diff --git a/ios/.DS_Store b/ios/.DS_Store new file mode 100644 index 0000000..3d110d8 Binary files /dev/null and b/ios/.DS_Store differ diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 0000000..e96ef60 --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,32 @@ +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..9367d48 --- /dev/null +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 8.0 + + diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..ec97fc6 --- /dev/null +++ b/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..c4855bf --- /dev/null +++ b/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000..1e8c3c9 --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,41 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '9.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 0000000..9457a75 --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,52 @@ +PODS: + - audioplayers (0.0.1): + - Flutter + - Flutter (1.0.0) + - image_picker (0.0.1): + - Flutter + - path_provider (0.0.1): + - Flutter + - sensors (0.0.1): + - Flutter + - share_plus (0.0.1): + - Flutter + - url_launcher (0.0.1): + - Flutter + +DEPENDENCIES: + - audioplayers (from `.symlinks/plugins/audioplayers/ios`) + - Flutter (from `Flutter`) + - image_picker (from `.symlinks/plugins/image_picker/ios`) + - path_provider (from `.symlinks/plugins/path_provider/ios`) + - sensors (from `.symlinks/plugins/sensors/ios`) + - share_plus (from `.symlinks/plugins/share_plus/ios`) + - url_launcher (from `.symlinks/plugins/url_launcher/ios`) + +EXTERNAL SOURCES: + audioplayers: + :path: ".symlinks/plugins/audioplayers/ios" + Flutter: + :path: Flutter + image_picker: + :path: ".symlinks/plugins/image_picker/ios" + path_provider: + :path: ".symlinks/plugins/path_provider/ios" + sensors: + :path: ".symlinks/plugins/sensors/ios" + share_plus: + :path: ".symlinks/plugins/share_plus/ios" + url_launcher: + :path: ".symlinks/plugins/url_launcher/ios" + +SPEC CHECKSUMS: + audioplayers: 84f968cea3f2deab00ec4f8ff53358b3c0b3992c + Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c + image_picker: 9c3312491f862b28d21ecd8fdf0ee14e601b3f09 + path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c + sensors: 84eb7a30e47a649e4172b71d6e81be614c280336 + share_plus: 2e6276f752c279a84cd68a9fc27dfbbe2a74b072 + url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef + +PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c + +COCOAPODS: 1.10.0 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..8ea1e18 --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,552 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 39928EF87EEC96441C45FB36 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 97CD8957ACF6D84A33D0686E /* Pods_Runner.framework */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 371C7ABE4B087857C42CE523 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 3ABB1A893CE0E8F52499AAB4 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 97CD8957ACF6D84A33D0686E /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E881A444DB36FD6DC5D6022F /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 39928EF87EEC96441C45FB36 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 3A6AC336FE1C0C01491FEBA6 /* Pods */ = { + isa = PBXGroup; + children = ( + E881A444DB36FD6DC5D6022F /* Pods-Runner.debug.xcconfig */, + 3ABB1A893CE0E8F52499AAB4 /* Pods-Runner.release.xcconfig */, + 371C7ABE4B087857C42CE523 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 3A6AC336FE1C0C01491FEBA6 /* Pods */, + EACBDF03A9879D151B32ED04 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + EACBDF03A9879D151B32ED04 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 97CD8957ACF6D84A33D0686E /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 09CCBA136446196EE1823583 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + E4271C201D82597302548AE1 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 09CCBA136446196EE1823583 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + E4271C201D82597302548AE1 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 57Y9Q45MLS; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = cat.love.mix; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 57Y9Q45MLS; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = cat.love.mix; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 57Y9Q45MLS; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = cat.love.mix; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..a28140c --- /dev/null +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..21a3cc1 --- /dev/null +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..70693e4 --- /dev/null +++ b/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d36b1fa --- /dev/null +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000..4e8d387 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000..d37a438 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000..a7457b1 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000..3e27ff9 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000..af8c383 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000..26a8866 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000..14864f5 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000..a7457b1 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000..426e232 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000..21e142c Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000..21e142c Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000..bffba12 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000..2e9db66 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000..4469b67 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000..c8825c3 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 0000000..0bedcf2 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000..89c2725 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +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. \ No newline at end of file diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..f2e259c --- /dev/null +++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f3c2851 --- /dev/null +++ b/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist new file mode 100644 index 0000000..2e43292 --- /dev/null +++ b/ios/Runner/Info.plist @@ -0,0 +1,52 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + watermelon + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + CFBundleDisplayName + 合成大瓜 + NSPhotoLibraryUsageDescription + 用于选择本地图片 + + + diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..308a2a5 --- /dev/null +++ b/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/lib/.DS_Store b/lib/.DS_Store new file mode 100644 index 0000000..5083e72 Binary files /dev/null and b/lib/.DS_Store differ diff --git a/lib/components/background.dart b/lib/components/background.dart new file mode 100644 index 0000000..480dca7 --- /dev/null +++ b/lib/components/background.dart @@ -0,0 +1,17 @@ +import 'package:flame/components.dart'; +import 'package:flame_forge2d/viewport.dart'; + +import '../game/level/levels.dart'; +import '../tools/image/image_tool.dart'; + +class Background extends SpriteComponent { + Background.create(Viewport viewport) { + resize(viewport); + sprite = Sprite(ImageTool.image(Levels.background)); + } + + void resize(Viewport viewport) { + width = viewport.size.x; + height = viewport.size.y; + } +} diff --git a/lib/components/ball.dart b/lib/components/ball.dart new file mode 100644 index 0000000..65b1970 --- /dev/null +++ b/lib/components/ball.dart @@ -0,0 +1,112 @@ +import 'package:flame/components.dart'; +import 'package:flame_forge2d/sprite_body_component.dart'; +import 'package:flame_forge2d/viewport.dart'; +import 'package:flutter/foundation.dart'; +import 'package:forge2d/forge2d.dart'; + +import '../game/level/levels.dart'; + +class Ball extends SpriteBodyComponent { + ///下落位置 + Vector2 fallPosition; + + ///是否下落 + bool isFalling; + + ///等级 + int level; + + ///半径 + double _radius; + + ///是否落地 + bool landed = false; + + ///level up + bool levelUp = false; + + ///是否remove + bool removed = false; + + ///是否开始移动 + bool moving = true; + + ///是否弹动 + bool bouncing = false; + + Vector2 get position => + viewport.getWorldToScreen(body?.position ?? Vector2.zero()); + + double get radius => _radius * viewport.scale; + + static Ball create( + Viewport viewport, { + @required Vector2 position, + @required int level, + bool moving, + bool canFall, + bool landed, + bool bounce, + }) { + position ??= Vector2.zero(); + level ??= 1; + canFall ??= false; + landed ??= false; + moving ??= true; + bounce ??= false; + return Ball( + level: level, + position: position, + canFall: canFall, + landed: landed, + moving: moving, + bounce: bounce, + sprite: Levels.sprite(level), + radius: Levels.radius(level) * (viewport.size.x / viewport.scale / 100), + ); + } + + Ball({ + @required Vector2 position, + @required Sprite sprite, + @required double radius, + @required this.level, + this.landed, + this.moving, + bool canFall, + bool bounce, + }) : super( + sprite, + bounce ? Vector2.zero() : Vector2(radius * 2, radius * 2), + ) { + fallPosition = position; + isFalling = canFall; + bouncing = bounce; + _radius = radius; + } + + ///物理实体 + @override + Body createBody() { + final shape = CircleShape()..radius = size.x / 2; + var position = fallPosition.clone(); + if (!isFalling) { + position.x = viewport.center.x; + } + var worldPosition = viewport.getScreenToWorld(position); + + final fixtureDef = FixtureDef() + ..shape = shape + ..restitution = 0.1 //弹性 + ..density = 0.1 //密度 + ..friction = 0.1; //摩擦力 + + final bodyDef = BodyDef() + ..userData = this //开启检测碰撞 + ..angularDamping = 0.1 //角速度阻尼 + ..position = worldPosition + ..type = isFalling ? BodyType.DYNAMIC : BodyType.KINEMATIC; + + return world.createBody(bodyDef)..createFixture(fixtureDef); + } +} diff --git a/lib/components/boundaries.dart b/lib/components/boundaries.dart new file mode 100644 index 0000000..aa1ea70 --- /dev/null +++ b/lib/components/boundaries.dart @@ -0,0 +1,44 @@ +import 'package:flame_forge2d/body_component.dart'; +import 'package:flame_forge2d/viewport.dart'; +import 'package:forge2d/forge2d.dart'; + +List createBoundaries(Viewport viewport) { + final screenSize = Vector2(viewport.size.x, viewport.size.y) / viewport.scale; + final topRight = (screenSize / 2); + final bottomLeft = topRight * -1; + final topLeft = Vector2(bottomLeft.x, topRight.y); + final bottomRight = topLeft * -1; + + return [ + Wall(topLeft, topRight, 1), + Wall(topRight, bottomRight, 2), + Wall(bottomRight, bottomLeft, 3), + Wall(bottomLeft, topLeft, 4), + ]; +} + +class Wall extends BodyComponent { + final Vector2 start; + final Vector2 end; + final int side; + + Wall(this.start, this.end, this.side); + + @override + Body createBody() { + final shape = PolygonShape(); + shape.setAsEdge(start, end); + + final fixtureDef = FixtureDef() + ..shape = shape + ..restitution = 0.0 + ..friction = 0.1; + + final bodyDef = BodyDef() + ..userData = this //检测碰撞 + ..position = Vector2.zero() + ..type = BodyType.STATIC; + + return world.createBody(bodyDef)..createFixture(fixtureDef); + } +} diff --git a/lib/components/dead_line.dart b/lib/components/dead_line.dart new file mode 100644 index 0000000..02f528b --- /dev/null +++ b/lib/components/dead_line.dart @@ -0,0 +1,40 @@ +import 'package:flame/components.dart'; +import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flame_forge2d/viewport.dart'; + +import '../tools/image/image_tool.dart'; +import '../tools/size_tool.dart'; + +class DeadLine extends SpriteComponent { + ///deadline距屏幕顶部距离,单位:vw + static double marginTop = 36; + + ///触发deadline显示,ball距屏幕顶部距离,单位:vw + static double showTop = marginTop + 44; + + ///是否显示 + static bool show = false; + + @override + Vector2 position; + + static DeadLine create(Viewport viewport) { + final sprite = Sprite(ImageTool.image('dead_line.png')); + return DeadLine( + sprite: sprite, + size: Vector2( + viewport.size.x, + viewport.vw(1), + ), + position: Vector2(0, viewport.vw(marginTop))); + } + + DeadLine({Sprite sprite, Vector2 size, this.position}) + : super.fromSprite(size, sprite); + + @override + void render(canvas) { + if (!show) return; + super.render(canvas); + } +} diff --git a/lib/components/scores.dart b/lib/components/scores.dart new file mode 100644 index 0000000..94bd361 --- /dev/null +++ b/lib/components/scores.dart @@ -0,0 +1,33 @@ +import 'package:flame/components.dart'; +import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flame_forge2d/viewport.dart'; +import 'package:flutter/material.dart' hide Viewport; + +import '../tools/size_tool.dart'; + +class Scores extends TextComponent { + static double margin = 5; + + @override + Vector2 position; + + static Scores create( + Viewport viewport, { + String text, + Color color, + double size, + }) { + color ??= Colors.orange; + size ??= viewport.vw(10); + return Scores( + text: text, + config: TextConfig(color: color, fontSize: size), + position: Vector2(viewport.vw(margin), viewport.vw(margin))); + } + + Scores({ + String text, + TextConfig config, + this.position, + }) : super(text, config: config); +} diff --git a/lib/components/setting_button.dart b/lib/components/setting_button.dart new file mode 100644 index 0000000..853831c --- /dev/null +++ b/lib/components/setting_button.dart @@ -0,0 +1,35 @@ +import 'package:flame/components.dart'; +import 'package:flame_forge2d/flame_forge2d.dart'; +import 'package:flame_forge2d/viewport.dart'; +import 'package:flutter/material.dart' hide Viewport; + +import '../game/game_life.dart'; +import '../tools/image/image_tool.dart'; +import '../tools/size_tool.dart'; + +class SettingButton extends SpriteComponent with Tapable, HasGameRef { + static double margin = 5; + + @override + Vector2 position; + + @override + bool onTapDown(TapDownDetails details) { + GameLife(gameRef).setting(); + return true; + } + + static SettingButton create(Viewport viewport) { + final sprite = Sprite(ImageTool.image('setting.png')); + return SettingButton( + sprite: sprite, + size: Vector2( + viewport.vw(10), + viewport.vw(10), + ), + position: Vector2(viewport.vw(100 - margin - 10), viewport.vw(margin))); + } + + SettingButton({Sprite sprite, Vector2 size, this.position}) + : super.fromSprite(size, sprite); +} diff --git a/lib/contacts/ball_ball_contact.dart b/lib/contacts/ball_ball_contact.dart new file mode 100644 index 0000000..cedfe16 --- /dev/null +++ b/lib/contacts/ball_ball_contact.dart @@ -0,0 +1,26 @@ +import 'package:flame_forge2d/contact_callbacks.dart'; +import 'package:flame_forge2d/flame_forge2d.dart'; + +import '../components/ball.dart'; +import '../game/game_state.dart'; + +class BallBallContactCallback extends ContactCallback { + @override + void begin(Ball ball1, Ball ball2, Contact contact) { + if (GameState.gameStatus != GameStatus.start) return; + ball1.landed = true; + ball2.landed = true; + if (ball1.level == ball2.level) { + if (ball1.position.y < ball2.position.y) { + ball1.removed = true; + ball2.levelUp = true; + } else { + ball2.removed = true; + ball1.levelUp = true; + } + } + } + + @override + void end(Ball ball1, Ball ball2, Contact contact) {} +} diff --git a/lib/contacts/ball_wall_contact.dart b/lib/contacts/ball_wall_contact.dart new file mode 100644 index 0000000..a1f148a --- /dev/null +++ b/lib/contacts/ball_wall_contact.dart @@ -0,0 +1,22 @@ +import 'package:flame_forge2d/contact_callbacks.dart'; +import 'package:flame_forge2d/flame_forge2d.dart'; + +import '../components/ball.dart'; +import '../components/boundaries.dart'; +import '../game/game_state.dart'; +import '../tools/audio_tool.dart'; + +class BallWallContactCallback extends ContactCallback { + @override + void begin(Ball ball, Wall wall, Contact contact) { + if (GameState.gameStatus != GameStatus.start) return; + if (wall.side != 3) return; //非底边 + if (!ball.landed) { + AudioTool.fall(); + } + ball.landed = true; + } + + @override + void end(Ball ball, Wall wall, Contact contact) {} +} diff --git a/lib/controllers/generate_ball.dart b/lib/controllers/generate_ball.dart new file mode 100644 index 0000000..5473130 --- /dev/null +++ b/lib/controllers/generate_ball.dart @@ -0,0 +1,40 @@ +import 'package:flame/components.dart'; + +import '../components/ball.dart'; +import '../game/game_state.dart'; +import '../game/level/levels.dart'; +import '../game/my_game.dart'; +import '../tools/size_tool.dart'; + +class GenerateBall { + MyGame gameRef; + GenerateBall(this.gameRef); + + bool get canGenerateBall => gameRef.components + .where((e) => e is Ball && e.moving && !e.landed) + .isEmpty; + + ///生成新球 + Future generateBall([double x = 0]) async { + if (gameRef.hide) return; + if (!canGenerateBall) return; + if (GameState.gameStatus != GameStatus.start) return; + if (GameState.lastBall != null) { + GameState.lastBall.fallPosition.x = x; + GameState.lastBall.moving = true; + } + final level = await Levels.generateLevel(); + final position = Vector2(x, gameRef.viewport.vw(Levels.radius(level) + 5)); + final ball = Ball.create( + gameRef.viewport, + position: position, + level: level, + moving: false, + bounce: true, + ); + Future.delayed(Duration(milliseconds: 600), () { + gameRef.add(ball); + }); + GameState.lastBall = ball; + } +} diff --git a/lib/controllers/update_balls_bounce.dart b/lib/controllers/update_balls_bounce.dart new file mode 100644 index 0000000..3434da2 --- /dev/null +++ b/lib/controllers/update_balls_bounce.dart @@ -0,0 +1,32 @@ +import 'package:flame/components.dart'; + +import '../components/ball.dart'; +import '../game/my_game.dart'; + +class UpdateBallsBounce extends Component with HasGameRef { + @override + void update(double dt) { + if (gameRef.hide) return; + // if (GameState.gameStatus != GameStatus.start) return; + gameRef.components.where((e) => e is Ball && e.bouncing).forEach((ball) { + Ball b = ball; + final realSize = b.radius * 2 / gameRef.viewport.scale; + if (b.size.x < realSize) { + var size = b.size.x + dt * 10 * realSize; + size = size.clamp(b.size.x, realSize); + b.size = Vector2(size, size); + } else { + b.bouncing = false; + if (!b.isFalling) return; + gameRef.remove(ball); + gameRef.add(Ball.create( + gameRef.viewport, + position: b.position, + level: b.level, + canFall: true, + landed: true, + )); + } + }); + } +} diff --git a/lib/controllers/update_balls_falling.dart b/lib/controllers/update_balls_falling.dart new file mode 100644 index 0000000..48c7ce6 --- /dev/null +++ b/lib/controllers/update_balls_falling.dart @@ -0,0 +1,37 @@ +import 'package:flame/components.dart'; + +import '../components/ball.dart'; +import '../game/game_state.dart'; +import '../game/my_game.dart'; +import '../tools/size_tool.dart'; + +class UpdateBallsFalling extends Component with HasGameRef { + @override + void update(double t) { + if (gameRef.hide) return; + if (GameState.gameStatus != GameStatus.start) return; + gameRef.components + .where((e) => e is Ball && e.isFalling == false) + .forEach((ball) { + Ball b = ball; + if (!b.moving) return; + final p = b.position; + final fp = b.fallPosition; + final width = gameRef.viewport.vw(100); + final left = fp.x < gameRef.viewport.center.x; + final center = + (fp.x - gameRef.viewport.center.x).abs() < gameRef.viewport.vw(5); + if (!center && b.body.linearVelocity.x == 0) { + b.body.linearVelocity = + Vector2((left ? -1 : 1) * gameRef.viewport.size.velocitySize, 0); + } + if (center || + (left && (p.x < b.radius || p.x < fp.x)) || + (!left && (width - p.x < b.radius || p.x > fp.x))) { + gameRef.remove(ball); + gameRef.add(Ball.create(gameRef.viewport, + position: p, level: b.level, canFall: true)); + } + }); + } +} diff --git a/lib/controllers/update_dead_line.dart b/lib/controllers/update_dead_line.dart new file mode 100644 index 0000000..91bd01a --- /dev/null +++ b/lib/controllers/update_dead_line.dart @@ -0,0 +1,31 @@ +import 'package:flame/components.dart'; + +import '../components/ball.dart'; +import '../components/dead_line.dart'; +import '../game/game_life.dart'; +import '../game/game_state.dart'; +import '../game/my_game.dart'; +import '../tools/size_tool.dart'; + +class UpdateDeadLine extends Component with HasGameRef { + @override + void update(double t) { + if (gameRef.hide) return; + if (GameState.gameStatus != GameStatus.start) return; + final almostDeads = gameRef.components.where((e) => + e is Ball && + e.landed && + e.position.y < gameRef.viewport.vw(DeadLine.showTop)); + if (almostDeads.isNotEmpty) { + DeadLine.show = true; + } else { + DeadLine.show = false; + } + if (gameRef.components.any((e) => + e is Ball && + e.landed && + e.position.y < gameRef.viewport.vw(DeadLine.marginTop))) { + GameLife(gameRef).dead(); + } + } +} diff --git a/lib/controllers/update_gravity.dart b/lib/controllers/update_gravity.dart new file mode 100644 index 0000000..a5a87fa --- /dev/null +++ b/lib/controllers/update_gravity.dart @@ -0,0 +1,36 @@ +import 'package:flame/components.dart'; + +import '../game/game_state.dart'; +import '../game/my_game.dart'; +import '../tools/sensor_tool.dart'; +import '../tools/size_tool.dart'; + +class UpdateGravity extends Component with HasGameRef { + void changeGravity(Vector2 gravity) => gameRef.world.setGravity(gravity); + + double get p { + final x = SensorTool.xyz.x; + if (x.abs() > 1) { + return -2 * (x / 10); + } + return 0; //middle + } + + @override + void update(double t) { + if (gameRef.hide) return; + // if (GameState.gameStatus != GameStatus.start) return; + final size = gameRef.size.gravitySize; + final gravity = Vector2(0, -1 * size); + if (GameState.gameSetting.gravity) { + final size = gameRef.size.gravitySize; + final offset = Vector2(size, 0) * p; + final newGravity = Vector2(0, -1 * size) + offset; + changeGravity(newGravity); + } else { + if (gameRef.world.getGravity() != gravity) { + changeGravity(gravity); + } + } + } +} diff --git a/lib/controllers/update_level_up.dart b/lib/controllers/update_level_up.dart new file mode 100644 index 0000000..d0cc496 --- /dev/null +++ b/lib/controllers/update_level_up.dart @@ -0,0 +1,40 @@ +import 'package:flame/components.dart'; + +import '../components/ball.dart'; +import '../game/game_life.dart'; +import '../game/game_state.dart'; +import '../game/level/levels.dart'; +import '../game/my_game.dart'; +import '../particles/bloom_particle.dart'; +import '../tools/audio_tool.dart'; + +class UpdateLevelUp extends Component with HasGameRef { + @override + void update(double t) { + if (gameRef.hide) return; + if (GameState.gameStatus != GameStatus.start) return; + gameRef.components + .where((e) => e is Ball && e.removed) + .forEach(gameRef.remove); + gameRef.components.where((e) => e is Ball && e.levelUp).forEach((ball) { + Ball b = ball; + final isLastLevel = Levels.isLastLevel(b.level + 1); + gameRef.remove(ball); + AudioTool.mix(); + GameState.updateScore(GameState.score + b.level); + final radius = Levels.radius(b.level + 1); + gameRef.add(Ball.create( + gameRef.viewport, + position: b.position..y += (radius - b.radius), + level: b.level + 1, + canFall: true, + landed: true, + bounce: true, + )); + BloomPartcle(gameRef).show(b.position.toOffset(), radius); + if (isLastLevel) { + GameLife(gameRef).win(); + } + }); + } +} diff --git a/lib/game/game_init.dart b/lib/game/game_init.dart new file mode 100644 index 0000000..5d87cbb --- /dev/null +++ b/lib/game/game_init.dart @@ -0,0 +1,26 @@ +import 'package:flame/components.dart'; +import 'package:flame_forge2d/viewport.dart'; + +import '../components/boundaries.dart'; +import '../contacts/ball_ball_contact.dart'; +import '../contacts/ball_wall_contact.dart'; +import '../tools/size_tool.dart'; +import 'my_game.dart'; + +class GameInit { + MyGame gameRef; + GameInit(this.gameRef); + + ///初始化 + void init(Vector2 size) { + final scale = 10.0; + final gravity = Vector2(0, -1) * size.gravitySize; + gameRef.world.setGravity(gravity); + gameRef.viewport = Viewport(size, scale); + final boundaries = createBoundaries(gameRef.viewport); + boundaries.forEach(gameRef.add); + //初始化碰撞检测器 + gameRef.addContactCallback(BallWallContactCallback()); + gameRef.addContactCallback(BallBallContactCallback()); + } +} diff --git a/lib/game/game_life.dart b/lib/game/game_life.dart new file mode 100644 index 0000000..cbf442d --- /dev/null +++ b/lib/game/game_life.dart @@ -0,0 +1,70 @@ +import '../pages/game_over_page.dart'; +import '../pages/game_page.dart'; +import '../pages/setting/game_setting_page.dart'; +import '../tools/audio_tool.dart'; +import '../tools/navigator_tool.dart'; +import 'game_onload.dart'; +import 'game_state.dart'; +import 'my_game.dart'; + +class GameLife { + MyGame gameRef; + GameLife(this.gameRef); + + static void start() async { + await GameOnload.init(); + await NavigatorTool.push(GamePage()); + } + + ///暂停 + void pause() { + gameRef.pauseEngine(); + GameState.gameStatus = GameStatus.pause; + } + + ///继续 + void resume() { + gameRef.resumeEngine(); + GameState.gameStatus = GameStatus.start; + } + + ///win + void win() { + AudioTool.win(); + GameState.gameStatus = GameStatus.win; + NavigatorTool.push(GameOverPage( + gameRef, + isWin: true, + )); + } + + ///game over + void dead() { + AudioTool.dead(); + GameState.gameStatus = GameStatus.over; + NavigatorTool.push(GameOverPage( + gameRef, + isWin: false, + )); + } + + ///重新开始 + void restart() { + pause(); + NavigatorTool.replace(GamePage()); + } + + ///回主页 + void back2Home() { + NavigatorTool.pop(); + } + + ///打开设置页面 + void setting() async { + pause(); + await NavigatorTool.push(GameSettingPage( + fromHome: false, + )); + resume(); + } +} diff --git a/lib/game/game_onload.dart b/lib/game/game_onload.dart new file mode 100644 index 0000000..eb4c270 --- /dev/null +++ b/lib/game/game_onload.dart @@ -0,0 +1,52 @@ +import '../components/background.dart'; +import '../components/dead_line.dart'; +import '../components/scores.dart'; +import '../components/setting_button.dart'; +import '../controllers/generate_ball.dart'; +import '../controllers/update_balls_bounce.dart'; +import '../controllers/update_balls_falling.dart'; +import '../controllers/update_dead_line.dart'; +import '../controllers/update_gravity.dart'; +import '../controllers/update_level_up.dart'; +import '../tools/audio_tool.dart'; +import '../tools/image/image_tool.dart'; +import 'game_state.dart'; +import 'level/levels.dart'; +import 'my_game.dart'; + +class GameOnload { + MyGame gameRef; + GameOnload(this.gameRef); + + static bool inited = false; + + static Future init() async { + await GameState.init(); + await Levels.init(); + if (inited) return; + await ImageTool.loadAll(); + await AudioTool.loadAll(); + inited = true; + } + + ///初始化 + Future onLoad() async { + await init(); + final background = Background.create(gameRef.viewport); + await gameRef.add(background); + final deadLine = DeadLine.create(gameRef.viewport); + await gameRef.add(deadLine); + GameState.scoreComponent = + Scores.create(gameRef.viewport, text: GameState.score.toString()); + await gameRef.add(GameState.scoreComponent); + final settingButton = SettingButton.create(gameRef.viewport); + await gameRef.add(settingButton); + await GenerateBall(gameRef).generateBall(); + //初始化 game controllers + await gameRef.add(UpdateBallsFalling()); + await gameRef.add(UpdateBallsBounce()); + await gameRef.add(UpdateLevelUp()); + await gameRef.add(UpdateDeadLine()); + await gameRef.add(UpdateGravity()); + } +} diff --git a/lib/game/game_setting.dart b/lib/game/game_setting.dart new file mode 100644 index 0000000..36cb89b --- /dev/null +++ b/lib/game/game_setting.dart @@ -0,0 +1,60 @@ +import 'dart:convert'; + +import '../game/game_state.dart'; + +class GameSetting { + ///合成大/小瓜 + bool levelUp; + + ///随机/只生成小、大瓜模式 + bool random; + + ///音效 + bool music; + + ///动效 + bool bloom; + + ///重力感应 + bool gravity; + + GameSetting({ + this.levelUp, + this.random, + this.music, + this.bloom, + this.gravity, + }) { + levelUp ??= true; + random ??= true; + music ??= true; + bloom ??= true; + gravity ??= false; + } + + GameSetting.fromJson(Map json) { + levelUp = json['levelUp']; + random = json['random']; + music = json['music']; + bloom = json['bloom']; + gravity = json['gravity']; + } + + Map toJson() { + final data = {}; + data['levelUp'] = levelUp; + data['random'] = random; + data['music'] = music; + data['bloom'] = bloom; + data['gravity'] = gravity; + return data; + } + + String toJsonStr() => jsonEncode(toJson()); + + static GameSetting fromJsonStr(String result) { + return GameSetting.fromJson(jsonDecode(result)); + } + + Future update() async => GameState.updateSetting(this); +} diff --git a/lib/game/game_state.dart b/lib/game/game_state.dart new file mode 100644 index 0000000..c1de012 --- /dev/null +++ b/lib/game/game_state.dart @@ -0,0 +1,77 @@ +import '../components/ball.dart'; +import '../components/scores.dart'; +import '../game/game_setting.dart'; +import '../tools/hive_tool.dart'; + +class GameState { + ///成绩 + static int score = 0; + + ///最高纪录 + static int record = 0; + + ///是否是新纪录 + static bool isNewRecord = false; + + ///游戏状态 + static GameStatus gameStatus = GameStatus.start; + + ///游戏设置 + static GameSetting gameSetting = GameSetting(); + + ///上一个小球 + static Ball lastBall; + + ///分数部件 + static Scores scoreComponent; + + static Future updateScore(int newScore) async { + score = newScore; + scoreComponent?.text = GameState.score.toString(); + if (newScore > record) { + record = newScore; + isNewRecord = true; + await HiveTool().set('record', score); + } + } + + static Future updateSetting(GameSetting setting) async { + gameSetting = setting; + await HiveTool().set('gameSetting', gameSetting.toJsonStr()); + } + + static bool inited = false; + + ///重置游戏状态 + static Future init() async { + score = 0; + isNewRecord = false; + gameStatus = GameStatus.start; + lastBall = null; + await initSetting(); + } + + static Future initSetting() async { + if (inited) return; + final n = await HiveTool().get('record'); + if (n != null) record = n; + final s = await HiveTool().get('gameSetting'); + if (s != null) gameSetting = GameSetting.fromJsonStr(s); + inited = true; + } +} + +///游戏状态 +enum GameStatus { + ///挂了 + over, + + ///赢了 + win, + + ///暂停 + pause, + + ///开始 + start, +} diff --git a/lib/game/level/level.dart b/lib/game/level/level.dart new file mode 100644 index 0000000..276f59b --- /dev/null +++ b/lib/game/level/level.dart @@ -0,0 +1,36 @@ +import 'dart:convert'; + +class Level { + String image; + double radius; + + Level(this.radius, this.image); + + Level.fromJson(Map json) { + image = json['image']; + radius = json['radius']; + } + + Map toJson() { + final data = {}; + data['image'] = image; + data['radius'] = radius; + return data; + } + + static List fromJsonList(List list) { + final results = []; + for (var i = 0; i < list.length; i++) { + results.add(Level.fromJson(list[i])); + } + return results; + } + + static String toJsons(List levels) => + levels.map((e) => jsonEncode(e.toJson())).toList().join('|'); + + static List fromJsons(String result) { + final levels = result.split('|').map((e) => jsonDecode(e)).toList(); + return fromJsonList(levels); + } +} diff --git a/lib/game/level/levels.dart b/lib/game/level/levels.dart new file mode 100644 index 0000000..1f2e4c6 --- /dev/null +++ b/lib/game/level/levels.dart @@ -0,0 +1,123 @@ +import 'dart:math'; +import 'dart:ui'; + +import 'package:flame/components.dart'; + +import '../../tools/hive_tool.dart'; +import '../../tools/image/image_tool.dart'; +import '../game_state.dart'; +import 'level.dart'; +import 'levels_inner.dart'; + +class Levels { + static bool isLastLevel(int level) => level > topLevel - 1; + + static int get topLevel => kLevels.length; + + static Future generateLevel() async { + if (!inited) await setDefaultLevels(); + if (!GameState.gameSetting.random) return 1; + while (true) { + if (topLevel < 1) { + kLevels.clear(); + kLevels.addAll(LevelsInner.levels['friut']); + } + final level = topLevel < 2 ? 1 : (Random().nextInt(topLevel - 1) + 1); + if (level < topLevel / 2) return level; + } + } + + ///小球半径 单位:vw + static double radius(int level) { + return !GameState.gameSetting.levelUp + ? (topLevel * 2 + 2) - level * 2.0 + : 2.0 + level * 2.0; + } + + ///小球贴图 + static Sprite sprite(int level) { + if (!GameState.gameSetting.levelUp) { + level = topLevel + 1 - level; + } + return Sprite(ImageTool.image(kLevels[level - 1].image)); + } + + static Image image(int level) { + if (!GameState.gameSetting.levelUp) { + level = topLevel + 1 - level; + } + return ImageTool.image(kLevels[level - 1].image); + } + + static String imagePath(int level) { + if (!GameState.gameSetting.levelUp) { + level = topLevel + 1 - level; + } + return kLevels[level - 1].image; + } + + ///等级表(level,radius) + static final kLevels = []; + + static String background = 'bg.png'; + + static Future setBackground(String path) async { + background = path; + await HiveTool().set('background', background); + } + + static bool get inited => kLevels.isNotEmpty; + + static Future init() async { + if (inited) return; + final bg = await HiveTool().get('background'); + if (bg != null) background = bg; + final result = await HiveTool().get('kLevels'); + if (result != null) { + final levels = Level.fromJsons(result); + if (levels != null) { + await sets(levels); + return; + } + } + await setDefaultLevels(); + } + + static Future setDefaultLevels() async { + return await sets(LevelsInner.levels['friut']); + } + + ///todo level增删查改 + static Future updates() async { + final result = Level.toJsons(kLevels); + await HiveTool().set('kLevels', result); + } + + static Future sets(List levels) async { + if (levels == null) return; + kLevels.clear(); + kLevels.addAll(levels); + await updates(); + } + + static Future add(Level level, {int index}) async { + index ??= kLevels.length; + if (index > kLevels.length) return; + kLevels.insert(index, level); + await updates(); + } + + static Future del({int index}) async { + index ??= kLevels.length - 1; + if (index > kLevels.length - 1) return; + kLevels.removeAt(index); + await updates(); + } + + static Future update(Level level, {int index}) async { + index ??= kLevels.length - 1; + if (index > kLevels.length - 1) return; + kLevels[index] = level; + await updates(); + } +} diff --git a/lib/game/level/levels_inner.dart b/lib/game/level/levels_inner.dart new file mode 100644 index 0000000..1b68f35 --- /dev/null +++ b/lib/game/level/levels_inner.dart @@ -0,0 +1,66 @@ +import 'level.dart'; + +class LevelsInner { + static final levels = { + 'friut': _friutsLevels, + 'emoji': _emojiLevels, + '985': _985Levels, + 'shandong': _shandongLevels, + }; + + static final _friutsLevels = [ + Level(2.0, 'friuts/1.png'), + Level(4.0, 'friuts/2.png'), + Level(6.0, 'friuts/3.png'), + Level(8.0, 'friuts/4.png'), + Level(10.0, 'friuts/5.png'), + Level(12.0, 'friuts/6.png'), + Level(14.0, 'friuts/7.png'), + Level(16.0, 'friuts/8.png'), + Level(18.0, 'friuts/9.png'), + Level(20.0, 'friuts/10.png'), + Level(22.0, 'friuts/11.png'), + ]; + + static final _emojiLevels = [ + Level(2.0, 'qq/1.png'), + Level(4.0, 'qq/2.png'), + Level(6.0, 'qq/3.png'), + Level(8.0, 'qq/4.png'), + Level(10.0, 'qq/5.png'), + Level(12.0, 'qq/6.png'), + Level(14.0, 'qq/7.png'), + Level(16.0, 'qq/8.png'), + Level(18.0, 'qq/9.png'), + Level(20.0, 'qq/10.png'), + Level(22.0, 'qq/11.png'), + ]; + + static final _985Levels = [ + Level(2.0, '985/1.png'), + Level(4.0, '985/2.png'), + Level(6.0, '985/3.png'), + Level(8.0, '985/4.png'), + Level(10.0, '985/5.png'), + Level(12.0, '985/6.png'), + Level(14.0, '985/7.png'), + Level(16.0, '985/8.png'), + Level(18.0, '985/9.png'), + Level(20.0, '985/10.png'), + Level(22.0, '985/11.png'), + ]; + + static final _shandongLevels = [ + Level(2.0, 'shandong/1.png'), + Level(4.0, 'shandong/2.png'), + Level(6.0, 'shandong/3.png'), + Level(8.0, 'shandong/4.png'), + Level(10.0, 'shandong/5.png'), + Level(12.0, 'shandong/6.png'), + Level(14.0, 'shandong/7.png'), + Level(16.0, 'shandong/8.png'), + Level(18.0, 'shandong/9.png'), + Level(20.0, 'shandong/10.png'), + Level(22.0, 'shandong/11.png'), + ]; +} diff --git a/lib/game/my_game.dart b/lib/game/my_game.dart new file mode 100644 index 0000000..15eec58 --- /dev/null +++ b/lib/game/my_game.dart @@ -0,0 +1,49 @@ +import 'package:flame/components.dart'; +import 'package:flame_forge2d/forge2d_game.dart'; +import 'package:flutter/material.dart'; +import 'package:forge2d/forge2d.dart'; + +import '../controllers/generate_ball.dart'; +import '../tools/size_tool.dart'; +import 'game_init.dart'; +import 'game_onload.dart'; + +class MyGame extends Forge2DGame with HasTapableComponents { + MyGame( + double width, + double height, { + this.hide, + }) { + hide ??= false; + final viewportSize = Vector2(width, height); + GameInit(this).init(viewportSize); + } + + bool hide; + + @override + Future onLoad() async { + await GameOnload(this).onLoad(); + } + + @override + void onTapDown(_, TapDownDetails details) { + if (hide) return; + super.onTapDown(_, details); + if (details.localPosition.dy > viewport.vw(30)) { + GenerateBall(this).generateBall(details.localPosition.dx); + } + } + + @override + void update(double dt) { + if (hide) return; + super.update(dt); + } + + @override + void render(Canvas canvas) { + if (hide) return; + super.render(canvas); + } +} diff --git a/lib/generated_plugin_registrant.dart b/lib/generated_plugin_registrant.dart new file mode 100644 index 0000000..13c6a39 --- /dev/null +++ b/lib/generated_plugin_registrant.dart @@ -0,0 +1,21 @@ +// +// Generated file. Do not edit. +// + +// ignore_for_file: lines_longer_than_80_chars + +import 'package:audioplayers/audioplayers_web.dart'; +import 'package:image_picker_web_redux/image_picker_web_redux.dart'; +import 'package:share_plus_web/share_plus_web.dart'; +import 'package:url_launcher_web/url_launcher_web.dart'; + +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; + +// ignore: public_member_api_docs +void registerPlugins(Registrar registrar) { + AudioplayersPlugin.registerWith(registrar); + ImagePickerWeb.registerWith(registrar); + SharePlusPlugin.registerWith(registrar); + UrlLauncherPlugin.registerWith(registrar); + registrar.registerMessageHandler(); +} diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..d3fdb6d --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; + +import 'pages/home_page.dart'; +import 'tools/navigator_tool.dart'; +import 'tools/system_tool.dart'; + +void main() async { + runApp(MyApp()); + SystemTool.keepPortrait(); +} + +class MyApp extends StatelessWidget { + @override + Widget build(BuildContext context) { + return MaterialApp( + title: '合成大瓜', + navigatorObservers: [NavigatorTool()], + home: HomePage(), + ); + } +} diff --git a/lib/pages/about_page.dart b/lib/pages/about_page.dart new file mode 100644 index 0000000..6d73039 --- /dev/null +++ b/lib/pages/about_page.dart @@ -0,0 +1,136 @@ +import 'package:flutter/material.dart'; + +import '../tools/navigator_tool.dart'; +import '../tools/screen/screen_config.dart'; +import '../tools/screen/screen_extension.dart'; +import '../tools/url_tool.dart'; +import '../widgets/base_widget.dart'; +import '../widgets/pulse.dart'; + +class AboutPage extends StatelessWidget { + void _back() { + NavigatorTool.pop(); + } + + @override + Widget build(BuildContext context) { + return ScreenConfig( + builder: () => Scaffold( + backgroundColor: Colors.grey[100], + body: SafeArea( + child: Center( + child: Column( + children: [ + _topAction(), + lExpanded(), + lExpanded(flex: 10), + lText( + 'A', + bold: true, + size: 18, + color: Colors.grey[600], + ), + lExpanded(), + lText( + 'Work', + bold: true, + size: 36, + color: Colors.black, + ), + lExpanded(), + lText( + 'by', + bold: true, + size: 18, + color: Colors.grey[600], + ), + lExpanded(), + Image.asset( + 'assets/images/qr.jpg', + width: 30.vw, + ), + lExpanded(flex: 10, child: _homeSite()), + _madeWithLove(), + lExpanded(), + _bottomAction(), + lExpanded(), + ], + ), + ), + ), + ), + ); + } + + Widget _homeSite() { + final url = 'https://xbox.work'; + return GestureDetector( + onTap: () { + UrlTool.open(url); + }, + child: lText( + url, + color: Colors.blue, + ), + ); + } + + Widget _topAction() => Container( + padding: EdgeInsets.all(5.vw), + child: Row( + children: [ + lIconButton( + Icons.chevron_left, + size: 10.vw, + color: Colors.black, + onTap: _back, + ), + lExpanded(), + ], + ), + ); + + Widget _madeWithLove() => Row( + children: [ + lExpanded(), + lText( + 'Made with ', + bold: true, + size: 18, + color: Colors.grey[600], + ), + Pulse( + child: Icon( + Icons.favorite, + size: 5.vw, + color: Colors.red, + ), + ), + lExpanded(), + ], + ); + + Widget _bottomAction() => Row( + children: [ + lExpanded(), + lText( + 'Powered by', + bold: true, + size: 18, + color: Colors.grey[600], + ), + lWidth(5.vw), + FlutterLogo(size: 8.vw), + Icon( + Icons.close, + size: 5.vw, + color: Colors.black54, + ), + Image.asset( + 'assets/images/flame.png', + width: 8.vw, + ), + lExpanded(), + ], + ); +} diff --git a/lib/pages/game_over_page.dart b/lib/pages/game_over_page.dart new file mode 100644 index 0000000..e044de1 --- /dev/null +++ b/lib/pages/game_over_page.dart @@ -0,0 +1,188 @@ +import 'package:flutter/material.dart'; + +import '../game/game_life.dart'; +import '../game/game_state.dart'; +import '../game/level/levels.dart'; +import '../game/my_game.dart'; +import '../tools/image/image_tool.dart'; +import '../tools/navigator_tool.dart'; +import '../tools/screen/screen_config.dart'; +import '../tools/screen/screen_extension.dart'; +import '../tools/share_tool.dart'; +import '../widgets/base_widget.dart'; +import '../widgets/spinner.dart'; +import 'setting/game_setting_page.dart'; + +// ignore: must_be_immutable +class GameOverPage extends StatelessWidget { + MyGame gameRef; + bool isWin; + + GameOverPage( + this.gameRef, { + this.isWin, + }) { + isWin ??= true; + } + + void _share() async { + await ShareTool.share( + '我合成大西瓜的最高分是${GameState.record}!关注微信号:乂乂又又,回复:大西瓜,就有链接了^^'); + } + + void _retry() { + NavigatorTool.pop(); + GameLife(gameRef).restart(); + } + + void _home() { + NavigatorTool.pop(); + GameLife(gameRef).back2Home(); + } + + void _setting() => NavigatorTool.push( + GameSettingPage( + fromHome: false, + ), + ); + + @override + Widget build(BuildContext context) { + return ScreenConfig( + builder: () => WillPopScope( + onWillPop: () async { + _retry(); + return false; + }, + child: Scaffold( + backgroundColor: Colors.black45, + body: SafeArea( + child: Center( + child: Column( + children: [ + lExpanded(child: _topAction()), + ...GameState.isNewRecord ? _newRecord() : _normalRecord(), + if (isWin) + Stack( + alignment: Alignment.center, + children: [ + _shine(), + _topBall(), + ], + ), + lHeight(10.vw), + lExpanded( + child: _bottomAction(), + ), + ], + ), + ), + ), + ), + ), + ); + } + + Widget _topAction() => Row( + children: [ + lWidth(10.vw), + lIconButton( + Icons.home, + size: 10.vw, + color: Colors.white, + onTap: _home, + ), + lExpanded(), + lIconButton( + Icons.settings, + size: 10.vw, + color: Colors.white, + onTap: _setting, + ), + lWidth(10.vw), + ], + ); + + Widget _bottomAction() => Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + lButton( + '分享一下', + onTap: _share, + height: 5.vw * 2.2, + colorBg: Colors.black, + colorText: Colors.white, + ), + lButton( + '再来一次', + onTap: _retry, + height: 5.vw * 2.2, + ), + ], + ); + + List _normalRecord() => [ + Text( + '最高分:${GameState.record}', + style: TextStyle( + fontSize: 24, + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + lHeight(10.vw), + Text( + '得分:${GameState.score}', + style: TextStyle( + fontSize: 36, + color: Colors.orange, + fontWeight: FontWeight.bold, + ), + ), + lHeight(10.vw), + ]; + + List _newRecord() => [ + Text( + '新纪录', + style: TextStyle( + fontSize: 36, + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + lHeight(5.vw), + Text( + '${GameState.score}', + style: TextStyle( + fontSize: 36, + color: Colors.orange, + fontWeight: FontWeight.bold, + ), + ), + lHeight(10.vw), + ]; + + Widget _shine() { + return Spinner( + child: Container( + width: 90.vw, + height: 90.vw, + child: RawImage( + image: ImageTool.image('shine.png'), + fit: BoxFit.cover, + ), + )); + } + + Widget _topBall() { + return Container( + width: Levels.radius(Levels.topLevel).vw * 2, + height: Levels.radius(Levels.topLevel).vw * 2, + child: RawImage( + image: Levels.image(Levels.topLevel), + fit: BoxFit.cover, + ), + ); + } +} diff --git a/lib/pages/game_page.dart b/lib/pages/game_page.dart new file mode 100644 index 0000000..71bae9a --- /dev/null +++ b/lib/pages/game_page.dart @@ -0,0 +1,57 @@ +import 'package:flame/game.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +import '../game/my_game.dart'; +import '../tools/navigator_tool.dart'; +import '../tools/sensor_tool.dart'; +import '../tools/system_tool.dart'; + +class GamePage extends StatefulWidget { + final bool hide; + GamePage({this.hide}); + @override + _GamePageState createState() => _GamePageState(); +} + +class _GamePageState extends State { + @override + void initState() { + super.initState(); + SensorTool.start(); + } + + @override + void dispose() { + SensorTool.stop(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onHorizontalDragEnd: (_) { + if (kIsWeb) { + //侧滑返回手势 + NavigatorTool.pop(); + } + }, + child: Scaffold( + body: SafeArea( + child: LayoutBuilder( + builder: (_, constraints) { + SystemTool.changeStatusBarColor(); + return GameWidget( + game: MyGame( + constraints.maxWidth, + constraints.maxHeight, + hide: widget.hide, + ), + ); + }, + ), + ), + ), + ); + } +} diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart new file mode 100644 index 0000000..4149b4e --- /dev/null +++ b/lib/pages/home_page.dart @@ -0,0 +1,95 @@ +import 'package:flutter/material.dart'; + +import '../game/game_life.dart'; +import '../game/game_state.dart'; +import '../tools/navigator_tool.dart'; +import '../tools/screen/screen_config.dart'; +import '../tools/screen/screen_extension.dart'; +import '../widgets/base_widget.dart'; +import 'about_page.dart'; +import 'game_page.dart'; +import 'setting/game_setting_page.dart'; + +class HomePage extends StatelessWidget { + void _start() { + GameLife.start(); + } + + void _about() { + NavigatorTool.push(AboutPage()); + } + + Future _setting() async { + await GameState.initSetting(); + await NavigatorTool.push( + GameSettingPage( + fromHome: true, + ), + ); + } + + @override + Widget build(BuildContext context) { + return ScreenConfig( + builder: () => Scaffold( + backgroundColor: Colors.grey[100], + body: SafeArea( + child: Center( + child: Column( + children: [ + _topAction(), + lExpanded( + child: _bottomAction(), + ), + _hideGame(), + ], + ), + ), + ), + ), + ); + } + + ///预加载 + Widget _hideGame() => Offstage( + child: Container( + width: 1, + height: 1, + child: GamePage(hide: true), + ), + ); + + Widget _topAction() => Container( + padding: EdgeInsets.all(5.vw), + child: Row( + children: [ + lIconButton( + Icons.info, + size: 10.vw, + color: Colors.black, + onTap: _about, + ), + lExpanded(), + lIconButton( + Icons.settings, + size: 10.vw, + color: Colors.black, + onTap: _setting, + ), + ], + ), + ); + + Widget _bottomAction() => Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + lButton( + '开始游戏', + onTap: _start, + height: 5.vw * 2.2, + colorBg: Colors.black, + colorText: Colors.white, + ), + ], + ); +} diff --git a/lib/pages/setting/background_page.dart b/lib/pages/setting/background_page.dart new file mode 100644 index 0000000..c525f6e --- /dev/null +++ b/lib/pages/setting/background_page.dart @@ -0,0 +1,102 @@ +import 'package:flutter/material.dart'; + +import '../../game/level/levels.dart'; +import '../../tools/image/image_pick_tool.dart'; +import '../../tools/image/image_tool.dart'; +import '../../tools/navigator_tool.dart'; +import '../../tools/screen/screen_config.dart'; +import '../../tools/screen/screen_extension.dart'; +import '../../widgets/base_widget.dart'; + +class BackgroundPage extends StatefulWidget { + @override + _BackgroundPageState createState() => _BackgroundPageState(); +} + +class _BackgroundPageState extends State { + void _back() { + NavigatorTool.pop(); + } + + void _pickImage() async { + final path = await ImagePickTool.pickImageAndSave(); + if (path != null) { + await Levels.setBackground(path); + setState(() {}); + } + } + + @override + Widget build(BuildContext context) { + return ScreenConfig( + builder: () => Scaffold( + backgroundColor: Colors.grey[100], + body: SafeArea( + child: Center( + child: Column( + children: [ + _topAction(), + lExpanded( + child: _background(), + ), + _bottomAction(), + ], + ), + ), + ), + ), + ); + } + + Widget _background() { + return Container( + width: 100.vw, + height: 100.vh, + child: RawImage( + image: ImageTool.image(Levels.background), + fit: BoxFit.cover, + ), + ); + } + + Widget _topAction() => Container( + padding: EdgeInsets.all(5.vw), + child: Row( + children: [ + lIconButton( + Icons.chevron_left, + size: 10.vw, + color: Colors.black, + onTap: _back, + ), + lExpanded( + child: lText( + '更换背景', + bold: true, + size: 18, + )), + lIconButton( + Icons.chevron_left, + size: 10.vw, + color: Colors.transparent, + ), + ], + ), + ); + + Widget _bottomAction() => Container( + padding: EdgeInsets.all(10.vw), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + lButton( + '更换图片', + onTap: _pickImage, + height: 5.vw * 2.2, + colorBg: Colors.black, + colorText: Colors.white, + ), + ], + ), + ); +} diff --git a/lib/pages/setting/game_setting_page.dart b/lib/pages/setting/game_setting_page.dart new file mode 100644 index 0000000..1166c26 --- /dev/null +++ b/lib/pages/setting/game_setting_page.dart @@ -0,0 +1,156 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +import '../../game/game_setting.dart'; +import '../../game/game_state.dart'; +import '../../game/level/levels.dart'; +import '../../tools/dialog_tool.dart'; +import '../../tools/navigator_tool.dart'; +import '../../tools/screen/screen_config.dart'; +import '../../tools/screen/screen_extension.dart'; +import '../../widgets/base_widget.dart'; +import 'more_setting_page.dart'; + +class GameSettingPage extends StatefulWidget { + final bool fromHome; + GameSettingPage({@required this.fromHome}); + @override + _GameSettingPageState createState() => _GameSettingPageState(); +} + +class _GameSettingPageState extends State { + void _back() { + NavigatorTool.pop(); + } + + void _goHome() { + NavigatorTool.pop(); //pop setting page + if (GameState.gameStatus != GameStatus.pause) { + NavigatorTool.pop(); //pop gameover page + } + NavigatorTool.pop(); //pop game page + } + + Future _more() async { + if (!widget.fromHome) { + await DialogTool.show( + context, + title: '提示', + content: '只能从首页进入高级设置', + actionText: '首页', + action: _goHome, + ); + return; + } + await Levels.init(); + await NavigatorTool.push(MoreSettingPage()); + } + + GameSetting get setting => GameState.gameSetting; + + String get _levelUp => setting.levelUp ? '合成大瓜' : '合成小瓜'; + + String get _random => setting.random + ? '随机模式' + : setting.levelUp + ? '小瓜模式' + : '大瓜模式'; + + @override + Widget build(BuildContext context) { + return ScreenConfig( + builder: () => Scaffold( + backgroundColor: Colors.grey[100], + body: SafeArea( + child: Center( + child: Column( + children: [ + _topAction(), + lExpanded(), + _switchItem(_levelUp, value: setting.levelUp, + onChanged: (v) async { + if (!widget.fromHome) { + await DialogTool.show( + context, + title: '提示', + content: '只能从首页进入设置该选项', + actionText: '首页', + action: _goHome, + ); + return; + } + setting.levelUp = v; + await setting.update(); + }), + _switchItem(_random, value: setting.random, + onChanged: (v) async { + setting.random = v; + await setting.update(); + }), + if (!kIsWeb) + _switchItem('重力感应', value: setting.gravity, + onChanged: (v) async { + setting.gravity = v; + await setting.update(); + }), + _switchItem('音效', value: setting.music, onChanged: (v) async { + setting.music = v; + await setting.update(); + }), + _switchItem('动效', value: setting.bloom, onChanged: (v) async { + setting.bloom = v; + await setting.update(); + }), + lExpanded(), + ], + ), + ), + ), + ), + ); + } + + Widget _topAction() => Container( + padding: EdgeInsets.all(5.vw), + child: Row( + children: [ + lIconButton( + Icons.chevron_left, + size: 10.vw, + color: Colors.black, + onTap: _back, + ), + lExpanded(), + lButton( + '高级设置', + onTap: _more, + height: 5.vw * 2.2, + colorBg: Colors.black, + colorText: Colors.white, + ), + ], + ), + ); + + Widget _switchItem(String lable, {bool value, Function(bool) onChanged}) => + lExpanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + lButton( + lable, + height: 5.vw * 2.2, + colorBg: Colors.black, + colorText: Colors.white, + ), + CupertinoSwitch( + value: value, + onChanged: (v) { + onChanged(v); + setState(() {}); + }), + ], + ), + ); +} diff --git a/lib/pages/setting/image_crop_page.dart b/lib/pages/setting/image_crop_page.dart new file mode 100644 index 0000000..7f6ed5f --- /dev/null +++ b/lib/pages/setting/image_crop_page.dart @@ -0,0 +1,130 @@ +import 'package:crop/crop.dart'; +import 'package:flutter/material.dart'; + +import '../../tools/image/image_pick_tool.dart'; +import '../../tools/image/image_tool.dart'; +import '../../tools/navigator_tool.dart'; +import '../../tools/screen/screen_config.dart'; +import '../../tools/screen/screen_extension.dart'; +import '../../widgets/base_widget.dart'; + +class ImageCropPage extends StatefulWidget { + @override + _ImageCropPageState createState() => _ImageCropPageState(); +} + +class _ImageCropPageState extends State { + void _back() { + NavigatorTool.pop(); + } + + final cropController = CropController(aspectRatio: 1); + final cropShape = BoxShape.circle; + final cropFit = BoxFit.contain; + + Widget cropImage; + + Future _crop() async { + final pixelRatio = MediaQuery.of(context).devicePixelRatio; + final cropped = await cropController.crop(pixelRatio: pixelRatio); + final path = await ImageTool.saveImage(cropped); + NavigatorTool.pop(path); + CircleAvatar(); + } + + void _pickImage() async { + final bytes = await ImagePickTool.pickImageAsBytes(); + if (bytes != null) { + cropImage = Image.memory( + bytes, + fit: cropFit, + ); + setState(() {}); + } + } + + @override + void initState() { + super.initState(); + cropImage = Image.asset( + 'assets/images/friuts/10.png', + fit: cropFit, + ); + _pickImage(); + } + + @override + Widget build(BuildContext context) { + return ScreenConfig( + builder: () => Scaffold( + backgroundColor: Colors.grey[100], + body: SafeArea( + child: Center( + child: Column( + children: [ + _topAction(), + lExpanded( + child: _cropArea(), + ), + _bottomAction(), + ], + ), + ), + ), + ), + ); + } + + Widget _cropArea() { + return AspectRatio( + aspectRatio: 1, + child: Crop( + controller: cropController, + shape: cropShape, + child: cropImage, + fit: cropFit, + ), + ); + } + + Widget _topAction() => Container( + padding: EdgeInsets.all(5.vw), + child: Row( + children: [ + lIconButton( + Icons.chevron_left, + size: 10.vw, + color: Colors.black, + onTap: _back, + ), + lExpanded( + child: lText( + '裁剪图片', + bold: true, + size: 18, + )), + lIconButton( + Icons.chevron_left, + size: 10.vw, + color: Colors.transparent, + ), + ], + ), + ); + + Widget _bottomAction() => Container( + padding: EdgeInsets.all(10.vw), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + lButton( + '确定', + onTap: _crop, + height: 5.vw * 2.2, + colorBg: Colors.black, + colorText: Colors.white, + ), + ], + ), + ); +} diff --git a/lib/pages/setting/inner_level_page.dart b/lib/pages/setting/inner_level_page.dart new file mode 100644 index 0000000..f84cea3 --- /dev/null +++ b/lib/pages/setting/inner_level_page.dart @@ -0,0 +1,220 @@ + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import '../../game/level/level.dart'; +import '../../game/level/levels.dart'; +import '../../game/level/levels_inner.dart'; +import '../../tools/image/image_tool.dart'; +import '../../tools/navigator_tool.dart'; +import '../../tools/screen/screen_config.dart'; +import '../../tools/screen/screen_extension.dart'; +import '../../widgets/base_widget.dart'; + +class InnerLevelPage extends StatefulWidget { + @override + _InnerLevelPageState createState() => _InnerLevelPageState(); +} + +class _InnerLevelPageState extends State { + void _back() { + NavigatorTool.pop(); + } + + bool loaded = false; + + List innerLevels = LevelsInner.levels.values.toList(); + + @override + void initState() { + super.initState(); + loadInnerLevels(); + } + + Future loadInnerLevels() async { + await ImageTool.loadInnerLevels(); + setState(() { + loaded = true; + }); + } + + @override + Widget build(BuildContext context) { + return ScreenConfig( + builder: () => Scaffold( + backgroundColor: Colors.grey[100], + body: SafeArea( + child: Center( + child: Column( + children: [ + _topAction(), + lExpanded(child: _innerLevelsList()), + ], + ), + ), + ), + ), + ); + } + + int checkedIndex; + + Widget _innerLevelsList() { + return !loaded + ? CircularProgressIndicator() + : ListView.builder( + physics: BouncingScrollPhysics(), + itemCount: innerLevels.length, + itemBuilder: (_, index) { + return Container( + padding: EdgeInsets.all(2.vw), + margin: EdgeInsets.all(5.vw), + decoration: BoxDecoration( + color: checkedIndex == index + ? Colors.greenAccent + : Colors.grey[200], + borderRadius: BorderRadiusDirectional.circular(5.vw), + ), + child: LevelImageList( + items: innerLevels[index], + onTap: () async { + checkedIndex = index; + await Levels.sets(innerLevels[index]); + setState(() {}); + }, + ), + ); + }, + ); + } + + Widget _topAction() => Container( + padding: EdgeInsets.all(5.vw), + child: Row( + children: [ + lIconButton( + Icons.chevron_left, + size: 10.vw, + color: Colors.black, + onTap: _back, + ), + lExpanded( + child: lText( + '更换主题', + bold: true, + size: 18, + )), + lIconButton( + Icons.chevron_left, + size: 10.vw, + color: Colors.transparent, + ), + ], + ), + ); +} + +class LevelImageList extends StatefulWidget { + final Function onTap; + final double width, height; + final List items; + LevelImageList({ + this.items, + this.width, + this.height, + this.onTap, + }); + @override + _LevelImageListState createState() => _LevelImageListState(); +} + +class _LevelImageListState extends State { + PageController controller; + + void onTapImage(Level level) async { + if (widget.onTap != null) await widget.onTap(); + } + + int currentPage = 0; + + void _pageListener() { + var next = controller.page.round(); + if (currentPage != next) { + setState(() { + currentPage = next; + }); + } + } + + double get _screenWidth => widget.width ?? 100.vw; + double get _height => widget.height ?? 20.vw; + + @override + void initState() { + super.initState(); + controller = PageController(viewportFraction: _height / _screenWidth); + controller.addListener(_pageListener); + Future.delayed(Duration.zero, () async { + if (widget.items.length > 1) { + await controller.animateToPage( + 2, //居中 + duration: Duration(milliseconds: 100), + curve: Curves.easeOutQuint, + ); + } + }); + } + + @override + void dispose() { + controller?.dispose(); + super.dispose(); + } + + Widget levelImageView(Level level, bool active) { + var top = active ? 0 : _height * 0.2; + return GestureDetector( + onTap: () async { + await onTapImage(level); + }, + child: Container( + width: _height, + height: _height, + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + AnimatedContainer( + width: _height, + height: _height - top, + duration: Duration(milliseconds: 500), + curve: Curves.easeOutQuint, + child: RawImage( + image: ImageTool.image(level.image), + fit: BoxFit.contain, + ), + ), + ], + ), + ), + ); + } + + @override + Widget build(BuildContext context) { + return Container( + width: _screenWidth, + height: _height, + alignment: Alignment.center, + child: PageView.builder( + physics: BouncingScrollPhysics(), + controller: controller, + itemCount: widget.items.length, + itemBuilder: (context, int currentIndex) { + var active = currentIndex == currentPage; + return levelImageView(widget.items[currentIndex], active); + }, + ), + ); + } +} diff --git a/lib/pages/setting/level_setting_page.dart b/lib/pages/setting/level_setting_page.dart new file mode 100644 index 0000000..400d0df --- /dev/null +++ b/lib/pages/setting/level_setting_page.dart @@ -0,0 +1,283 @@ +import 'package:flutter/material.dart'; + +import '../../game/level/level.dart'; +import '../../game/level/levels.dart'; +import '../../tools/image/image_crop_tool.dart'; +import '../../tools/image/image_tool.dart'; +import '../../tools/navigator_tool.dart'; +import '../../tools/screen/screen_config.dart'; +import '../../tools/screen/screen_extension.dart'; +import '../../widgets/base_widget.dart'; + +class LevelSettingPage extends StatefulWidget { + @override + _LevelSettingPageState createState() => _LevelSettingPageState(); +} + +class _LevelSettingPageState extends State { + void _back() { + NavigatorTool.pop(); + } + + Future _pickImage() async { + final path = await ImageCropTool.crop(); + if (path != null) { + await Levels.update( + levels[currentPage]..image = path, + index: currentPage, + ); + setState(() {}); + } + } + + Future onTapImage(Level level) async => _pickImage(); + + Future next() async { + if (isLast) return; + await controller.nextPage( + duration: Duration(milliseconds: 300), + curve: Curves.easeOutQuint, + ); + } + + Future pre() async { + if (isFirst) return; + await controller.previousPage( + duration: Duration(milliseconds: 300), + curve: Curves.easeOutQuint, + ); + } + + bool get isLast => currentPage == levels.length - 1; + bool get isFirst => currentPage < 1; + int get currentPage => controller.page.toInt(); + + bool loaded = false; + + List get levels => Levels.kLevels; + + PageController controller = PageController(viewportFraction: 1); + + @override + void initState() { + super.initState(); + loadInnerLevels(); + } + + @override + void dispose() { + controller?.dispose(); + super.dispose(); + } + + Future loadInnerLevels() async { + await ImageTool.loadAll(); + setState(() { + loaded = true; + }); + } + + @override + Widget build(BuildContext context) { + return ScreenConfig( + builder: () => Scaffold( + backgroundColor: Colors.grey[100], + body: SafeArea( + child: Center( + child: Column( + children: [ + _topAction(), + lExpanded( + child: _body(), + ), + _bottomAction(), + ], + ), + ), + ), + ), + ); + } + + Widget _body() { + return !loaded + ? CircularProgressIndicator() + : Container( + child: Stack( + alignment: Alignment.center, + children: [ + _Levels(), + Container( + padding: EdgeInsets.all(5.vw), + child: Row( + children: [ + lIconButton( + Icons.chevron_left, + color: Colors.black, + onTap: pre, + ), + lExpanded(), + lIconButton( + Icons.chevron_right, + color: Colors.black, + onTap: next, + ), + ], + ), + ), + ], + ), + ); + } + + Widget _Levels() { + return LevelEditImageList( + width: 100.vw, + height: 100.vw, + controller: controller, + onTap: onTapImage, + ); + } + + Widget _topAction() => Container( + padding: EdgeInsets.all(5.vw), + child: Row( + children: [ + lIconButton( + Icons.chevron_left, + size: 10.vw, + color: Colors.black, + onTap: _back, + ), + lExpanded( + child: lText( + '自定义图片', + bold: true, + size: 18, + )), + lIconButton( + Icons.chevron_left, + size: 10.vw, + color: Colors.transparent, + ), + ], + ), + ); + + Widget _bottomAction() => Container( + padding: EdgeInsets.all(10.vw), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + lButton( + '更换图片', + onTap: _pickImage, + height: 5.vw * 2.2, + colorBg: Colors.black, + colorText: Colors.white, + ), + ], + ), + ); +} + +class LevelEditImageList extends StatefulWidget { + final Function(Level level) onTap; + final double width, height; + final PageController controller; + LevelEditImageList({ + this.width, + this.height, + this.onTap, + this.controller, + }); + @override + _LevelEditImageListState createState() => _LevelEditImageListState(); +} + +class _LevelEditImageListState extends State { + PageController controller; + + void onTapImage(Level level) async { + if (widget.onTap != null) await widget.onTap(level); + } + + int currentPage = 0; + List get levels => Levels.kLevels; + + void _pageListener() { + var next = controller.page.round(); + if (currentPage != next) { + setState(() { + currentPage = next; + }); + } + } + + double get _screenWidth => widget.width ?? 100.vw; + double get _height => widget.height ?? 20.vw; + + @override + void dispose() { + if (widget.controller == null) { + controller?.dispose(); + } + super.dispose(); + } + + @override + void initState() { + super.initState(); + controller = widget.controller ?? + PageController(viewportFraction: _height / _screenWidth); + controller.addListener(_pageListener); + } + + Widget levelImageView(Level level, bool active) { + final size = Levels.radius(currentPage).vw * 2; + var top = active ? 0 : size * 0.3; + return GestureDetector( + onTap: () async { + await onTapImage(level); + }, + child: Container( + width: _height, + height: _height, + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + AnimatedContainer( + width: size, + height: size - top, + duration: Duration(milliseconds: 500), + curve: Curves.easeOutQuint, + child: RawImage( + image: ImageTool.image(level.image), + fit: BoxFit.contain, + ), + ), + ], + ), + ), + ); + } + + @override + Widget build(BuildContext context) { + return Container( + width: _screenWidth, + height: _height, + alignment: Alignment.center, + child: PageView.builder( + physics: BouncingScrollPhysics(), + controller: controller, + itemCount: levels.length, + itemBuilder: (context, int currentIndex) { + var active = currentIndex == currentPage; + return levelImageView(levels[currentIndex], active); + }, + ), + ); + } +} diff --git a/lib/pages/setting/more_setting_page.dart b/lib/pages/setting/more_setting_page.dart new file mode 100644 index 0000000..5488eb7 --- /dev/null +++ b/lib/pages/setting/more_setting_page.dart @@ -0,0 +1,78 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import '../../game/game_setting.dart'; +import '../../game/game_state.dart'; +import '../../tools/navigator_tool.dart'; +import '../../tools/screen/screen_config.dart'; +import '../../tools/screen/screen_extension.dart'; +import '../../widgets/base_widget.dart'; +import 'background_page.dart'; +import 'inner_level_page.dart'; +import 'level_setting_page.dart'; + +class MoreSettingPage extends StatelessWidget { + void _back() { + NavigatorTool.pop(); + } + + + GameSetting get setting => GameState.gameSetting; + + @override + Widget build(BuildContext context) { + return ScreenConfig( + builder: () => Scaffold( + backgroundColor: Colors.grey[100], + body: SafeArea( + child: Center( + child: Column( + children: [ + _topAction(), + lExpanded(), + _button('更换主题', InnerLevelPage()), + lHeight(10.vw), + _button('更换背景', BackgroundPage()), + lHeight(10.vw), + _button('更换图片', LevelSettingPage()), + lExpanded(), + ], + ), + ), + ), + ), + ); + } + + Widget _topAction() => Container( + padding: EdgeInsets.all(5.vw), + child: Row( + children: [ + lIconButton( + Icons.chevron_left, + size: 10.vw, + color: Colors.black, + onTap: _back, + ), + lExpanded( + child: lText( + '高级设置', + bold: true, + size: 18, + )), + lIconButton( + Icons.chevron_left, + size: 10.vw, + color: Colors.transparent, + ), + ], + ), + ); + + Widget _button(String lable, Widget page) => lButton(lable, + height: 5.vw * 2.2, + colorBg: Colors.black, + colorText: Colors.white, onTap: () { + NavigatorTool.push(page); + }); +} diff --git a/lib/particles/bloom_particle.dart b/lib/particles/bloom_particle.dart new file mode 100644 index 0000000..0291949 --- /dev/null +++ b/lib/particles/bloom_particle.dart @@ -0,0 +1,84 @@ +import 'dart:math'; +import 'dart:ui'; + +import 'package:flame/components.dart'; +import 'package:flame/composition.dart'; +import 'package:flame/particles.dart'; +import 'package:flutter/material.dart'; + +import '../game/game_state.dart'; +import '../game/my_game.dart'; +import '../tools/size_tool.dart'; + +class BloomPartcle { + MyGame gameRef; + BloomPartcle(this.gameRef); + + static final List bloomColors = [ + Colors.amberAccent, + Colors.pink, + Colors.blueAccent, + Colors.greenAccent, + Colors.purpleAccent, + Colors.deepOrange, + ]; + + static final Random rnd = Random(); + double randomSpeed(double radius) => + (2 + rnd.nextDouble() * 1) * gameRef.viewport.vw(radius); + double randomRadius(double radius) => + (2 + rnd.nextDouble() * 1) * gameRef.viewport.vw(radius); + double randomAngle(double angle) => angle + rnd.nextDouble() * pi / 6; + double randomTime(double radius) => 0.2 + rnd.nextDouble() * 0.5; + int randomCount(double radius) => 6 + rnd.nextInt(4) + (radius ~/ 2); + Color randomColor(double radius) => + bloomColors[(radius ~/ 2) % bloomColors.length]; + + void show(Offset position, double radius) { + if (!GameState.gameSetting.bloom) return; + final n = randomCount(radius); + final color = randomColor(radius); + gameRef.add( + ParticleComponent( + particle: Particle.generate( + count: n, + lifespan: randomTime(radius), + generator: (i) { + final angle = randomAngle((2 * pi / n) * i); + return generate( + position: position, + angle: Offset(sin(angle), cos(angle)), + radius: randomRadius(radius), + speed: randomSpeed(radius), + color: color, + ); + }, + ), + ), + ); + } + + AcceleratedParticle generate({ + Offset position, + Offset angle, + double speed, + double radius, + Color color, + }) { + return AcceleratedParticle( + position: position, + speed: angle * speed, + acceleration: angle * radius, + child: ComputedParticle( + renderer: (canvas, particle) => canvas.drawCircle( + Offset.zero, + particle.progress * 5, + Paint() + ..color = Color.lerp( + color, + Colors.white, + particle.progress * 0.1, + ), + ))); + } +} diff --git a/lib/tools/audio_tool.dart b/lib/tools/audio_tool.dart new file mode 100644 index 0000000..b704208 --- /dev/null +++ b/lib/tools/audio_tool.dart @@ -0,0 +1,54 @@ +import 'package:flame_audio/flame_audio.dart'; +import 'package:flutter/foundation.dart'; + +import '../game/game_state.dart'; + +class AudioTool { + // static Future save(Image img) async { + // final timestamp = DateTime.now().millisecondsSinceEpoch.toString(); + // final bytes = await img.toBytes(); + // final path = '/audios/$timestamp.a'; + // await FileTool.write(path, bytes); + // return path; + // } + + static void loadAll() async { + if (kIsWeb) return; //audioplayers不支持web端音频缓存 + await FlameAudio.audioCache.loadAll([ + 'boom.mp3', + 'boom1.mp3', + 'boom2.mp3', + 'cheer.mp3', + 'coin.wav', + 'fall.mp3', + 'mix.wav', + ]); + } + + static int boomCount = 0; + + static void play(String path) async { + if (!GameState.gameSetting.music) return; + await FlameAudio.play(path); + } + + static void fall() => play('fall.mp3'); + static void win() => play('cheer.mp3'); + static void dead() => play('boom1.mp3'); + + static void mix() async { + boomCount++; + Future.delayed(Duration(milliseconds: 100), () { + if (boomCount == 1) { + play('boom2.mp3'); + } else if (boomCount == 2) { + play('mix.wav'); + } else if (boomCount == 3) { + play('coin.wav'); + } else if (boomCount > 3) { + play('boom.mp3'); + } + boomCount = 0; + }); + } +} diff --git a/lib/tools/cache/audio_caches.dart b/lib/tools/cache/audio_caches.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/tools/cache/image_caches.dart b/lib/tools/cache/image_caches.dart new file mode 100644 index 0000000..14f7e75 --- /dev/null +++ b/lib/tools/cache/image_caches.dart @@ -0,0 +1,82 @@ +import 'dart:async'; +import 'dart:typed_data'; +import 'dart:ui'; + +import 'package:flutter/services.dart'; + +import '../file_tool.dart'; + +class ImageCaches { + final Map _loadedFiles = {}; + + void clear() { + _loadedFiles.clear(); + } + + Image fromCache(String fileName) { + final image = _loadedFiles[fileName]; + //todo default img + return image?.loadedImage ?? _loadedFiles.values.first.loadedImage; + } + + Future loadBytes(String path, Uint8List bytes) async { + _loadedFiles[path] = _ImageLoader(_loadBytes(bytes)); + return await _loadedFiles[path].retrieve(); + } + + Future loadImage(String path, Image img) async { + _loadedFiles[path] = _ImageLoader(Future.value(img)); + return await _loadedFiles[path].retrieve(); + } + + Future> loadAll(List fileNames) async { + return Future.wait(fileNames.map(load)); + } + + Future load(String fileName) async { + return fileName.startsWith('/') ? fromFile(fileName) : fromBundle(fileName); + } + + Future fromBundle(String fileName) async { + if (!_loadedFiles.containsKey(fileName)) { + _loadedFiles[fileName] = _ImageLoader(_fetchToMemory(fileName)); + } + return await _loadedFiles[fileName].retrieve(); + } + + Future fromFile(String path) async { + if (!_loadedFiles.containsKey(path)) { + _loadedFiles[path] = _ImageLoader(_fetchFromFile(path)); + } + return await _loadedFiles[path].retrieve(); + } + + Future _fetchFromFile(String path) async { + final bytes = await FileTool.read(path); + return _loadBytes(bytes); + } + + Future _fetchToMemory(String name) async { + final data = await rootBundle.load('assets/images/' + name); + final bytes = Uint8List.view(data.buffer); + return _loadBytes(bytes); + } + + Future _loadBytes(Uint8List bytes) { + final completer = Completer(); + decodeImageFromList(bytes, (image) => completer.complete(image)); + return completer.future; + } +} + +class _ImageLoader { + _ImageLoader(this.future); + + Image loadedImage; + Future future; + + Future retrieve() async { + loadedImage ??= await future; + return loadedImage; + } +} diff --git a/lib/tools/dialog_tool.dart b/lib/tools/dialog_tool.dart new file mode 100644 index 0000000..80e19cc --- /dev/null +++ b/lib/tools/dialog_tool.dart @@ -0,0 +1,61 @@ +import 'package:flutter/cupertino.dart'; + +import '../tools/navigator_tool.dart'; + +class DialogTool { + static Future show( + BuildContext context, { + String title, + String content, + Function action, + String actionText, + }) async { + await showCupertinoDialog( + context: context, + builder: (BuildContext context) { + return CupertinoAlertDialog( + title: Text('$title'), + content: Text('$content'), + actions: [ + if (actionText != null) + CupertinoDialogAction( + onPressed: () { + Navigator.of(context).pop(); + if (action != null) action(); + }, + child: Text('$actionText'), + ), + CupertinoDialogAction( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text('确定'), + ), + ], + ); + }); + } + + static bool showing = false; + + static void loading(String title) { + showing = true; + showCupertinoDialog( + context: NavigatorTool.gContext, + builder: (BuildContext context) { + return CupertinoAlertDialog( + title: Text('$title'), + content: Container( + padding: EdgeInsets.all(10), + child: Text('这需要一点时间,请稍候...'), + ), + ); + }); + } + + static Future close() async { + if (!showing) return; + await Navigator.of(NavigatorTool.gContext).pop(); + showing = false; + } +} diff --git a/lib/tools/file/file_io.dart b/lib/tools/file/file_io.dart new file mode 100644 index 0000000..7f623cd --- /dev/null +++ b/lib/tools/file/file_io.dart @@ -0,0 +1,29 @@ +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:path_provider/path_provider.dart'; + +class FileTool { + static Future read(String path) async { + final directory = await getApplicationDocumentsDirectory(); + var file = File(directory.path + path); + if (!await file.exists()) return null; + return await file.readAsBytes(); + } + + static Future write(String path, Uint8List bytes) async { + final directory = await getApplicationDocumentsDirectory(); + var file = File(directory.path + path); + if (!await file.exists()) { + file = await file.create(recursive: true); + } + await file.writeAsBytes(bytes, flush: true); + } + + static Future delete(String path) async { + final directory = await getApplicationDocumentsDirectory(); + var file = File(directory.path + path); + if (!await file.exists()) return; + file.deleteSync(); + } +} diff --git a/lib/tools/file/file_web.dart b/lib/tools/file/file_web.dart new file mode 100644 index 0000000..4e4f0f7 --- /dev/null +++ b/lib/tools/file/file_web.dart @@ -0,0 +1,23 @@ +import 'dart:typed_data'; + +import '../hive_tool.dart'; +import '../image/ui_image_tool.dart'; + +class FileTool { + static Future read(String path) async { + if (!HiveTool().inited) await HiveTool().init(); + final value = await HiveTool().box.get(path); + if (value == null) return null; + return (value as String).toBytes(); + } + + static Future write(String path, Uint8List bytes) async { + if (!HiveTool().inited) await HiveTool().init(); + await HiveTool().box.put(path, bytes.toBase64()); + } + + static Future delete(String path) async { + if (!HiveTool().inited) await HiveTool().init(); + await HiveTool().box.delete(path); + } +} diff --git a/lib/tools/file_tool.dart b/lib/tools/file_tool.dart new file mode 100644 index 0000000..08855bc --- /dev/null +++ b/lib/tools/file_tool.dart @@ -0,0 +1 @@ +export 'file/file_io.dart' if (dart.library.html) 'file/file_web.dart'; diff --git a/lib/tools/hive_tool.dart b/lib/tools/hive_tool.dart new file mode 100644 index 0000000..722c0ae --- /dev/null +++ b/lib/tools/hive_tool.dart @@ -0,0 +1,35 @@ +import 'package:flutter/foundation.dart'; +import 'package:hive/hive.dart'; +import 'package:path_provider/path_provider.dart'; + +class HiveTool { + factory HiveTool() => _singleton; + HiveTool._(); + static final HiveTool _singleton = HiveTool._(); + + Box box; + String boxName = 'app'; + + bool get inited => box != null; + + Future init() async { + if (kIsWeb) { + //nothing + } else { + final directory = await getApplicationDocumentsDirectory(); + Hive.init(directory.path); + } + box = await Hive.openBox(boxName); + } + + Future get(String key) async { + if (!inited) await HiveTool().init(); + final value = await HiveTool().box.get(key); + return value as T; + } + + Future set(String key, T value) async { + if (!HiveTool().inited) await HiveTool().init(); + await HiveTool().box.put(key, value); + } +} diff --git a/lib/tools/image/image_crop_tool.dart b/lib/tools/image/image_crop_tool.dart new file mode 100644 index 0000000..0858de6 --- /dev/null +++ b/lib/tools/image/image_crop_tool.dart @@ -0,0 +1,23 @@ +import 'package:flutter/foundation.dart'; +import 'package:image/image.dart'; + +import '../../pages/setting/image_crop_page.dart'; +import '../../tools/dialog_tool.dart'; +import '../navigator_tool.dart'; +import 'image_pick_tool.dart'; +import 'image_tool.dart'; + +class ImageCropTool { + static Future crop() async { + if (kIsWeb) { + DialogTool.loading('加载中'); + final bytes = await ImagePickTool.pickImageAsBytes(); + final image = decodeImage(bytes); + final croped = copyCropCircle(image); + final path = await ImageTool.saveBytes(encodePng(croped)); + await DialogTool.close(); + return path; + } + return await NavigatorTool.push(ImageCropPage()); + } +} diff --git a/lib/tools/image/image_pick/image_pick_io.dart b/lib/tools/image/image_pick/image_pick_io.dart new file mode 100644 index 0000000..773d606 --- /dev/null +++ b/lib/tools/image/image_pick/image_pick_io.dart @@ -0,0 +1,19 @@ +import 'dart:typed_data'; +import 'package:image_picker/image_picker.dart'; + +import '../image_tool.dart'; + +class ImagePickTool { + static final picker = ImagePicker(); + + static Future pickImageAsBytes() async { + final pickedFile = await picker.getImage(source: ImageSource.gallery); + return await pickedFile?.readAsBytes(); + } + + static Future pickImageAndSave() async { + final bytes = await pickImageAsBytes(); + if (bytes == null) return null; + return await ImageTool.saveBytes(bytes); + } +} diff --git a/lib/tools/image/image_pick/image_pick_web.dart b/lib/tools/image/image_pick/image_pick_web.dart new file mode 100644 index 0000000..e421489 --- /dev/null +++ b/lib/tools/image/image_pick/image_pick_web.dart @@ -0,0 +1,20 @@ +import 'dart:typed_data'; +import 'package:flutter/foundation.dart'; +import 'package:image_picker_web_redux/image_picker_web_redux.dart'; + +import '../image_tool.dart'; + +class ImagePickTool { + static Future pickImageAsBytes() async { + if (kIsWeb) { + return await ImagePickerWeb.getImage(outputType: ImageType.bytes); + } + return null; + } + + static Future pickImageAndSave() async { + final bytes = await pickImageAsBytes(); + if (bytes == null) return null; + return await ImageTool.saveBytes(bytes); + } +} diff --git a/lib/tools/image/image_pick_tool.dart b/lib/tools/image/image_pick_tool.dart new file mode 100644 index 0000000..2ca77c3 --- /dev/null +++ b/lib/tools/image/image_pick_tool.dart @@ -0,0 +1 @@ +export 'image_pick/image_pick_io.dart' if (dart.library.html) 'image_pick/image_pick_web.dart'; \ No newline at end of file diff --git a/lib/tools/image/image_tool.dart b/lib/tools/image/image_tool.dart new file mode 100644 index 0000000..0325379 --- /dev/null +++ b/lib/tools/image/image_tool.dart @@ -0,0 +1,66 @@ +import 'dart:typed_data'; +import 'dart:ui'; + +import '../../game/level/levels.dart'; +import '../../game/level/levels_inner.dart'; +import '../../tools/cache/image_caches.dart'; +import '../file_tool.dart'; + +import 'ui_image_tool.dart'; + +class ImageTool { + static ImageCaches imageCaches = ImageCaches(); + + static void loadAll() async { + if (!Levels.inited) { + await Levels.init(); + } + final levelImages = Levels.kLevels.map((e) => e.image).toList(); + await imageCaches.loadAll([ + 'bg.png', + 'shine.png', + 'setting.png', + 'dead_line.png', + ...levelImages, + Levels.background, + ]); + } + + static void loadInnerLevels() async { + if (!Levels.inited) { + await Levels.init(); + } + final levelsImages = []; + LevelsInner.levels.values.forEach((levels) { + final images = levels.map((e) => e.image).toList(); + levelsImages.addAll(images); + }); + await imageCaches.loadAll(levelsImages); + } + + static Image image(String path) => imageCaches.fromCache(path); + + static Future imageBytes(String path) async => + image(path).toBytes(); + + static Future saveImage(Image img) async { + if (img == null) return null; + final timestamp = DateTime.now().millisecondsSinceEpoch.toString(); + final path = '/images/$timestamp.m'; + final bytes = await img.toBytes(); + await imageCaches.loadImage(path, img); //直接加载到内存 + await FileTool.write(path, bytes); //持久化到本地 + // await imageCaches.load(path); //从本地加载到内存 + return path; + } + + static Future saveBytes(Uint8List bytes) async { + if (bytes == null || bytes.isEmpty) return null; + final timestamp = DateTime.now().millisecondsSinceEpoch.toString(); + final path = '/images/$timestamp.m'; + await imageCaches.loadBytes(path, bytes); //直接加载到内存 + await FileTool.write(path, bytes); //持久化到本地 + // await imageCaches.load(path); //从本地加载到内存 + return path; + } +} diff --git a/lib/tools/image/ui_image_tool.dart b/lib/tools/image/ui_image_tool.dart new file mode 100644 index 0000000..b010ce9 --- /dev/null +++ b/lib/tools/image/ui_image_tool.dart @@ -0,0 +1,18 @@ +import 'dart:typed_data'; +import 'dart:convert'; +import 'dart:ui'; + +extension UiImageToBytes on Image { + Future toBytes() async { + final byteData = await toByteData(format: ImageByteFormat.png); + return byteData.buffer.asUint8List(); + } +} + +extension Base64ToBytes on String { + Uint8List toBytes() => base64Decode(this); +} + +extension BytesToBase64 on Uint8List { + String toBase64() => base64Encode(this); +} diff --git a/lib/tools/navigator_tool.dart b/lib/tools/navigator_tool.dart new file mode 100644 index 0000000..04a4ba6 --- /dev/null +++ b/lib/tools/navigator_tool.dart @@ -0,0 +1,41 @@ +import 'package:flutter/widgets.dart'; + +class NavigatorTool extends NavigatorObserver { + factory NavigatorTool() => _instance; + NavigatorTool._(); + static final NavigatorTool _instance = NavigatorTool._(); + + static BuildContext get gContext => _instance.navigator.context; + + static void pop([T result]) => + _instance.navigator.pop(result); + + static Future push(Widget child) => _instance.navigator.push(_page(child)); + + static Future replace(Widget child) => + _instance.navigator.pushReplacement(_page(child)); + + static Route _page(Widget child) { + return PageRouteBuilder( + opaque: false, + pageBuilder: (_, animation, __) => _animationPage(animation, child), + transitionsBuilder: (_, animation, __, child) => + _animationPage(animation, child), + ); + } + + static Widget _animationPage(Animation animation, Widget child) { + final value = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation( + parent: animation, + curve: Curves.fastOutSlowIn, + ), + ); + return FadeTransition( + opacity: value, + child: ScaleTransition( + scale: value, + child: child, + )); + } +} diff --git a/lib/tools/screen/screen_config.dart b/lib/tools/screen/screen_config.dart new file mode 100644 index 0000000..b26fe79 --- /dev/null +++ b/lib/tools/screen/screen_config.dart @@ -0,0 +1,36 @@ +import 'package:flutter/widgets.dart'; + +import 'screen_tool.dart'; + +class ScreenConfig extends StatelessWidget { + ScreenConfig({ + @required this.builder, + this.designSize = ScreenTool.defaultSize, + this.allowFontScaling = false, + Key key, + }) : super(key: key); + + final Widget Function() builder; + + /// 设计稿尺寸,单位px + final Size designSize; + + /// 是否允许字体大小缩放 + final bool allowFontScaling; + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (_, BoxConstraints constraints) { + if (constraints.maxWidth != 0) { + ScreenTool().init( + constraints, + designSize: designSize, + allowFontScaling: allowFontScaling, + ); + } + return builder(); + }, + ); + } +} diff --git a/lib/tools/screen/screen_extension.dart b/lib/tools/screen/screen_extension.dart new file mode 100644 index 0000000..447de1b --- /dev/null +++ b/lib/tools/screen/screen_extension.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; + +import 'screen_tool.dart'; + +extension SizeExtension on num { + double get w => ScreenTool().width(this); + double get h => ScreenTool().height(this); + double get vw => ScreenTool().screenWidth * this * 0.01; + double get vh => ScreenTool().screenHeight * this * 0.01; + double get r => ScreenTool().radius(this); + double get px => ScreenTool().width(this); //px2dp + double get sp => ScreenTool().font(this); + double get ssp => ScreenTool().font(this, allowScaling: true); + double get nsp => ScreenTool().font(this, allowScaling: false); +} + +extension ContextExtensionss on BuildContext { + Orientation get orientation => MediaQuery.of(this).orientation; + + ///横屏 + bool get isLandscape => orientation == Orientation.landscape; + + ///竖屏 + bool get isPortrait => orientation == Orientation.portrait; + + ///最短边 + double get shortestSide => mediaQuery.size.shortestSide; + double get height => mediaQuery.size.height; + double get width => mediaQuery.size.width; + ThemeData get theme => Theme.of(this); + bool get isDarkMode => theme.brightness == Brightness.dark; + Color get iconColor => theme.iconTheme.color; + TextTheme get textTheme => theme.textTheme; + MediaQueryData get mediaQuery => MediaQuery.of(this); + bool get showNavbar => (width > 800); + double get devicePixelRatio => MediaQuery.of(this).devicePixelRatio; + double get textScaleFactor => MediaQuery.of(this).textScaleFactor; + + T responsiveValue({ + T mobile, + T tablet, + T desktop, + T watch, + }) { + if (shortestSide >= 1200 && desktop != null) return desktop; + if (shortestSide >= 600 && tablet != null) return tablet; + if (shortestSide < 300 && watch != null) return watch; + return mobile; + } +} diff --git a/lib/tools/screen/screen_tool.dart b/lib/tools/screen/screen_tool.dart new file mode 100644 index 0000000..5f01f42 --- /dev/null +++ b/lib/tools/screen/screen_tool.dart @@ -0,0 +1,97 @@ +import 'dart:math'; +import 'dart:ui' as ui; + +import 'package:flutter/material.dart'; + +class ScreenTool { + factory ScreenTool() => _instance; + ScreenTool._(); + static final ScreenTool _instance = ScreenTool._(); + + static const Size defaultSize = Size(1080, 1920); + + /// 设计稿尺寸,单位px + Size uiSize; + + /// 是否允许字体大小缩放 + bool allowFontScaling; + + double _pixelRatio = 1; + double _textScaleFactor = 1; + double _screenWidth = 0; + double _screenHeight = 0; + double _statusBarHeight = 0; + double _bottomBarHeight = 0; + + void init( + BoxConstraints constraints, { + Size designSize, + bool allowFontScaling, + }) { + designSize ??= defaultSize; + allowFontScaling ??= false; + uiSize = designSize; + this.allowFontScaling = allowFontScaling; + + _screenWidth = constraints.maxWidth; //此处是当前组件的最大宽度 + _screenHeight = constraints.maxHeight; //此处是当前组件的最大高度度 + + var window = WidgetsBinding.instance?.window ?? ui.window; + + _pixelRatio = window.devicePixelRatio; + _statusBarHeight = window.padding.top; + _bottomBarHeight = window.padding.bottom; + _textScaleFactor = window.textScaleFactor; + } + + /// 根据UI设计的设备宽度适配 + double width(num width) => width * scaleWidth; + + /// 根据UI设计的设备高度适配 + double height(num height) => height * scaleHeight; + + /// 根据宽度或高度中的较小值进行适配 + double radius(num r) => r * scaleText; + + /// 字体大小适配方法,单位px. + double font(num fontSize, {bool allowScaling}) => allowScaling == null + ? (allowFontScaling + ? (fontSize * scaleText) * _textScaleFactor + : (fontSize * scaleText)) + : (allowScaling + ? (fontSize * scaleText) * _textScaleFactor + : (fontSize * scaleText)); + + /// 每个逻辑像素的字体像素数,字体的缩放比例 + double get textScaleFactor => _textScaleFactor; + + /// 设备的像素密度 + double get pixelRatio => _pixelRatio; + + /// 当前设备宽度 dp + double get screenWidth => _screenWidth; + + /// 当前设备高度 dp + double get screenHeight => _screenHeight; + + /// 当前设备最短边 dp + double get screenMin => min(_screenWidth, _screenHeight); + + /// 当前设备最长边 dp + double get screenMax => max(_screenWidth, _screenHeight); + + /// 状态栏高度 dp 刘海屏会更高 + double get statusBarHeight => _statusBarHeight / _pixelRatio; + + /// 底部安全区距离 dp + double get bottomBarHeight => _bottomBarHeight / _pixelRatio; + + /// 实际宽度与设计宽度的比例 + double get scaleWidth => _screenWidth / uiSize.width; + + /// 实际高度与设计高度的比例 + double get scaleHeight => _screenHeight / uiSize.height; + + /// 实际字体大小与设计字体大小的比例 + double get scaleText => min(scaleWidth, scaleHeight); +} diff --git a/lib/tools/sensor_tool.dart b/lib/tools/sensor_tool.dart new file mode 100644 index 0000000..0d4f7aa --- /dev/null +++ b/lib/tools/sensor_tool.dart @@ -0,0 +1,34 @@ +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:sensors/sensors.dart'; + +class XYZ { + XYZ(this.x, this.y, this.z); + final double x; + final double y; + final double z; + + @override + String toString() => 'x: $x, y: $y, z: $z'; +} + +class SensorTool { + static StreamSubscription _stream; + + static XYZ _xyz; + + static XYZ get xyz => _xyz ?? XYZ(0, 0, 0); + + static Future start() async { + if (kIsWeb) return; + await stop(); + _stream = accelerometerEvents.listen((data) { + _xyz = XYZ(data.x, data.y, data.z); + }); + } + + static Future stop() async { + if (!kIsWeb) await _stream?.cancel(); + } +} diff --git a/lib/tools/share_tool.dart b/lib/tools/share_tool.dart new file mode 100644 index 0000000..2877db9 --- /dev/null +++ b/lib/tools/share_tool.dart @@ -0,0 +1,5 @@ +import 'package:share_plus/share_plus.dart'; + +class ShareTool { + static Future share(String text) async => Share.share('$text'); +} diff --git a/lib/tools/size_tool.dart b/lib/tools/size_tool.dart new file mode 100644 index 0000000..26dc22e --- /dev/null +++ b/lib/tools/size_tool.dart @@ -0,0 +1,27 @@ +import 'package:flame/game.dart'; +import 'package:flame_forge2d/viewport.dart'; +import 'package:flutter/widgets.dart' hide Viewport; + +extension Size2Vector on Size { + Vector2 get toVector => Vector2(width, height); +} + +extension Offset2Vector on Offset { + Vector2 get toVector => Vector2(dx, dy); +} + +extension Vector2Offset on Vector2 { + Offset get toVector => Offset(x, y); + double get gravitySize => y / 600 * 50; + double get velocitySize => x / 6; +} + +extension SizeVector on BuildContext { + Size get size => MediaQuery.of(this).size; + Vector2 get vector => Vector2(size.width, size.height); +} + +extension VW on Viewport { + double vw(double percent) => percent * (size.x / 100); + double vh(double percent) => percent * (size.y / 100); +} diff --git a/lib/tools/system_tool.dart b/lib/tools/system_tool.dart new file mode 100644 index 0000000..c5b50d2 --- /dev/null +++ b/lib/tools/system_tool.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class SystemTool { + static void changeStatusBarColor([Color color]) { + color ??= Colors.white; + final style = SystemUiOverlayStyle( + statusBarColor: color, + systemNavigationBarDividerColor: null, + systemNavigationBarColor: color, + systemNavigationBarIconBrightness: Brightness.dark, + statusBarIconBrightness: Brightness.dark, + ); + SystemChrome.setSystemUIOverlayStyle(style); + } + + static void keepPortrait() { + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + DeviceOrientation.portraitDown, + ]); + } +} diff --git a/lib/tools/url_tool.dart b/lib/tools/url_tool.dart new file mode 100644 index 0000000..d5293d3 --- /dev/null +++ b/lib/tools/url_tool.dart @@ -0,0 +1,9 @@ +import 'package:url_launcher/url_launcher.dart'; + +class UrlTool { + static Future open(String url) async { + if (await canLaunch(url)) { + await launch(url); + } + } +} diff --git a/lib/widgets/base_widget.dart b/lib/widgets/base_widget.dart new file mode 100644 index 0000000..289a1ab --- /dev/null +++ b/lib/widgets/base_widget.dart @@ -0,0 +1,133 @@ +import 'package:flutter/material.dart'; + +TextStyle lTextStyle({ + Color color, + double size, + bool bold, +}) { + size ??= 14; + bold ??= false; + color ??= Colors.black; + return TextStyle( + color: color, + fontSize: size, + fontWeight: bold ? FontWeight.bold : FontWeight.normal, + ); +} + +Widget lText( + String text, { + Color color, + double size, + bool bold, + TextOverflow overflow, +}) { + size ??= 14; + bold ??= false; + color ??= Colors.black; + return Text( + '$text', + overflow: overflow, + style: TextStyle( + color: color, + fontSize: size, + fontWeight: bold ? FontWeight.bold : FontWeight.normal, + ), + ); +} + +Widget lHeight(double height) { + height ??= 10; + return SizedBox(height: height); +} + +Widget lWidth(double width) { + width ??= 10; + return SizedBox(width: width); +} + +Widget lBlank() { + return Container(); +} + +Widget lExpanded({int flex, Widget child}) { + flex ??= 1; + child ??= Container(); + return Expanded(flex: flex, child: Center(child: child)); +} + +Widget lTextField({ + String hintText, + double padding, + Function(String) onChanged, + Function(String) onSubmitted, + TextInputType keyboardType, +}) { + hintText ??= '请输入...'; + padding ??= 10; + onChanged ??= (_) {}; + onSubmitted ??= (_) {}; + keyboardType ??= TextInputType.number; + return Container( + child: TextField( + onChanged: onChanged, + onSubmitted: onSubmitted, + keyboardType: keyboardType, + decoration: InputDecoration( + contentPadding: EdgeInsets.all(padding), + hintText: hintText, + border: OutlineInputBorder(), + ), + ), + ); +} + +Widget lButton( + String text, { + void Function() onTap, + double height, + double fontSize, + double width, + double radius, + Color colorText, + Color colorBg, +}) { + height ??= 30; + width ??= height * 2 / 0.7; + radius ??= height / 2; + fontSize ??= 14; + colorText ??= Colors.black; + colorBg ??= Colors.grey[100]; + return GestureDetector( + onTap: onTap, + child: Container( + width: width, + height: height, + alignment: Alignment.center, + decoration: BoxDecoration( + color: colorBg, + borderRadius: BorderRadiusDirectional.all(Radius.circular(radius))), + child: lText(text, + color: colorText ?? Colors.black, size: fontSize, bold: true), + ), + ); +} + +Widget lIconButton( + IconData icon, { + double size, + Color color, + Function onTap, +}) { + size ??= 36; + color ??= Colors.white; + return IconButton( + iconSize: size, + icon: Icon( + icon, + size: size, + color: color, + ), + onPressed: onTap, + ); +} diff --git a/lib/widgets/pulse.dart b/lib/widgets/pulse.dart new file mode 100644 index 0000000..0aae709 --- /dev/null +++ b/lib/widgets/pulse.dart @@ -0,0 +1,42 @@ + +import 'package:flutter/material.dart'; + +class Pulse extends StatefulWidget { + final Widget child; + Pulse({this.child}); + @override + _PulseState createState() => _PulseState(); +} + +class _PulseState extends State with SingleTickerProviderStateMixin { + AnimationController _controller; + + @override + void initState() { + super.initState(); + _controller = AnimationController( + duration: Duration(milliseconds: 1200), + vsync: this, + )..repeat(); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return AnimatedBuilder( + animation: _controller, + child: widget.child, + builder: (BuildContext context, Widget child) { + return Transform.scale( + scale: 0.6 + 0.4 * (_controller.value % 0.5), + child: child, + ); + }, + ); + } +} diff --git a/lib/widgets/spinner.dart b/lib/widgets/spinner.dart new file mode 100644 index 0000000..9c633d7 --- /dev/null +++ b/lib/widgets/spinner.dart @@ -0,0 +1,43 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; + +class Spinner extends StatefulWidget { + final Widget child; + Spinner({this.child}); + @override + _SpinnerState createState() => _SpinnerState(); +} + +class _SpinnerState extends State with SingleTickerProviderStateMixin { + AnimationController _controller; + + @override + void initState() { + super.initState(); + _controller = AnimationController( + duration: const Duration(seconds: 10), + vsync: this, + )..repeat(); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return AnimatedBuilder( + animation: _controller, + child: widget.child, + builder: (BuildContext context, Widget child) { + return Transform.rotate( + angle: _controller.value * 2.0 * pi, + child: child, + ); + }, + ); + } +} diff --git a/lib/widgets/ui_image.dart b/lib/widgets/ui_image.dart new file mode 100644 index 0000000..7758bdc --- /dev/null +++ b/lib/widgets/ui_image.dart @@ -0,0 +1,29 @@ +import 'dart:typed_data'; + +import 'package:flutter/material.dart'; + +import '../tools/image/image_tool.dart'; + +class UiImage extends StatelessWidget { + final String path; + final Function(Uint8List) builder; + + UiImage(this.path, {@required this.builder}); + + @override + Widget build(BuildContext context) { + // 等价于 + // return RawImage(image: ImageTool.image(path)); + return FutureBuilder( + future: ImageTool.imageBytes(path), + builder: (context, snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.done: + return builder(snapshot.data); + default: + return Container(); + } + }, + ); + } +} diff --git a/logo.png b/logo.png new file mode 100644 index 0000000..e5abd07 Binary files /dev/null and b/logo.png differ diff --git a/macos/.DS_Store b/macos/.DS_Store new file mode 100644 index 0000000..98237d5 Binary files /dev/null and b/macos/.DS_Store differ diff --git a/macos/.gitignore b/macos/.gitignore new file mode 100644 index 0000000..d2fd377 --- /dev/null +++ b/macos/.gitignore @@ -0,0 +1,6 @@ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/xcuserdata/ diff --git a/macos/Flutter/Flutter-Debug.xcconfig b/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 0000000..4b81f9b --- /dev/null +++ b/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/Flutter-Release.xcconfig b/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 0000000..5caa9d1 --- /dev/null +++ b/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 0000000..d2b1699 --- /dev/null +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,16 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import audioplayers +import path_provider_macos +import url_launcher_macos + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + AudioplayersPlugin.register(with: registry.registrar(forPlugin: "AudioplayersPlugin")) + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) +} diff --git a/macos/Podfile b/macos/Podfile new file mode 100644 index 0000000..dade8df --- /dev/null +++ b/macos/Podfile @@ -0,0 +1,40 @@ +platform :osx, '10.11' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/macos/Podfile.lock b/macos/Podfile.lock new file mode 100644 index 0000000..e18c39b --- /dev/null +++ b/macos/Podfile.lock @@ -0,0 +1,34 @@ +PODS: + - audioplayers (0.0.1): + - FlutterMacOS + - FlutterMacOS (1.0.0) + - path_provider_macos (0.0.1): + - FlutterMacOS + - url_launcher_macos (0.0.1): + - FlutterMacOS + +DEPENDENCIES: + - audioplayers (from `Flutter/ephemeral/.symlinks/plugins/audioplayers/macos`) + - FlutterMacOS (from `Flutter/ephemeral`) + - path_provider_macos (from `Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos`) + - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) + +EXTERNAL SOURCES: + audioplayers: + :path: Flutter/ephemeral/.symlinks/plugins/audioplayers/macos + FlutterMacOS: + :path: Flutter/ephemeral + path_provider_macos: + :path: Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos + url_launcher_macos: + :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos + +SPEC CHECKSUMS: + audioplayers: 882556ed7be47c58b26f1098177c7e814d8a1f2a + FlutterMacOS: 57701585bf7de1b3fc2bb61f6378d73bbdea8424 + path_provider_macos: a0a3fd666cb7cd0448e936fb4abad4052961002b + url_launcher_macos: 45af3d61de06997666568a7149c1be98b41c95d4 + +PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c + +COCOAPODS: 1.9.3 diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..4edef71 --- /dev/null +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,644 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + CF2ACE8E1975D9AE44035182 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 823B980B951A3F1A74A7A904 /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* watermelon.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = watermelon.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 5AD90A13C074106A052038D4 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 823B980B951A3F1A74A7A904 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 8BB218566A43A6FA03D917FD /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + A3D59C8347626AC9BE5A4D13 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CF2ACE8E1975D9AE44035182 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + 5EAD3A561E2AE6D947D06927 /* Pods */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* watermelon.app */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + 5EAD3A561E2AE6D947D06927 /* Pods */ = { + isa = PBXGroup; + children = ( + A3D59C8347626AC9BE5A4D13 /* Pods-Runner.debug.xcconfig */, + 5AD90A13C074106A052038D4 /* Pods-Runner.release.xcconfig */, + 8BB218566A43A6FA03D917FD /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 823B980B951A3F1A74A7A904 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + EBC39B516F739D4C97913235 /* [CP] Check Pods Manifest.lock */, + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + 2077C5ABFC9CBA472D96CBE6 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* watermelon.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 0930; + ORGANIZATIONNAME = "The Flutter Authors"; + TargetAttributes = { + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 8.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 2077C5ABFC9CBA472D96CBE6 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; + EBC39B516F739D4C97913235 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter/ephemeral", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter/ephemeral", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter/ephemeral", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..12cf116 --- /dev/null +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macos/Runner.xcworkspace/contents.xcworkspacedata b/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..21a3cc1 --- /dev/null +++ b/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/macos/Runner/AppDelegate.swift b/macos/Runner/AppDelegate.swift new file mode 100644 index 0000000..d53ef64 --- /dev/null +++ b/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@NSApplicationMain +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..a2ec33f --- /dev/null +++ b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 0000000..3c4935a Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 0000000..ed4cc16 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100644 index 0000000..483be61 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100644 index 0000000..bcbf36d Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png new file mode 100644 index 0000000..9c0a652 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100644 index 0000000..e71a726 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100644 index 0000000..8a31fe2 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ diff --git a/macos/Runner/Base.lproj/MainMenu.xib b/macos/Runner/Base.lproj/MainMenu.xib new file mode 100644 index 0000000..537341a --- /dev/null +++ b/macos/Runner/Base.lproj/MainMenu.xib @@ -0,0 +1,339 @@ + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macos/Runner/Configs/AppInfo.xcconfig b/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 0000000..10cad7e --- /dev/null +++ b/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = watermelon + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = cat.love.mix + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2021 com.example. All rights reserved. diff --git a/macos/Runner/Configs/Debug.xcconfig b/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 0000000..36b0fd9 --- /dev/null +++ b/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/macos/Runner/Configs/Release.xcconfig b/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 0000000..dff4f49 --- /dev/null +++ b/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/macos/Runner/Configs/Warnings.xcconfig b/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 0000000..42bcbf4 --- /dev/null +++ b/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/macos/Runner/DebugProfile.entitlements b/macos/Runner/DebugProfile.entitlements new file mode 100644 index 0000000..dddb8a3 --- /dev/null +++ b/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/macos/Runner/Info.plist b/macos/Runner/Info.plist new file mode 100644 index 0000000..4789daa --- /dev/null +++ b/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/macos/Runner/MainFlutterWindow.swift b/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 0000000..2722837 --- /dev/null +++ b/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController.init() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/macos/Runner/Release.entitlements b/macos/Runner/Release.entitlements new file mode 100644 index 0000000..852fa1a --- /dev/null +++ b/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..cd25b2d --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,515 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + archive: + dependency: transitive + description: + name: archive + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.13" + args: + dependency: transitive + description: + name: args + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.6.0" + async: + dependency: transitive + description: + name: async + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.5.0" + audioplayers: + dependency: transitive + description: + name: audioplayers + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.15.1" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.0" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.0" + clock: + dependency: transitive + description: + name: clock + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.0" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.15.0" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.1" + crop: + dependency: "direct main" + description: + path: "." + ref: circle + resolved-ref: "5dbcadaf6bdcb10463de0a49c52f96525299c601" + url: "https://github.com/idootop/flutter_crop.git" + source: git + version: "0.4.2" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.5" + fake_async: + dependency: transitive + description: + name: fake_async + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.0" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.1.3" + file: + dependency: transitive + description: + name: file + url: "https://pub.flutter-io.cn" + source: hosted + version: "5.2.1" + flame: + dependency: "direct main" + description: + name: flame + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.0-rc6" + flame_audio: + dependency: "direct main" + description: + path: "." + ref: "576c7cd" + resolved-ref: "576c7cd4e31460751f8c834e2298fced94fb4f7e" + url: "https://github.com/idootop/flame_audio.git" + source: git + version: "0.1.0-rc3" + flame_forge2d: + dependency: "direct main" + description: + name: flame_forge2d + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.6.2-rc3" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.11" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + forge2d: + dependency: transitive + description: + name: forge2d + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.6.2" + hive: + dependency: "direct main" + description: + name: hive + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.4.4+1" + http: + dependency: transitive + description: + name: http + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.12.2" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.1.4" + image: + dependency: "direct main" + description: + path: "." + ref: crop + resolved-ref: d25d422edb328fb9234e8c562ddde715daa735f5 + url: "https://github.com/idootop/image.git" + source: git + version: "2.1.19" + image_picker: + dependency: "direct main" + description: + name: image_picker + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.6.7+22" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.6" + image_picker_web_redux: + dependency: "direct main" + description: + name: image_picker_web_redux + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.3" + intl: + dependency: transitive + description: + name: intl + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.16.1" + js: + dependency: transitive + description: + name: js + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.6.3" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.12.10" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.3.0" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.9.7" + ordered_set: + dependency: transitive + description: + name: ordered_set + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.1" + path: + dependency: transitive + description: + name: path + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.8.0" + path_provider: + dependency: "direct main" + description: + name: path_provider + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.6.27" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.0.1+2" + path_provider_macos: + dependency: transitive + description: + name: path_provider_macos + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.0.4+8" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.4" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.0.4+3" + pedantic: + dependency: "direct main" + description: + name: pedantic + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.10.0-nullsafety.3" + petitparser: + dependency: transitive + description: + name: petitparser + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.1.0" + platform: + dependency: transitive + description: + name: platform + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.0.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.3" + process: + dependency: transitive + description: + name: process + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.0.13" + sensors: + dependency: "direct main" + description: + name: sensors + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.4.2+6" + share_plus: + dependency: "direct main" + description: + name: share_plus + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.0" + share_plus_linux: + dependency: transitive + description: + name: share_plus_linux + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.0" + share_plus_platform_interface: + dependency: transitive + description: + name: share_plus_platform_interface + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.0" + share_plus_web: + dependency: transitive + description: + name: share_plus_web + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.1.0" + share_plus_windows: + dependency: transitive + description: + name: share_plus_windows + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.1.0" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.8.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.10.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.0" + synchronized: + dependency: transitive + description: + name: synchronized + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.2.0+2" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.0" + test_api: + dependency: transitive + description: + name: test_api + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.2.19" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.3.0" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + url: "https://pub.flutter-io.cn" + source: hosted + version: "5.7.10" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.0.1+4" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.0.1+9" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.9" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.1.5+3" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.0.1+3" + uuid: + dependency: transitive + description: + name: uuid + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.2.2" + vector_math: + dependency: transitive + description: + name: vector_math + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.0" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.7.4+1" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.1.2" + xml: + dependency: transitive + description: + name: xml + url: "https://pub.flutter-io.cn" + source: hosted + version: "4.5.1" +sdks: + dart: ">=2.12.0-0.0 <3.0.0" + flutter: ">=1.22.0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..70d565a --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,55 @@ +name: watermelon +description: Flutter版合成大西瓜 + +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +version: 1.0.0+1 + +environment: + sdk: ">=2.7.0 <3.0.0" + +dependencies: + flutter: + sdk: flutter + pedantic: ^1.9.2 + flame: ^1.0.0-rc6 + flame_forge2d: ^0.6.2-rc3 + path_provider: ^1.6.27 + hive: ^1.4.4+1 + sensors: ^0.4.2+6 + url_launcher: ^5.7.10 + image_picker: ^0.6.7+22 + image_picker_web_redux: ^1.1.3 + share_plus: ^1.2.0 + flame_audio: + git: + url: https://github.com/idootop/flame_audio.git + ref: 576c7cd + crop: + git: + url: https://github.com/idootop/flutter_crop.git + ref: circle + image: + git: + url: https://github.com/idootop/image.git + ref: crop + + +dev_dependencies: + flutter_test: + sdk: flutter + +flutter: + uses-material-design: true + assets: + - assets/audio/ + - assets/images/ + - assets/images/friuts/ + - assets/images/qq/ + - assets/images/985/ + - assets/images/shandong/ + +flutter_icons: + image_path: "logo.png" + android: true + ios: true \ No newline at end of file diff --git a/screenshots/img.jpg b/screenshots/img.jpg new file mode 100644 index 0000000..684ce93 Binary files /dev/null and b/screenshots/img.jpg differ diff --git a/screenshots/inner.jpg b/screenshots/inner.jpg new file mode 100644 index 0000000..e698d51 Binary files /dev/null and b/screenshots/inner.jpg differ diff --git a/screenshots/logo.png b/screenshots/logo.png new file mode 100644 index 0000000..553630a Binary files /dev/null and b/screenshots/logo.png differ diff --git a/screenshots/play.jpg b/screenshots/play.jpg new file mode 100644 index 0000000..c54c8b6 Binary files /dev/null and b/screenshots/play.jpg differ diff --git a/screenshots/win.jpg b/screenshots/win.jpg new file mode 100644 index 0000000..904813d Binary files /dev/null and b/screenshots/win.jpg differ diff --git a/watermelon.iml b/watermelon.iml new file mode 100644 index 0000000..e5c8371 --- /dev/null +++ b/watermelon.iml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/favicon.png b/web/favicon.png new file mode 100644 index 0000000..8aaa46a Binary files /dev/null and b/web/favicon.png differ diff --git a/web/icons/Icon-192.png b/web/icons/Icon-192.png new file mode 100644 index 0000000..b749bfe Binary files /dev/null and b/web/icons/Icon-192.png differ diff --git a/web/icons/Icon-512.png b/web/icons/Icon-512.png new file mode 100644 index 0000000..88cfd48 Binary files /dev/null and b/web/icons/Icon-512.png differ diff --git a/web/index.html b/web/index.html new file mode 100644 index 0000000..4e242ce --- /dev/null +++ b/web/index.html @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + 合成大瓜 + + + + + + + + + + \ No newline at end of file diff --git a/web/manifest.json b/web/manifest.json new file mode 100644 index 0000000..9fec97b --- /dev/null +++ b/web/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "watermelon", + "short_name": "watermelon", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +}