diff --git a/CHANGELOG.md b/CHANGELOG.md index b500173deb5..8da65e2bed0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # CHANGELOG +## 0.27.0 + - Improved the accuracy of the `FPSCounter` by using Flutter's internal frame timings. + - Adding MouseMovementDetector + - Adding ScrollDetector + - Fixes BGM error + - Adding Isometric Tile Maps + ## 0.26.0 - Improving Flame image auto cache - Fix bug in the Box2DGame's add and addLater method , when the Component extends BodyComponent and mixin HasGameRef or other mixins ,the mixins will not be set correctly diff --git a/doc/README.md b/doc/README.md index f9d9e789321..eaa91e75898 100644 --- a/doc/README.md +++ b/doc/README.md @@ -18,7 +18,7 @@ Put the pub package as your dependency by dropping the following in your `pubspe ```yaml dependencies: - flame: ^0.26.0 + flame: ^0.27.0 ``` And start using it! diff --git a/doc/components.md b/doc/components.md index 6de3373ee47..0cbdd3b5820 100644 --- a/doc/components.md +++ b/doc/components.md @@ -235,6 +235,26 @@ Currently we have a very basic implementation of a Tiled component. This API use An example of how to use the API can be found [here](/doc/examples/tiled). +# Isometric Tile Map Component + +This component allows you to render an isometric map based on a cartesian matrix of blocks and an isometric tileset. + +A simple example on how to use it: + +```dart + // creates a tileset, the block ids are automatically assigned sequentially starting at 0, from left to right and then top to bottom. + final tileset = await IsometricTileset.load('tileset.png', 32); + // each element is a block id, -1 means nothing + final matrix = [[0, 1, 0], [1, 0, 0], [1, 1, 1]]; + add(IsometricTileMapComponent(tileset, matrix)); +``` + +It also provides methods for converting coordinates so you can handle clicks, hovers, render entities on top of tiles, add a selector, etc. + +A more in-depth example can be found [here](/doc/examples/isometric). + +![An example of a isometric map with selector](images/isometric.png) + # Nine Tile Box Component A Nine Tile Box is a rectangle drawn using a grid sprite. diff --git a/doc/examples/cleanup.sh b/doc/examples/cleanup.sh index 4ed2dc25d05..1e9effb8264 100755 --- a/doc/examples/cleanup.sh +++ b/doc/examples/cleanup.sh @@ -1,9 +1,11 @@ #!/bin/bash -xe -rm -rf */build -rm -rf */android -rm -rf */ios -rm -rf */web -rm -rf */macos -rm -rf */test -rm -rf */.dart_tool +shopt -s globstar + +rm -rf **/build +rm -rf **/android +rm -rf **/ios +rm -rf **/web +rm -rf **/macos +rm -rf **/test +rm -rf **/.dart_tool diff --git a/doc/examples/gestures/lib/main_mouse_movement.dart b/doc/examples/gestures/lib/main_mouse_movement.dart new file mode 100644 index 00000000000..c1f323cf4bb --- /dev/null +++ b/doc/examples/gestures/lib/main_mouse_movement.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; +import 'package:flame/game.dart'; +import 'package:flame/gestures.dart'; +import 'package:flame/palette.dart'; +import 'package:flame/position.dart'; + +void main() { + final game = MyGame(); + runApp(game.widget); +} + +class MyGame extends Game with MouseMovementDetector { + static const SPEED = 200; + + Position position = Position(0, 0); + Position target; + + final Paint _blue = Paint()..color = const Color(0xFF0000FF); + + bool _onTarget = false; + + @override + void onMouseMove(event) { + target = Position.fromOffset(event.localPosition); + } + + Rect _toRect() => Rect.fromLTWH( + position.x, + position.y, + 50, + 50, + ); + + @override + void render(Canvas canvas) { + canvas.drawRect( + _toRect(), + _onTarget ? _blue : BasicPalette.white.paint, + ); + } + + @override + void update(double dt) { + if (target != null) { + _onTarget = _toRect().contains(target.toOffset()); + + if (!_onTarget) { + final dir = target.clone().minus(position).normalize(); + + position.add(dir.times(SPEED * dt)); + } + } + } +} diff --git a/doc/examples/gestures/lib/main_scroll.dart b/doc/examples/gestures/lib/main_scroll.dart new file mode 100644 index 00000000000..24edf640aaf --- /dev/null +++ b/doc/examples/gestures/lib/main_scroll.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; +import 'package:flame/game.dart'; +import 'package:flame/gestures.dart'; +import 'package:flame/palette.dart'; +import 'package:flame/position.dart'; + +void main() { + final game = MyGame(); + runApp(game.widget); +} + +class MyGame extends Game with ScrollDetector { + static const SPEED = 200; + + Position position = Position(0, 0); + Position target; + + @override + void onScroll(event) { + target = position.minus(Position.fromOffset(event.scrollDelta)); + } + + @override + void render(Canvas canvas) { + canvas.drawRect( + Rect.fromLTWH( + position.x, + position.y, + 50, + 50, + ), + BasicPalette.white.paint, + ); + } + + @override + void update(double dt) { + if (target != null) { + final dir = target.clone().minus(position).normalize(); + + position.add(dir.times(SPEED * dt)); + } + } +} diff --git a/doc/examples/isometric/.metadata b/doc/examples/isometric/.metadata new file mode 100644 index 00000000000..6a633e0880a --- /dev/null +++ b/doc/examples/isometric/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 7fc14a55af64462763d28abfb4e610086c6e0f39 + channel: dev + +project_type: app diff --git a/doc/examples/isometric/README.md b/doc/examples/isometric/README.md new file mode 100644 index 00000000000..0e9837f200e --- /dev/null +++ b/doc/examples/isometric/README.md @@ -0,0 +1,3 @@ +# isometric + +A Flame game showcasing how to use the Isometric Tile Map component. diff --git a/doc/examples/isometric/assets/images/selector.png b/doc/examples/isometric/assets/images/selector.png new file mode 100644 index 00000000000..35703080514 Binary files /dev/null and b/doc/examples/isometric/assets/images/selector.png differ diff --git a/doc/examples/isometric/assets/images/tiles.png b/doc/examples/isometric/assets/images/tiles.png new file mode 100644 index 00000000000..93645b5b262 Binary files /dev/null and b/doc/examples/isometric/assets/images/tiles.png differ diff --git a/doc/examples/isometric/lib/main.dart b/doc/examples/isometric/lib/main.dart new file mode 100644 index 00000000000..17059c39ad7 --- /dev/null +++ b/doc/examples/isometric/lib/main.dart @@ -0,0 +1,85 @@ +import 'package:flame/components/component.dart'; +import 'package:flame/flame.dart'; +import 'package:flame/game.dart'; +import 'package:flame/components/isometric_tile_map_component.dart'; +import 'package:flame/gestures.dart'; +import 'package:flame/position.dart'; +import 'package:flame/sprite.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; + +const x = 500.0; +const y = 500.0; +const s = 64; +final topLeft = Position(x, y); + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + final Size size = await Flame.util.initialDimensions(); + final game = MyGame(size); + runApp(game.widget); +} + +class Selector extends SpriteComponent { + bool show = false; + + Selector(double s) + : super.fromSprite(s, s, Sprite('selector.png', width: 32, height: 32)); + + @override + void render(Canvas canvas) { + if (!show) { + return; + } + + super.render(canvas); + } +} + +class MyGame extends BaseGame with MouseMovementDetector { + IsometricTileMapComponent base; + Selector selector; + + MyGame(Size size) { + init(); + } + + void init() async { + final tileset = await IsometricTileset.load('tiles.png', 32); + final matrix = [ + [3, 1, 1, 1, 0, 0], + [-1, 1, 2, 1, 0, 0], + [-1, 0, 1, 1, 0, 0], + [-1, 1, 1, 1, 0, 0], + [1, 1, 1, 1, 0, 2], + [1, 3, 3, 3, 0, 2], + ]; + add( + base = IsometricTileMapComponent(tileset, matrix, destTileSize: s) + ..x = x + ..y = y, + ); + add(selector = Selector(s.toDouble())); + } + + @override + void render(Canvas canvas) { + super.render(canvas); + + canvas.drawRect( + const Rect.fromLTWH(x - 1, y - 1, 3, 3), + Paint()..color = const Color(0xFFFF00FF), + ); + } + + @override + void onMouseMove(PointerHoverEvent event) { + if (base == null || selector == null) { + return; // loading + } + final screenPosition = Position.fromOffset(event.position); + final block = base.getBlock(screenPosition); + selector.show = base.containsBlock(block); + selector.setByPosition(base.getBlockPosition(block).add(topLeft)); + } +} diff --git a/doc/examples/isometric/pubspec.yaml b/doc/examples/isometric/pubspec.yaml new file mode 100644 index 00000000000..5b6e39e4df0 --- /dev/null +++ b/doc/examples/isometric/pubspec.yaml @@ -0,0 +1,22 @@ +name: isometric +description: Example of isometric tilemap using Flame + +version: 0.1.0 + +environment: + sdk: ">=2.1.0 <3.0.0" + +dependencies: + flutter: + sdk: flutter + flame: + path: ../../../ + +dev_dependencies: + flutter_test: + sdk: flutter + +flutter: + assets: + - assets/images/tiles.png + - assets/images/selector.png diff --git a/doc/images/isometric.png b/doc/images/isometric.png new file mode 100644 index 00000000000..635b0560de3 Binary files /dev/null and b/doc/images/isometric.png differ diff --git a/doc/input.md b/doc/input.md index 24465588a42..2b431f1f268 100644 --- a/doc/input.md +++ b/doc/input.md @@ -4,6 +4,8 @@ Inside `package:flame/gestures.dart` you can find a whole set of `mixin`s which can be included on your game class instance to be able to receive touch input events. Below you can see the full list of these `mixin`s and its methods: + +## Touch and mouse detectors ``` - TapDetector - onTap @@ -68,11 +70,19 @@ Inside `package:flame/gestures.dart` you can find a whole set of `mixin`s which - onReceiveDrag ``` +Mouse only events +``` + - MouseMovementDetector + - onMouseMove + - ScrollDetector + - onScroll +``` + Many of these detectors can conflict with each other. For example, you can't register both Vertical and Horizontal drags, so not all of them can be used together. It is also not possible to mix advanced detectors (`MultiTouch*`) with basic detectors as they will *always win the gesture arena* and the basic detectors will never be triggered. So for example, you can use both `MultiTouchDragDetector` and `MultiTouchDragDetector` together, but if you try to use `MultiTouchTapDetector` and `PanDetector`, no events will be triggered for the later. -Flame's GestureApi is provided byt Flutter's Gestures Widgets, including [GestureDetector widget](https://api.flutter.dev/flutter/widgets/GestureDetector-class.html) and [RawGestureDetector widget](https://api.flutter.dev/flutter/widgets/RawGestureDetector-class.html), you can also read more about Flutter's gestures [here](https://api.flutter.dev/flutter/gestures/gestures-library.html). +Flame's GestureApi is provided byt Flutter's Gestures Widgets, including [GestureDetector widget](https://api.flutter.dev/flutter/widgets/GestureDetector-class.html), [RawGestureDetector widget](https://api.flutter.dev/flutter/widgets/RawGestureDetector-class.html) and [MouseRegion widget](https://api.flutter.dev/flutter/widgets/MouseRegion-class.html), you can also read more about Flutter's gestures [here](https://api.flutter.dev/flutter/gestures/gestures-library.html). ## Example diff --git a/lib/assets_cache.dart b/lib/assets_cache.dart index 033060acf26..14a1ca94b07 100644 --- a/lib/assets_cache.dart +++ b/lib/assets_cache.dart @@ -1,6 +1,7 @@ -import 'package:flutter/services.dart' show rootBundle; import 'dart:typed_data'; +import 'package:flutter/services.dart' show rootBundle; + /// A class that loads, and cache files /// /// it automatically looks for files on the assets folder diff --git a/lib/bgm.dart b/lib/bgm.dart index 0c3d8944c65..68ef332f090 100644 --- a/lib/bgm.dart +++ b/lib/bgm.dart @@ -1,9 +1,10 @@ import 'dart:io'; import 'package:audioplayers/audioplayers.dart'; -import 'package:flame/flame.dart'; import 'package:flutter/widgets.dart'; +import 'flame.dart'; + /// The looping background music class. /// /// This class helps with looping background music management that reacts to @@ -43,7 +44,7 @@ class Bgm extends WidgetsBindingObserver { /// /// It is safe to call this function even when a current BGM track is /// playing. - void play(String filename, {double volume}) async { + Future play(String filename, {double volume}) async { volume ??= 1; if (audioPlayer != null && audioPlayer.state != AudioPlayerState.STOPPED) { @@ -51,14 +52,11 @@ class Bgm extends WidgetsBindingObserver { } isPlaying = true; - audioPlayer = await Flame.audio.loopLongAudio( - filename, - volume: volume, - ); + audioPlayer = await Flame.audio.loopLongAudio(filename, volume: volume); } /// Stops the currently playing background music track (if any). - void stop() async { + Future stop() async { isPlaying = false; if (audioPlayer != null) { await audioPlayer.stop(); @@ -66,28 +64,28 @@ class Bgm extends WidgetsBindingObserver { } /// Resumes the currently played (but resumed) background music. - void resume() { + Future resume() async { if (audioPlayer != null) { isPlaying = true; - audioPlayer.resume(); + await audioPlayer.resume(); } } /// Pauses the background music without unloading or resetting the audio /// player. - void pause() { + Future pause() async { if (audioPlayer != null) { isPlaying = false; - audioPlayer.pause(); + await audioPlayer.pause(); } } - /// Prefetch an audio and store it in the cache. + /// Pre-fetch an audio and store it in the cache. /// /// Alias of `FlameAudio.load();`. Future load(String file) => Flame.audio.load(file); - /// Prefetch a list of audios and store them in the cache. + /// Pre-fetch a list of audios and store them in the cache. /// /// Alias of `FlameAudio.loadAll();`. Future> loadAll(List files) => Flame.audio.loadAll(files); @@ -98,8 +96,8 @@ class Bgm extends WidgetsBindingObserver { void clear(String file) => Flame.audio.clear(file); /// Clears all the audios in the cache. - /// Alias of `FlameAudio.clearAll();`. /// + /// Alias of `FlameAudio.clearAll();`. void clearAll() => Flame.audio.clearAll(); /// Handler for AppLifecycleState changes. @@ -110,13 +108,11 @@ class Bgm extends WidgetsBindingObserver { @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { - if (isPlaying && - audioPlayer != null && - audioPlayer.state == AudioPlayerState.PAUSED) { + if (isPlaying && audioPlayer?.state == AudioPlayerState.PAUSED) { audioPlayer.resume(); } } else { - audioPlayer.pause(); + audioPlayer?.pause(); } } } diff --git a/lib/box2d/box2d_component.dart b/lib/box2d/box2d_component.dart index d83d1316457..d3d9eec6cd0 100644 --- a/lib/box2d/box2d_component.dart +++ b/lib/box2d/box2d_component.dart @@ -1,8 +1,8 @@ import 'dart:ui'; import 'package:box2d_flame/box2d.dart' hide Timer; -import 'package:flame/box2d/viewport.dart'; -import 'package:flame/components/component.dart'; +import 'viewport.dart'; +import '../components/component.dart'; import 'package:ordered_set/comparing.dart'; import 'package:ordered_set/ordered_set.dart'; diff --git a/lib/box2d/box2d_game.dart b/lib/box2d/box2d_game.dart index b28d00cb4fa..70facf34489 100644 --- a/lib/box2d/box2d_game.dart +++ b/lib/box2d/box2d_game.dart @@ -1,7 +1,7 @@ -import 'package:flame/box2d/box2d_component.dart'; -import 'package:flame/box2d/contact_callbacks.dart'; -import 'package:flame/components/component.dart'; -import 'package:flame/game/base_game.dart'; +import '../components/component.dart'; +import '../game/base_game.dart'; +import 'box2d_component.dart'; +import 'contact_callbacks.dart'; class Box2DGame extends BaseGame { final Box2DComponent box; diff --git a/lib/box2d/contact_callbacks.dart b/lib/box2d/contact_callbacks.dart index f16729f7d18..84c831b0b99 100644 --- a/lib/box2d/contact_callbacks.dart +++ b/lib/box2d/contact_callbacks.dart @@ -1,5 +1,6 @@ import 'package:box2d_flame/box2d.dart'; -import 'package:flame/box2d/box2d_component.dart'; + +import 'box2d_component.dart'; class ContactTypes { // If o1 is, or inherits from, T1 or T2 diff --git a/lib/box2d/viewport.dart b/lib/box2d/viewport.dart index 2900b4c0928..2a217fb563f 100644 --- a/lib/box2d/viewport.dart +++ b/lib/box2d/viewport.dart @@ -1,7 +1,8 @@ import 'dart:ui'; import 'package:box2d_flame/box2d.dart'; -import 'package:flame/box2d/box2d_component.dart'; + +import 'box2d_component.dart'; class Viewport extends ViewportTransform { Size size; diff --git a/lib/components/animation_component.dart b/lib/components/animation_component.dart index c33662dbfce..b0aaa1cd874 100644 --- a/lib/components/animation_component.dart +++ b/lib/components/animation_component.dart @@ -1,7 +1,7 @@ import 'dart:ui'; -import 'component.dart'; import '../animation.dart'; +import 'component.dart'; class AnimationComponent extends PositionComponent { Animation animation; diff --git a/lib/components/component.dart b/lib/components/component.dart index 35cd27cc59e..0bec3806da5 100644 --- a/lib/components/component.dart +++ b/lib/components/component.dart @@ -4,11 +4,11 @@ import 'dart:ui'; import 'package:flutter/painting.dart'; import 'package:meta/meta.dart'; -import '../sprite.dart'; -import '../position.dart'; import '../anchor.dart'; -import '../text_config.dart'; import '../effects/effects.dart'; +import '../position.dart'; +import '../sprite.dart'; +import '../text_config.dart'; /// This represents a Component for your game. /// diff --git a/lib/components/composed_component.dart b/lib/components/composed_component.dart index e536c2c0feb..7f131111d22 100644 --- a/lib/components/composed_component.dart +++ b/lib/components/composed_component.dart @@ -1,13 +1,13 @@ import 'dart:ui'; -import 'package:flame/components/mixins/has_game_ref.dart'; -import 'package:flame/components/mixins/tapable.dart'; -import 'package:flame/game/base_game.dart'; import 'package:ordered_set/comparing.dart'; import 'package:ordered_set/ordered_set.dart'; +import '../game/base_game.dart'; import 'component.dart'; +import 'mixins/has_game_ref.dart'; import 'mixins/resizable.dart'; +import 'mixins/tapable.dart'; /// A mixin that helps you to make a `Component` wraps other components. It is useful to group visual components through a hierarchy. /// When implemented, makes every item in its `components` collection field be updated and rendered with the same conditions. diff --git a/lib/components/flare_component.dart b/lib/components/flare_component.dart index 926e29103e4..5ef1b7fa732 100644 --- a/lib/components/flare_component.dart +++ b/lib/components/flare_component.dart @@ -1,7 +1,7 @@ import 'dart:ui'; +import '../flare_animation.dart'; import 'component.dart'; -import 'package:flame/flare_animation.dart'; @Deprecated("Use flame_flare package instead") class FlareComponent extends PositionComponent { diff --git a/lib/components/isometric_tile_map_component.dart b/lib/components/isometric_tile_map_component.dart new file mode 100644 index 00000000000..8d2a8aa315a --- /dev/null +++ b/lib/components/isometric_tile_map_component.dart @@ -0,0 +1,153 @@ +import 'dart:ui'; + +import 'package:flame/components/component.dart'; + +import '../flame.dart'; +import '../position.dart'; +import '../sprite.dart'; + +/// This represents an isometric tileset to be used in a tilemap. +/// +/// It's basically a grid of squares, each square has a tile, in order. +/// The block ids are calculated going row per row, left to right, top to +/// bottom. +/// +/// This class will cache the usage of sprites to improve performance. +class IsometricTileset { + /// The image for this tileset. + final Image tileset; + + /// The size of each square block within the image. + /// + /// The image width and height must be multiples of this number. + final int size; + + final Map _spriteCache = {}; + + IsometricTileset(this.tileset, this.size); + + /// Compute the number of columns the image has + /// by using the image width and tile size. + int get columns => tileset.width ~/ size; + + /// Compute the number of rows the image has + /// by using the image height and tile size. + int get rows => tileset.height ~/ size; + + /// Get a sprite to render one specific tile given its id. + /// + /// The ids are assigned left to right, top to bottom, row per row. + /// The returned sprite will be cached, so don't modify it! + Sprite getTile(int tileId) { + return _spriteCache[tileId] ??= _computeTile(tileId); + } + + Sprite _computeTile(int tileId) { + final i = tileId % columns; + final j = tileId ~/ columns; + final s = size.toDouble(); + return Sprite.fromImage(tileset, x: s * i, y: s * j, width: s, height: s); + } + + /// Load a tileset based on a file name. + static Future load(String fileName, int size) async { + final image = await Flame.images.load(fileName); + return IsometricTileset(image, size); + } +} + +/// This is just a pair of int, int. +/// +/// Represents a position in a matrix, or in this case, on the tilemap. +class Block { + /// x and y coordinates on the matrix + int x, y; + + Block(this.x, this.y); + + @override + String toString() => '($x, $y)'; +} + +/// This component renders a tilemap, represented by an int matrix, given a +/// tileset, in witch the integers are the block ids. +/// +/// It can change the scale of each block by using the optional destTileSize +/// property. +class IsometricTileMapComponent extends PositionComponent { + /// This is the tileset that will be used to render this map. + IsometricTileset tileset; + + /// The positions of each block will be placed respecting this matrix. + List> matrix; + + /// Optionally provide a new tile size to render it scaled. + int destTileSize; + + IsometricTileMapComponent(this.tileset, this.matrix, {this.destTileSize}); + + /// This is the size the tiles will be drawn (either original or overwritten). + int get effectiveTileSize => destTileSize ?? tileset.size; + + @override + void render(Canvas c) { + prepareCanvas(c); + + final size = Position.fromInts(effectiveTileSize, effectiveTileSize); + for (int i = 0; i < matrix.length; i++) { + for (int j = 0; j < matrix[i].length; j++) { + final element = matrix[i][j]; + if (element != -1) { + final sprite = tileset.getTile(element); + final p = getBlockPositionInts(j, i); + sprite.renderRect(c, Position.rectFrom(p, size)); + } + } + } + } + + /// Get the position in witch a block must be in the isometric space. + /// + /// This does not include the (x,y) PositionComponent offset! + Position getBlockPosition(Block block) { + return getBlockPositionInts(block.x, block.y); + } + + Position getBlockPositionInts(int i, int j) { + final s = effectiveTileSize.toDouble() / 2; + return cartToIso(Position(i * s, j * s)).minus(Position(s, 0)); + } + + /// Converts a coordinate from the isometric space to the cartesian space. + Position isoToCart(Position p) { + final x = (2 * p.y + p.x) / 2; + final y = (2 * p.y - p.x) / 2; + return Position(x, y); + } + + /// Converts a coordinate from the cartesian space to the isometric space. + Position cartToIso(Position p) { + final x = p.x - p.y; + final y = (p.x + p.y) / 2; + return Position(x, y); + } + + /// Get what block is at isometric position p. + /// + /// This can be used to handle clicks or hovers. + Block getBlock(Position p) { + final s = effectiveTileSize.toDouble() / 2; + final cart = isoToCart(p.clone().minus(toPosition())); + final px = cart.x ~/ s; + final py = cart.y ~/ s; + return Block(px, py); + } + + /// Return whether the matrix contains a block in its bounds. + bool containsBlock(Block block) { + return block.x >= 0 && + block.x < matrix.length && + block.y >= 0 && + block.y < matrix[block.x].length; + } +} diff --git a/lib/components/joystick/joystick_action.dart b/lib/components/joystick/joystick_action.dart index f269554f725..b53964aff5f 100644 --- a/lib/components/joystick/joystick_action.dart +++ b/lib/components/joystick/joystick_action.dart @@ -1,9 +1,9 @@ import 'dart:math'; -import 'package:flame/components/joystick/joystick_component.dart'; -import 'package:flame/components/joystick/joystick_events.dart'; -import 'package:flame/gestures.dart'; -import 'package:flame/sprite.dart'; +import 'joystick_component.dart'; +import 'joystick_events.dart'; +import '../../gestures.dart'; +import '../../sprite.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; diff --git a/lib/components/joystick/joystick_component.dart b/lib/components/joystick/joystick_component.dart index f58a3466703..0baac57cb40 100644 --- a/lib/components/joystick/joystick_component.dart +++ b/lib/components/joystick/joystick_component.dart @@ -1,12 +1,12 @@ import 'dart:ui'; -import 'package:flame/components/component.dart'; -import 'package:flame/components/joystick/joystick_action.dart'; -import 'package:flame/components/joystick/joystick_directional.dart'; -import 'package:flame/components/joystick/joystick_events.dart'; -import 'package:flame/components/mixins/has_game_ref.dart'; -import 'package:flame/game/base_game.dart'; -import 'package:flame/gestures.dart'; +import '../../game/base_game.dart'; +import '../../gestures.dart'; +import '../component.dart'; +import '../mixins/has_game_ref.dart'; +import 'joystick_action.dart'; +import 'joystick_directional.dart'; +import 'joystick_events.dart'; mixin JoystickListener { void joystickChangeDirectional(JoystickDirectionalEvent event); diff --git a/lib/components/joystick/joystick_directional.dart b/lib/components/joystick/joystick_directional.dart index 4d3aa95c7c5..87843cbe46e 100644 --- a/lib/components/joystick/joystick_directional.dart +++ b/lib/components/joystick/joystick_directional.dart @@ -1,12 +1,12 @@ import 'dart:math'; -import 'package:flame/components/joystick/joystick_component.dart'; -import 'package:flame/components/joystick/joystick_events.dart'; -import 'package:flame/gestures.dart'; -import 'package:flame/sprite.dart'; import 'package:flutter/material.dart'; +import '../../gestures.dart'; import '../../position.dart'; +import '../../sprite.dart'; +import 'joystick_component.dart'; +import 'joystick_events.dart'; class JoystickDirectional { final double size; diff --git a/lib/components/nine_tile_box_component.dart b/lib/components/nine_tile_box_component.dart index d583ca1ccf7..4c5ce2a4799 100644 --- a/lib/components/nine_tile_box_component.dart +++ b/lib/components/nine_tile_box_component.dart @@ -1,7 +1,7 @@ import 'dart:ui'; -import 'package:flame/components/component.dart'; -import 'package:flame/nine_tile_box.dart'; +import '../nine_tile_box.dart'; +import 'component.dart'; /// This class is a thin wrapper on top of [NineTileBox] as a component. class NineTileBoxComponent extends PositionComponent { diff --git a/lib/components/parallax_component.dart b/lib/components/parallax_component.dart index 1c550e754f1..16f3ed6278d 100644 --- a/lib/components/parallax_component.dart +++ b/lib/components/parallax_component.dart @@ -1,10 +1,11 @@ import 'dart:async'; import 'dart:ui'; -import 'package:flame/components/component.dart'; -import 'package:flame/flame.dart'; import 'package:flutter/painting.dart'; +import '../flame.dart'; +import 'component.dart'; + /// Specifications with a path to an image and how it should be drawn in /// relation to the device screen class ParallaxImage { diff --git a/lib/components/text_box_component.dart b/lib/components/text_box_component.dart index 02e9be5e890..2ebe206bab7 100644 --- a/lib/components/text_box_component.dart +++ b/lib/components/text_box_component.dart @@ -1,13 +1,14 @@ import 'dart:async'; -import 'dart:ui'; import 'dart:math' as math; +import 'dart:ui'; + import 'package:flutter/widgets.dart' as widgets; -import 'component.dart'; -import 'mixins/resizable.dart'; -import '../text_config.dart'; import '../palette.dart'; import '../position.dart'; +import '../text_config.dart'; +import 'component.dart'; +import 'mixins/resizable.dart'; class TextBoxConfig { final double maxWidth; diff --git a/lib/components/text_component.dart b/lib/components/text_component.dart index 4e52ca28b85..83d9f0decdb 100644 --- a/lib/components/text_component.dart +++ b/lib/components/text_component.dart @@ -2,8 +2,8 @@ import 'dart:ui'; import 'package:flutter/painting.dart'; -import 'component.dart'; import '../text_config.dart'; +import 'component.dart'; class TextComponent extends PositionComponent { String _text; diff --git a/lib/components/timer_component.dart b/lib/components/timer_component.dart index 50f092c57dd..108eb766c37 100644 --- a/lib/components/timer_component.dart +++ b/lib/components/timer_component.dart @@ -1,4 +1,5 @@ import 'dart:ui'; + import './component.dart'; import '../time.dart'; diff --git a/lib/effects/combined_effect.dart b/lib/effects/combined_effect.dart index 74bebf49bf7..f6d7f5dd361 100644 --- a/lib/effects/combined_effect.dart +++ b/lib/effects/combined_effect.dart @@ -1,9 +1,9 @@ import 'dart:math'; -import 'package:flame/components/component.dart'; import 'package:meta/meta.dart'; import './effects.dart'; +import '../components/component.dart'; class CombinedEffect extends PositionComponentEffect { final List effects; diff --git a/lib/effects/effects.dart b/lib/effects/effects.dart index 65835118202..4854f1f46a6 100644 --- a/lib/effects/effects.dart +++ b/lib/effects/effects.dart @@ -1,4 +1,5 @@ import 'dart:math'; + import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -6,8 +7,8 @@ import '../components/component.dart'; import '../position.dart'; export './move_effect.dart'; -export './scale_effect.dart'; export './rotate_effect.dart'; +export './scale_effect.dart'; export './sequence_effect.dart'; abstract class PositionComponentEffect { diff --git a/lib/effects/move_effect.dart b/lib/effects/move_effect.dart index a60d0bcd964..fd2f8743022 100644 --- a/lib/effects/move_effect.dart +++ b/lib/effects/move_effect.dart @@ -1,8 +1,8 @@ +import 'dart:math'; + import 'package:flutter/animation.dart'; import 'package:meta/meta.dart'; -import 'dart:math'; - import './effects.dart'; import '../position.dart'; diff --git a/lib/effects/scale_effect.dart b/lib/effects/scale_effect.dart index 41a52565867..188b74eb0c4 100644 --- a/lib/effects/scale_effect.dart +++ b/lib/effects/scale_effect.dart @@ -1,9 +1,9 @@ +import 'dart:math'; +import 'dart:ui'; + import 'package:flutter/animation.dart'; import 'package:meta/meta.dart'; -import 'dart:ui'; -import 'dart:math'; - import './effects.dart'; import '../position.dart'; diff --git a/lib/effects/sequence_effect.dart b/lib/effects/sequence_effect.dart index 953ce83ca48..a216bbaff9d 100644 --- a/lib/effects/sequence_effect.dart +++ b/lib/effects/sequence_effect.dart @@ -1,7 +1,7 @@ -import 'package:flame/components/component.dart'; import 'package:meta/meta.dart'; import './effects.dart'; +import '../components/component.dart'; class SequenceEffect extends PositionComponentEffect { final List effects; diff --git a/lib/flame.dart b/lib/flame.dart index 64ed74c1927..94fe605149c 100644 --- a/lib/flame.dart +++ b/lib/flame.dart @@ -4,10 +4,10 @@ import 'package:audioplayers/audio_cache.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; -import 'flame_audio.dart'; +import 'assets_cache.dart'; import 'bgm.dart'; +import 'flame_audio.dart'; import 'images.dart'; -import 'assets_cache.dart'; import 'util.dart'; /// This class holds static references to some useful objects to use in your game. diff --git a/lib/flame_audio.dart b/lib/flame_audio.dart index 05f594e1fb5..cc49542511c 100644 --- a/lib/flame_audio.dart +++ b/lib/flame_audio.dart @@ -1,9 +1,8 @@ import 'dart:io'; -import 'package:flutter/foundation.dart'; - -import 'package:audioplayers/audioplayers.dart'; import 'package:audioplayers/audio_cache.dart'; +import 'package:audioplayers/audioplayers.dart'; +import 'package:flutter/foundation.dart'; /// Handles flame audio functions class FlameAudio { diff --git a/lib/flare_animation.dart b/lib/flare_animation.dart index fa2cd32d1cf..27f16c3726d 100644 --- a/lib/flare_animation.dart +++ b/lib/flare_animation.dart @@ -1,10 +1,11 @@ -import 'dart:ui'; import 'dart:math'; +import 'dart:ui'; -import "flame.dart"; import "package:flare_flutter/flare.dart"; import "package:flare_flutter/flare_actor.dart"; +import "flame.dart"; + @Deprecated("Use flame_flare package instead") class FlareAnimation { final FlutterActorArtboard _artboard; diff --git a/lib/fps_counter.dart b/lib/fps_counter.dart index 96ba59f1269..7e2254749d8 100644 --- a/lib/fps_counter.dart +++ b/lib/fps_counter.dart @@ -1,39 +1,33 @@ -import 'dart:math' as math; +import 'package:flutter/scheduler.dart'; import 'game/game.dart'; +const _maxFrames = 60; +const frameInterval = + Duration(microseconds: Duration.microsecondsPerSecond ~/ _maxFrames); + mixin FPSCounter on Game { - /// List of deltas used in debug mode to calculate FPS - final List _dts = []; + List _previousTimings = []; + + @override + void onTimingsCallback(List timings) => + _previousTimings = timings; - /// Returns whether this [Game] is should record fps or not + /// Returns whether this [Game] is should record fps or not. /// /// Returns `false` by default. Override to use the `fps` counter method. /// In recording fps, the [recordDt] method actually records every `dt` for statistics. /// Then, you can use the [fps] method to check the game FPS. + @Deprecated('Flame is now using Flutter frame times, will be removed in v1') bool recordFps(); - /// This is a hook that comes from the RenderBox to allow recording of render times and statistics. - @override - void recordDt(double dt) { - if (recordFps()) { - _dts.add(dt); - } - } - - /// Returns the average FPS for the last [average] measures. - /// - /// The values are only saved if in debug mode (override [recordFps] to use this). - /// Selects the last [average] dts, averages then, and returns the inverse value. - /// So it's technically updates per second, but the relation between updates and renders is 1:1. - /// Returns 0 if empty. + /// Returns the FPS based on the frame times from [onTimingsCallback]. double fps([int average = 1]) { - final List dts = _dts.sublist(math.max(0, _dts.length - average)); - if (dts.isEmpty) { - return 0.0; - } - final double dtSum = dts.reduce((s, t) => s + t); - final double averageDt = dtSum / average; - return 1 / averageDt; + return _previousTimings.length * + _maxFrames / + _previousTimings.map((t) { + return (t.totalSpan.inMicroseconds ~/ frameInterval.inMicroseconds) + + 1; + }).fold(0, (a, b) => a + b); } } diff --git a/lib/game.dart b/lib/game.dart index 362d3d1bd4b..00250ed1ce2 100644 --- a/lib/game.dart +++ b/lib/game.dart @@ -1,3 +1,3 @@ // Keeping compatible with earlier versions of Flame -export './game/game.dart'; export './game/base_game.dart'; +export './game/game.dart'; diff --git a/lib/game/base_game.dart b/lib/game/base_game.dart index bdbd1fc39c7..3b25ab922f1 100644 --- a/lib/game/base_game.dart +++ b/lib/game/base_game.dart @@ -1,16 +1,16 @@ import 'dart:ui'; -import 'package:flame/components/composed_component.dart'; -import 'package:flame/fps_counter.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart' hide WidgetBuilder; -import 'package:flutter/foundation.dart'; import 'package:ordered_set/comparing.dart'; import 'package:ordered_set/ordered_set.dart'; import '../components/component.dart'; +import '../components/composed_component.dart'; import '../components/mixins/has_game_ref.dart'; import '../components/mixins/tapable.dart'; +import '../fps_counter.dart'; import '../position.dart'; import 'game.dart'; diff --git a/lib/game/embedded_game_widget.dart b/lib/game/embedded_game_widget.dart index 620e69db7e2..376e4e08671 100644 --- a/lib/game/embedded_game_widget.dart +++ b/lib/game/embedded_game_widget.dart @@ -2,9 +2,8 @@ import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart' hide WidgetBuilder; import '../position.dart'; - -import 'game_render_box.dart'; import 'game.dart'; +import 'game_render_box.dart'; /// This a widget to embed a game inside the Widget tree. You can use it in pair with [BaseGame] or any other more complex [Game], as desired. /// diff --git a/lib/game/game.dart b/lib/game/game.dart index ddde8b28e23..84444a5091c 100644 --- a/lib/game/game.dart +++ b/lib/game/game.dart @@ -1,14 +1,13 @@ -import 'dart:ui'; import 'dart:async'; +import 'dart:ui'; +import 'package:flutter/foundation.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/scheduler.dart'; -import 'package:flutter/widgets.dart' hide WidgetBuilder; -import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart' hide WidgetBuilder; import '../keyboard.dart'; - import 'widget_builder.dart'; /// Represents a generic game. @@ -44,8 +43,12 @@ abstract class Game { void lifecycleStateChange(AppLifecycleState state) {} /// Used for debugging + @Deprecated('Gets called for backward compatibility, will be removed in v1') void recordDt(double dt) {} + /// Use for caluclating the FPS. + void onTimingsCallback(List timings) {} + /// Returns the game widget. Put this in your structure to start rendering and updating the game. /// You can add it directly to the runApp method or inside your widget structure (if you use vanilla screens and widgets). Widget get widget => builder.build(this); diff --git a/lib/game/game_render_box.dart b/lib/game/game_render_box.dart index 249274ecb50..9ca4cc4be33 100644 --- a/lib/game/game_render_box.dart +++ b/lib/game/game_render_box.dart @@ -5,8 +5,8 @@ import 'package:flutter/rendering.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter/widgets.dart' hide WidgetBuilder; -import 'game_loop.dart'; import 'game.dart'; +import 'game_loop.dart'; class GameRenderBox extends RenderBox with WidgetsBindingObserver { BuildContext context; @@ -15,6 +15,7 @@ class GameRenderBox extends RenderBox with WidgetsBindingObserver { GameRenderBox(this.context, this.game) { gameLoop = GameLoop(gameLoopCallback); + WidgetsBinding.instance.addTimingsCallback(game.onTimingsCallback); } @override @@ -53,6 +54,7 @@ class GameRenderBox extends RenderBox with WidgetsBindingObserver { if (!attached) { return; } + // ignore: deprecated_member_use_from_same_package game.recordDt(dt); game.update(dt); markNeedsPaint(); diff --git a/lib/game/widget_builder.dart b/lib/game/widget_builder.dart index c5adc4751e7..55000e07857 100644 --- a/lib/game/widget_builder.dart +++ b/lib/game/widget_builder.dart @@ -1,8 +1,8 @@ -import 'package:flutter/widgets.dart'; import 'package:flutter/gestures.dart'; +import 'package:flutter/widgets.dart'; -import '../gestures.dart'; import '../components/mixins/tapable.dart'; +import '../gestures.dart'; import 'embedded_game_widget.dart'; import 'game.dart'; @@ -22,6 +22,9 @@ bool _hasAdvancedGesturesDetectors(Game game) => game is MultiTouchDragDetector || game is HasTapableComponents; +bool _hasMouseDetectors(Game game) => + game is MouseMovementDetector || game is ScrollDetector; + class _GenericTapEventHandler { void Function(int pointerId) onTap; void Function(int pointerId) onTapCancel; @@ -204,6 +207,18 @@ Widget _applyBasicGesturesDetectors(Game game, Widget child) { ); } +Widget _applyMouseDetectors(game, Widget child) { + return MouseRegion( + child: Listener( + child: child, + onPointerSignal: (event) => + game is ScrollDetector && event is PointerScrollEvent + ? game.onScroll(event) + : null), + onHover: game is MouseMovementDetector ? game.onMouseMove : null, + ); +} + class WidgetBuilder { Offset offset = Offset.zero; @@ -224,6 +239,10 @@ class WidgetBuilder { widget = _applyAdvancedGesturesDetectors(game, widget); } + if (_hasMouseDetectors(game)) { + widget = _applyMouseDetectors(game, widget); + } + return widget; } } diff --git a/lib/gestures.dart b/lib/gestures.dart index 7dbe4f6944a..2c0d9b57043 100644 --- a/lib/gestures.dart +++ b/lib/gestures.dart @@ -99,3 +99,11 @@ mixin ScaleDetector on Game { void onScaleUpdate(ScaleUpdateDetails details) {} void onScaleEnd(ScaleEndDetails details) {} } + +mixin MouseMovementDetector on Game { + void onMouseMove(PointerHoverEvent event) {} +} + +mixin ScrollDetector on Game { + void onScroll(PointerScrollEvent event) {} +} diff --git a/lib/images.dart b/lib/images.dart index 75903d5e81e..b94429f671c 100644 --- a/lib/images.dart +++ b/lib/images.dart @@ -1,9 +1,9 @@ import 'dart:async'; +import 'dart:convert' show base64; import 'dart:typed_data'; import 'dart:ui'; -import 'dart:convert' show base64; -import 'package:flame/flame.dart'; +import 'flame.dart'; class Images { Map loadedFiles = {}; diff --git a/lib/keyboard.dart b/lib/keyboard.dart index a10417c8b37..73600935f8d 100644 --- a/lib/keyboard.dart +++ b/lib/keyboard.dart @@ -1,4 +1,5 @@ import 'package:flutter/services.dart'; + import './game.dart'; mixin KeyboardEvents on Game { diff --git a/lib/layer/layer.dart b/lib/layer/layer.dart index 4983e210ea4..184d7e80791 100644 --- a/lib/layer/layer.dart +++ b/lib/layer/layer.dart @@ -1,7 +1,9 @@ -import 'package:meta/meta.dart'; import 'dart:ui'; +import 'package:meta/meta.dart'; + import './processors.dart'; + export './processors.dart'; abstract class Layer { diff --git a/lib/nine_tile_box.dart b/lib/nine_tile_box.dart index dbd738e0133..7f10a9a1c0a 100644 --- a/lib/nine_tile_box.dart +++ b/lib/nine_tile_box.dart @@ -1,7 +1,7 @@ import 'dart:ui'; -import 'package:flame/palette.dart'; -import 'package:flame/sprite.dart'; +import 'palette.dart'; +import 'sprite.dart'; /// This allows you to create a rectangle textured with a 9-sliced image. /// diff --git a/lib/particle.dart b/lib/particle.dart index b9c04da6d61..602e80576e0 100644 --- a/lib/particle.dart +++ b/lib/particle.dart @@ -1,17 +1,17 @@ import 'dart:math'; import 'dart:ui'; -import 'package:flame/components/particle_component.dart'; -import 'package:flame/particles/accelerated_particle.dart'; -import 'package:flame/particles/moving_particle.dart'; -import 'package:flame/particles/rotating_particle.dart'; -import 'package:flame/particles/scaled_particle.dart'; -import 'package:flame/particles/translated_particle.dart'; import 'package:flutter/animation.dart'; import 'package:flutter/foundation.dart'; import 'components/component.dart'; +import 'components/particle_component.dart'; +import 'particles/accelerated_particle.dart'; import 'particles/composed_particle.dart'; +import 'particles/moving_particle.dart'; +import 'particles/rotating_particle.dart'; +import 'particles/scaled_particle.dart'; +import 'particles/translated_particle.dart'; import 'time.dart'; /// A function which returns [Particle] when called diff --git a/lib/particles/component_particle.dart b/lib/particles/component_particle.dart index a6037830214..7f1c85f5aa1 100644 --- a/lib/particles/component_particle.dart +++ b/lib/particles/component_particle.dart @@ -2,9 +2,9 @@ import 'dart:ui'; import 'package:flutter/foundation.dart'; +import '../components/component.dart'; import '../particle.dart'; import '../position.dart'; -import '../components/component.dart'; class ComponentParticle extends Particle { final Component component; diff --git a/lib/particles/composed_particle.dart b/lib/particles/composed_particle.dart index 2e1bf8c38a8..fe123a7aeb8 100644 --- a/lib/particles/composed_particle.dart +++ b/lib/particles/composed_particle.dart @@ -1,8 +1,9 @@ import 'dart:ui'; -import 'package:flame/particle.dart'; import 'package:flutter/foundation.dart'; +import '../particle.dart'; + /// A single [Particle] which manages multiple children /// by proxying all lifecycle hooks. class ComposedParticle extends Particle { diff --git a/lib/particles/moving_particle.dart b/lib/particles/moving_particle.dart index 412a3b234e9..256a8715124 100644 --- a/lib/particles/moving_particle.dart +++ b/lib/particles/moving_particle.dart @@ -3,8 +3,8 @@ import 'dart:ui'; import 'package:flutter/animation.dart'; import 'package:flutter/foundation.dart'; -import '../particle.dart'; import '../components/mixins/single_child_particle.dart'; +import '../particle.dart'; import '../particles/curved_particle.dart'; /// Statically offset given child [Particle] by given [Offset] diff --git a/lib/position.dart b/lib/position.dart index 9c8aac4e000..9cdd884287e 100644 --- a/lib/position.dart +++ b/lib/position.dart @@ -1,5 +1,6 @@ import 'dart:math' as math; import 'dart:ui' as ui; + import 'package:box2d_flame/box2d.dart' as b2d; /// An ordered pair representation (point, position, offset). diff --git a/lib/sprite.dart b/lib/sprite.dart index 54c88469f17..3394ec33c86 100644 --- a/lib/sprite.dart +++ b/lib/sprite.dart @@ -1,9 +1,9 @@ +import 'dart:async'; import 'dart:ui'; -import 'dart:async'; import 'flame.dart'; -import 'position.dart'; import 'palette.dart'; +import 'position.dart'; class Sprite { Paint paint = BasicPalette.white.paint; diff --git a/lib/spritesheet.dart b/lib/spritesheet.dart index 996c05a3739..677d776becb 100644 --- a/lib/spritesheet.dart +++ b/lib/spritesheet.dart @@ -1,8 +1,9 @@ +import 'dart:ui'; + import 'package:meta/meta.dart'; -import 'sprite.dart'; -import 'animation.dart'; -import 'dart:ui'; +import 'animation.dart'; +import 'sprite.dart'; /// Utility class to help extract animations and sprites from a spritesheet image class SpriteSheet { diff --git a/lib/text_config.dart b/lib/text_config.dart index 088b6280514..433fd6c1755 100644 --- a/lib/text_config.dart +++ b/lib/text_config.dart @@ -1,10 +1,11 @@ import 'dart:ui'; -import 'package:flame/components/text_component.dart'; + import 'package:flutter/material.dart' as material; -import 'position.dart'; import 'anchor.dart'; +import 'components/text_component.dart'; import 'memory_cache.dart'; +import 'position.dart'; /// A Text Config contains all typographical information required to render texts; i.e., font size and color, family, etc. /// diff --git a/lib/util.dart b/lib/util.dart index 523986d47c5..fc2d83084b3 100644 --- a/lib/util.dart +++ b/lib/util.dart @@ -1,17 +1,17 @@ import 'dart:async'; import 'dart:ui'; +import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/services.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart' as widgets; import 'animation.dart'; +import 'components/animation_component.dart'; import 'game/base_game.dart'; import 'game/embedded_game_widget.dart'; -import 'sprite.dart'; -import 'components/animation_component.dart'; import 'position.dart'; +import 'sprite.dart'; /// Some utilities that did not fit anywhere else. /// diff --git a/lib/widgets/animation_widget.dart b/lib/widgets/animation_widget.dart index b380531811d..73d54a3f90e 100644 --- a/lib/widgets/animation_widget.dart +++ b/lib/widgets/animation_widget.dart @@ -1,10 +1,10 @@ -import 'package:flutter/material.dart' hide Animation; -import 'package:flame/animation.dart'; - import 'dart:math'; -import '../anchor.dart'; +import 'package:flutter/material.dart' hide Animation; + import './sprite_widget.dart'; +import '../anchor.dart'; +import '../animation.dart'; class AnimationWidget extends StatefulWidget { final Animation animation; diff --git a/lib/widgets/nine_tile_box.dart b/lib/widgets/nine_tile_box.dart index 29d574b9c97..cd0125c478e 100644 --- a/lib/widgets/nine_tile_box.dart +++ b/lib/widgets/nine_tile_box.dart @@ -1,8 +1,10 @@ +import 'dart:ui'; + import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart' as widgets; import 'package:meta/meta.dart'; + import '../sprite.dart'; -import 'dart:ui'; class _Painter extends widgets.CustomPainter { final Image image; diff --git a/lib/widgets/sprite_button.dart b/lib/widgets/sprite_button.dart index 35d1dd1a3eb..51333b029ae 100644 --- a/lib/widgets/sprite_button.dart +++ b/lib/widgets/sprite_button.dart @@ -1,7 +1,8 @@ import 'package:flutter/widgets.dart'; -import '../sprite.dart'; import 'package:meta/meta.dart'; +import '../sprite.dart'; + class SpriteButton extends StatefulWidget { final VoidCallback onPressed; final Widget label; diff --git a/lib/widgets/sprite_widget.dart b/lib/widgets/sprite_widget.dart index d1c7ea78ae4..e74a044d90d 100644 --- a/lib/widgets/sprite_widget.dart +++ b/lib/widgets/sprite_widget.dart @@ -1,9 +1,10 @@ +import 'dart:math'; + import 'package:flutter/widgets.dart'; import 'package:meta/meta.dart'; -import 'dart:math'; -import '../sprite.dart'; import '../anchor.dart'; +import '../sprite.dart'; class SpriteWidget extends StatelessWidget { final Sprite sprite; diff --git a/pubspec.yaml b/pubspec.yaml index 02354e28990..ca0643a68a6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flame description: A minimalist Flutter game engine, provides a nice set of somewhat independent modules you can choose from. -version: 0.26.0 +version: 0.27.0 homepage: https://github.com/flame-engine/flame dependencies: