diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cf72ae59..98493289e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ - Remove Position class in favor of new Vector2 extension - Remove Box2D as a dependency +## 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 f9d9e7893..eaa91e758 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 1e582a60c..23db48678 100644 --- a/doc/components.md +++ b/doc/components.md @@ -239,6 +239,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/animation_widget/pubspec.yaml b/doc/examples/animation_widget/pubspec.yaml index 2c51ff39d..e9591a61a 100644 --- a/doc/examples/animation_widget/pubspec.yaml +++ b/doc/examples/animation_widget/pubspec.yaml @@ -4,7 +4,7 @@ description: A sample Flame project to showcase the SpriteAnimationWidget widget version: 0.1.0 environment: - sdk: ">=2.0.0-dev.68.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/animations/pubspec.yaml b/doc/examples/animations/pubspec.yaml index 563ff9376..e0f54bae6 100644 --- a/doc/examples/animations/pubspec.yaml +++ b/doc/examples/animations/pubspec.yaml @@ -4,7 +4,7 @@ description: Flame sample game showcasing animations features version: 1.0.0+1 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/aseprite/pubspec.yaml b/doc/examples/aseprite/pubspec.yaml index 356f34ca4..5ba515aeb 100644 --- a/doc/examples/aseprite/pubspec.yaml +++ b/doc/examples/aseprite/pubspec.yaml @@ -4,7 +4,7 @@ description: Flame sample for using Aseprite animations version: 1.0.0+1 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/audiopool/pubspec.yaml b/doc/examples/audiopool/pubspec.yaml index c74f16297..3a16b7c19 100644 --- a/doc/examples/audiopool/pubspec.yaml +++ b/doc/examples/audiopool/pubspec.yaml @@ -3,7 +3,7 @@ description: Flame example application showcasing the audiopool class version: 0.1.0 environment: - sdk: ">=2.0.0-dev.68.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/cleanup.sh b/doc/examples/cleanup.sh index 4ed2dc25d..1e9effb82 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/debug/pubspec.yaml b/doc/examples/debug/pubspec.yaml index 6dea24adf..1f944b75f 100644 --- a/doc/examples/debug/pubspec.yaml +++ b/doc/examples/debug/pubspec.yaml @@ -4,7 +4,7 @@ description: Flame sample for using debug features version: 1.0.0+1 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/effects/combined_effects/pubspec.yaml b/doc/examples/effects/combined_effects/pubspec.yaml index 55d48e57f..60b9011d9 100644 --- a/doc/examples/effects/combined_effects/pubspec.yaml +++ b/doc/examples/effects/combined_effects/pubspec.yaml @@ -4,7 +4,7 @@ description: Flame sample game showcasing combined effects version: 1.0.0+1 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/effects/infinite_effects/pubspec.yaml b/doc/examples/effects/infinite_effects/pubspec.yaml index 59cc1f3bb..e1eef9021 100644 --- a/doc/examples/effects/infinite_effects/pubspec.yaml +++ b/doc/examples/effects/infinite_effects/pubspec.yaml @@ -4,7 +4,7 @@ description: Flame sample game showcasing infinite effects version: 1.0.0+1 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/effects/sequence_effect/pubspec.yaml b/doc/examples/effects/sequence_effect/pubspec.yaml index 6d5931ecf..909bf094f 100644 --- a/doc/examples/effects/sequence_effect/pubspec.yaml +++ b/doc/examples/effects/sequence_effect/pubspec.yaml @@ -4,7 +4,7 @@ description: Flame sample game showcasing the sequence effect version: 1.0.0+1 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/effects/simple/pubspec.yaml b/doc/examples/effects/simple/pubspec.yaml index 69b27db77..332abc333 100644 --- a/doc/examples/effects/simple/pubspec.yaml +++ b/doc/examples/effects/simple/pubspec.yaml @@ -4,7 +4,7 @@ description: A Flame game showcasing the use of the effects api version: 1.0.0+1 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: 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 000000000..36880b8ef --- /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/extensions/vector2.dart'; +import 'package:flame/extensions/offset.dart'; + +void main() { + final game = MyGame(); + runApp(game.widget); +} + +class MyGame extends Game with MouseMovementDetector { + static const SPEED = 200; + + Vector2 position = Vector2(0, 0); + Vector2 target; + + final Paint _blue = Paint()..color = const Color(0xFF0000FF); + + bool _onTarget = false; + + @override + void onMouseMove(event) { + target = event.localPosition.toVector2(); + } + + 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 - position).normalized(); + position += dir * (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 000000000..fbd5497b7 --- /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/extensions/vector2.dart'; +import 'package:flame/extensions/offset.dart'; + +void main() { + final game = MyGame(); + runApp(game.widget); +} + +class MyGame extends Game with ScrollDetector { + static const SPEED = 200; + + Vector2 position = Vector2(0, 0); + Vector2 target; + + @override + void onScroll(event) { + target = position - event.scrollDelta.toVector2(); + } + + @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 - position).normalized(); + position += dir * (SPEED * dt); + } + } +} diff --git a/doc/examples/gestures/pubspec.yaml b/doc/examples/gestures/pubspec.yaml index 5a74dc912..e11e43bcd 100644 --- a/doc/examples/gestures/pubspec.yaml +++ b/doc/examples/gestures/pubspec.yaml @@ -4,7 +4,7 @@ description: A flame game showcasing the use of gestures callbacks version: 1.0.0+1 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/go_desktop/pubspec.yaml b/doc/examples/go_desktop/pubspec.yaml index ea3336287..0b15f44d2 100644 --- a/doc/examples/go_desktop/pubspec.yaml +++ b/doc/examples/go_desktop/pubspec.yaml @@ -4,7 +4,7 @@ description: Flame sample game on using the go flutter desktop framework version: 1.0.0+1 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/isometric/.metadata b/doc/examples/isometric/.metadata new file mode 100644 index 000000000..6a633e088 --- /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 000000000..0e9837f20 --- /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 000000000..357030805 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 000000000..93645b5b2 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 000000000..769834026 --- /dev/null +++ b/doc/examples/isometric/lib/main.dart @@ -0,0 +1,86 @@ +import 'package:flame/components/sprite_component.dart'; +import 'package:flame/extensions/vector2.dart'; +import 'package:flame/extensions/offset.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/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 = Vector2(x, y); + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + final 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(Vector2 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 = event.position.toVector2(); + final block = base.getBlock(screenPosition); + selector.show = base.containsBlock(block); + selector.setPosition(base.getBlockPosition(block) + topLeft); + } +} diff --git a/doc/examples/isometric/pubspec.yaml b/doc/examples/isometric/pubspec.yaml new file mode 100644 index 000000000..4320a5fa1 --- /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.7.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/examples/joystick/pubspec.yaml b/doc/examples/joystick/pubspec.yaml index 163960615..7fa6ffd1a 100644 --- a/doc/examples/joystick/pubspec.yaml +++ b/doc/examples/joystick/pubspec.yaml @@ -4,7 +4,7 @@ description: A flame game showcasing the use of joystick version: 1.0.0+1 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/keyboard/pubspec.yaml b/doc/examples/keyboard/pubspec.yaml index 2daeceacf..c9625537e 100644 --- a/doc/examples/keyboard/pubspec.yaml +++ b/doc/examples/keyboard/pubspec.yaml @@ -4,7 +4,7 @@ description: Simple Flame project showcasing how to use the Keyboard events version: 1.0.0+1 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/nine_tile_box/pubspec.yaml b/doc/examples/nine_tile_box/pubspec.yaml index cb8f5a8f1..c7ff137be 100644 --- a/doc/examples/nine_tile_box/pubspec.yaml +++ b/doc/examples/nine_tile_box/pubspec.yaml @@ -4,7 +4,7 @@ description: Flame sample for using the nine_tile_box feature version: 1.0.0+1 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/parallax/pubspec.yaml b/doc/examples/parallax/pubspec.yaml index 97338cc98..ac7cd9b36 100644 --- a/doc/examples/parallax/pubspec.yaml +++ b/doc/examples/parallax/pubspec.yaml @@ -4,7 +4,7 @@ description: Flame sample game showcasing the parallax features version: 1.0.0+1 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/particles/pubspec.yaml b/doc/examples/particles/pubspec.yaml index 2856e4544..baac77e2b 100644 --- a/doc/examples/particles/pubspec.yaml +++ b/doc/examples/particles/pubspec.yaml @@ -4,7 +4,7 @@ description: Flame sample game showcasing particle effects version: 1.0.0 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/render_flip/pubspec.yaml b/doc/examples/render_flip/pubspec.yaml index a2e63c764..4f0f283e3 100644 --- a/doc/examples/render_flip/pubspec.yaml +++ b/doc/examples/render_flip/pubspec.yaml @@ -4,7 +4,7 @@ description: Flame sample game showcasing animations features version: 1.0.0+1 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/sound/pubspec.yaml b/doc/examples/sound/pubspec.yaml index e84837187..457747824 100644 --- a/doc/examples/sound/pubspec.yaml +++ b/doc/examples/sound/pubspec.yaml @@ -3,7 +3,7 @@ description: Flame example application showcasing the audio features version: 0.1.0 environment: - sdk: ">=2.0.0-dev.68.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/sprite_batch/pubspec.yaml b/doc/examples/sprite_batch/pubspec.yaml index eab9766ea..82cdac14e 100644 --- a/doc/examples/sprite_batch/pubspec.yaml +++ b/doc/examples/sprite_batch/pubspec.yaml @@ -4,7 +4,7 @@ description: Showcasing SpriteBatch features version: 1.0.0+1 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/sprites/pubspec.yaml b/doc/examples/sprites/pubspec.yaml index 757cce955..192683f5f 100644 --- a/doc/examples/sprites/pubspec.yaml +++ b/doc/examples/sprites/pubspec.yaml @@ -4,7 +4,7 @@ description: Flame sample game showcasing rendering 500 sprites version: 1.0.0+1 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/spritesheet/pubspec.yaml b/doc/examples/spritesheet/pubspec.yaml index dec48fabf..9ee3bda77 100644 --- a/doc/examples/spritesheet/pubspec.yaml +++ b/doc/examples/spritesheet/pubspec.yaml @@ -4,7 +4,7 @@ description: Flame sample game showcasing spritesheet features version: 1.0.0+1 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/text/pubspec.yaml b/doc/examples/text/pubspec.yaml index de4ff0969..2aa1ae78f 100644 --- a/doc/examples/text/pubspec.yaml +++ b/doc/examples/text/pubspec.yaml @@ -4,7 +4,7 @@ description: A sample Flame project that renders texts. version: 0.1.0 environment: - sdk: ">=2.0.0-dev.68.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/timer/pubspec.yaml b/doc/examples/timer/pubspec.yaml index 18a7824e7..254ad4c32 100644 --- a/doc/examples/timer/pubspec.yaml +++ b/doc/examples/timer/pubspec.yaml @@ -4,7 +4,7 @@ description: Example app using Timer class version: 1.0.0+1 environment: - sdk: ">=2.0.0-dev.68.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/widgets/pubspec.yaml b/doc/examples/widgets/pubspec.yaml index 9c9856cc4..a3d939579 100644 --- a/doc/examples/widgets/pubspec.yaml +++ b/doc/examples/widgets/pubspec.yaml @@ -4,7 +4,7 @@ description: A Flutter project showcasing Flame's widgets. version: 1.0.0+1 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/examples/with_widgets_overlay/pubspec.yaml b/doc/examples/with_widgets_overlay/pubspec.yaml index f465b6781..2214f3731 100644 --- a/doc/examples/with_widgets_overlay/pubspec.yaml +++ b/doc/examples/with_widgets_overlay/pubspec.yaml @@ -4,7 +4,7 @@ description: A Flame game showcasing how to use the WithWidgetsOverlay feature version: 1.0.0+1 environment: - sdk: ">=2.0.0-dev.68.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: flutter: diff --git a/doc/images/isometric.png b/doc/images/isometric.png new file mode 100644 index 000000000..635b0560d Binary files /dev/null and b/doc/images/isometric.png differ diff --git a/doc/input.md b/doc/input.md index 24465588a..2b431f1f2 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/doc/particles.md b/doc/particles.md index 0d7fd6380..98c9df58b 100644 --- a/doc/particles.md +++ b/doc/particles.md @@ -226,7 +226,7 @@ game.add( ParticleComponent( particle: SpriteParticle( sprite: Sprite('sprite.png'), - size: Position(64, 64), + size: Vector2(64, 64), ) ) ); diff --git a/lib/assets_cache.dart b/lib/assets_cache.dart index 033060acf..14a1ca94b 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 0c3d8944c..68ef332f0 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/components/component.dart b/lib/components/component.dart index deef6d801..eb4e7f992 100644 --- a/lib/components/component.dart +++ b/lib/components/component.dart @@ -50,7 +50,7 @@ abstract class Component { /// If two components share the same priority, they will probably be drawn in the order they were added. int priority() => 0; - /// Called when the component has been added and preperad by the game instance. + /// Called when the component has been added and prepared by the game instance. /// /// This can be used to make initializations on your component as, when this method is called, /// things like resize (and other mixins) are already set and usable. diff --git a/lib/components/isometric_tile_map_component.dart b/lib/components/isometric_tile_map_component.dart new file mode 100644 index 000000000..39742a994 --- /dev/null +++ b/lib/components/isometric_tile_map_component.dart @@ -0,0 +1,156 @@ +import 'dart:ui'; + +import 'package:flame/components/position_component.dart'; + +import '../flame.dart'; +import '../sprite.dart'; +import '../extensions/vector2.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) { + super.render(c); + + final size = Vector2( + effectiveTileSize.toDouble(), + effectiveTileSize.toDouble(), + ); + 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, p.toRect(size)); + } + } + } + } + + /// Get the position in witch a block must be in the isometric space. + /// + /// This does not include the (x,y) PositionComponent offset! + Vector2 getBlockPosition(Block block) { + return getBlockPositionInts(block.x, block.y); + } + + Vector2 getBlockPositionInts(int i, int j) { + final s = effectiveTileSize.toDouble() / 2; + return cartToIso(Vector2(i * s, j * s)) - Vector2(s, 0); + } + + /// Converts a coordinate from the isometric space to the cartesian space. + Vector2 isoToCart(Vector2 p) { + final x = (2 * p.y + p.x) / 2; + final y = (2 * p.y - p.x) / 2; + return Vector2(x, y); + } + + /// Converts a coordinate from the cartesian space to the isometric space. + Vector2 cartToIso(Vector2 p) { + final x = p.x - p.y; + final y = (p.x + p.y) / 2; + return Vector2(x, y); + } + + /// Get what block is at isometric position p. + /// + /// This can be used to handle clicks or hovers. + Block getBlock(Vector2 p) { + final s = effectiveTileSize.toDouble() / 2; + final cart = isoToCart(p - position); + 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 558fede3d..70ca4b13b 100644 --- a/lib/components/joystick/joystick_action.dart +++ b/lib/components/joystick/joystick_action.dart @@ -1,10 +1,10 @@ import 'dart:math'; import 'dart:ui'; -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 c1992c9ab..a0137165d 100644 --- a/lib/components/joystick/joystick_component.dart +++ b/lib/components/joystick/joystick_component.dart @@ -1,13 +1,13 @@ import 'dart:ui'; +import '../../extensions/vector2.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'; -import '../component.dart'; -import '../mixins/has_game_ref.dart'; -import '../../game/base_game.dart'; -import '../../gestures.dart'; -import '../../extensions/vector2.dart'; mixin JoystickListener { void joystickChangeDirectional(JoystickDirectionalEvent event); diff --git a/lib/components/joystick/joystick_directional.dart b/lib/components/joystick/joystick_directional.dart index 56ad3d4cc..7aa9a0e08 100644 --- a/lib/components/joystick/joystick_directional.dart +++ b/lib/components/joystick/joystick_directional.dart @@ -1,13 +1,13 @@ 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 '../../extensions/offset.dart'; import '../../extensions/vector2.dart'; +import '../../gestures.dart'; +import '../../sprite.dart'; +import 'joystick_component.dart'; +import 'joystick_events.dart'; class JoystickDirectional { final double size; diff --git a/lib/components/parallax_component.dart b/lib/components/parallax_component.dart index 395bc63c4..c16dbce19 100644 --- a/lib/components/parallax_component.dart +++ b/lib/components/parallax_component.dart @@ -1,11 +1,11 @@ import 'dart:async'; import 'dart:ui'; -import 'package:flame/extensions/vector2.dart'; -import 'package:flame/extensions/rect.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/painting.dart'; +import '../extensions/vector2.dart'; +import '../extensions/rect.dart'; import '../flame.dart'; import 'position_component.dart'; diff --git a/lib/components/timer_component.dart b/lib/components/timer_component.dart index 50f092c57..108eb766c 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/move_effect.dart b/lib/effects/move_effect.dart index 9bb442e1e..39ef3f1b3 100644 --- a/lib/effects/move_effect.dart +++ b/lib/effects/move_effect.dart @@ -1,10 +1,10 @@ +import 'dart:math'; + import 'package:flutter/animation.dart'; import 'package:meta/meta.dart'; -import 'dart:math'; - import '../extensions/vector2.dart'; -import './effects.dart'; +import 'effects.dart'; double _direction(double p, double d) => (p - d).sign; double _distance(double a, double b) => (a - b).abs(); diff --git a/lib/effects/scale_effect.dart b/lib/effects/scale_effect.dart index b31291f91..4d8c75342 100644 --- a/lib/effects/scale_effect.dart +++ b/lib/effects/scale_effect.dart @@ -2,7 +2,7 @@ import 'package:flutter/animation.dart'; import 'package:meta/meta.dart'; import '../extensions/vector2.dart'; -import './effects.dart'; +import 'effects.dart'; double _direction(double p, double d) => (p - d).sign; double _length(double a, double b) => (a - b).abs(); diff --git a/lib/effects/sequence_effect.dart b/lib/effects/sequence_effect.dart index 933fe5109..3fb9ea1e1 100644 --- a/lib/effects/sequence_effect.dart +++ b/lib/effects/sequence_effect.dart @@ -1,7 +1,7 @@ import 'package:meta/meta.dart'; -import './effects.dart'; import '../components/position_component.dart'; +import 'effects.dart'; class SequenceEffect extends PositionComponentEffect { final List effects; diff --git a/lib/extensions/offset.dart b/lib/extensions/offset.dart index 705780ec4..5aea2c673 100644 --- a/lib/extensions/offset.dart +++ b/lib/extensions/offset.dart @@ -15,6 +15,6 @@ extension OffsetExtension on Offset { /// Creates a [Point] from the [Offset] Point toPoint() => Point(dx, dy); - /// Creates a [Rect] starting in origo and going the [Offset] + /// Creates a [Rect] starting in origin and going the [Offset] Rect toRect() => Rect.fromLTWH(0, 0, dx, dy); } diff --git a/lib/extensions/vector2.dart b/lib/extensions/vector2.dart index fb9a76956..85085db92 100644 --- a/lib/extensions/vector2.dart +++ b/lib/extensions/vector2.dart @@ -15,10 +15,10 @@ extension Vector2Extension on Vector2 { /// Creates a [Point] from the [Vector2] Point toPoint() => Point(x, y); - /// Creates a [Rect] starting from [x, y] and going the [Vector2] + /// Creates a [Rect] starting from [x, y] and having size [to]. Rect toRect(Vector2 to) => Rect.fromLTWH(x, y, to.x, to.y); - /// Creates a [Rect] starting in origo and going the [Vector2] + /// Creates a [Rect] starting in origin and having size [to]. Rect toOriginRect() => Rect.fromLTWH(0, 0, x, y); /// Linearly interpolate towards another Vector2 diff --git a/lib/flame.dart b/lib/flame.dart index 64ed74c19..94fe60514 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 'bgm.dart'; -import 'images.dart'; import 'assets_cache.dart'; +import 'bgm.dart'; +import 'flame_audio.dart'; +import 'images.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 05f594e1f..cc4954251 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 fa2cd32d1..27f16c372 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 96ba59f12..7e2254749 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'; -mixin FPSCounter on Game { - /// List of deltas used in debug mode to calculate FPS - final List _dts = []; +const _maxFrames = 60; +const frameInterval = + Duration(microseconds: Duration.microsecondsPerSecond ~/ _maxFrames); - /// Returns whether this [Game] is should record fps or not +mixin FPSCounter on Game { + List _previousTimings = []; + + @override + void onTimingsCallback(List timings) => + _previousTimings = timings; + + /// 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 362d3d1bd..00250ed1c 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 3d1f8f5e1..7ed77e615 100644 --- a/lib/game/base_game.dart +++ b/lib/game/base_game.dart @@ -1,7 +1,6 @@ import 'dart:ui'; import 'package:flutter/foundation.dart'; -import 'package:flame/fps_counter.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart' hide WidgetBuilder; import 'package:ordered_set/comparing.dart'; @@ -12,6 +11,7 @@ import '../components/mixins/has_game_ref.dart'; import '../components/mixins/tapable.dart'; import '../components/position_component.dart'; import '../extensions/vector2.dart'; +import '../fps_counter.dart'; import 'game.dart'; /// This is a more complete and opinionated implementation of Game. diff --git a/lib/game/embedded_game_widget.dart b/lib/game/embedded_game_widget.dart index 1fde3d675..8eaf2955b 100644 --- a/lib/game/embedded_game_widget.dart +++ b/lib/game/embedded_game_widget.dart @@ -2,8 +2,8 @@ import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart' hide WidgetBuilder; import '../extensions/vector2.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 d17b3e4c3..0f8ae67a4 100644 --- a/lib/game/game.dart +++ b/lib/game/game.dart @@ -1,15 +1,14 @@ -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 '../keyboard.dart'; +import 'package:flutter/widgets.dart' hide WidgetBuilder; import '../extensions/vector2.dart'; +import '../keyboard.dart'; import 'widget_builder.dart'; /// Represents a generic game. @@ -45,8 +44,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 b8c86b322..ad6abda20 100644 --- a/lib/game/game_render_box.dart +++ b/lib/game/game_render_box.dart @@ -6,8 +6,8 @@ import 'package:flutter/scheduler.dart'; import 'package:flutter/widgets.dart' hide WidgetBuilder; import '../extensions/size.dart'; -import 'game_loop.dart'; import 'game.dart'; +import 'game_loop.dart'; class GameRenderBox extends RenderBox with WidgetsBindingObserver { BuildContext context; @@ -16,6 +16,7 @@ class GameRenderBox extends RenderBox with WidgetsBindingObserver { GameRenderBox(this.context, this.game) { gameLoop = GameLoop(gameLoopCallback); + WidgetsBinding.instance.addTimingsCallback(game.onTimingsCallback); } @override @@ -54,6 +55,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 3f98abb86..bae5b49b2 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,19 @@ 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 +240,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 7dbe4f694..2c0d9b570 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 75903d5e8..b94429f67 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 a10417c8b..73600935f 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 4983e210e..184d7e807 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 9a1dbbcbc..86f626a80 100644 --- a/lib/nine_tile_box.dart +++ b/lib/nine_tile_box.dart @@ -1,8 +1,8 @@ import 'dart:ui'; -import 'package:flame/palette.dart'; -import 'package:flame/sprite.dart'; -import 'package:flame/extensions/vector2.dart'; +import 'extensions/vector2.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 b9c04da6d..602e80576 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 931684d5b..28769d865 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 '../particle.dart'; import '../components/component.dart'; import '../extensions/vector2.dart'; +import '../particle.dart'; class ComponentParticle extends Particle { final Component component; diff --git a/lib/particles/composed_particle.dart b/lib/particles/composed_particle.dart index 2e1bf8c38..fe123a7ae 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 7c778c861..1542c8656 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/sprite.dart b/lib/sprite.dart index f4743c015..53d5b0d85 100644 --- a/lib/sprite.dart +++ b/lib/sprite.dart @@ -1,6 +1,5 @@ -import 'dart:ui'; - import 'dart:async'; +import 'dart:ui'; import 'flame.dart'; import 'palette.dart'; diff --git a/lib/spritesheet.dart b/lib/spritesheet.dart index c3b550db7..df78fce96 100644 --- a/lib/spritesheet.dart +++ b/lib/spritesheet.dart @@ -1,9 +1,9 @@ +import 'dart:ui'; + import 'package:meta/meta.dart'; import 'sprite.dart'; import 'sprite_animation.dart'; -import 'dart:ui'; - /// Utility class to help extract animations and sprites from a spritesheet image class SpriteSheet { int textureWidth; diff --git a/lib/text_config.dart b/lib/text_config.dart index 1db1fa9e1..aee148653 100644 --- a/lib/text_config.dart +++ b/lib/text_config.dart @@ -1,8 +1,9 @@ import 'dart:ui'; -import 'package:flame/components/text_component.dart'; + import 'package:flutter/material.dart' as material; import 'anchor.dart'; +import 'components/text_component.dart'; import 'memory_cache.dart'; import 'extensions/size.dart'; import 'extensions/vector2.dart'; diff --git a/lib/util.dart b/lib/util.dart index b173f69d9..181c0e1cb 100644 --- a/lib/util.dart +++ b/lib/util.dart @@ -1,9 +1,9 @@ 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 'extensions/size.dart'; import 'extensions/vector2.dart'; diff --git a/lib/widgets/animation_widget.dart b/lib/widgets/animation_widget.dart index 7ed30d678..8eb2f74b8 100644 --- a/lib/widgets/animation_widget.dart +++ b/lib/widgets/animation_widget.dart @@ -1,10 +1,12 @@ -import 'package:flutter/material.dart'; -import 'package:flame/sprite_animation.dart'; - import 'dart:math'; +import 'package:flutter/material.dart' hide Animation; +import 'package:flame/sprite_animation.dart'; + import '../anchor.dart'; -import './sprite_widget.dart'; +import '../sprite_animation.dart'; + +import 'sprite_widget.dart'; /// A [StatefulWidget] that render a [SpriteAnimation]. class SpriteAnimationWidget extends StatefulWidget { diff --git a/lib/widgets/nine_tile_box.dart b/lib/widgets/nine_tile_box.dart index d9e99fbea..fb7c13071 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 35d1dd1a3..51333b029 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 0bcf7bab6..0311172de 100644 --- a/lib/widgets/sprite_widget.dart +++ b/lib/widgets/sprite_widget.dart @@ -1,10 +1,11 @@ -import 'package:flame/widgets/animation_widget.dart'; -import 'package:flutter/widgets.dart'; -import 'package:meta/meta.dart'; import 'dart:math'; -import '../sprite.dart'; +import 'package:flutter/widgets.dart'; +import 'package:meta/meta.dart'; + import '../anchor.dart'; +import '../sprite.dart'; +import 'animation_widget.dart'; /// A [StatefulWidget] that renders a still [Sprite]. /// diff --git a/pubspec.yaml b/pubspec.yaml index 9c4daa262..b26c68f60 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: