From 999caca10fbeb834e85461b6cc828b1bce62bbf9 Mon Sep 17 00:00:00 2001 From: Pasha Stetsenko Date: Sun, 18 Sep 2022 13:21:03 -0700 Subject: [PATCH] docs: Added Style Guide and Test Writing Guide (#1897) The Style Guide moved into the Documentation site for better visibility. Removed lots of discussion around topics that are already enforced by the formatter/linter. Added new advice regarding a variety of topics. The Test Writing Guide discusses how to write tests for Flame, and what kinds of tests are available. --- .github/pull_request_template.md | 50 ++-- CONTRIBUTING.md | 51 +++-- STYLEGUIDE.md | 165 -------------- doc/development/development.md | 6 +- doc/development/style_guide.md | 213 ++++++++++++++++++ doc/development/testing_guide.md | 160 +++++++++++++ .../geometry/shapes/rounded_rectangle.dart | 1 - .../flame/test/widgets/loading_widget.dart | 2 +- 8 files changed, 436 insertions(+), 212 deletions(-) delete mode 100644 STYLEGUIDE.md create mode 100644 doc/development/style_guide.md create mode 100644 doc/development/testing_guide.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 0f3a56611cd..8b697bb3adf 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,45 +1,49 @@ # Description - - +and what motivated the change. If this is a breaking change, specify explicitly which APIs were +changed. +--> -## Checklist - +## Checklist + - [ ] The title of my PR starts with a [Conventional Commit] prefix (`fix:`, `feat:`, `docs:` etc). -- [ ] I have read the [Contributor Guide] and followed the process outlined for submitting PRs. +- [ ] I have followed the [Contributor Guide] when preparing my PR. - [ ] I have updated/added tests for ALL new/updated/fixed functionality. - [ ] I have updated/added relevant documentation in `docs` and added dartdoc comments with `///`. -- [ ] I have updated/added relevant examples in `examples`. +- [ ] I have updated/added relevant examples in `examples` or `docs`. -## Breaking Change - - -- [ ] Yes, this is a breaking change. -- [ ] No, this is *not* a breaking change. +If yes, then the title of the PR should include "!" (for example, `feat!:`, `fix!:`). See +[Conventional Commit] for details. Also, for a breaking PR uncomment and fill in the "Migration +instructions" section below. - -## Related Issues +- [ ] Yes, this PR is a breaking change. +- [ ] No, this PR is not a breaking change. - + +## Related Issues + -[issue database]: https://github.com/flame-engine/flame/issues [Contributor Guide]: https://github.com/flame-engine/flame/blob/main/CONTRIBUTING.md -[Flame Style Guide]: https://github.com/flame-engine/flame/blob/main/STYLEGUIDE.md [Conventional Commit]: https://conventionalcommits.org diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c80b4b16e5a..50355d753a8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -23,11 +23,10 @@ please read these instructions carefully. ### New Features - If you'd like to add a feature to the library that doesn't already exist, feel free to describe the feature in a new [GitHub issue]. - - You can also join us on [Discord] to discuss some initials - thoughts. + - You can also join us on [Discord] to discuss some initials thoughts. - If you'd like to implement the new feature, please wait for feedback from the project maintainers before spending too much time writing the code. In some cases, enhancements may not align well - with the project objectives at the time. + with the project future development direction. - Implement the code for the new feature and please read the [How To](#how-to-contribute). @@ -41,18 +40,18 @@ please read these instructions carefully. ## How To Contribute ### Requirements -For a contribution to be accepted: -- Documentation should always be updated or added.* -- Examples should always be updated or added.* -- Tests should always be updated or added.* -- Format the Dart code accordingly with `flutter format`. -- Your code should pass the analyzer checks `melos run analyze`. -- Your code should pass all tests `melos run test`. -- Start your PR title with a [conventional commit] type - (`feat:`, `fix:` etc). +For a contribution to be accepted: -*When applicable. +- Follow the [Style Guide] when writing the code; +- Format the code using `flutter format .`; +- Lint the code with `melos run analyze`; +- Check that all tests pass: `melos run test`; +- Documentation should always be updated or added (if applicable); +- Examples should always be updated or added (if applicable); +- Tests should always be updated or added (if applicable) -- check the [Test writing guide] for + more details; +- The PR title should start with a [conventional commit] prefix (`feat:`, `fix:` etc). If the contribution doesn't meet these criteria, a maintainer will discuss it with you on the issue or PR. You can still continue to add more commits to the branch you have sent the Pull Request from @@ -60,6 +59,7 @@ and it will be automatically reflected in the PR. ## Open an issue and fork the repository + - If it is a bigger change or a new feature, first of all [file a bug or feature report][GitHub issues], so that we can discuss what direction to follow. - [Fork the project][fork guide] on GitHub. @@ -68,9 +68,9 @@ and it will be automatically reflected in the PR. ### Environment Setup -Flame uses [Melos] to manage the project and dependencies. -To install Melos, run the following command from your terminal: +Flame uses [Melos] to manage the project and dependencies. To install Melos, run the following +command from your terminal: ```bash flutter pub global activate melos @@ -91,6 +91,7 @@ command once. ### Performing changes + - Create a new local branch from `main` (e.g. `git checkout -b my-new-feature`) - Make your changes (try to split them up with one PR per feature/fix). - When committing your changes, make sure that each commit message is clear @@ -117,17 +118,23 @@ void deprecatedFeature() {} ### Open a pull request + Go to the [pull request page of Flame][PRs] and in the top of the page it will ask you if you want to open a pull request from your newly created branch. The title of the pull request should start with a [conventional commit] type. -Examples of such types: - - `fix:` - patches a bug and is not a new feature. - - `feat:` - introduces a new feature. - - `docs:` - updates or adds documentation or examples. - - `test:` - updates or adds tests. - - `refactor:` - refactors code but doesn't introduce any changes or additions to the public API. +Allowed types are: + - `fix:` -- patches a bug and is not a new feature; + - `feat:` -- introduces a new feature; + - `docs:` -- updates or adds documentation or examples; + - `test:` -- updates or adds tests; + - `refactor:` -- refactors code but doesn't introduce any changes or additions to the public API; + - `perf:` -- code change that improves performance; + - `build:` -- code change that affects the build system or external dependencies; + - `ci:` -- changes to the CI configuration files and scripts; + - `chore:` -- other changes that don't modify source or test files; + - `revert:` -- reverts a previous commit. If you introduce a **breaking change** the conventional commit type MUST end with an exclamation mark (e.g. `feat!: Remove the position argument from PositionComponent`). @@ -183,3 +190,5 @@ There are a few things to think about when doing a release: [Melos]: https://github.com/invertase/melos [pubspec doc]: https://dart.dev/tools/pub/pubspec [conventional commit]: https://www.conventionalcommits.org +[style guide]: https://docs.flame-engine.org/main/development/style_guide.md +[test writing guide]: https://docs.flame-engine.org/main/development/testing_guide.md diff --git a/STYLEGUIDE.md b/STYLEGUIDE.md deleted file mode 100644 index 715f1962fcc..00000000000 --- a/STYLEGUIDE.md +++ /dev/null @@ -1,165 +0,0 @@ -# Style Guide - -This is a general style guide that shall govern over all Flame repositories. The aim is to keep -all codebases clean and pristine. This includes high level guidance to help with simple decisions -in the day-to-day development life. - -This extends rules on the official [Flutter Style -Guide](https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo) and [Effective Dart -Patterns](https://dart.dev/guides/language/effective-dart). Those rules apply unless otherwise -specified in this document. - -Note that this is not yet an exhaustive guide, and consider it a work in progress. PRs are welcome! - -## Code Formatting - -### Max line length - -For all files, including markdown, keep each line within a hundred or less characters. - -### Trailing Commas and Wrapping - -List of elements must always be all in one line or one element per line. This includes parameters, -arguments, collection literals, etc. Furthermore, if multiline, the last element must have a -trailing comma. - -For the sake of example, let's use a function invocation (the same apply for all cases): - -``` -// good -foo(p1, p2, p3) - -// good -foo( - p1, - p2, - p3, -) - -// bad: missing trailing comma -foo( - p1, - p2, - p3 -) - -// bad: mixed argument lines -foo( - p1, p2, - p3, -) - -// bad: mixed argument lines -foo(f1, - f2) -``` - -### Imports - -* Never include unused or duplicated imports. -* You must always use relative imports for imports within the Flame library (internal imports must - be relative). -* Omit `./` for relative imports from the same directory. -* Avoid importing groups of APIs internally, for example, importing `lib/effects.dart` just to use - `ScaleEffect`. -* Order your imports by: - * Three main blocks, each separated by exactly one empty line: - * Dart SDK dependencies, - * External libraries/Flutter imports, - * Internal (same library) imports. - * Then, for each block, order alphabetically. - * For relative imports, that means further away (more `../`) imports will be first. - -For example: - -``` -import 'dart:math'; - -import 'package:flutter/foundation.dart'; -import 'package:flutter/rendering.dart'; -import 'package:flutter/widgets.dart' hide WidgetBuilder, Viewport; -import 'package:ordered_set/comparing.dart'; -import 'package:ordered_set/ordered_set.dart'; - -import '../../extensions.dart'; -import '../components/component.dart'; -import '../components/mixins/has_game_ref.dart'; -import '../components/mixins/tappable.dart'; -import '../components/position_component.dart'; -import '../fps_counter.dart'; -import 'camera.dart'; -import 'game.dart'; -import 'viewport.dart'; -``` - -## Code Structure -### Global Variables - -Do not use public global variables or constants; namespace everything inside appropriate scopes. - -### Asserts - -Use asserts to detect contract violation. - -Example: - -````dart -void something(int smaller, int bigger) { - assert(small < bigger, 'smaller is not smaller than bigger'); - // ... -} -```` - -## Comments - -* For any `//` comments, always add a space after the second slash and before the next character. -* Use `//` (or block comments) for comments about the code; use `///` for dartdocs about APIs. - -### TODO - -TODO comments should follow this template: `// TODO(username): Comment` - -I.e., double slash, one space, `TODO` in caps followed by your name in parenthesis, colon, one space -and the comment, capitalized as a sentence. No need to include a period if it's a single sentence. - -```dart -// bad: missing identifier, mixed-case "TODO" and lowercase comment - -// Todo: this thing should be that thing -final thisThing = 13; - -// good: - -// TODO(wolfenrain): This thing should be that thing -const thisThing = 13; -``` - - -### Dartdocs - -#### Consider adding examples - -Some elements may benefit from a simple usage example. - -#### Avoid useless code documentation - -Avoid documentation that just repeats the obvious. For example, `void doStuff()` be documented as -"Method that does stuff". - -#### Consider adding linkage between docs - -You should use `[]` (brackets) to link dartdoc elements that can be referenced on the same file. -Also, consider adding a "See also" section to element documentation. - -## Examples - -There are a few things to consider when adding an example to the examples directory: - - - Put your example in a fitting section. - - Always add a description named `description` in the game object (if you have one). - - Always add that `description` to the `info` field of the story. - - Always add the path to the source of the example in `codeLink` on the story. - - Always have the game class (if there exists one) in the top of your examples file. - - Name your game class with a relevant name and suffix it with `Example`, for example - `AnimationExample`. - - The filename should be the game's (or example's) name, for example `move_effect_example.dart` \ No newline at end of file diff --git a/doc/development/development.md b/doc/development/development.md index 929247a1adf..d9f15301e94 100644 --- a/doc/development/development.md +++ b/doc/development/development.md @@ -1,5 +1,9 @@ # Development ```{toctree} -Documentation +:maxdepth: 2 + +Documentation +Style Guide +Tests Guide ``` diff --git a/doc/development/style_guide.md b/doc/development/style_guide.md new file mode 100644 index 00000000000..baca3a73ed6 --- /dev/null +++ b/doc/development/style_guide.md @@ -0,0 +1,213 @@ +# Flame Style Guide + +This is a general style guide for writing code within Flame and adjacent projects. We strive to +maintain the code clean and readable -- both for the benefit of the users who will need to study +this code in order to understand how a particular feature works or debug something that is breaking, +and for the benefit of the current and future maintainers. + +This guide extends upon the official [Dart's style guide][effective dart]. Please make sure to read +that document first, as it is sure to improve your skill in Dart programming. + + +## Code Formatting + +Most of the code formatting rules are enforced automatically via the linter. Run the following +commands to ensure the code is conformant and to fix any easy formatting problems: +```console +$ flutter analyze +$ flutter format . +``` + + +## Code Structure + +### Imports + +- If you're using an external symbol that's defined in multiple libraries, prefer importing the + smallest of them. For example, use `package:meta/meta.dart` to import annotations like + `@protected`, or `dart:ui` to import `Canvas`. + +- Never import `package:flutter/cupertino.dart` or `package:flutter/material.dart` -- prefer + a much smaller library `package:flutter/widgets.dart` if you're working with widgets. + + +### Exports + +- Strongly prefer to have only one public class per file, and name the file after that class. + Having several private classes within the file is perfectly reasonable. + +- A possible exception to this rule is if the "main" class requires some small "helper" classes + that need to be public. Or if the file hosts multiple very small related classes. + +- The "main" class in a file should be located at the start of the file (right after the imports + section), so that it can be seen immediately upon opening the file. All other definitions, + including typedefs, helper classes and functions, should be moved below the main class. + +- If multiple public symbols are defined in a file, then they must be exported explicitly using + the `export ... show ...` statement. For example: + ```dart + export 'src/effects/provider_interfaces.dart' + show + AnchorProvider, + AngleProvider, + PositionProvider, + ScaleProvider, + SizeProvider; + ``` + + +### Assertions + +Use `assert`s to detect contract violations, or pre-condition/post-condition failures. Sometimes, +however, using exceptions would be more appropriate. The following rules of thumb apply: + +- Use an assert with a clear error message to check for a condition that is in developers' control. + For example, when creating a component that takes an `opacity` level as an input, you should check + whether the value is in the range from 0 to 1. Consider also including the value itself into the + error message, to make it easier for the developer to debug the error: + ```dart + assert(0 <= opacity && opacity <= 1, 'The opacity value must be from 0 to 1: $opacity'); + ``` + Always use asserts as early as possible to detect possible violations. For example, check the + validity of `opacity` in the constructor/setter, instead of in the render function. + + When adding such an assert, also include a test that checks that the assert triggers. This test + would verify that the component does not accept invalid input, and that the error message is what + you expect it to be. + +- Use an assert without an error message to check for a condition that cannot be triggered by the + developer through any means known to you. If such an assert does trigger, it would indicate a bug + in the Flame framework. + + Such asserts serve as "mini-tests" directly in the code, and protect against future refactorings + that could create an erroneous internal state. It should not be possible to write a test that + would deliberately trigger such an assert. + +- Use an explicit if-check with an exception to test for a condition that may be outside of the + developer's control (i.e. it may depend on the environment or on user's input). When deciding + whether to use an assert or exception, consider the following question: is it possible for the + error condition to occur in production even after the developer has done extensive testing on + their side? + + +### Class structure + +- Consider putting all class constructors at the top of the class. This makes it much easier to see + how the class ought to be used. + +- Try to make as much of your class' API private as possible, do not expose members "just in case". + This makes it much easier to modify/refactor the class later without it being a breaking change. + + Remember to document all your public members! Documenting things is harder than it looks, and one + way to avoid the burden of documentation is to make as many variables private as possible. + +- If a class exposes a `List` or `Vector2` property -- it is **NOT** an invitation to modify + them at will! Consider such properties as read-only, unless the documentation explicitly says that + they are allowed to be modified. + +- When a class becomes sufficiently big, consider adding *regions* inside it, which help with code + navigation and collapsing (note the lack of space after `//`): + ```dart + //#region Region description + ... + //#endregion + ``` + +- If a class has a private member that needs to be exposed via a getter/setter, prefer the following + code structure: + ```dart + class MyClass { + MyClass(); + + ... + int _variable; + ... + + /// Docs for both the getter and the setter. + int get variable => _variable; + set variable(int value) { + assert(value >= 0, 'variable must be non-negative: $value'); + _variable = value; + } + } + ``` + This would gather all private variables in a single block near the top of the class, allowing one + to quickly see what data the class has. + + +## Documentation + +- Use dartdocs `///` to explain the meaning/purpose of a class, method, or a variable. + +- Use regular comments `//` to explain implementation details of a particular code fragment. That + is, these comments explain HOW something works. + +- Use markdown documentation in `doc/` folder to give the high-level overview of the functionality, + and especially how it fits into the overall Flame framework. + + +### Dartdocs + +- Check the [Flutter Documentation Guide] -- it contains lots of great advice on writing good + documentation. + - However, disregard the advice about writing in a passive voice. + +- Class documentation should ideally start with the class name itself, and follow a pattern such as: + ```dart + /// [MyClass] is ... + /// [MyClass] serves as ... + /// [MyClass] does the following ... + ``` + The reason for such convention is that often the documentation for a class becomes sufficiently + long, and it may not be immediately apparent when looking at the top of the doc what exactly is + being documented there. + +- Method documentation should start with a verb in the present simple tense, with the method name + as an implicit subject. Add a paragraph break after the first sentence. Try to think about what + could be unclear to the users of the method; and mention any pre- and post-conditions. + For example: + ```dart + /// Adds a new [child] into the container, and becomes the owner of that child. + /// + /// The child will be disposed of when this container is destroyed. It is an error to try to add a + /// child that already belongs to another container. + void addChild(T child) { ... } + ``` + Avoid stating the obvious (or at least only the obvious). + +- Constructor documentation may follow either the style of a method (i.e. "Creates ...", + "Constructs ..."), or of the class but omitting the name of the class (i.e. "Rectangular-shaped + component"). Constructor documentation may be omitted if (1) it's the main constructor of the + class, and (2) all the parameters are obvious and coincide with the public members of the class. + + **Do not** use macros to copy the class documentation into the constructor's dartdoc. Generally, + the class documentation answers the question "what the class is", whereas the constructor docs + answer "how it will be constructed". + + +### Main docs + +This refers to the docs on the main Flame Documentation website, the one you're reading right now. +The main documentation site serves as a place where people go to learn about various functionality +available in Flame. If you're adding a new class, then it must be documented both at the dartdocs +level, and on the main docs site. The latter serves the purposes of discoverability of your class. +Without the docs site, your class might never be used (or at least used less than it could have +been), because the developers would simply not know about it. + +When adding the documentation to the main docs site, consider also including an example directly +into the docs. This will make readers more excited about trying this new functionality. + +Check the [Documentation] manual about how to work with the docs site. + +The following style rules generally apply when writing documentation (although we currently don't +have a linter to enforce them strictly): +- Maximum line length of 100 characters; +- Prefer to define external links at the bottom of the document, so as to make reading the plain + text of the document easier; +- Separate headers from the preceding content with 2 blank lines -- this makes it easier to see the + sections within the plain text. + + +[effective dart]: https://dart.dev/guides/language/effective-dart +[flutter documentation guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#documentation-dartdocs-javadocs-etc +[documentation]: documentation.md diff --git a/doc/development/testing_guide.md b/doc/development/testing_guide.md new file mode 100644 index 00000000000..bbb2bf7c7ec --- /dev/null +++ b/doc/development/testing_guide.md @@ -0,0 +1,160 @@ +# Writing tests + +- All new functionality must be tested, if at all possible. When fixing a bug, tests must be added + to ensure that this bug would not reappear in the future. + +- Run `melos run coverage` to execute all tests in the "coverage" mode. The results will be saved + in the `coverage/index.html` file, which can be opened in a browser. Try to achieve 100% coverage + for any new functionality added. + +- Every source file should have a corresponding test file, with the `_test` suffix. For example, + if you're making a `SpookyEffect` and the source file is `src/effects/spooky_effect.dart`, then + the test file should be `test/effects/spooky_effect_test.dart` mirroring the source directory. + +- The test file should contain a `main()` function with a single `group()` whose name matches the + name of the class being tested. If the source file contains multiple public classes, then each of + them should have its own group. For example: + ```dart + void main() { + group('SpookyEffect', () { + // tests here + }); + } + ``` + +- For a larger class, multiple groups can be created inside the top-level group, allowing to + navigate the test suite easier. The names of the nested groups should be capitalized. + +- The names of the individual tests should normally start with a lowercase. + +- Often, you would need to define multiple helper classes to run the tests. Such classes should be + private (start with an underscore), and placed at the end of the file. The reason for this is that + whenever some test breaks, the first thing one needs to do is to go into the test file and run all + the tests. Having the `main()` function at the top of the file makes this process much easier. + + +## Types of tests + +### Simple tests + +```dart +test('the name of the test', () { + expect(...); +}); +``` +This is the simplest kind of test available, and also the fastest. Use these tests for checking +some classes/methods that can function in isolation from the rest of the Flame framework. + + +### FlameGame tests + +It is very common to want to have a `FlameGame` instance inside a test, so that you can add some +components to it and verify various behaviors. The following approach is recommended: +```dart +testWithFlameGame('the name of the test', (game) async { + game.add(...); + await game.ready(); + + expect(...); +}); +``` +Here the `game` instance that is passed to the test body is a fully initialized game that behaves +as if it was mounted to a `GameWidget`. The `game.ready()` method waits until all the scheduled +components are loaded and mounted to the component tree. + +The time within the `game` can be advanced with `game.update(dt)`. + +If you need to have a custom game inside this test (say, a game with some mixin), then use +```dart +testWithGame<_MyGame>( + 'the name of the test', + _MyGame.new, + (game) async { + // test body... + }, +); +``` + + +### Widget tests + +Sometimes having a "naked" `FlameGame` is insufficient, and you want to have access to the Flutter +infrastructure as well. That is, to have a game mounted into a real `GameWidget` embedded into an +actual Flutter framework. In such cases, use +```dart +testWidgets('test name', (tester) async { + final game = _MyGame(); + await tester.pumpWidget(GameWidget(game: game)); + await tester.pump(); + await tester.pump(); + + // At this point the game is fully initialized, and you can run your checks against it + expect(...); + + // Equivalent to game.update(0) + await tester.pump(); + + // Advances in-game time by 20 milliseconds + await tester.pump(const Duration(milliseconds: 20)); +}); +``` +There are some additional methods available on the `tester` controller, for example in order to +simulate taps, or drags, or key presses. + + +### Golden tests + +These tests verify that things render as intended. The process of creating a golden test is +simple: + +1. Write the test, using the following template: + ```dart + testGolden( + 'the name of the test', + (game) async { + // Set up the game by adding the necessary components + // You can add `expect()` checks here too, if you want to + }, + size: Vector2(300, 200), + goldenFile: '.../_goldens/my_test_file.png', + ); + ``` + Here the `size` parameter determines the size of the game canvas and of the output image. The + `goldenFile` parameter is the name of the file where you want to store the "golden" results. This + should be a relative path to the `test/_goldens` directory, starting from your test file. + +2. Run + ```console + $ flutter test --update-goldens + ``` + this would create the golden file for the first time. Open the file to verify that it renders + exactly as you intended. If not, then delete the file and go back to step 1. + +3. Subsequent runs of `flutter test` will check whether the output of the golden test matches the + saved golden file. If not, Flutter will save the image-diff files into the `failures/` directory + where your test is located. + +```{note} +Avoid using text in your golden tests -- it does not render reliably across different platforms, +due to font discrepancies and differences in anti-aliasing algorithms. +``` + + +### Random tests + +These are the tests that use a random number generator in order to construct a randomized input and +then check its correctness. Use as follows: +```dart +testRandom('test name', (Random random) { + // Use [random] to generate random input +}); +``` +You can add `repeatCount: 1000` parameter to run this test the specified number of times, each one +with a different seed. It is useful to run a high `repeatCount` when developing the test, to ensure +that it doesn't break. However, when submitting the test to the main repository, avoid repeatCounts +higher than 10. + +If the test breaks at some particular seed, then that seed will be shown in the test output. Add it +as the `seed: NNN` parameter to your test, and you'll be able to run it for the same seed as long +as you need until the test is fixed. Do not leave the `seed:` parameter when submitting your code, +as it defeats the purpose of having the test randomized. diff --git a/packages/flame/lib/src/experimental/geometry/shapes/rounded_rectangle.dart b/packages/flame/lib/src/experimental/geometry/shapes/rounded_rectangle.dart index a72a43befb4..3ccfd64bf7c 100644 --- a/packages/flame/lib/src/experimental/geometry/shapes/rounded_rectangle.dart +++ b/packages/flame/lib/src/experimental/geometry/shapes/rounded_rectangle.dart @@ -3,7 +3,6 @@ import 'dart:ui'; import 'package:flame/src/experimental/geometry/shapes/shape.dart'; import 'package:flame/src/game/transform2d.dart'; -import 'package:flutter/cupertino.dart'; import 'package:meta/meta.dart'; import 'package:vector_math/vector_math_64.dart'; diff --git a/packages/flame/test/widgets/loading_widget.dart b/packages/flame/test/widgets/loading_widget.dart index cff29c0994b..1ec2868d4cb 100644 --- a/packages/flame/test/widgets/loading_widget.dart +++ b/packages/flame/test/widgets/loading_widget.dart @@ -1,4 +1,4 @@ -import 'package:flutter/cupertino.dart'; +import 'package:flutter/widgets.dart'; class LoadingWidget extends StatelessWidget { const LoadingWidget({super.key});