├── .gitignore ├── .metadata ├── .vscode └── launch.json ├── LICENSE ├── README.md ├── analysis_options.yaml ├── assets └── images │ └── spritesheet.png ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings ├── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ └── Runner-Bridging-Header.h └── RunnerTests │ └── RunnerTests.swift ├── lib ├── game │ ├── entities │ │ ├── ground.dart │ │ ├── ship.dart │ │ └── smoke.dart │ ├── game.dart │ ├── post_process │ │ ├── sea_post_process.dart │ │ ├── ship_post_process.dart │ │ ├── smoke_post_process.dart │ │ ├── vignette_post_process.dart │ │ └── wake_post_process.dart │ ├── utilities │ │ ├── camera_target.dart │ │ ├── game_perspective.dart │ │ ├── input_interface.dart │ │ ├── isometric_component.dart │ │ └── konstants.dart │ └── view │ │ └── game_view.dart └── main.dart ├── macos ├── .gitignore ├── Flutter │ ├── Flutter-Debug.xcconfig │ ├── Flutter-Release.xcconfig │ └── GeneratedPluginRegistrant.swift ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── app_icon_1024.png │ │ │ ├── app_icon_128.png │ │ │ ├── app_icon_16.png │ │ │ ├── app_icon_256.png │ │ │ ├── app_icon_32.png │ │ │ ├── app_icon_512.png │ │ │ └── app_icon_64.png │ ├── Base.lproj │ │ └── MainMenu.xib │ ├── Configs │ │ ├── AppInfo.xcconfig │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── Warnings.xcconfig │ ├── DebugProfile.entitlements │ ├── Info.plist │ ├── MainFlutterWindow.swift │ └── Release.entitlements └── RunnerTests │ └── RunnerTests.swift ├── pubspec.lock ├── pubspec.yaml ├── shaders ├── sea.frag ├── ship.frag ├── ship_wake.frag ├── smoke.frag └── vignette.frag ├── test └── widget_test.dart └── web ├── favicon.png ├── icons ├── Icon-192.png ├── Icon-512.png ├── Icon-maskable-192.png └── Icon-maskable-512.png ├── index.html └── manifest.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .build/ 9 | .buildlog/ 10 | .history 11 | .svn/ 12 | .swiftpm/ 13 | migrate_working_dir/ 14 | 15 | .vscode/ 16 | 17 | # IntelliJ related 18 | *.iml 19 | *.ipr 20 | *.iws 21 | .idea/ 22 | 23 | # The .vscode folder contains launch configuration and tasks you configure in 24 | # VS Code which you may wish to be included in version control, so this line 25 | # is commented out by default. 26 | #.vscode/ 27 | 28 | # Flutter/Dart/Pub related 29 | **/doc/api/ 30 | **/ios/Flutter/.last_build_id 31 | .dart_tool/ 32 | .flutter-plugins-dependencies 33 | .pub-cache/ 34 | .pub/ 35 | /build/ 36 | /coverage/ 37 | 38 | # Symbolication related 39 | app.*.symbols 40 | 41 | # Obfuscation related 42 | app.*.map.json 43 | 44 | # Android Studio will place build artifacts here 45 | /android/app/debug 46 | /android/app/profile 47 | /android/app/release 48 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "c84cdd0d0b582d1b65028a05bb39ba5f0a1599c2" 8 | channel: "beta" 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: c84cdd0d0b582d1b65028a05bb39ba5f0a1599c2 17 | base_revision: c84cdd0d0b582d1b65028a05bb39ba5f0a1599c2 18 | - platform: ios 19 | create_revision: c84cdd0d0b582d1b65028a05bb39ba5f0a1599c2 20 | base_revision: c84cdd0d0b582d1b65028a05bb39ba5f0a1599c2 21 | - platform: macos 22 | create_revision: c84cdd0d0b582d1b65028a05bb39ba5f0a1599c2 23 | base_revision: c84cdd0d0b582d1b65028a05bb39ba5f0a1599c2 24 | - platform: web 25 | create_revision: c84cdd0d0b582d1b65028a05bb39ba5f0a1599c2 26 | base_revision: c84cdd0d0b582d1b65028a05bb39ba5f0a1599c2 27 | 28 | # User provided section 29 | 30 | # List of Local paths (relative to this file) that should be 31 | # ignored by the migrate tool. 32 | # 33 | # Files that are not part of the templates will be ignored by default. 34 | unmanaged_files: 35 | - 'lib/main.dart' 36 | - 'ios/Runner.xcodeproj/project.pbxproj' 37 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Ship game", 9 | "request": "launch", 10 | "type": "dart" 11 | }, 12 | { 13 | "name": "Ship game (profile mode)", 14 | "request": "launch", 15 | "type": "dart", 16 | "flutterMode": "profile" 17 | }, 18 | { 19 | "name": "Ship game (release mode)", 20 | "request": "launch", 21 | "type": "dart", 22 | "flutterMode": "release" 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ship Game 2 | 3 | An experiment with the [Flame Engine](https://flame-engine.org/) used with the fragment shaders. Built for my talk at [Flutter & Friends 2025](https://www.flutterfriends.dev/). 4 | 5 | 6 | 7 | 8 | 9 | https://github.com/user-attachments/assets/8fba222e-3602-4832-a44f-dbc740e825fa 10 | 11 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flame_lint/analysis_options_with_dcm.yaml 2 | -------------------------------------------------------------------------------- /assets/images/spritesheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/assets/images/spritesheet.png -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 13.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 54; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 12 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 13 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 14 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 15 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 16 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXContainerItemProxy section */ 20 | 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { 21 | isa = PBXContainerItemProxy; 22 | containerPortal = 97C146E61CF9000F007C117D /* Project object */; 23 | proxyType = 1; 24 | remoteGlobalIDString = 97C146ED1CF9000F007C117D; 25 | remoteInfo = Runner; 26 | }; 27 | /* End PBXContainerItemProxy section */ 28 | 29 | /* Begin PBXCopyFilesBuildPhase section */ 30 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 31 | isa = PBXCopyFilesBuildPhase; 32 | buildActionMask = 2147483647; 33 | dstPath = ""; 34 | dstSubfolderSpec = 10; 35 | files = ( 36 | ); 37 | name = "Embed Frameworks"; 38 | runOnlyForDeploymentPostprocessing = 0; 39 | }; 40 | /* End PBXCopyFilesBuildPhase section */ 41 | 42 | /* Begin PBXFileReference section */ 43 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 44 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 45 | 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 46 | 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 47 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 48 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 49 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 50 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 51 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 52 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 53 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 55 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 56 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 57 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 58 | /* End PBXFileReference section */ 59 | 60 | /* Begin PBXFrameworksBuildPhase section */ 61 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 62 | isa = PBXFrameworksBuildPhase; 63 | buildActionMask = 2147483647; 64 | files = ( 65 | ); 66 | runOnlyForDeploymentPostprocessing = 0; 67 | }; 68 | /* End PBXFrameworksBuildPhase section */ 69 | 70 | /* Begin PBXGroup section */ 71 | 331C8082294A63A400263BE5 /* RunnerTests */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | 331C807B294A618700263BE5 /* RunnerTests.swift */, 75 | ); 76 | path = RunnerTests; 77 | sourceTree = ""; 78 | }; 79 | 9740EEB11CF90186004384FC /* Flutter */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 83 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 84 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 85 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 86 | ); 87 | name = Flutter; 88 | sourceTree = ""; 89 | }; 90 | 97C146E51CF9000F007C117D = { 91 | isa = PBXGroup; 92 | children = ( 93 | 9740EEB11CF90186004384FC /* Flutter */, 94 | 97C146F01CF9000F007C117D /* Runner */, 95 | 97C146EF1CF9000F007C117D /* Products */, 96 | 331C8082294A63A400263BE5 /* RunnerTests */, 97 | ); 98 | sourceTree = ""; 99 | }; 100 | 97C146EF1CF9000F007C117D /* Products */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | 97C146EE1CF9000F007C117D /* Runner.app */, 104 | 331C8081294A63A400263BE5 /* RunnerTests.xctest */, 105 | ); 106 | name = Products; 107 | sourceTree = ""; 108 | }; 109 | 97C146F01CF9000F007C117D /* Runner */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 113 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 114 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 115 | 97C147021CF9000F007C117D /* Info.plist */, 116 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 117 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 118 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 119 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 120 | ); 121 | path = Runner; 122 | sourceTree = ""; 123 | }; 124 | /* End PBXGroup section */ 125 | 126 | /* Begin PBXNativeTarget section */ 127 | 331C8080294A63A400263BE5 /* RunnerTests */ = { 128 | isa = PBXNativeTarget; 129 | buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; 130 | buildPhases = ( 131 | 331C807D294A63A400263BE5 /* Sources */, 132 | 331C807F294A63A400263BE5 /* Resources */, 133 | ); 134 | buildRules = ( 135 | ); 136 | dependencies = ( 137 | 331C8086294A63A400263BE5 /* PBXTargetDependency */, 138 | ); 139 | name = RunnerTests; 140 | productName = RunnerTests; 141 | productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; 142 | productType = "com.apple.product-type.bundle.unit-test"; 143 | }; 144 | 97C146ED1CF9000F007C117D /* Runner */ = { 145 | isa = PBXNativeTarget; 146 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 147 | buildPhases = ( 148 | 9740EEB61CF901F6004384FC /* Run Script */, 149 | 97C146EA1CF9000F007C117D /* Sources */, 150 | 97C146EB1CF9000F007C117D /* Frameworks */, 151 | 97C146EC1CF9000F007C117D /* Resources */, 152 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 153 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 154 | ); 155 | buildRules = ( 156 | ); 157 | dependencies = ( 158 | ); 159 | name = Runner; 160 | productName = Runner; 161 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 162 | productType = "com.apple.product-type.application"; 163 | }; 164 | /* End PBXNativeTarget section */ 165 | 166 | /* Begin PBXProject section */ 167 | 97C146E61CF9000F007C117D /* Project object */ = { 168 | isa = PBXProject; 169 | attributes = { 170 | BuildIndependentTargetsInParallel = YES; 171 | LastUpgradeCheck = 1510; 172 | ORGANIZATIONNAME = ""; 173 | TargetAttributes = { 174 | 331C8080294A63A400263BE5 = { 175 | CreatedOnToolsVersion = 14.0; 176 | TestTargetID = 97C146ED1CF9000F007C117D; 177 | }; 178 | 97C146ED1CF9000F007C117D = { 179 | CreatedOnToolsVersion = 7.3.1; 180 | LastSwiftMigration = 1100; 181 | }; 182 | }; 183 | }; 184 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 185 | compatibilityVersion = "Xcode 9.3"; 186 | developmentRegion = en; 187 | hasScannedForEncodings = 0; 188 | knownRegions = ( 189 | en, 190 | Base, 191 | ); 192 | mainGroup = 97C146E51CF9000F007C117D; 193 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 194 | projectDirPath = ""; 195 | projectRoot = ""; 196 | targets = ( 197 | 97C146ED1CF9000F007C117D /* Runner */, 198 | 331C8080294A63A400263BE5 /* RunnerTests */, 199 | ); 200 | }; 201 | /* End PBXProject section */ 202 | 203 | /* Begin PBXResourcesBuildPhase section */ 204 | 331C807F294A63A400263BE5 /* Resources */ = { 205 | isa = PBXResourcesBuildPhase; 206 | buildActionMask = 2147483647; 207 | files = ( 208 | ); 209 | runOnlyForDeploymentPostprocessing = 0; 210 | }; 211 | 97C146EC1CF9000F007C117D /* Resources */ = { 212 | isa = PBXResourcesBuildPhase; 213 | buildActionMask = 2147483647; 214 | files = ( 215 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 216 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 217 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 218 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 219 | ); 220 | runOnlyForDeploymentPostprocessing = 0; 221 | }; 222 | /* End PBXResourcesBuildPhase section */ 223 | 224 | /* Begin PBXShellScriptBuildPhase section */ 225 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 226 | isa = PBXShellScriptBuildPhase; 227 | alwaysOutOfDate = 1; 228 | buildActionMask = 2147483647; 229 | files = ( 230 | ); 231 | inputPaths = ( 232 | "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", 233 | ); 234 | name = "Thin Binary"; 235 | outputPaths = ( 236 | ); 237 | runOnlyForDeploymentPostprocessing = 0; 238 | shellPath = /bin/sh; 239 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 240 | }; 241 | 9740EEB61CF901F6004384FC /* Run Script */ = { 242 | isa = PBXShellScriptBuildPhase; 243 | alwaysOutOfDate = 1; 244 | buildActionMask = 2147483647; 245 | files = ( 246 | ); 247 | inputPaths = ( 248 | ); 249 | name = "Run Script"; 250 | outputPaths = ( 251 | ); 252 | runOnlyForDeploymentPostprocessing = 0; 253 | shellPath = /bin/sh; 254 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 255 | }; 256 | /* End PBXShellScriptBuildPhase section */ 257 | 258 | /* Begin PBXSourcesBuildPhase section */ 259 | 331C807D294A63A400263BE5 /* Sources */ = { 260 | isa = PBXSourcesBuildPhase; 261 | buildActionMask = 2147483647; 262 | files = ( 263 | 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, 264 | ); 265 | runOnlyForDeploymentPostprocessing = 0; 266 | }; 267 | 97C146EA1CF9000F007C117D /* Sources */ = { 268 | isa = PBXSourcesBuildPhase; 269 | buildActionMask = 2147483647; 270 | files = ( 271 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 272 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 273 | ); 274 | runOnlyForDeploymentPostprocessing = 0; 275 | }; 276 | /* End PBXSourcesBuildPhase section */ 277 | 278 | /* Begin PBXTargetDependency section */ 279 | 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { 280 | isa = PBXTargetDependency; 281 | target = 97C146ED1CF9000F007C117D /* Runner */; 282 | targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; 283 | }; 284 | /* End PBXTargetDependency section */ 285 | 286 | /* Begin PBXVariantGroup section */ 287 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 288 | isa = PBXVariantGroup; 289 | children = ( 290 | 97C146FB1CF9000F007C117D /* Base */, 291 | ); 292 | name = Main.storyboard; 293 | sourceTree = ""; 294 | }; 295 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 296 | isa = PBXVariantGroup; 297 | children = ( 298 | 97C147001CF9000F007C117D /* Base */, 299 | ); 300 | name = LaunchScreen.storyboard; 301 | sourceTree = ""; 302 | }; 303 | /* End PBXVariantGroup section */ 304 | 305 | /* Begin XCBuildConfiguration section */ 306 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 307 | isa = XCBuildConfiguration; 308 | buildSettings = { 309 | ALWAYS_SEARCH_USER_PATHS = NO; 310 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 311 | CLANG_ANALYZER_NONNULL = YES; 312 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 313 | CLANG_CXX_LIBRARY = "libc++"; 314 | CLANG_ENABLE_MODULES = YES; 315 | CLANG_ENABLE_OBJC_ARC = YES; 316 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 317 | CLANG_WARN_BOOL_CONVERSION = YES; 318 | CLANG_WARN_COMMA = YES; 319 | CLANG_WARN_CONSTANT_CONVERSION = YES; 320 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 321 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 322 | CLANG_WARN_EMPTY_BODY = YES; 323 | CLANG_WARN_ENUM_CONVERSION = YES; 324 | CLANG_WARN_INFINITE_RECURSION = YES; 325 | CLANG_WARN_INT_CONVERSION = YES; 326 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 327 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 328 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 329 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 330 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 331 | CLANG_WARN_STRICT_PROTOTYPES = YES; 332 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 333 | CLANG_WARN_UNREACHABLE_CODE = YES; 334 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 335 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 336 | COPY_PHASE_STRIP = NO; 337 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 338 | ENABLE_NS_ASSERTIONS = NO; 339 | ENABLE_STRICT_OBJC_MSGSEND = YES; 340 | ENABLE_USER_SCRIPT_SANDBOXING = NO; 341 | GCC_C_LANGUAGE_STANDARD = gnu99; 342 | GCC_NO_COMMON_BLOCKS = YES; 343 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 344 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 345 | GCC_WARN_UNDECLARED_SELECTOR = YES; 346 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 347 | GCC_WARN_UNUSED_FUNCTION = YES; 348 | GCC_WARN_UNUSED_VARIABLE = YES; 349 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 350 | MTL_ENABLE_DEBUG_INFO = NO; 351 | SDKROOT = iphoneos; 352 | SUPPORTED_PLATFORMS = iphoneos; 353 | TARGETED_DEVICE_FAMILY = "1,2"; 354 | VALIDATE_PRODUCT = YES; 355 | }; 356 | name = Profile; 357 | }; 358 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 359 | isa = XCBuildConfiguration; 360 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 361 | buildSettings = { 362 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 363 | CLANG_ENABLE_MODULES = YES; 364 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 365 | DEVELOPMENT_TEAM = ZR5SPHW7AC; 366 | ENABLE_BITCODE = NO; 367 | INFOPLIST_FILE = Runner/Info.plist; 368 | LD_RUNPATH_SEARCH_PATHS = ( 369 | "$(inherited)", 370 | "@executable_path/Frameworks", 371 | ); 372 | PRODUCT_BUNDLE_IDENTIFIER = gg.renan.demo2; 373 | PRODUCT_NAME = "$(TARGET_NAME)"; 374 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 375 | SWIFT_VERSION = 5.0; 376 | VERSIONING_SYSTEM = "apple-generic"; 377 | }; 378 | name = Profile; 379 | }; 380 | 331C8088294A63A400263BE5 /* Debug */ = { 381 | isa = XCBuildConfiguration; 382 | buildSettings = { 383 | BUNDLE_LOADER = "$(TEST_HOST)"; 384 | CODE_SIGN_STYLE = Automatic; 385 | CURRENT_PROJECT_VERSION = 1; 386 | GENERATE_INFOPLIST_FILE = YES; 387 | MARKETING_VERSION = 1.0; 388 | PRODUCT_BUNDLE_IDENTIFIER = gg.renan.demo2.RunnerTests; 389 | PRODUCT_NAME = "$(TARGET_NAME)"; 390 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 391 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 392 | SWIFT_VERSION = 5.0; 393 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; 394 | }; 395 | name = Debug; 396 | }; 397 | 331C8089294A63A400263BE5 /* Release */ = { 398 | isa = XCBuildConfiguration; 399 | buildSettings = { 400 | BUNDLE_LOADER = "$(TEST_HOST)"; 401 | CODE_SIGN_STYLE = Automatic; 402 | CURRENT_PROJECT_VERSION = 1; 403 | GENERATE_INFOPLIST_FILE = YES; 404 | MARKETING_VERSION = 1.0; 405 | PRODUCT_BUNDLE_IDENTIFIER = gg.renan.demo2.RunnerTests; 406 | PRODUCT_NAME = "$(TARGET_NAME)"; 407 | SWIFT_VERSION = 5.0; 408 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; 409 | }; 410 | name = Release; 411 | }; 412 | 331C808A294A63A400263BE5 /* Profile */ = { 413 | isa = XCBuildConfiguration; 414 | buildSettings = { 415 | BUNDLE_LOADER = "$(TEST_HOST)"; 416 | CODE_SIGN_STYLE = Automatic; 417 | CURRENT_PROJECT_VERSION = 1; 418 | GENERATE_INFOPLIST_FILE = YES; 419 | MARKETING_VERSION = 1.0; 420 | PRODUCT_BUNDLE_IDENTIFIER = gg.renan.demo2.RunnerTests; 421 | PRODUCT_NAME = "$(TARGET_NAME)"; 422 | SWIFT_VERSION = 5.0; 423 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; 424 | }; 425 | name = Profile; 426 | }; 427 | 97C147031CF9000F007C117D /* Debug */ = { 428 | isa = XCBuildConfiguration; 429 | buildSettings = { 430 | ALWAYS_SEARCH_USER_PATHS = NO; 431 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 432 | CLANG_ANALYZER_NONNULL = YES; 433 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 434 | CLANG_CXX_LIBRARY = "libc++"; 435 | CLANG_ENABLE_MODULES = YES; 436 | CLANG_ENABLE_OBJC_ARC = YES; 437 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 438 | CLANG_WARN_BOOL_CONVERSION = YES; 439 | CLANG_WARN_COMMA = YES; 440 | CLANG_WARN_CONSTANT_CONVERSION = YES; 441 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 442 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 443 | CLANG_WARN_EMPTY_BODY = YES; 444 | CLANG_WARN_ENUM_CONVERSION = YES; 445 | CLANG_WARN_INFINITE_RECURSION = YES; 446 | CLANG_WARN_INT_CONVERSION = YES; 447 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 448 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 449 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 450 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 451 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 452 | CLANG_WARN_STRICT_PROTOTYPES = YES; 453 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 454 | CLANG_WARN_UNREACHABLE_CODE = YES; 455 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 456 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 457 | COPY_PHASE_STRIP = NO; 458 | DEBUG_INFORMATION_FORMAT = dwarf; 459 | ENABLE_STRICT_OBJC_MSGSEND = YES; 460 | ENABLE_TESTABILITY = YES; 461 | ENABLE_USER_SCRIPT_SANDBOXING = NO; 462 | GCC_C_LANGUAGE_STANDARD = gnu99; 463 | GCC_DYNAMIC_NO_PIC = NO; 464 | GCC_NO_COMMON_BLOCKS = YES; 465 | GCC_OPTIMIZATION_LEVEL = 0; 466 | GCC_PREPROCESSOR_DEFINITIONS = ( 467 | "DEBUG=1", 468 | "$(inherited)", 469 | ); 470 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 471 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 472 | GCC_WARN_UNDECLARED_SELECTOR = YES; 473 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 474 | GCC_WARN_UNUSED_FUNCTION = YES; 475 | GCC_WARN_UNUSED_VARIABLE = YES; 476 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 477 | MTL_ENABLE_DEBUG_INFO = YES; 478 | ONLY_ACTIVE_ARCH = YES; 479 | SDKROOT = iphoneos; 480 | TARGETED_DEVICE_FAMILY = "1,2"; 481 | }; 482 | name = Debug; 483 | }; 484 | 97C147041CF9000F007C117D /* Release */ = { 485 | isa = XCBuildConfiguration; 486 | buildSettings = { 487 | ALWAYS_SEARCH_USER_PATHS = NO; 488 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 489 | CLANG_ANALYZER_NONNULL = YES; 490 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 491 | CLANG_CXX_LIBRARY = "libc++"; 492 | CLANG_ENABLE_MODULES = YES; 493 | CLANG_ENABLE_OBJC_ARC = YES; 494 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 495 | CLANG_WARN_BOOL_CONVERSION = YES; 496 | CLANG_WARN_COMMA = YES; 497 | CLANG_WARN_CONSTANT_CONVERSION = YES; 498 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 499 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 500 | CLANG_WARN_EMPTY_BODY = YES; 501 | CLANG_WARN_ENUM_CONVERSION = YES; 502 | CLANG_WARN_INFINITE_RECURSION = YES; 503 | CLANG_WARN_INT_CONVERSION = YES; 504 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 505 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 506 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 507 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 508 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 509 | CLANG_WARN_STRICT_PROTOTYPES = YES; 510 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 511 | CLANG_WARN_UNREACHABLE_CODE = YES; 512 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 513 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 514 | COPY_PHASE_STRIP = NO; 515 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 516 | ENABLE_NS_ASSERTIONS = NO; 517 | ENABLE_STRICT_OBJC_MSGSEND = YES; 518 | ENABLE_USER_SCRIPT_SANDBOXING = NO; 519 | GCC_C_LANGUAGE_STANDARD = gnu99; 520 | GCC_NO_COMMON_BLOCKS = YES; 521 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 522 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 523 | GCC_WARN_UNDECLARED_SELECTOR = YES; 524 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 525 | GCC_WARN_UNUSED_FUNCTION = YES; 526 | GCC_WARN_UNUSED_VARIABLE = YES; 527 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 528 | MTL_ENABLE_DEBUG_INFO = NO; 529 | SDKROOT = iphoneos; 530 | SUPPORTED_PLATFORMS = iphoneos; 531 | SWIFT_COMPILATION_MODE = wholemodule; 532 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 533 | TARGETED_DEVICE_FAMILY = "1,2"; 534 | VALIDATE_PRODUCT = YES; 535 | }; 536 | name = Release; 537 | }; 538 | 97C147061CF9000F007C117D /* Debug */ = { 539 | isa = XCBuildConfiguration; 540 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 541 | buildSettings = { 542 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 543 | CLANG_ENABLE_MODULES = YES; 544 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 545 | DEVELOPMENT_TEAM = ZR5SPHW7AC; 546 | ENABLE_BITCODE = NO; 547 | INFOPLIST_FILE = Runner/Info.plist; 548 | LD_RUNPATH_SEARCH_PATHS = ( 549 | "$(inherited)", 550 | "@executable_path/Frameworks", 551 | ); 552 | PRODUCT_BUNDLE_IDENTIFIER = gg.renan.demo2; 553 | PRODUCT_NAME = "$(TARGET_NAME)"; 554 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 555 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 556 | SWIFT_VERSION = 5.0; 557 | VERSIONING_SYSTEM = "apple-generic"; 558 | }; 559 | name = Debug; 560 | }; 561 | 97C147071CF9000F007C117D /* Release */ = { 562 | isa = XCBuildConfiguration; 563 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 564 | buildSettings = { 565 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 566 | CLANG_ENABLE_MODULES = YES; 567 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 568 | DEVELOPMENT_TEAM = ZR5SPHW7AC; 569 | ENABLE_BITCODE = NO; 570 | INFOPLIST_FILE = Runner/Info.plist; 571 | LD_RUNPATH_SEARCH_PATHS = ( 572 | "$(inherited)", 573 | "@executable_path/Frameworks", 574 | ); 575 | PRODUCT_BUNDLE_IDENTIFIER = gg.renan.demo2; 576 | PRODUCT_NAME = "$(TARGET_NAME)"; 577 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 578 | SWIFT_VERSION = 5.0; 579 | VERSIONING_SYSTEM = "apple-generic"; 580 | }; 581 | name = Release; 582 | }; 583 | /* End XCBuildConfiguration section */ 584 | 585 | /* Begin XCConfigurationList section */ 586 | 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { 587 | isa = XCConfigurationList; 588 | buildConfigurations = ( 589 | 331C8088294A63A400263BE5 /* Debug */, 590 | 331C8089294A63A400263BE5 /* Release */, 591 | 331C808A294A63A400263BE5 /* Profile */, 592 | ); 593 | defaultConfigurationIsVisible = 0; 594 | defaultConfigurationName = Release; 595 | }; 596 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 597 | isa = XCConfigurationList; 598 | buildConfigurations = ( 599 | 97C147031CF9000F007C117D /* Debug */, 600 | 97C147041CF9000F007C117D /* Release */, 601 | 249021D3217E4FDB00AE95B9 /* Profile */, 602 | ); 603 | defaultConfigurationIsVisible = 0; 604 | defaultConfigurationName = Release; 605 | }; 606 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 607 | isa = XCConfigurationList; 608 | buildConfigurations = ( 609 | 97C147061CF9000F007C117D /* Debug */, 610 | 97C147071CF9000F007C117D /* Release */, 611 | 249021D4217E4FDB00AE95B9 /* Profile */, 612 | ); 613 | defaultConfigurationIsVisible = 0; 614 | defaultConfigurationName = Release; 615 | }; 616 | /* End XCConfigurationList section */ 617 | }; 618 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 619 | } 620 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 38 | 39 | 40 | 41 | 44 | 50 | 51 | 52 | 53 | 54 | 66 | 68 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | 4 | @main 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Demo 2 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | demo_2 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | CADisableMinimumFrameDurationOnPhone 45 | 46 | UIApplicationSupportsIndirectInputEvents 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /ios/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /lib/game/entities/ground.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:ui' 3 | show 4 | Paint, 5 | Color, 6 | Canvas, 7 | Path, 8 | Gradient, 9 | Offset, 10 | Rect, 11 | ImageFilter, 12 | BlendMode; 13 | 14 | import 'package:demo_2/game/game.dart'; 15 | import 'package:demo_2/game/post_process/wake_post_process.dart'; 16 | import 'package:demo_2/game/utilities/game_perspective.dart'; 17 | import 'package:demo_2/game/utilities/isometric_component.dart'; 18 | import 'package:flame/components.dart'; 19 | import 'package:flame/post_process.dart'; 20 | 21 | class Ground extends PositionComponent with HasGameReference { 22 | Ground({super.children}) { 23 | anchor = Anchor.center; 24 | } 25 | 26 | GamePerspective? appliedPerspective; 27 | 28 | @override 29 | Future onLoad() async { 30 | add( 31 | IsometricPlaneComponent( 32 | plane: IsometricPlane.ground, 33 | children: [ 34 | ShipWake( 35 | position: Vector2(size.x / 2, size.y / 2), 36 | postProcess: WakePostProcess( 37 | fragmentProgram: game.preloadedPrograms.wake, 38 | game: game, 39 | ), 40 | ), 41 | ], 42 | ), 43 | ); 44 | } 45 | } 46 | 47 | class ShipWake extends PostProcessComponent with HasGameReference { 48 | ShipWake({required super.postProcess, super.position}) { 49 | size = Vector2(860, 1460); 50 | anchor = Anchor.topCenter; 51 | priority = -1; 52 | position.translate(0, -230); 53 | add(OuterWakeShapeComponent()..position = Vector2(size.x / 2, 0)); 54 | add(InnerWakeShapeComponent()..position = Vector2(size.x / 2, 0)); 55 | } 56 | } 57 | 58 | class OuterWakeShapeComponent extends ShapeComponent { 59 | OuterWakeShapeComponent() 60 | : super(anchor: Anchor.topCenter, position: Vector2(0, -10)) { 61 | size = Vector2(900, 1760); 62 | paint = Paint()..color = const Color(0xFF00FF00); 63 | } 64 | 65 | /// Draws a parabolic shape 66 | late final shapePath = () { 67 | final path = Path(); 68 | final current = Vector2(size.x / 2, 0); 69 | path.moveTo(current.x, current.y); 70 | final desloc = Vector2(size.x / 2, size.y); 71 | final curve = Vector4(.21, 0.0, .39, .16); 72 | path.relativeCubicTo( 73 | curve.x * desloc.x, 74 | curve.y * desloc.y, 75 | curve.z * desloc.x, 76 | curve.w * desloc.y, 77 | desloc.x, 78 | desloc.y, 79 | ); 80 | current.add(desloc); 81 | 82 | path.lineTo(0, size.y); 83 | current.setValues(0, size.y); 84 | 85 | path.relativeCubicTo( 86 | (1 - curve.z) * desloc.x, 87 | -(1 - curve.w) * desloc.y, 88 | (1 - curve.x) * desloc.x, 89 | -(1 - curve.y) * desloc.y, 90 | desloc.x, 91 | -desloc.y, 92 | ); 93 | current.add(Vector2(desloc.x, -desloc.y)); 94 | 95 | return path; 96 | }(); 97 | 98 | late final blurPaint = Paint() 99 | ..imageFilter = ImageFilter.blur(sigmaX: 10, sigmaY: 10); 100 | late final excludePaint = Paint() 101 | ..blendMode = BlendMode.dstOut 102 | ..imageFilter = ImageFilter.blur(sigmaX: 100, sigmaY: 200); 103 | 104 | @override 105 | void render(Canvas canvas) { 106 | canvas.saveLayer(Offset.zero & size.toSize(), blurPaint); 107 | { 108 | canvas.drawPath(shapePath, paint); 109 | canvas.save(); 110 | { 111 | canvas.translate(0, 30); 112 | canvas.drawPath(shapePath, excludePaint); 113 | } 114 | canvas.restore(); 115 | } 116 | canvas.restore(); 117 | } 118 | } 119 | 120 | class InnerWakeShapeComponent extends ShapeComponent { 121 | InnerWakeShapeComponent() 122 | : super(anchor: Anchor.topCenter, position: Vector2(0, 10)) { 123 | size = Vector2(100, 2000); 124 | paint = Paint()..color = const Color(0xFFFF0000); 125 | } 126 | 127 | /// Draws a parabolic shape 128 | late final shapePath = () { 129 | final path = Path(); 130 | final current = Vector2(size.x / 2, 0); 131 | path.moveTo(current.x, current.y); 132 | 133 | final desloc = Vector2(size.x / 2, 400); 134 | final curve = Vector4(.19, 0, .98, .25); 135 | path.relativeCubicTo( 136 | curve.x * desloc.x, 137 | curve.y * desloc.y, 138 | curve.z * desloc.x, 139 | curve.w * desloc.y, 140 | desloc.x, 141 | desloc.y, 142 | ); 143 | current.add(desloc); 144 | 145 | path.lineTo(current.x, size.y); 146 | current.setValues(current.x, size.y); 147 | 148 | path.lineTo(0, size.y); 149 | current.setValues(0, size.y); 150 | 151 | path.lineTo(0, desloc.y); 152 | current.setValues(0, desloc.y); 153 | 154 | path.relativeCubicTo( 155 | (1 - curve.z) * desloc.x, 156 | -(1 - curve.w) * desloc.y, 157 | (1 - curve.x) * desloc.x, 158 | -(1 - curve.y) * desloc.y, 159 | desloc.x, 160 | -desloc.y, 161 | ); 162 | current.add(Vector2(desloc.x, -desloc.y)); 163 | return path; 164 | }(); 165 | 166 | late final blurPaint = Paint() 167 | ..imageFilter = ImageFilter.blur(sigmaX: 5, sigmaY: 5) 168 | ..blendMode = BlendMode.screen; 169 | late final excludePaint = Paint() 170 | ..blendMode = BlendMode.dstOut 171 | ..imageFilter = ImageFilter.blur(sigmaX: 30, sigmaY: 200); 172 | 173 | @override 174 | void render(Canvas canvas) { 175 | canvas.saveLayer(Offset.zero & size.toSize(), blurPaint); 176 | { 177 | canvas.drawPath(shapePath, paint); 178 | canvas.drawPath(shapePath, excludePaint); 179 | } 180 | canvas.restore(); 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /lib/game/entities/ship.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui' show Image; 2 | 3 | import 'package:demo_2/game/game.dart'; 4 | import 'package:demo_2/game/post_process/ship_post_process.dart'; 5 | import 'package:demo_2/game/utilities/game_perspective.dart'; 6 | import 'package:flame/collisions.dart'; 7 | import 'package:flame/components.dart'; 8 | import 'package:flame/layout.dart'; 9 | import 'package:flame/post_process.dart'; 10 | import 'package:flame/sprite.dart'; 11 | 12 | class Ship extends PositionComponent 13 | with CollisionCallbacks, HasGameReference { 14 | Ship(); 15 | 16 | @override 17 | Future onLoad() async { 18 | add( 19 | PostProcessComponent( 20 | postProcess: ShipPostProcess( 21 | fragmentProgram: game.preloadedPrograms.ship, 22 | game: game, 23 | ), 24 | size: Vector2(480, 264), 25 | anchor: Anchor.center, 26 | children: [ 27 | SpriteShip(), 28 | ], 29 | ), 30 | ); 31 | } 32 | } 33 | 34 | class SpriteShip extends SpriteComponent 35 | with CollisionCallbacks, HasGameReference { 36 | SpriteShip() : super(size: Vector2(480, 264)); 37 | 38 | late ShipSpriteSheet spriteSheet; 39 | 40 | GamePerspective _currentDirection = GamePerspective.deadAhead; 41 | 42 | @override 43 | Future onLoad() async { 44 | spriteSheet = ShipSpriteSheet(game.spriteImage); 45 | sprite = spriteSheet.getShipSprite(_currentDirection); 46 | 47 | return super.onLoad(); 48 | } 49 | 50 | @override 51 | void update(double dt) { 52 | super.update(dt); 53 | final perspective = game.gameValues.perspective; 54 | if (perspective != _currentDirection) { 55 | _currentDirection = perspective; 56 | sprite = spriteSheet.getShipSprite(_currentDirection); 57 | final val = _currentDirection.val; 58 | // There are some errors in how the sprite was projected by blender, 59 | // these lines correct them (kind of) 60 | double angleCorrectionX; 61 | final absVal = val.abs(); 62 | if (val == 0) { 63 | angleCorrectionX = 0; 64 | } else if (absVal <= 9) { 65 | angleCorrectionX = val.sign * (absVal / 9) * 10; // 0 to ±10 66 | } else { 67 | angleCorrectionX = 68 | val.sign * (10 + ((absVal - 9) / 9) * -5); // ±10 to ±5 69 | } 70 | final angleCorrectionY = -10 + (10 * (_currentDirection.val.abs() / 18)); 71 | position = Vector2(angleCorrectionX * -2, angleCorrectionY); 72 | } 73 | } 74 | } 75 | 76 | class ShipSpriteSheet extends SpriteSheet { 77 | ShipSpriteSheet(Image image) 78 | : super.fromColumnsAndRows(image: image, columns: 6, rows: 7); 79 | 80 | Sprite getShipSprite(GamePerspective direction) { 81 | return getSpriteById(direction.val + 18); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /lib/game/entities/smoke.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:math' as math; 3 | 4 | import 'package:demo_2/game/game.dart'; 5 | import 'package:demo_2/game/utilities/isometric_component.dart'; 6 | import 'package:demo_2/game/utilities/konstants.dart'; 7 | import 'package:flame/components.dart'; 8 | import 'package:flame/effects.dart'; 9 | import 'package:flutter/material.dart'; 10 | 11 | class SmokeParticles extends PositionComponent 12 | with HasGameReference { 13 | SmokeParticles() { 14 | anchor = Anchor.center; 15 | } 16 | 17 | late final random = math.Random(); 18 | 19 | late Timer timer; 20 | 21 | Timer get initialTimer => Timer(1, onTick: onTick, autoStart: false); 22 | 23 | Iterable get currentSmokeParticles => 24 | children.query(); 25 | 26 | @override 27 | FutureOr onLoad() { 28 | timer = initialTimer..start(); 29 | children.register(); 30 | } 31 | 32 | void onTick() { 33 | final nextInterval = 0.8 + random.nextDouble() * 0.2; 34 | timer = Timer(nextInterval, onTick: onTick); 35 | 36 | var xDeviation = (random.nextDouble() - 0.5) * 200; 37 | var yDeviation = (random.nextDouble() - 0.5) * 50; 38 | 39 | add( 40 | SmokeParticle( 41 | position3: Vector3(0, -60, -86), 42 | toX: xDeviation, 43 | toY: yDeviation, 44 | ), 45 | ); 46 | 47 | xDeviation = (random.nextDouble() - 0.5) * 400; 48 | yDeviation = (random.nextDouble() - 0.5) * 150; 49 | 50 | add( 51 | SmokeParticle( 52 | position3: Vector3(0, 0, -86), 53 | toX: xDeviation, 54 | toY: yDeviation, 55 | ), 56 | ); 57 | } 58 | 59 | @override 60 | void update(double dt) { 61 | timer.update(dt); 62 | } 63 | } 64 | 65 | class SmokeParticle extends PositionComponent { 66 | SmokeParticle({ 67 | required this.position3, 68 | required this.toX, 69 | required this.toY, 70 | }); 71 | 72 | Vector3 position3; 73 | final double toX; 74 | final double toY; 75 | 76 | late final innerPos = PositionComponent( 77 | children: [], 78 | )..position = position3.xy; 79 | late final IsometricPlaneComponent plane = IsometricPlaneComponent( 80 | plane: IsometricPlane.ground, 81 | planDisplacement: position3.z, 82 | children: [innerPos], 83 | ); 84 | 85 | double get progress => effect._progress; 86 | double get smokeRadius => 2.9 * kSmokeRadiusCurve.transform(progress) + 0.3; 87 | double get smokeOpacity { 88 | final acceleratedProgress = (progress * 1.4).clamp(0.0, 1.0); 89 | return (1.0 - kSmokeOpacityCurve.transform(acceleratedProgress)) * 0.5; 90 | } 91 | 92 | @override 93 | Future onLoad() async { 94 | add(plane); 95 | await add(effect); 96 | } 97 | 98 | late IsometricSmokeEffect effect = IsometricSmokeEffect( 99 | Vector3(toX, 1000, -300 + toY), 100 | LinearEffectController(10), 101 | this, 102 | onComplete: removeFromParent, 103 | ); 104 | 105 | @override 106 | void update(double dt) { 107 | innerPos.position = position3.xy; 108 | plane.planDisplacement = position3.z; 109 | 110 | super.update(dt); 111 | } 112 | } 113 | 114 | class IsometricSmokeEffect extends Effect with EffectTarget { 115 | IsometricSmokeEffect( 116 | Vector3 offset, 117 | super.controller, 118 | SmokeParticle? target, { 119 | super.onComplete, 120 | super.key, 121 | }) : _offset = offset { 122 | this.target = target; 123 | } 124 | 125 | final Vector3 _offset; 126 | 127 | double lastCurvedProgress = 0; 128 | 129 | double _progress = 0; 130 | 131 | @override 132 | void apply(double progress) { 133 | _progress = progress; 134 | final curvedProgress = Curves.easeOutCirc.transform(progress); 135 | 136 | target.position3.xy += _offset.xy * (progress - previousProgress); 137 | target.position3.z += _offset.z * (curvedProgress - lastCurvedProgress); 138 | lastCurvedProgress = curvedProgress; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /lib/game/game.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:ui' show Image, FragmentProgram, Color, Paint; 3 | 4 | import 'package:demo_2/game/entities/ground.dart'; 5 | import 'package:demo_2/game/entities/ship.dart'; 6 | import 'package:demo_2/game/entities/smoke.dart'; 7 | import 'package:demo_2/game/post_process/sea_post_process.dart'; 8 | import 'package:demo_2/game/post_process/smoke_post_process.dart'; 9 | import 'package:demo_2/game/post_process/vignette_post_process.dart'; 10 | import 'package:demo_2/game/utilities/camera_target.dart'; 11 | import 'package:demo_2/game/utilities/game_perspective.dart'; 12 | import 'package:demo_2/game/utilities/input_interface.dart'; 13 | import 'package:demo_2/game/utilities/konstants.dart'; 14 | import 'package:flame/camera.dart'; 15 | import 'package:flame/components.dart'; 16 | import 'package:flame/events.dart'; 17 | import 'package:flame/flame.dart'; 18 | import 'package:flame/game.dart'; 19 | import 'package:flame/post_process.dart'; 20 | 21 | class SomeShipGame extends FlameGame 22 | with 23 | HasKeyboardHandlerComponents, 24 | HasCollisionDetection, 25 | SingleGameInstance, 26 | HorizontalDragDetector { 27 | SomeShipGame({required this.preloadedPrograms}) 28 | : super( 29 | camera: CameraComponent( 30 | backdrop: RectangleComponent( 31 | size: kResolution, 32 | paint: Paint()..color = const Color.fromARGB(255, 0, 73, 102), 33 | ), 34 | viewport: FixedResolutionViewport(resolution: kResolution), 35 | ), 36 | world: MyWorld(), 37 | ) { 38 | camera.postProcess = PostProcessSequentialGroup( 39 | postProcesses: [ 40 | SeaPostProcess(fragmentProgram: preloadedPrograms.sea, game: this), 41 | SmokePostProcess(fragmentProgram: preloadedPrograms.smoke, game: this), 42 | VignettePostProcess(fragmentProgram: preloadedPrograms.vignette), 43 | ], 44 | ); 45 | } 46 | 47 | final PreloadedPrograms preloadedPrograms; 48 | 49 | late final Image spriteImage; 50 | late final GameValues gameValues; 51 | late final InputInterface inputInterface; 52 | 53 | @override 54 | Future onLoad() async { 55 | spriteImage = await Flame.images.load('spritesheet.png'); 56 | camera.follow(world.cameraTarget); 57 | add(gameValues = GameValues()); 58 | add(inputInterface = InputInterface()); 59 | } 60 | 61 | @override 62 | void update(double dt) { 63 | camera.viewfinder.visibleGameSize = kResolution / 20; 64 | 65 | super.update(dt); 66 | } 67 | 68 | @override 69 | void onHorizontalDragDown(DragDownInfo info) { 70 | inputInterface.onHorizontalDragDown(info); 71 | } 72 | 73 | @override 74 | void onHorizontalDragStart(DragStartInfo info) { 75 | inputInterface.onHorizontalDragStart(info); 76 | } 77 | 78 | @override 79 | void onHorizontalDragUpdate(DragUpdateInfo info) { 80 | inputInterface.onHorizontalDragUpdate(info); 81 | } 82 | 83 | @override 84 | void onHorizontalDragEnd(DragEndInfo info) { 85 | inputInterface.onHorizontalDragEnd(info); 86 | } 87 | 88 | @override 89 | void onHorizontalDragCancel() { 90 | inputInterface.onHorizontalDragCancel(); 91 | } 92 | } 93 | 94 | class MyWorld extends World { 95 | MyWorld({super.children, super.key}) { 96 | addAll([ 97 | ground = Ground(children: [cameraTarget = CameraTarget()]), 98 | ship = Ship(), 99 | smokeParticles = SmokeParticles(), 100 | ]); 101 | } 102 | 103 | late final Ship ship; 104 | late final CameraTarget cameraTarget; 105 | late final Ground ground; 106 | late final SmokeParticles smokeParticles; 107 | } 108 | 109 | // Set of fragment programs to be loaded 110 | // at the start of the application, on widget level. 111 | typedef PreloadedPrograms = ({ 112 | FragmentProgram sea, 113 | FragmentProgram wake, 114 | FragmentProgram ship, 115 | FragmentProgram smoke, 116 | FragmentProgram vignette, 117 | }); 118 | -------------------------------------------------------------------------------- /lib/game/post_process/sea_post_process.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:demo_2/game/game.dart'; 4 | import 'package:flame/game.dart'; 5 | import 'package:flame/post_process.dart'; 6 | 7 | class SeaPostProcess extends PostProcess { 8 | SeaPostProcess({ 9 | required this.fragmentProgram, 10 | required this.game, 11 | super.pixelRatio, 12 | }); 13 | 14 | final SomeShipGame game; 15 | final FragmentProgram fragmentProgram; 16 | late final shader = fragmentProgram.fragmentShader(); 17 | 18 | double time = 0.0; 19 | 20 | @override 21 | void update(double dt) { 22 | super.update(dt); 23 | time += dt; 24 | } 25 | 26 | @override 27 | void postProcess(Vector2 size, Canvas canvas) { 28 | shader.setFloatUniforms((value) { 29 | value 30 | ..setVector(size) 31 | ..setFloat(time) 32 | ..setFloat(game.gameValues.perspective.angle); 33 | }); 34 | 35 | canvas 36 | ..save() 37 | ..drawRect(Offset.zero & size.toSize(), Paint()..shader = shader) 38 | ..restore(); 39 | 40 | renderSubtree(canvas); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/game/post_process/ship_post_process.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:demo_2/game/game.dart'; 4 | import 'package:flame/game.dart'; 5 | import 'package:flame/post_process.dart'; 6 | 7 | class ShipPostProcess extends PostProcess { 8 | ShipPostProcess({ 9 | required this.fragmentProgram, 10 | required this.game, 11 | super.pixelRatio, 12 | }); 13 | 14 | final SomeShipGame game; 15 | final FragmentProgram fragmentProgram; 16 | late final shader = fragmentProgram.fragmentShader(); 17 | 18 | @override 19 | void postProcess(Vector2 size, Canvas canvas) { 20 | final shipRendered = rasterizeSubtree(); 21 | 22 | shader.setFloatUniforms((value) { 23 | value 24 | ..setVector(size) 25 | ..setFloat(pixelRatio); 26 | }); 27 | shader.setImageSampler(0, shipRendered); 28 | 29 | canvas 30 | ..save() 31 | ..drawRect( 32 | Offset.zero & size.toSize(), 33 | Paint()..shader = shader, 34 | ) 35 | ..restore(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/game/post_process/smoke_post_process.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math' as math; 2 | import 'dart:ui'; 3 | 4 | import 'package:demo_2/game/game.dart'; 5 | import 'package:flame/components.dart'; 6 | import 'package:flame/post_process.dart'; 7 | 8 | class SmokePostProcess extends PostProcess { 9 | SmokePostProcess({ 10 | required this.fragmentProgram, 11 | required this.game, 12 | super.pixelRatio, 13 | }); 14 | 15 | final FragmentProgram fragmentProgram; 16 | final SomeShipGame game; 17 | late final shader = fragmentProgram.fragmentShader(); 18 | 19 | final List sphereCenters = List.filled( 20 | 20, 21 | Vector3.zero(), 22 | ); 23 | final List sphereRadii = List.filled(20, 0.0); 24 | final List sphereOpacities = List.filled(20, 0.0); 25 | 26 | @override 27 | void postProcess(Vector2 size, Canvas canvas) { 28 | final particles = game.world.smokeParticles.currentSmokeParticles 29 | .toList() 30 | .reversed; 31 | 32 | for (var i = 0; i < 20; i++) { 33 | final particle = particles.elementAtOrNull(i); 34 | 35 | if (particle == null) { 36 | sphereCenters[i] = Vector3(0, 0, 0); 37 | sphereRadii[i] = 0.0; 38 | continue; 39 | } 40 | 41 | sphereRadii[i] = particle.smokeRadius; 42 | sphereOpacities[i] = particle.smokeOpacity; 43 | 44 | // Translate the isometric position to the one in the shader. 45 | final og = particle.position3; 46 | sphereCenters[i] = Vector3( 47 | og.x * -0.0155, 48 | og.z * (4 / 215), 49 | og.y * 0.01635, 50 | ); 51 | } 52 | 53 | shader.setFloatUniforms((value) { 54 | value 55 | ..setVector(size) 56 | ..setFloat(game.gameValues.perspective.angle * -180 / math.pi) 57 | ..setVectors(sphereCenters) 58 | ..setFloats(sphereRadii) 59 | ..setFloats(sphereOpacities); 60 | }); 61 | 62 | renderSubtree(canvas); 63 | 64 | canvas 65 | ..save() 66 | ..drawRect(Offset.zero & size.toSize(), Paint()..shader = shader) 67 | ..restore(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /lib/game/post_process/vignette_post_process.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flame/game.dart'; 4 | import 'package:flame/post_process.dart'; 5 | 6 | class VignettePostProcess extends PostProcess { 7 | VignettePostProcess({required this.fragmentProgram, super.pixelRatio}); 8 | 9 | final FragmentProgram fragmentProgram; 10 | late final shader = fragmentProgram.fragmentShader(); 11 | 12 | @override 13 | void postProcess(Vector2 size, Canvas canvas) { 14 | renderSubtree(canvas); 15 | 16 | shader.setFloatUniforms((value) { 17 | value 18 | ..setVector(size) 19 | ..setVector(Vector2(0.5, 0.4)) 20 | ..setVector(Vector4(0.24, 0.20, 0.0, 0.2)) // sepia color 21 | ; 22 | }); 23 | 24 | canvas.drawRect( 25 | Offset.zero & size.toSize(), 26 | Paint() 27 | ..shader = shader 28 | ..blendMode = BlendMode.multiply, 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/game/post_process/wake_post_process.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:demo_2/game/game.dart'; 4 | import 'package:flame/game.dart'; 5 | import 'package:flame/post_process.dart'; 6 | 7 | class WakePostProcess extends PostProcess { 8 | WakePostProcess({ 9 | required this.fragmentProgram, 10 | required this.game, 11 | super.pixelRatio, 12 | }); 13 | 14 | final FragmentProgram fragmentProgram; 15 | final SomeShipGame game; 16 | late final shader = fragmentProgram.fragmentShader(); 17 | 18 | double time = 0.0; 19 | 20 | @override 21 | void update(double dt) { 22 | super.update(dt); 23 | time += dt; 24 | } 25 | 26 | @override 27 | void postProcess(Vector2 size, Canvas canvas) { 28 | final normals = rasterizeSubtree(); 29 | 30 | shader.setFloatUniforms((value) { 31 | value 32 | ..setVector(size) 33 | ..setFloat(time) 34 | ..setFloat(pixelRatio); 35 | }); 36 | 37 | shader.setImageSampler(0, normals); 38 | 39 | canvas 40 | ..save() 41 | ..drawRect(Offset.zero & size.toSize(), Paint()..shader = shader) 42 | ..restore(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /lib/game/utilities/camera_target.dart: -------------------------------------------------------------------------------- 1 | import 'package:demo_2/game/game.dart'; 2 | import 'package:demo_2/game/utilities/game_perspective.dart'; 3 | import 'package:flame/components.dart'; 4 | import 'package:flame/effects.dart'; 5 | import 'package:flutter/animation.dart'; 6 | 7 | class CameraTarget extends PositionComponent 8 | with HasGameReference { 9 | CameraTarget() 10 | : super( 11 | position: Vector2(0, 0), 12 | size: Vector2.all(0), 13 | anchor: Anchor.center, 14 | priority: 0x7fffffff, 15 | ); 16 | 17 | final effectController = GoodCurvedEffectController(0.1, Curves.easeInOut) 18 | ..setToEnd(); 19 | 20 | late final moveEffect = MoveCameraTarget(position, effectController); 21 | 22 | GamePerspective? appliedPerspective; 23 | 24 | @override 25 | Future onLoad() async { 26 | await add(moveEffect); 27 | } 28 | 29 | void go({ 30 | required Vector2 to, 31 | Curve curve = Curves.easeInOut, 32 | double duration = 0.25, 33 | double scale = 1, 34 | }) { 35 | effectController 36 | ..duration = duration * 4 37 | ..curve = curve; 38 | 39 | moveEffect.go(to: to); 40 | } 41 | 42 | @override 43 | void update(double dt) { 44 | super.update(dt); 45 | game.camera.viewfinder.zoom = scale.x; 46 | 47 | position = Vector2(0.0, -50); 48 | } 49 | } 50 | 51 | class MoveCameraTarget extends Effect with EffectTarget { 52 | MoveCameraTarget(this._to, super.controller); 53 | 54 | @override 55 | void onMount() { 56 | super.onMount(); 57 | _from = target.position; 58 | } 59 | 60 | Vector2 _to; 61 | late Vector2 _from; 62 | 63 | @override 64 | bool get removeOnFinish => false; 65 | 66 | @override 67 | void apply(double progress) { 68 | final delta = _to - _from; 69 | final position = _from + delta * progress; 70 | target.position = position; 71 | } 72 | 73 | void go({required Vector2 to}) { 74 | reset(); 75 | _to = to; 76 | _from = target.position; 77 | } 78 | } 79 | 80 | class GoodCurvedEffectController extends DurationEffectController { 81 | GoodCurvedEffectController(super.duration, this.curve) 82 | : assert(duration > 0, 'Duration must be positive: $duration'); 83 | 84 | Curve curve; 85 | 86 | @override 87 | double get progress => curve.transform(timer / duration); 88 | } 89 | -------------------------------------------------------------------------------- /lib/game/utilities/game_perspective.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math' as math; 2 | 3 | import 'package:demo_2/game/game.dart'; 4 | import 'package:flame/components.dart'; 5 | 6 | enum GamePerspective { 7 | starboard18(-18), 8 | starboard17(-17), 9 | starboard16(-16), 10 | starboard15(-15), 11 | starboard14(-14), 12 | starboard13(-13), 13 | starboard12(-12), 14 | starboard11(-11), 15 | starboard10(-10), 16 | starboard9(-9), 17 | starboard8(-8), 18 | starboard7(-7), 19 | starboard6(-6), 20 | starboard5(-5), 21 | starboard4(-4), 22 | starboard3(-3), 23 | starboard2(-2), 24 | starboard1(-1), 25 | deadAhead(0), 26 | port1(1), 27 | port2(2), 28 | port3(3), 29 | port4(4), 30 | port5(5), 31 | port6(6), 32 | port7(7), 33 | port8(8), 34 | port9(9), 35 | port10(10), 36 | port11(11), 37 | port12(12), 38 | port13(13), 39 | port14(14), 40 | port15(15), 41 | port16(16), 42 | port17(17), 43 | port18(18); 44 | 45 | const GamePerspective(this.val); 46 | 47 | static GamePerspective fromVal(int val) { 48 | return GamePerspective.values[val + 18]; 49 | } 50 | 51 | final int val; 52 | 53 | double get angle { 54 | return (val / -18.0) * (math.pi / 2); 55 | } 56 | } 57 | 58 | class GameValues extends Component with HasGameReference { 59 | GamePerspective perspective = GamePerspective.deadAhead; 60 | } 61 | -------------------------------------------------------------------------------- /lib/game/utilities/input_interface.dart: -------------------------------------------------------------------------------- 1 | import 'package:demo_2/game/game.dart'; 2 | import 'package:demo_2/game/utilities/game_perspective.dart'; 3 | import 'package:flame/components.dart'; 4 | import 'package:flame/events.dart'; 5 | 6 | class InputInterface extends Component with HasGameReference { 7 | Vector2? _startDragPosition; 8 | 9 | void onHorizontalDragDown(DragDownInfo info) { 10 | _startDragPosition = info.eventPosition.widget; 11 | } 12 | 13 | void onHorizontalDragStart(DragStartInfo info) { 14 | _startDragPosition = info.eventPosition.widget; 15 | } 16 | 17 | void onHorizontalDragUpdate(DragUpdateInfo info) { 18 | if (_startDragPosition != null) { 19 | final delta = info.eventPosition.widget - _startDragPosition!; 20 | final xAbs = delta.x.abs(); 21 | final xSign = delta.x.sign.toInt(); 22 | final changeUnits = xAbs ~/ 50; 23 | 24 | if (changeUnits > 0) { 25 | _startDragPosition = info.eventPosition.widget; 26 | game.gameValues.perspective = GamePerspective.fromVal( 27 | (game.gameValues.perspective.val + changeUnits * xSign).clamp( 28 | -18, 29 | 18, 30 | ), 31 | ); 32 | } 33 | } 34 | } 35 | 36 | void onHorizontalDragEnd(DragEndInfo info) { 37 | _startDragPosition = null; 38 | } 39 | 40 | void onHorizontalDragCancel() { 41 | _startDragPosition = null; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lib/game/utilities/isometric_component.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math' as math; 2 | import 'dart:ui'; 3 | 4 | import 'package:demo_2/game/game.dart'; 5 | import 'package:demo_2/game/utilities/game_perspective.dart'; 6 | import 'package:flame/components.dart'; 7 | 8 | enum IsometricPlane { 9 | // Represent the plane parealel to the ground 10 | ground, 11 | 12 | // Represent the vertical plane along the ship's length 13 | verticalAlong, 14 | 15 | // Represent the vertical plane across the ship's width 16 | verticalAcross, 17 | } 18 | 19 | RectangleComponent getS() => RectangleComponent( 20 | size: Vector2(200, 200), 21 | paint: Paint() 22 | ..shader = Gradient.linear(Offset.zero, const Offset(200, 200), [ 23 | const Color(0xFF00FF00), 24 | const Color(0xFF0000FF), 25 | ]), 26 | 27 | anchor: Anchor.center, 28 | ); 29 | 30 | RectangleComponent getS2() => RectangleComponent( 31 | size: Vector2(200, 200), 32 | paint: Paint() 33 | ..shader = Gradient.linear(Offset.zero, const Offset(200, 200), [ 34 | const Color.fromARGB(255, 255, 175, 2), 35 | const Color(0xFF0000FF), 36 | ]), 37 | 38 | anchor: Anchor.center, 39 | ); 40 | 41 | class IsometricPlaneComponent extends PositionComponent 42 | with HasGameReference { 43 | IsometricPlaneComponent({ 44 | IsometricPlane? plane, 45 | this.planDisplacement = 0, 46 | super.position, 47 | super.size, 48 | super.scale, 49 | super.angle, 50 | super.nativeAngle, 51 | super.anchor, 52 | super.children, 53 | super.priority, 54 | super.key, 55 | }) { 56 | _plane = plane ?? IsometricPlane.ground; 57 | } 58 | 59 | IsometricPlane? _plane; 60 | double planDisplacement; 61 | 62 | set plane(IsometricPlane? value) { 63 | _plane = value; 64 | _applyIsometricTransformation(); 65 | } 66 | 67 | IsometricPlane? get plane => _plane; 68 | 69 | GamePerspective? appliedPerspective; 70 | 71 | @override 72 | void update(double dt) { 73 | super.update(dt); 74 | 75 | _applyIsometricTransformation(); 76 | } 77 | 78 | void _applyIsometricTransformation() { 79 | switch (_plane) { 80 | case IsometricPlane.ground: 81 | _applyForGroundPlane(); 82 | case IsometricPlane.verticalAlong: 83 | _applyForVerticalAlongPlane(); 84 | case IsometricPlane.verticalAcross: 85 | _applyForVerticalAcrossPlane(); 86 | case null: 87 | break; 88 | } 89 | } 90 | 91 | void _applyForVerticalAlongPlane() { 92 | final angle = game.gameValues.perspective.angle; 93 | const rAngle = 90 - 60.5593; 94 | const radAngle = rAngle * (math.pi / 180); 95 | 96 | final centerX = size.x / 2; 97 | final centerY = size.y / 2; 98 | 99 | transform.transformMatrix.setIdentity(); 100 | anchor = Anchor.center; 101 | 102 | transform.transformMatrix 103 | ..translateByVector3(Vector3(centerX, centerY, 0)) 104 | ..rotateX(radAngle) 105 | ..rotateY(math.pi / 2 + angle) 106 | ..rotateZ(math.pi / 2) 107 | ..translateByVector3(Vector3(-centerX, -centerY, 0)); 108 | 109 | appliedPerspective = game.gameValues.perspective; 110 | } 111 | 112 | void _applyForGroundPlane() { 113 | final angle = game.gameValues.perspective.angle; 114 | const rAngle = 90 - 60.5593; 115 | const radAngle = rAngle * (math.pi / 180); 116 | final scaleY = math.sin(radAngle); 117 | 118 | final centerX = size.x / 2; 119 | final centerY = size.y / 2; 120 | 121 | transform.transformMatrix.setIdentity(); 122 | anchor = Anchor.center; 123 | 124 | transform.transformMatrix 125 | ..translateByVector3(Vector3(0, planDisplacement, 0)) 126 | ..translateByVector3(Vector3(centerX, centerY, 0)) 127 | ..setEntry(1, 1, scaleY) 128 | ..rotateZ(angle) 129 | ..translateByVector3(Vector3(-centerX, -centerY, 0)); 130 | 131 | appliedPerspective = game.gameValues.perspective; 132 | } 133 | 134 | void _applyForVerticalAcrossPlane() { 135 | final angle = game.gameValues.perspective.angle; 136 | const rAngle = 90 - 60.5593; 137 | const radAngle = rAngle * (math.pi / 180); 138 | 139 | transform.transformMatrix.setIdentity(); 140 | anchor = Anchor.center; 141 | 142 | transform.transformMatrix 143 | ..rotateX(radAngle) 144 | ..rotateY(angle) 145 | ..rotateZ(math.pi / 2); 146 | 147 | appliedPerspective = game.gameValues.perspective; 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /lib/game/utilities/konstants.dart: -------------------------------------------------------------------------------- 1 | import 'package:flame/game.dart'; 2 | import 'package:flutter/animation.dart' show Cubic, Curves; 3 | 4 | final kResolution = Vector2(1279, 801); 5 | const kSmokeRadiusCurve = Curves.easeOutQuart; 6 | const kSmokeOpacityCurve = Cubic(.38, 0, 1, .05); 7 | -------------------------------------------------------------------------------- /lib/game/view/game_view.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui' show FragmentProgram; 2 | 3 | import 'package:demo_2/game/game.dart'; 4 | import 'package:flame/game.dart' hide Route; 5 | import 'package:flutter/material.dart'; 6 | import 'package:flutter/services.dart'; 7 | 8 | class GameView extends StatelessWidget { 9 | const GameView({super.key}); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return const Scaffold(body: _GameView()); 14 | } 15 | } 16 | 17 | class _GameView extends StatelessWidget { 18 | const _GameView(); 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | return const _GameWrapper(); 23 | } 24 | } 25 | 26 | class _GameWrapper extends StatefulWidget { 27 | const _GameWrapper(); 28 | 29 | @override 30 | State<_GameWrapper> createState() => _GameWrapperState(); 31 | } 32 | 33 | class _GameWrapperState extends State<_GameWrapper> { 34 | SomeShipGame? game; 35 | 36 | // PreloadedPrograms is a simple data class that holds the preloaded 37 | late final Future preloadedPrograms = 38 | Future.wait([ 39 | FragmentProgram.fromAsset('shaders/sea.frag'), 40 | FragmentProgram.fromAsset('shaders/ship_wake.frag'), 41 | FragmentProgram.fromAsset('shaders/ship.frag'), 42 | FragmentProgram.fromAsset('shaders/smoke.frag'), 43 | FragmentProgram.fromAsset('shaders/vignette.frag'), 44 | ]).then( 45 | (l) => (sea: l[0], wake: l[1], ship: l[2], smoke: l[3], vignette: l[4]), 46 | ); 47 | 48 | @override 49 | void initState() { 50 | super.initState(); 51 | SystemChrome.setEnabledSystemUIMode(SystemUiMode.leanBack); 52 | } 53 | 54 | @override 55 | Widget build(BuildContext context) { 56 | return Focus( 57 | autofocus: true, 58 | child: DefaultTextStyle.merge( 59 | textAlign: TextAlign.center, 60 | style: const TextStyle(color: Color(0xFFFBE294), fontSize: 12), 61 | child: FutureBuilder( 62 | future: preloadedPrograms, 63 | builder: (context, snapshot) { 64 | if (snapshot.hasError) { 65 | throw snapshot.error!; 66 | } 67 | 68 | // Show a loading indicator while the fragment programs are loading 69 | if (!snapshot.hasData) { 70 | return const Center(child: CircularProgressIndicator()); 71 | } 72 | 73 | return GameWidget( 74 | // It is a good idea to save the game instance on state 75 | // to avoid issues with hot reload 76 | game: game ??= SomeShipGame( 77 | preloadedPrograms: snapshot.data!, 78 | ), 79 | ); 80 | }, 81 | ), 82 | ), 83 | ); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:demo_2/game/view/game_view.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | void main() { 5 | runApp(const MyApp()); 6 | } 7 | 8 | class MyApp extends StatelessWidget { 9 | const MyApp({super.key}); 10 | 11 | // This widget is the root of your application. 12 | @override 13 | Widget build(BuildContext context) { 14 | return MaterialApp( 15 | title: 'Demo 2', 16 | theme: ThemeData(), 17 | home: const GameView(), 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/dgph 7 | **/xcuserdata/ 8 | -------------------------------------------------------------------------------- /macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | 9 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 10 | } 11 | -------------------------------------------------------------------------------- /macos/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 54; 7 | objects = { 8 | 9 | /* Begin PBXAggregateTarget section */ 10 | 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { 11 | isa = PBXAggregateTarget; 12 | buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; 13 | buildPhases = ( 14 | 33CC111E2044C6BF0003C045 /* ShellScript */, 15 | ); 16 | dependencies = ( 17 | ); 18 | name = "Flutter Assemble"; 19 | productName = FLX; 20 | }; 21 | /* End PBXAggregateTarget section */ 22 | 23 | /* Begin PBXBuildFile section */ 24 | 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; 25 | 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; 26 | 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; 27 | 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 28 | 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 29 | 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; 30 | /* End PBXBuildFile section */ 31 | 32 | /* Begin PBXContainerItemProxy section */ 33 | 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { 34 | isa = PBXContainerItemProxy; 35 | containerPortal = 33CC10E52044A3C60003C045 /* Project object */; 36 | proxyType = 1; 37 | remoteGlobalIDString = 33CC10EC2044A3C60003C045; 38 | remoteInfo = Runner; 39 | }; 40 | 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { 41 | isa = PBXContainerItemProxy; 42 | containerPortal = 33CC10E52044A3C60003C045 /* Project object */; 43 | proxyType = 1; 44 | remoteGlobalIDString = 33CC111A2044C6BA0003C045; 45 | remoteInfo = FLX; 46 | }; 47 | /* End PBXContainerItemProxy section */ 48 | 49 | /* Begin PBXCopyFilesBuildPhase section */ 50 | 33CC110E2044A8840003C045 /* Bundle Framework */ = { 51 | isa = PBXCopyFilesBuildPhase; 52 | buildActionMask = 2147483647; 53 | dstPath = ""; 54 | dstSubfolderSpec = 10; 55 | files = ( 56 | ); 57 | name = "Bundle Framework"; 58 | runOnlyForDeploymentPostprocessing = 0; 59 | }; 60 | /* End PBXCopyFilesBuildPhase section */ 61 | 62 | /* Begin PBXFileReference section */ 63 | 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 64 | 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 65 | 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 66 | 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; 67 | 33CC10ED2044A3C60003C045 /* demo_2.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "demo_2.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 68 | 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 69 | 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; 70 | 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 71 | 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; 72 | 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; 73 | 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; 74 | 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; 75 | 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; 76 | 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 77 | 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 78 | 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; 79 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 80 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; 81 | /* End PBXFileReference section */ 82 | 83 | /* Begin PBXFrameworksBuildPhase section */ 84 | 331C80D2294CF70F00263BE5 /* Frameworks */ = { 85 | isa = PBXFrameworksBuildPhase; 86 | buildActionMask = 2147483647; 87 | files = ( 88 | ); 89 | runOnlyForDeploymentPostprocessing = 0; 90 | }; 91 | 33CC10EA2044A3C60003C045 /* Frameworks */ = { 92 | isa = PBXFrameworksBuildPhase; 93 | buildActionMask = 2147483647; 94 | files = ( 95 | ); 96 | runOnlyForDeploymentPostprocessing = 0; 97 | }; 98 | /* End PBXFrameworksBuildPhase section */ 99 | 100 | /* Begin PBXGroup section */ 101 | 331C80D6294CF71000263BE5 /* RunnerTests */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | 331C80D7294CF71000263BE5 /* RunnerTests.swift */, 105 | ); 106 | path = RunnerTests; 107 | sourceTree = ""; 108 | }; 109 | 33BA886A226E78AF003329D5 /* Configs */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | 33E5194F232828860026EE4D /* AppInfo.xcconfig */, 113 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 114 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 115 | 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, 116 | ); 117 | path = Configs; 118 | sourceTree = ""; 119 | }; 120 | 33CC10E42044A3C60003C045 = { 121 | isa = PBXGroup; 122 | children = ( 123 | 33FAB671232836740065AC1E /* Runner */, 124 | 33CEB47122A05771004F2AC0 /* Flutter */, 125 | 331C80D6294CF71000263BE5 /* RunnerTests */, 126 | 33CC10EE2044A3C60003C045 /* Products */, 127 | D73912EC22F37F3D000D13A0 /* Frameworks */, 128 | ); 129 | sourceTree = ""; 130 | }; 131 | 33CC10EE2044A3C60003C045 /* Products */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 33CC10ED2044A3C60003C045 /* demo_2.app */, 135 | 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, 136 | ); 137 | name = Products; 138 | sourceTree = ""; 139 | }; 140 | 33CC11242044D66E0003C045 /* Resources */ = { 141 | isa = PBXGroup; 142 | children = ( 143 | 33CC10F22044A3C60003C045 /* Assets.xcassets */, 144 | 33CC10F42044A3C60003C045 /* MainMenu.xib */, 145 | 33CC10F72044A3C60003C045 /* Info.plist */, 146 | ); 147 | name = Resources; 148 | path = ..; 149 | sourceTree = ""; 150 | }; 151 | 33CEB47122A05771004F2AC0 /* Flutter */ = { 152 | isa = PBXGroup; 153 | children = ( 154 | 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, 155 | 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, 156 | 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, 157 | 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, 158 | ); 159 | path = Flutter; 160 | sourceTree = ""; 161 | }; 162 | 33FAB671232836740065AC1E /* Runner */ = { 163 | isa = PBXGroup; 164 | children = ( 165 | 33CC10F02044A3C60003C045 /* AppDelegate.swift */, 166 | 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, 167 | 33E51913231747F40026EE4D /* DebugProfile.entitlements */, 168 | 33E51914231749380026EE4D /* Release.entitlements */, 169 | 33CC11242044D66E0003C045 /* Resources */, 170 | 33BA886A226E78AF003329D5 /* Configs */, 171 | ); 172 | path = Runner; 173 | sourceTree = ""; 174 | }; 175 | D73912EC22F37F3D000D13A0 /* Frameworks */ = { 176 | isa = PBXGroup; 177 | children = ( 178 | ); 179 | name = Frameworks; 180 | sourceTree = ""; 181 | }; 182 | /* End PBXGroup section */ 183 | 184 | /* Begin PBXNativeTarget section */ 185 | 331C80D4294CF70F00263BE5 /* RunnerTests */ = { 186 | isa = PBXNativeTarget; 187 | buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; 188 | buildPhases = ( 189 | 331C80D1294CF70F00263BE5 /* Sources */, 190 | 331C80D2294CF70F00263BE5 /* Frameworks */, 191 | 331C80D3294CF70F00263BE5 /* Resources */, 192 | ); 193 | buildRules = ( 194 | ); 195 | dependencies = ( 196 | 331C80DA294CF71000263BE5 /* PBXTargetDependency */, 197 | ); 198 | name = RunnerTests; 199 | productName = RunnerTests; 200 | productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; 201 | productType = "com.apple.product-type.bundle.unit-test"; 202 | }; 203 | 33CC10EC2044A3C60003C045 /* Runner */ = { 204 | isa = PBXNativeTarget; 205 | buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; 206 | buildPhases = ( 207 | 33CC10E92044A3C60003C045 /* Sources */, 208 | 33CC10EA2044A3C60003C045 /* Frameworks */, 209 | 33CC10EB2044A3C60003C045 /* Resources */, 210 | 33CC110E2044A8840003C045 /* Bundle Framework */, 211 | 3399D490228B24CF009A79C7 /* ShellScript */, 212 | ); 213 | buildRules = ( 214 | ); 215 | dependencies = ( 216 | 33CC11202044C79F0003C045 /* PBXTargetDependency */, 217 | ); 218 | name = Runner; 219 | productName = Runner; 220 | productReference = 33CC10ED2044A3C60003C045 /* demo_2.app */; 221 | productType = "com.apple.product-type.application"; 222 | }; 223 | /* End PBXNativeTarget section */ 224 | 225 | /* Begin PBXProject section */ 226 | 33CC10E52044A3C60003C045 /* Project object */ = { 227 | isa = PBXProject; 228 | attributes = { 229 | BuildIndependentTargetsInParallel = YES; 230 | LastSwiftUpdateCheck = 0920; 231 | LastUpgradeCheck = 1510; 232 | ORGANIZATIONNAME = ""; 233 | TargetAttributes = { 234 | 331C80D4294CF70F00263BE5 = { 235 | CreatedOnToolsVersion = 14.0; 236 | TestTargetID = 33CC10EC2044A3C60003C045; 237 | }; 238 | 33CC10EC2044A3C60003C045 = { 239 | CreatedOnToolsVersion = 9.2; 240 | LastSwiftMigration = 1100; 241 | ProvisioningStyle = Automatic; 242 | SystemCapabilities = { 243 | com.apple.Sandbox = { 244 | enabled = 1; 245 | }; 246 | }; 247 | }; 248 | 33CC111A2044C6BA0003C045 = { 249 | CreatedOnToolsVersion = 9.2; 250 | ProvisioningStyle = Manual; 251 | }; 252 | }; 253 | }; 254 | buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; 255 | compatibilityVersion = "Xcode 9.3"; 256 | developmentRegion = en; 257 | hasScannedForEncodings = 0; 258 | knownRegions = ( 259 | en, 260 | Base, 261 | ); 262 | mainGroup = 33CC10E42044A3C60003C045; 263 | productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; 264 | projectDirPath = ""; 265 | projectRoot = ""; 266 | targets = ( 267 | 33CC10EC2044A3C60003C045 /* Runner */, 268 | 331C80D4294CF70F00263BE5 /* RunnerTests */, 269 | 33CC111A2044C6BA0003C045 /* Flutter Assemble */, 270 | ); 271 | }; 272 | /* End PBXProject section */ 273 | 274 | /* Begin PBXResourcesBuildPhase section */ 275 | 331C80D3294CF70F00263BE5 /* Resources */ = { 276 | isa = PBXResourcesBuildPhase; 277 | buildActionMask = 2147483647; 278 | files = ( 279 | ); 280 | runOnlyForDeploymentPostprocessing = 0; 281 | }; 282 | 33CC10EB2044A3C60003C045 /* Resources */ = { 283 | isa = PBXResourcesBuildPhase; 284 | buildActionMask = 2147483647; 285 | files = ( 286 | 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, 287 | 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, 288 | ); 289 | runOnlyForDeploymentPostprocessing = 0; 290 | }; 291 | /* End PBXResourcesBuildPhase section */ 292 | 293 | /* Begin PBXShellScriptBuildPhase section */ 294 | 3399D490228B24CF009A79C7 /* ShellScript */ = { 295 | isa = PBXShellScriptBuildPhase; 296 | alwaysOutOfDate = 1; 297 | buildActionMask = 2147483647; 298 | files = ( 299 | ); 300 | inputFileListPaths = ( 301 | ); 302 | inputPaths = ( 303 | ); 304 | outputFileListPaths = ( 305 | ); 306 | outputPaths = ( 307 | ); 308 | runOnlyForDeploymentPostprocessing = 0; 309 | shellPath = /bin/sh; 310 | shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; 311 | }; 312 | 33CC111E2044C6BF0003C045 /* ShellScript */ = { 313 | isa = PBXShellScriptBuildPhase; 314 | buildActionMask = 2147483647; 315 | files = ( 316 | ); 317 | inputFileListPaths = ( 318 | Flutter/ephemeral/FlutterInputs.xcfilelist, 319 | ); 320 | inputPaths = ( 321 | Flutter/ephemeral/tripwire, 322 | ); 323 | outputFileListPaths = ( 324 | Flutter/ephemeral/FlutterOutputs.xcfilelist, 325 | ); 326 | outputPaths = ( 327 | ); 328 | runOnlyForDeploymentPostprocessing = 0; 329 | shellPath = /bin/sh; 330 | shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; 331 | }; 332 | /* End PBXShellScriptBuildPhase section */ 333 | 334 | /* Begin PBXSourcesBuildPhase section */ 335 | 331C80D1294CF70F00263BE5 /* Sources */ = { 336 | isa = PBXSourcesBuildPhase; 337 | buildActionMask = 2147483647; 338 | files = ( 339 | 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, 340 | ); 341 | runOnlyForDeploymentPostprocessing = 0; 342 | }; 343 | 33CC10E92044A3C60003C045 /* Sources */ = { 344 | isa = PBXSourcesBuildPhase; 345 | buildActionMask = 2147483647; 346 | files = ( 347 | 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, 348 | 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, 349 | 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, 350 | ); 351 | runOnlyForDeploymentPostprocessing = 0; 352 | }; 353 | /* End PBXSourcesBuildPhase section */ 354 | 355 | /* Begin PBXTargetDependency section */ 356 | 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { 357 | isa = PBXTargetDependency; 358 | target = 33CC10EC2044A3C60003C045 /* Runner */; 359 | targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; 360 | }; 361 | 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { 362 | isa = PBXTargetDependency; 363 | target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; 364 | targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; 365 | }; 366 | /* End PBXTargetDependency section */ 367 | 368 | /* Begin PBXVariantGroup section */ 369 | 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { 370 | isa = PBXVariantGroup; 371 | children = ( 372 | 33CC10F52044A3C60003C045 /* Base */, 373 | ); 374 | name = MainMenu.xib; 375 | path = Runner; 376 | sourceTree = ""; 377 | }; 378 | /* End PBXVariantGroup section */ 379 | 380 | /* Begin XCBuildConfiguration section */ 381 | 331C80DB294CF71000263BE5 /* Debug */ = { 382 | isa = XCBuildConfiguration; 383 | buildSettings = { 384 | BUNDLE_LOADER = "$(TEST_HOST)"; 385 | CURRENT_PROJECT_VERSION = 1; 386 | GENERATE_INFOPLIST_FILE = YES; 387 | MARKETING_VERSION = 1.0; 388 | PRODUCT_BUNDLE_IDENTIFIER = gg.renan.demo2.RunnerTests; 389 | PRODUCT_NAME = "$(TARGET_NAME)"; 390 | SWIFT_VERSION = 5.0; 391 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/demo_2.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/demo_2"; 392 | }; 393 | name = Debug; 394 | }; 395 | 331C80DC294CF71000263BE5 /* Release */ = { 396 | isa = XCBuildConfiguration; 397 | buildSettings = { 398 | BUNDLE_LOADER = "$(TEST_HOST)"; 399 | CURRENT_PROJECT_VERSION = 1; 400 | GENERATE_INFOPLIST_FILE = YES; 401 | MARKETING_VERSION = 1.0; 402 | PRODUCT_BUNDLE_IDENTIFIER = gg.renan.demo2.RunnerTests; 403 | PRODUCT_NAME = "$(TARGET_NAME)"; 404 | SWIFT_VERSION = 5.0; 405 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/demo_2.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/demo_2"; 406 | }; 407 | name = Release; 408 | }; 409 | 331C80DD294CF71000263BE5 /* Profile */ = { 410 | isa = XCBuildConfiguration; 411 | buildSettings = { 412 | BUNDLE_LOADER = "$(TEST_HOST)"; 413 | CURRENT_PROJECT_VERSION = 1; 414 | GENERATE_INFOPLIST_FILE = YES; 415 | MARKETING_VERSION = 1.0; 416 | PRODUCT_BUNDLE_IDENTIFIER = gg.renan.demo2.RunnerTests; 417 | PRODUCT_NAME = "$(TARGET_NAME)"; 418 | SWIFT_VERSION = 5.0; 419 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/demo_2.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/demo_2"; 420 | }; 421 | name = Profile; 422 | }; 423 | 338D0CE9231458BD00FA5F75 /* Profile */ = { 424 | isa = XCBuildConfiguration; 425 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 426 | buildSettings = { 427 | ALWAYS_SEARCH_USER_PATHS = NO; 428 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 429 | CLANG_ANALYZER_NONNULL = YES; 430 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 431 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 432 | CLANG_CXX_LIBRARY = "libc++"; 433 | CLANG_ENABLE_MODULES = YES; 434 | CLANG_ENABLE_OBJC_ARC = YES; 435 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 436 | CLANG_WARN_BOOL_CONVERSION = YES; 437 | CLANG_WARN_CONSTANT_CONVERSION = YES; 438 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 439 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 440 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 441 | CLANG_WARN_EMPTY_BODY = YES; 442 | CLANG_WARN_ENUM_CONVERSION = YES; 443 | CLANG_WARN_INFINITE_RECURSION = YES; 444 | CLANG_WARN_INT_CONVERSION = YES; 445 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 446 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 447 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 448 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 449 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 450 | CODE_SIGN_IDENTITY = "-"; 451 | COPY_PHASE_STRIP = NO; 452 | DEAD_CODE_STRIPPING = YES; 453 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 454 | ENABLE_NS_ASSERTIONS = NO; 455 | ENABLE_STRICT_OBJC_MSGSEND = YES; 456 | ENABLE_USER_SCRIPT_SANDBOXING = NO; 457 | GCC_C_LANGUAGE_STANDARD = gnu11; 458 | GCC_NO_COMMON_BLOCKS = YES; 459 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 460 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 461 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 462 | GCC_WARN_UNUSED_FUNCTION = YES; 463 | GCC_WARN_UNUSED_VARIABLE = YES; 464 | MACOSX_DEPLOYMENT_TARGET = 10.15; 465 | MTL_ENABLE_DEBUG_INFO = NO; 466 | SDKROOT = macosx; 467 | SWIFT_COMPILATION_MODE = wholemodule; 468 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 469 | }; 470 | name = Profile; 471 | }; 472 | 338D0CEA231458BD00FA5F75 /* Profile */ = { 473 | isa = XCBuildConfiguration; 474 | baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; 475 | buildSettings = { 476 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 477 | CLANG_ENABLE_MODULES = YES; 478 | CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; 479 | CODE_SIGN_STYLE = Automatic; 480 | COMBINE_HIDPI_IMAGES = YES; 481 | INFOPLIST_FILE = Runner/Info.plist; 482 | LD_RUNPATH_SEARCH_PATHS = ( 483 | "$(inherited)", 484 | "@executable_path/../Frameworks", 485 | ); 486 | PROVISIONING_PROFILE_SPECIFIER = ""; 487 | SWIFT_VERSION = 5.0; 488 | }; 489 | name = Profile; 490 | }; 491 | 338D0CEB231458BD00FA5F75 /* Profile */ = { 492 | isa = XCBuildConfiguration; 493 | buildSettings = { 494 | CODE_SIGN_STYLE = Manual; 495 | PRODUCT_NAME = "$(TARGET_NAME)"; 496 | }; 497 | name = Profile; 498 | }; 499 | 33CC10F92044A3C60003C045 /* Debug */ = { 500 | isa = XCBuildConfiguration; 501 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 502 | buildSettings = { 503 | ALWAYS_SEARCH_USER_PATHS = NO; 504 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 505 | CLANG_ANALYZER_NONNULL = YES; 506 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 507 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 508 | CLANG_CXX_LIBRARY = "libc++"; 509 | CLANG_ENABLE_MODULES = YES; 510 | CLANG_ENABLE_OBJC_ARC = YES; 511 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 512 | CLANG_WARN_BOOL_CONVERSION = YES; 513 | CLANG_WARN_CONSTANT_CONVERSION = YES; 514 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 515 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 516 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 517 | CLANG_WARN_EMPTY_BODY = YES; 518 | CLANG_WARN_ENUM_CONVERSION = YES; 519 | CLANG_WARN_INFINITE_RECURSION = YES; 520 | CLANG_WARN_INT_CONVERSION = YES; 521 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 522 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 523 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 524 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 525 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 526 | CODE_SIGN_IDENTITY = "-"; 527 | COPY_PHASE_STRIP = NO; 528 | DEAD_CODE_STRIPPING = YES; 529 | DEBUG_INFORMATION_FORMAT = dwarf; 530 | ENABLE_STRICT_OBJC_MSGSEND = YES; 531 | ENABLE_TESTABILITY = YES; 532 | ENABLE_USER_SCRIPT_SANDBOXING = NO; 533 | GCC_C_LANGUAGE_STANDARD = gnu11; 534 | GCC_DYNAMIC_NO_PIC = NO; 535 | GCC_NO_COMMON_BLOCKS = YES; 536 | GCC_OPTIMIZATION_LEVEL = 0; 537 | GCC_PREPROCESSOR_DEFINITIONS = ( 538 | "DEBUG=1", 539 | "$(inherited)", 540 | ); 541 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 542 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 543 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 544 | GCC_WARN_UNUSED_FUNCTION = YES; 545 | GCC_WARN_UNUSED_VARIABLE = YES; 546 | MACOSX_DEPLOYMENT_TARGET = 10.15; 547 | MTL_ENABLE_DEBUG_INFO = YES; 548 | ONLY_ACTIVE_ARCH = YES; 549 | SDKROOT = macosx; 550 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 551 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 552 | }; 553 | name = Debug; 554 | }; 555 | 33CC10FA2044A3C60003C045 /* Release */ = { 556 | isa = XCBuildConfiguration; 557 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 558 | buildSettings = { 559 | ALWAYS_SEARCH_USER_PATHS = NO; 560 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 561 | CLANG_ANALYZER_NONNULL = YES; 562 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 563 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 564 | CLANG_CXX_LIBRARY = "libc++"; 565 | CLANG_ENABLE_MODULES = YES; 566 | CLANG_ENABLE_OBJC_ARC = YES; 567 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 568 | CLANG_WARN_BOOL_CONVERSION = YES; 569 | CLANG_WARN_CONSTANT_CONVERSION = YES; 570 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 571 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 572 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 573 | CLANG_WARN_EMPTY_BODY = YES; 574 | CLANG_WARN_ENUM_CONVERSION = YES; 575 | CLANG_WARN_INFINITE_RECURSION = YES; 576 | CLANG_WARN_INT_CONVERSION = YES; 577 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 578 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 579 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 580 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 581 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 582 | CODE_SIGN_IDENTITY = "-"; 583 | COPY_PHASE_STRIP = NO; 584 | DEAD_CODE_STRIPPING = YES; 585 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 586 | ENABLE_NS_ASSERTIONS = NO; 587 | ENABLE_STRICT_OBJC_MSGSEND = YES; 588 | ENABLE_USER_SCRIPT_SANDBOXING = NO; 589 | GCC_C_LANGUAGE_STANDARD = gnu11; 590 | GCC_NO_COMMON_BLOCKS = YES; 591 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 592 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 593 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 594 | GCC_WARN_UNUSED_FUNCTION = YES; 595 | GCC_WARN_UNUSED_VARIABLE = YES; 596 | MACOSX_DEPLOYMENT_TARGET = 10.15; 597 | MTL_ENABLE_DEBUG_INFO = NO; 598 | SDKROOT = macosx; 599 | SWIFT_COMPILATION_MODE = wholemodule; 600 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 601 | }; 602 | name = Release; 603 | }; 604 | 33CC10FC2044A3C60003C045 /* Debug */ = { 605 | isa = XCBuildConfiguration; 606 | baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; 607 | buildSettings = { 608 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 609 | CLANG_ENABLE_MODULES = YES; 610 | CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; 611 | CODE_SIGN_STYLE = Automatic; 612 | COMBINE_HIDPI_IMAGES = YES; 613 | INFOPLIST_FILE = Runner/Info.plist; 614 | LD_RUNPATH_SEARCH_PATHS = ( 615 | "$(inherited)", 616 | "@executable_path/../Frameworks", 617 | ); 618 | PROVISIONING_PROFILE_SPECIFIER = ""; 619 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 620 | SWIFT_VERSION = 5.0; 621 | }; 622 | name = Debug; 623 | }; 624 | 33CC10FD2044A3C60003C045 /* Release */ = { 625 | isa = XCBuildConfiguration; 626 | baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; 627 | buildSettings = { 628 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 629 | CLANG_ENABLE_MODULES = YES; 630 | CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; 631 | CODE_SIGN_STYLE = Automatic; 632 | COMBINE_HIDPI_IMAGES = YES; 633 | INFOPLIST_FILE = Runner/Info.plist; 634 | LD_RUNPATH_SEARCH_PATHS = ( 635 | "$(inherited)", 636 | "@executable_path/../Frameworks", 637 | ); 638 | PROVISIONING_PROFILE_SPECIFIER = ""; 639 | SWIFT_VERSION = 5.0; 640 | }; 641 | name = Release; 642 | }; 643 | 33CC111C2044C6BA0003C045 /* Debug */ = { 644 | isa = XCBuildConfiguration; 645 | buildSettings = { 646 | CODE_SIGN_STYLE = Manual; 647 | PRODUCT_NAME = "$(TARGET_NAME)"; 648 | }; 649 | name = Debug; 650 | }; 651 | 33CC111D2044C6BA0003C045 /* Release */ = { 652 | isa = XCBuildConfiguration; 653 | buildSettings = { 654 | CODE_SIGN_STYLE = Automatic; 655 | PRODUCT_NAME = "$(TARGET_NAME)"; 656 | }; 657 | name = Release; 658 | }; 659 | /* End XCBuildConfiguration section */ 660 | 661 | /* Begin XCConfigurationList section */ 662 | 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { 663 | isa = XCConfigurationList; 664 | buildConfigurations = ( 665 | 331C80DB294CF71000263BE5 /* Debug */, 666 | 331C80DC294CF71000263BE5 /* Release */, 667 | 331C80DD294CF71000263BE5 /* Profile */, 668 | ); 669 | defaultConfigurationIsVisible = 0; 670 | defaultConfigurationName = Release; 671 | }; 672 | 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { 673 | isa = XCConfigurationList; 674 | buildConfigurations = ( 675 | 33CC10F92044A3C60003C045 /* Debug */, 676 | 33CC10FA2044A3C60003C045 /* Release */, 677 | 338D0CE9231458BD00FA5F75 /* Profile */, 678 | ); 679 | defaultConfigurationIsVisible = 0; 680 | defaultConfigurationName = Release; 681 | }; 682 | 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { 683 | isa = XCConfigurationList; 684 | buildConfigurations = ( 685 | 33CC10FC2044A3C60003C045 /* Debug */, 686 | 33CC10FD2044A3C60003C045 /* Release */, 687 | 338D0CEA231458BD00FA5F75 /* Profile */, 688 | ); 689 | defaultConfigurationIsVisible = 0; 690 | defaultConfigurationName = Release; 691 | }; 692 | 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { 693 | isa = XCConfigurationList; 694 | buildConfigurations = ( 695 | 33CC111C2044C6BA0003C045 /* Debug */, 696 | 33CC111D2044C6BA0003C045 /* Release */, 697 | 338D0CEB231458BD00FA5F75 /* Profile */, 698 | ); 699 | defaultConfigurationIsVisible = 0; 700 | defaultConfigurationName = Release; 701 | }; 702 | /* End XCConfigurationList section */ 703 | }; 704 | rootObject = 33CC10E52044A3C60003C045 /* Project object */; 705 | } 706 | -------------------------------------------------------------------------------- /macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 43 | 49 | 50 | 51 | 52 | 53 | 64 | 66 | 72 | 73 | 74 | 75 | 81 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @main 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | 10 | override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { 11 | return true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "app_icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "app_icon_32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "app_icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "app_icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "app_icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "app_icon_256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "app_icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "app_icon_512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "app_icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "app_icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /macos/Runner/Base.lproj/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | -------------------------------------------------------------------------------- /macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = demo_2 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = gg.renan.demo2 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2025 gg.renan. All rights reserved. 15 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "2.13.0" 12 | boolean_selector: 13 | dependency: transitive 14 | description: 15 | name: boolean_selector 16 | sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "2.1.2" 20 | characters: 21 | dependency: transitive 22 | description: 23 | name: characters 24 | sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "1.4.0" 28 | clock: 29 | dependency: transitive 30 | description: 31 | name: clock 32 | sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "1.1.2" 36 | collection: 37 | dependency: transitive 38 | description: 39 | name: collection 40 | sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "1.19.1" 44 | fake_async: 45 | dependency: transitive 46 | description: 47 | name: fake_async 48 | sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "1.3.3" 52 | flame: 53 | dependency: "direct main" 54 | description: 55 | name: flame 56 | sha256: c50e2f39e118f5f6a6f3339ce6825ee803c7e5fada95ec50fb02eb27944e0e76 57 | url: "https://pub.dev" 58 | source: hosted 59 | version: "1.30.1" 60 | flame_lint: 61 | dependency: "direct dev" 62 | description: 63 | name: flame_lint 64 | sha256: "11c92624996dce2aeec2a41d44a61d7a560d551e4b5e447e2ad0b3812e8c2836" 65 | url: "https://pub.dev" 66 | source: hosted 67 | version: "1.4.2" 68 | flutter: 69 | dependency: "direct main" 70 | description: flutter 71 | source: sdk 72 | version: "0.0.0" 73 | flutter_test: 74 | dependency: "direct dev" 75 | description: flutter 76 | source: sdk 77 | version: "0.0.0" 78 | leak_tracker: 79 | dependency: transitive 80 | description: 81 | name: leak_tracker 82 | sha256: "8dcda04c3fc16c14f48a7bb586d4be1f0d1572731b6d81d51772ef47c02081e0" 83 | url: "https://pub.dev" 84 | source: hosted 85 | version: "11.0.1" 86 | leak_tracker_flutter_testing: 87 | dependency: transitive 88 | description: 89 | name: leak_tracker_flutter_testing 90 | sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" 91 | url: "https://pub.dev" 92 | source: hosted 93 | version: "3.0.10" 94 | leak_tracker_testing: 95 | dependency: transitive 96 | description: 97 | name: leak_tracker_testing 98 | sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" 99 | url: "https://pub.dev" 100 | source: hosted 101 | version: "3.0.2" 102 | lints: 103 | dependency: transitive 104 | description: 105 | name: lints 106 | sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0 107 | url: "https://pub.dev" 108 | source: hosted 109 | version: "6.0.0" 110 | matcher: 111 | dependency: transitive 112 | description: 113 | name: matcher 114 | sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 115 | url: "https://pub.dev" 116 | source: hosted 117 | version: "0.12.17" 118 | material_color_utilities: 119 | dependency: transitive 120 | description: 121 | name: material_color_utilities 122 | sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec 123 | url: "https://pub.dev" 124 | source: hosted 125 | version: "0.11.1" 126 | meta: 127 | dependency: transitive 128 | description: 129 | name: meta 130 | sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" 131 | url: "https://pub.dev" 132 | source: hosted 133 | version: "1.17.0" 134 | ordered_set: 135 | dependency: transitive 136 | description: 137 | name: ordered_set 138 | sha256: d6c1d053a533e84931a388cbf03f1ad21a0543bf06c7a281859d3ffacd8e15f2 139 | url: "https://pub.dev" 140 | source: hosted 141 | version: "8.0.0" 142 | path: 143 | dependency: transitive 144 | description: 145 | name: path 146 | sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" 147 | url: "https://pub.dev" 148 | source: hosted 149 | version: "1.9.1" 150 | sky_engine: 151 | dependency: transitive 152 | description: flutter 153 | source: sdk 154 | version: "0.0.0" 155 | source_span: 156 | dependency: transitive 157 | description: 158 | name: source_span 159 | sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" 160 | url: "https://pub.dev" 161 | source: hosted 162 | version: "1.10.1" 163 | stack_trace: 164 | dependency: transitive 165 | description: 166 | name: stack_trace 167 | sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" 168 | url: "https://pub.dev" 169 | source: hosted 170 | version: "1.12.1" 171 | stream_channel: 172 | dependency: transitive 173 | description: 174 | name: stream_channel 175 | sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" 176 | url: "https://pub.dev" 177 | source: hosted 178 | version: "2.1.4" 179 | string_scanner: 180 | dependency: transitive 181 | description: 182 | name: string_scanner 183 | sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" 184 | url: "https://pub.dev" 185 | source: hosted 186 | version: "1.4.1" 187 | term_glyph: 188 | dependency: transitive 189 | description: 190 | name: term_glyph 191 | sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" 192 | url: "https://pub.dev" 193 | source: hosted 194 | version: "1.2.2" 195 | test_api: 196 | dependency: transitive 197 | description: 198 | name: test_api 199 | sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 200 | url: "https://pub.dev" 201 | source: hosted 202 | version: "0.7.7" 203 | vector_math: 204 | dependency: transitive 205 | description: 206 | name: vector_math 207 | sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b 208 | url: "https://pub.dev" 209 | source: hosted 210 | version: "2.2.0" 211 | vm_service: 212 | dependency: transitive 213 | description: 214 | name: vm_service 215 | sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" 216 | url: "https://pub.dev" 217 | source: hosted 218 | version: "15.0.2" 219 | sdks: 220 | dart: ">=3.10.0-75.1.beta <4.0.0" 221 | flutter: ">=3.27.1" 222 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: demo_2 2 | description: "A new Flutter project." 3 | publish_to: "none" 4 | 5 | version: 1.0.0+1 6 | 7 | environment: 8 | sdk: ^3.10.0-75.1.beta 9 | 10 | dependencies: 11 | flame: ^1.30.1 12 | flutter: 13 | sdk: flutter 14 | 15 | dev_dependencies: 16 | flame_lint: ^1.4.2 17 | flutter_test: 18 | sdk: flutter 19 | 20 | flutter: 21 | uses-material-design: true 22 | assets: 23 | - assets/images/spritesheet.png 24 | shaders: 25 | - shaders/sea.frag 26 | - shaders/ship_wake.frag 27 | - shaders/ship.frag 28 | - shaders/smoke.frag 29 | - shaders/vignette.frag 30 | -------------------------------------------------------------------------------- /shaders/sea.frag: -------------------------------------------------------------------------------- 1 | #version 460 core 2 | 3 | precision mediump float; 4 | 5 | #include 6 | 7 | uniform vec2 uSize; 8 | uniform float uTime; 9 | uniform float uRotation; 10 | 11 | out vec4 fragColor; 12 | 13 | const int NUM_STEPS = 1; 14 | const float PI = 3.141592; 15 | const float EPSILON = 1e-3; 16 | #define EPSILON_NRM (0.08 / uSize.x) 17 | const int ITER_GEOMETRY = 2; 18 | const int ITER_FRAGMENT = 2; 19 | const float SEA_HEIGHT = 1.9; 20 | const float SEA_CHOPPY = 1.3; 21 | const float SEA_SPEED = 0.81; 22 | const float SEA_FREQ = 0.32; 23 | const vec3 SEA_BASE = vec3(0.005); 24 | #define SEA_TIME (1.0 + uTime * SEA_SPEED) 25 | const mat2 octave_m = mat2(1.2, 1.2, -1.2, 1.6); 26 | 27 | /* 28 | * "Seascape" by Alexander Alekseev aka TDM - 2014 29 | * License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 30 | * Changes made to the original shader: 31 | * - Changed base colors to look black and white 32 | * - remove camera moviment and synced to a uniform to define the angle and speed of the camera 33 | * - Remove a lot of perspective look more octonogal-ish 34 | * - Increased water highlights 35 | * - Adapted to Flutters style fo shader 36 | */ 37 | mat3 fromEuler(vec3 ang) { 38 | vec2 a1 = vec2(sin(ang.x), cos(ang.x)); 39 | vec2 a2 = vec2(sin(ang.y), cos(ang.y)); 40 | vec2 a3 = vec2(sin(ang.z), cos(ang.z)); 41 | mat3 m; 42 | m[0] = vec3(a1.y * a3.y + a1.x * a2.x * a3.x, a1.y * a2.x * a3.x + a3.y * a1.x, -a2.y * a3.x); 43 | m[1] = vec3(-a2.y * a1.x, a1.y * a2.y, a2.x); 44 | m[2] = vec3(a3.y * a1.x * a2.x + a1.y * a3.x, a1.x * a3.x - a1.y * a3.y * a2.x, a2.y * a3.y); 45 | return m; 46 | } 47 | 48 | float hash(vec2 p) { 49 | float h = dot(p, vec2(127.1, 311.7)); 50 | return fract(sin(h) * 43758.5453123); 51 | } 52 | 53 | float noise(in vec2 p) { 54 | vec2 i = floor(p); 55 | vec2 f = fract(p); 56 | vec2 u = f * f * (3.0 - 2.0 * f); 57 | return -1.0 + 2.0 * mix(mix(hash(i), hash(i + vec2(1.0, 0.0)), u.x), mix(hash(i + vec2(0.0, 1.0)), hash(i + vec2(1.0, 1.0)), u.x), u.y); 58 | } 59 | 60 | float diffuse(vec3 n, vec3 l, float p) { 61 | return pow(dot(n, l) * 0.0 + 0.6, p); 62 | } 63 | 64 | float specular(vec3 n, vec3 l, vec3 e, float s) { 65 | float nrm = (s + 8.0) / (PI * 8.0); 66 | return pow(max(dot(reflect(e, n), l), 0.0), s) * nrm; 67 | } 68 | 69 | float sea_octave(vec2 uv, float choppy) { 70 | uv += noise(uv); 71 | vec2 wv = 1.0 - abs(sin(uv)); 72 | vec2 swv = abs(cos(uv)); 73 | wv = mix(wv, swv, wv); 74 | return pow(1.0 - pow(wv.x * wv.y, 0.65), choppy); 75 | } 76 | 77 | float map(vec3 p) { 78 | float freq = SEA_FREQ; 79 | float choppy = SEA_CHOPPY; 80 | vec2 uv = p.xz; 81 | uv.x *= 0.75; 82 | 83 | float d, h = 0.0; 84 | for(int i = 0; i < ITER_GEOMETRY; i++) { 85 | d = sea_octave((uv + SEA_TIME) * freq, choppy); 86 | d += sea_octave((uv - SEA_TIME) * freq, choppy); 87 | uv *= octave_m; 88 | freq *= 1.9; 89 | choppy = mix(choppy, 1.0, 0.2); 90 | } 91 | return p.y - h; 92 | } 93 | 94 | float map_detailed(vec3 p) { 95 | float freq = SEA_FREQ; 96 | float amp = SEA_HEIGHT; 97 | float choppy = SEA_CHOPPY; 98 | vec2 uv = p.xz; 99 | uv.x *= 0.3; 100 | uv.y *= 0.3; 101 | 102 | float d, h = 0.0; 103 | for(int i = 0; i < ITER_FRAGMENT; i++) { 104 | d = sea_octave((uv + SEA_TIME) * freq, choppy); 105 | d += sea_octave((uv - SEA_TIME) * freq, choppy); 106 | h += d * amp; 107 | uv *= octave_m; 108 | freq *= 1.9; 109 | amp *= 0.22; 110 | choppy = mix(choppy, 1.0, 0.2); 111 | } 112 | return p.y - h; 113 | } 114 | 115 | vec3 getSeaColor(vec3 p, vec3 n, vec3 l, vec3 eye, vec3 dist) { 116 | float fresnel = clamp(1.0 - dot(n, -eye), 0.0, 1.0); 117 | fresnel = min(fresnel * fresnel * fresnel, .5); 118 | 119 | vec3 reflected = vec3(.0); 120 | vec3 refracted = SEA_BASE + diffuse(n, l, 50.0); 121 | 122 | vec3 color = mix(refracted, reflected, fresnel); 123 | 124 | color += specular(n, l, eye, 1000.0 * inversesqrt(dot(dist, dist * 0.01))); 125 | 126 | return color; 127 | } 128 | 129 | vec3 getNormal(vec3 p, float eps) { 130 | vec3 n; 131 | n.y = map_detailed(p); 132 | n.x = map_detailed(vec3(p.x + eps, p.y, p.z)) - n.y; 133 | n.z = map_detailed(vec3(p.x, p.y, p.z + eps)) - n.y; 134 | n.y = eps; 135 | return normalize(n); 136 | } 137 | 138 | float heightMapTracing(vec3 ori, vec3 dir, out vec3 p) { 139 | float tm = 0.0; 140 | float tx = 1000.0; 141 | 142 | float hx = map(ori + dir * tx); 143 | if(hx > 0.0) { 144 | p = ori + dir * tx; 145 | return tx; 146 | } 147 | float hm = map(ori); 148 | for(int i = 0; i < NUM_STEPS; i++) { 149 | float tmid = mix(tm, tx, hm / (hm - hx)); 150 | p = ori + dir * tmid; 151 | float hmid = map(p); 152 | if(hmid < 0.0) { 153 | tx = tmid; 154 | hx = hmid; 155 | } else { 156 | tm = tmid; 157 | hm = hmid; 158 | } 159 | if(abs(hmid) < EPSILON) 160 | break; 161 | } 162 | return mix(tm, tx, hm / (hm - hx)); 163 | } 164 | 165 | vec3 getPixel(in vec2 coord, float time) { 166 | vec2 uv = coord / uSize.xy; 167 | uv = uv * 2.0 - 1.0; 168 | uv.x *= uSize.x / uSize.y; 169 | 170 | float r = 1480.0; 171 | 172 | float t = uRotation; 173 | 174 | vec3 ang = vec3(0.0, 0.83, -t); 175 | vec3 ori = vec3(r * sin(t), 178.5, time + r * cos(t)); 176 | vec3 dir = normalize(vec3(uv.xy, -2.0)); 177 | dir.z += length(uv) * 0.01; 178 | dir = normalize(dir) * fromEuler(ang); 179 | 180 | vec3 p; 181 | heightMapTracing(ori, dir, p); 182 | vec3 dist = p - ori + vec3(0.0, 30.5, 0.0); 183 | vec3 n = getNormal(p, dot(dist, dist) * EPSILON_NRM); 184 | vec3 light = normalize(vec3(0.0, 1000.5, -1500)) * 0.96; 185 | 186 | vec3 color = mix(vec3(1), getSeaColor(p, n, light, dir, dist), pow(smoothstep(0.0, -0.02, dir.y), 0.2)); 187 | 188 | float brightness = dot(color, vec3(0.299, 0.587, 0.114)); 189 | float highlightMask = pow(brightness, 2.5); 190 | color = color + color * highlightMask * 2.5; 191 | 192 | return color; 193 | } 194 | 195 | void main() { 196 | float time = -uTime * 14.0; 197 | vec2 fragCoord = FlutterFragCoord().xy * vec2(1.0, -1.0) + vec2(0.0, uSize.y); 198 | vec3 color = getPixel(fragCoord, time); 199 | fragColor = vec4(pow(color, vec3(0.85)), 1.0); 200 | 201 | } 202 | -------------------------------------------------------------------------------- /shaders/ship.frag: -------------------------------------------------------------------------------- 1 | #version 460 core 2 | 3 | precision mediump float; 4 | 5 | #include 6 | 7 | uniform vec2 uSize; 8 | uniform float uPixelSize; 9 | uniform sampler2D tTexture; 10 | 11 | out vec4 fragColor; 12 | 13 | void main() { 14 | vec2 pos = FlutterFragCoord().xy / uPixelSize; 15 | vec2 uv = pos / uSize; 16 | vec4 texColor = texture(tTexture, uv); 17 | float grey = (texColor.r + texColor.g + texColor.b) / 3.0; 18 | texColor.rgb = vec3(grey); 19 | fragColor = texColor; 20 | } 21 | -------------------------------------------------------------------------------- /shaders/ship_wake.frag: -------------------------------------------------------------------------------- 1 | #version 460 core 2 | 3 | precision mediump float; 4 | 5 | #include 6 | 7 | uniform vec2 uSize; 8 | uniform float uTime; 9 | uniform float uPixelSize; 10 | 11 | uniform sampler2D tTexture; 12 | 13 | out vec4 fragColor; 14 | 15 | const float PI = 3.14159265359; 16 | 17 | float hash(vec2 p) { 18 | float h = dot(p, vec2(127.1, 311.7)); 19 | return fract(sin(h) * 43758.5453123); 20 | } 21 | float vnoise(vec2 p) { 22 | vec2 i = floor(p), f = fract(p); 23 | vec2 u = f * f * (3.0 - 2.0 * f); 24 | float a = hash(i); 25 | float b = hash(i + vec2(1.0, 0.0)); 26 | float c = hash(i + vec2(0.0, 1.0)); 27 | float d = hash(i + vec2(1.0, 1.0)); 28 | return mix(mix(a, b, u.x), mix(c, d, u.x), u.y); 29 | } 30 | 31 | mat2 rot(float a) { 32 | float c = cos(a), s = sin(a); 33 | return mat2(c, -s, s, c); 34 | } 35 | 36 | // psrdnoise (c) Stefan Gustavson and Ian McEwan, 37 | // ver. 2021-12-02, published under the MIT license: 38 | // https://github.com/stegu/psrdnoise/ 39 | float psrdnoise(vec2 x, vec2 period, float alpha, out vec2 gradient) { 40 | vec2 uv = vec2(x.x + x.y * 0.5, x.y); 41 | vec2 i0 = floor(uv), f0 = fract(uv); 42 | float cmp = step(f0.y, f0.x); 43 | vec2 o1 = vec2(cmp, 1.0 - cmp); 44 | vec2 i1 = i0 + o1, i2 = i0 + 1.0; 45 | vec2 v0 = vec2(i0.x - i0.y * 0.5, i0.y); 46 | vec2 v1 = vec2(v0.x + o1.x - o1.y * 0.5, v0.y + o1.y); 47 | vec2 v2 = vec2(v0.x + 0.5, v0.y + 1.0); 48 | vec2 x0 = x - v0, x1 = x - v1, x2 = x - v2; 49 | vec3 iu, iv, xw, yw; 50 | if(any(greaterThan(period, vec2(0.0)))) { 51 | xw = vec3(v0.x, v1.x, v2.x); 52 | yw = vec3(v0.y, v1.y, v2.y); 53 | if(period.x > 0.0) 54 | xw = mod(vec3(v0.x, v1.x, v2.x), period.x); 55 | if(period.y > 0.0) 56 | yw = mod(vec3(v0.y, v1.y, v2.y), period.y); 57 | iu = floor(xw + 0.5 * yw + 0.5); 58 | iv = floor(yw + 0.5); 59 | } else { 60 | iu = vec3(i0.x, i1.x, i2.x); 61 | iv = vec3(i0.y, i1.y, i2.y); 62 | } 63 | vec3 hash = mod(iu, 289.0); 64 | hash = mod((hash * 51.0 + 2.0) * hash + iv, 289.0); 65 | hash = mod((hash * 34.0 + 10.0) * hash, 289.0); 66 | vec3 psi = hash * 0.07482 + alpha; 67 | vec3 gx = cos(psi); 68 | vec3 gy = sin(psi); 69 | vec2 g0 = vec2(gx.x, gy.x); 70 | vec2 g1 = vec2(gx.y, gy.y); 71 | vec2 g2 = vec2(gx.z, gy.z); 72 | vec3 w = 0.8 - vec3(dot(x0, x0), dot(x1, x1), dot(x2, x2)); 73 | w = max(w, 0.0); 74 | vec3 w2 = w * w; 75 | vec3 w4 = w2 * w2; 76 | vec3 gdotx = vec3(dot(g0, x0), dot(g1, x1), dot(g2, x2)); 77 | float n = dot(w4, gdotx); 78 | vec3 w3 = w2 * w; 79 | vec3 dw = -8.0 * w3 * gdotx; 80 | vec2 dn0 = w4.x * g0 + dw.x * x0; 81 | vec2 dn1 = w4.y * g1 + dw.y * x1; 82 | vec2 dn2 = w4.z * g2 + dw.z * x2; 83 | gradient = 10.9 * (dn0 + dn1 + dn2); 84 | return 10.9 * n; 85 | } 86 | 87 | vec2 domainWarp(vec2 p, float t, float k) { 88 | vec2 q = p * 0.6 + 0.10 * t; 89 | vec2 w = vec2(vnoise(q), vnoise(q + 10000.0)); 90 | return p + k * w; 91 | } 92 | 93 | float streakFoam(vec2 uv, vec2 flowDir, float t) { 94 | vec2 T = normalize(flowDir); 95 | vec2 N = vec2(-T.y, T.x); 96 | 97 | mat2 A = mat2(6.0 * T + 1.9 * N, 0.25 * T + 22.0 * N); 98 | 99 | vec2 P = A * uv; 100 | 101 | P += T * (t * 0.05); // << movement along the wake 102 | P = domainWarp(P, t, 0.10); 103 | 104 | float sum = 0.0, amp = 0.8, frq = 2; 105 | for(int i = 0; i < 20; i++) { 106 | vec2 g; 107 | float n = abs(psrdnoise(P * frq, vec2(0.0), t * 6.0, g)); 108 | sum += amp * n; 109 | frq *= 2.0; 110 | amp *= 0.55; 111 | } 112 | 113 | float hp = smoothstep(0.55, 0.85, sum) - smoothstep(0.85, 1.00, sum); 114 | hp += 0.08 * (vnoise(uv * 18.0 - vec2(0.0, 0.5 * t)) - 0.5); 115 | return clamp(hp * 1.6, 0.0, 1.0); 116 | } 117 | 118 | vec2 wakeEmitter(vec2 uv) { 119 | vec4 tex = texture(tTexture, uv); 120 | 121 | vec2 res = vec2(0.0); 122 | res.x = smoothstep(0.10, 0.85, tex.g); 123 | res.y = smoothstep(0.00, 0.95, tex.r); 124 | return res; 125 | } 126 | 127 | void main() { 128 | vec2 frag = FlutterFragCoord().xy / uPixelSize; 129 | vec2 uv = frag / uSize; 130 | 131 | float t = -uTime * 0.4; 132 | 133 | vec2 flowDir = vec2(1.0, 0.0); 134 | 135 | // emitter from texture, with soft edges 136 | vec2 emtieres = wakeEmitter(uv); 137 | vec4 tex = texture(tTexture, uv); // r: inner, g: outer 138 | 139 | float emitg = emtieres.x; // outer (gentle) foam 140 | float emitr = emtieres.y; // inner (strong) foam 141 | 142 | float speedg = 0.12; 143 | float speedr = 0.10; // speed of wake travel 144 | 145 | // structured foam (streaks) advected over time 146 | float filg = streakFoam(uv * 4.0 - vec2(0, uTime * speedg), flowDir, t); 147 | float filr = streakFoam(uv * 4.0 - vec2(0, uTime * speedr), flowDir, t); 148 | 149 | float foamg = emitg * (0.05 * emitg + filg); 150 | float foamr = emitr * (emitr + filr); 151 | 152 | // clean onset and cap 153 | foamg = smoothstep(0.30, 0.95, foamg); 154 | foamr = smoothstep(0.30, 0.95, foamr); 155 | 156 | float foam = max(foamg, foamr); 157 | 158 | // final: only foam, no texture color rendered 159 | vec3 foamColor = vec3(0.93, 0.98, 1.0); // cold white foam 160 | 161 | fragColor = vec4(foamColor * foam, foam); 162 | 163 | float fade = smoothstep(0.0, 0.5, uv.y); 164 | fragColor.rgb *= (1.0 - fade); 165 | } -------------------------------------------------------------------------------- /shaders/smoke.frag: -------------------------------------------------------------------------------- 1 | #version 460 core 2 | 3 | precision mediump float; 4 | 5 | #include 6 | 7 | uniform vec2 uSize; 8 | uniform float uCameraOrbitAngle; 9 | uniform vec3 uSpherePositions[20]; 10 | uniform float uSphereRadii[20]; 11 | uniform float uSphereOpacities[20]; 12 | 13 | out vec4 fragColor; 14 | 15 | const int steps = 5; 16 | const float eps = 1e-4; 17 | const int levels = 10; 18 | const float ditherScale = 1.85; 19 | const vec3 sphereBaseColor = vec3(0.42); 20 | const float lightIntensity = 0.5; 21 | 22 | float bayer4(vec2 p) { 23 | ivec2 ip = ivec2(floor(mod(p, 4.0))); 24 | int idx = ip.x + ip.y * 4; 25 | const mat4 M = mat4(vec4(0, 8, 2, 10), vec4(12, 4, 14, 6), vec4(3, 11, 1, 9), vec4(15, 7, 13, 5)); 26 | int val = 0; 27 | 28 | for(int i = 0; i < 4; i++) { 29 | for(int j = 0; j < 4; j++) { 30 | if(idx == i + j * 4) { 31 | val = int(M[i][j]); 32 | } 33 | } 34 | } 35 | return (float(val) + 0.5) / 16.0; 36 | } 37 | 38 | /// Tonemapping from Uncharted 2, by John Hable, Learn about it on: http://filmicworlds.com/blog/filmic-tonemapping-operators/ and https://mini.gmshaders.com/p/tonemaps 39 | 40 | vec3 tonemapUncharted2(vec3 linearColor) { 41 | const float A = 0.15; 42 | const float B = 0.50; 43 | const float C = 0.10; 44 | const float D = 0.20; 45 | const float E = 0.02; 46 | const float F = 0.30; 47 | 48 | return ((linearColor * (A * linearColor + C * B) + D * E) / (linearColor * (A * linearColor + B) + D * F)) - E / F; 49 | } 50 | 51 | vec3 tonemapFilmic(vec3 hdrColor, float exposure) { 52 | vec3 exposed = hdrColor * exposure; 53 | vec3 mapped = tonemapUncharted2(exposed); 54 | vec3 white = tonemapUncharted2(vec3(11.2)); 55 | mapped /= white; 56 | return pow(clamp(mapped, 0.0, 1.0), vec3(1.0 / 2.2)); 57 | } 58 | 59 | vec3 raySphere(vec3 rayOrigin, vec3 rayDirection, vec3 sphereCenter, float sphereRadius) { 60 | vec3 originToCenter = rayOrigin - sphereCenter; 61 | float halfB = dot(originToCenter, rayDirection); 62 | float cTerm = dot(originToCenter, originToCenter) - sphereRadius * sphereRadius; 63 | float discriminant = halfB * halfB - cTerm; 64 | 65 | if(discriminant <= 0.0) { 66 | return vec3(0.0, 0.0, 0.0); 67 | } 68 | 69 | float root = sqrt(discriminant); 70 | float t0 = -halfB - root; 71 | float t1 = -halfB + root; 72 | return vec3(t0, t1, 1.0); 73 | } 74 | 75 | float sphereDensity(vec3 samplePoint, vec3 sphereCenter, float sphereRadius, float edgeThickness) { 76 | float distanceFromCenter = length(samplePoint - sphereCenter); 77 | return smoothstep(sphereRadius, sphereRadius - edgeThickness, distanceFromCenter); 78 | } 79 | 80 | void main() { 81 | vec2 fragCoord = FlutterFragCoord().xy; 82 | vec4 backgroundColor = vec4(0.0); 83 | 84 | fragCoord.y += -43.0; 85 | 86 | vec2 screenUV = (fragCoord - 0.5 * uSize.xy) / uSize.y; 87 | 88 | float orbitAngleRad = radians(uCameraOrbitAngle); 89 | float orbitRadius = 31.5; 90 | vec3 cameraOrigin = vec3(orbitRadius * sin(orbitAngleRad), -20.0, orbitRadius * cos(orbitAngleRad)); 91 | 92 | vec3 cameraTarget = vec3(0.0, 0.0, 0.0); 93 | vec3 cameraForward = normalize(cameraTarget - cameraOrigin); 94 | vec3 cameraRight = normalize(cross(vec3(0.0, 1.0, 0.0), cameraForward)); 95 | vec3 cameraUp = cross(cameraForward, cameraRight); 96 | float focalLength = 1.72; 97 | vec3 rayDirection = normalize(screenUV.x * cameraRight + 98 | screenUV.y * cameraUp + 99 | focalLength * cameraForward); 100 | 101 | float sphereEdgeThickness = 20.5; 102 | 103 | vec3 lightDirection = normalize(vec3(0, 1000.0, -300)); 104 | 105 | float anySphereHit = 0.0; 106 | float tNear = 1e9; 107 | float tFar = -1e9; 108 | for(int i = 0; i < 20; ++i) { 109 | vec3 sphereCenter = uSpherePositions[i]; 110 | float sphereRadius = uSphereRadii[i]; 111 | vec3 hitData = raySphere(cameraOrigin, rayDirection, sphereCenter, sphereRadius); 112 | 113 | if(hitData.z > 0.5) { 114 | anySphereHit = 1.0; 115 | tNear = min(tNear, max(hitData.x, 0.0)); 116 | tFar = max(tFar, hitData.y); 117 | } 118 | } 119 | 120 | if(anySphereHit == 0.0) { 121 | fragColor = backgroundColor; 122 | return; 123 | } 124 | 125 | if(tFar <= 0.0) { 126 | fragColor = backgroundColor; 127 | return; 128 | } 129 | 130 | tNear = max(tNear, 0.0); 131 | 132 | float absorptionCoefficient = 50.0; 133 | float emissionStrength = 4.0; 134 | float segmentLength = max(tFar - tNear, eps); 135 | float stepSize = segmentLength / float(steps); 136 | vec3 accumulatedColor = vec3(0.0); 137 | float transmittance = 1.0; 138 | 139 | float currentT = tNear; 140 | for(int stepIndex = 0; stepIndex < steps; ++stepIndex) { 141 | vec3 samplePoint = cameraOrigin + rayDirection * currentT; 142 | 143 | float densityAccum = 0.0; 144 | vec3 gradientApprox = vec3(0.0); 145 | for(int i = 0; i < 20; ++i) { 146 | vec3 sphereCenter = uSpherePositions[i]; 147 | float sphereRadius = uSphereRadii[i]; 148 | float sphereOpacity = uSphereOpacities[i]; 149 | float seff = sphereEdgeThickness; 150 | seff = mix(1.0, 13.0, (sphereRadius - 0.5) / (2.5)); 151 | 152 | float density = sphereDensity(samplePoint, sphereCenter, sphereRadius, seff) * sphereOpacity; 153 | densityAccum += density; 154 | 155 | if(density > eps) 156 | gradientApprox += (samplePoint - sphereCenter) * density; 157 | } 158 | 159 | float combinedDensity = clamp(densityAccum, 0.0, 1.0); 160 | 161 | if(combinedDensity > eps) { 162 | vec3 normalApprox = normalize(gradientApprox + 1e-2); 163 | float lambert = clamp(dot(normalApprox, lightDirection), 0.0, 1.0); 164 | lambert = lambert * lightIntensity + 0.1; 165 | vec3 sliceColor = sphereBaseColor * lambert; 166 | float absorb = 1.0 - exp(-absorptionCoefficient * combinedDensity * stepSize); 167 | accumulatedColor += transmittance * sliceColor * absorb * emissionStrength; 168 | transmittance *= (1.0 - absorb); 169 | if(transmittance < 0.01) 170 | break; 171 | } 172 | 173 | currentT += stepSize; 174 | } 175 | 176 | float exposure = 0.2; 177 | backgroundColor.rgb = tonemapFilmic(accumulatedColor, exposure); 178 | 179 | backgroundColor.a = clamp(1.0 - transmittance, 0.0, 1.0); 180 | 181 | fragColor = backgroundColor; 182 | 183 | /// Apply dither. See more on: https://www.shadertoy.com/view/tfByD1 184 | float luminance = fragColor.r; 185 | float threshold = bayer4(fragCoord.xy / ditherScale); 186 | float scaled = clamp(luminance * float(levels), 0.0, float(levels) - 1e-6); 187 | float baseBin = floor(scaled); 188 | float fracPart = scaled - baseBin; 189 | float chosenBin = baseBin + (fracPart > threshold ? 1.0 : 0.0); 190 | chosenBin = clamp(chosenBin, 0.0, float(levels - 1)); 191 | float outGray = chosenBin / float(levels - 1); 192 | 193 | fragColor.rgb = vec3(outGray); 194 | } 195 | -------------------------------------------------------------------------------- /shaders/vignette.frag: -------------------------------------------------------------------------------- 1 | #version 460 core 2 | 3 | precision mediump float; 4 | 5 | #include 6 | 7 | uniform vec2 uSize; 8 | uniform vec2 uCenter; 9 | uniform vec4 uSepiaColor; 10 | out vec4 fragColor; 11 | 12 | void main() { 13 | // Basic UV calculation 14 | vec2 pos = FlutterFragCoord().xy; 15 | vec2 uv = pos / uSize; 16 | 17 | //. Get pixel distance from center 18 | float dist = length(uv - 0.5); 19 | 20 | float vignetteRadius = 0.4; 21 | float vignetteEdge = 0.6; 22 | float vignette = smoothstep(vignetteRadius, vignetteEdge, dist); 23 | vec4 sepiaColor = vec4(uSepiaColor.rgb * 0.9, 0.2); 24 | vec4 vignetteColor = vec4(0.0, 0.0, 0.0, vignette); 25 | // Combine the sepia color with the vignette effect 26 | fragColor = sepiaColor * (1.0 - vignette) + vignetteColor; 27 | } 28 | -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility in the flutter_test package. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:demo_2/main.dart'; 9 | import 'package:flutter/material.dart'; 10 | import 'package:flutter_test/flutter_test.dart'; 11 | 12 | void main() { 13 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 14 | // Build our app and trigger a frame. 15 | await tester.pumpWidget(const MyApp()); 16 | 17 | // Verify that our counter starts at 0. 18 | expect(find.text('0'), findsOneWidget); 19 | expect(find.text('1'), findsNothing); 20 | 21 | // Tap the '+' icon and trigger a frame. 22 | await tester.tap(find.byIcon(Icons.add)); 23 | await tester.pump(); 24 | 25 | // Verify that our counter has incremented. 26 | expect(find.text('0'), findsNothing); 27 | expect(find.text('1'), findsOneWidget); 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/web/favicon.png -------------------------------------------------------------------------------- /web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/web/icons/Icon-192.png -------------------------------------------------------------------------------- /web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/web/icons/Icon-512.png -------------------------------------------------------------------------------- /web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/renancaraujo/ship_game/d95b236b5041d7300b9b20888dd7dc6f00bdbdca/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | demo_2 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo_2", 3 | "short_name": "demo_2", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "icons/Icon-maskable-192.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/Icon-maskable-512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } 36 | --------------------------------------------------------------------------------