From 4f053ed74c09d4e19a53694130b5d5c0d3e23aa6 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Fri, 16 Feb 2024 15:09:45 +0100 Subject: [PATCH 01/79] fix: Vertices in `PolygonComponent` should subtract vertices positioning (#3040) If the vertices in the `PolygonComponent` weren't starting at 0,0 they got the wrong hitbox, but rendered correctly. This PR fixes that. Closes: #3031 --- .../lib/src/geometry/polygon_component.dart | 37 ++++++++----------- .../test/components/shape_component_test.dart | 28 +++++++++++++- 2 files changed, 43 insertions(+), 22 deletions(-) diff --git a/packages/flame/lib/src/geometry/polygon_component.dart b/packages/flame/lib/src/geometry/polygon_component.dart index b43a6d0a9d6..ce650f0788e 100644 --- a/packages/flame/lib/src/geometry/polygon_component.dart +++ b/packages/flame/lib/src/geometry/polygon_component.dart @@ -25,8 +25,6 @@ class PolygonComponent extends ShapeComponent { /// With this constructor you create your [PolygonComponent] from positions in /// anywhere in the 2d-space. It will automatically calculate the [size] of /// the Polygon (the bounding box) if no size it given. - /// NOTE: Always define your polygon in a counter-clockwise fashion (in the - /// screen coordinate system). PolygonComponent( this._vertices, { super.position, @@ -110,10 +108,6 @@ class PolygonComponent extends ShapeComponent { .toList(growable: false); } - // Used to not create new Vector2 objects when calculating the top left of the - // bounds of the polygon. - final _topLeft = Vector2.zero(); - @protected void refreshVertices({ required List newVertices, @@ -128,24 +122,29 @@ class PolygonComponent extends ShapeComponent { if (_isClockwise(newVertices)) { newVertices.reverse(); } - _topLeft.setFrom(newVertices[0]); - newVertices.forEachIndexed((i, _) { + final topLeft = Vector2.zero(); + topLeft.setFrom(newVertices[0]); + for (var i = 0; i < newVertices.length; i++) { final newVertex = newVertices[i]; _vertices[i].setFrom(newVertex); - _topLeft.x = min(_topLeft.x, newVertex.x); - _topLeft.y = min(_topLeft.y, newVertex.y); - }); + topLeft.x = min(topLeft.x, newVertex.x); + topLeft.y = min(topLeft.y, newVertex.y); + } + for (var i = 0; i < newVertices.length; i++) { + final newVertex = newVertices[i]; + _vertices[i].setFrom(newVertex - topLeft); + } _path ..reset() ..addPolygon( - vertices.map((p) => (p - _topLeft).toOffset()).toList(growable: false), + _vertices.map((p) => p.toOffset()).toList(growable: false), true, ); if (shrinkToBoundsOverride ?? shrinkToBounds) { final bounds = _path.getBounds(); size.setValues(bounds.width, bounds.height); if (!manuallyPositioned) { - position = Anchor.topLeft.toOtherAnchorPosition(_topLeft, anchor, size); + position = Anchor.topLeft.toOtherAnchorPosition(topLeft, anchor, size); } } } @@ -161,14 +160,14 @@ class PolygonComponent extends ShapeComponent { scale, angle, ])) { - vertices.forEachIndexed((i, vertex) { + for (var i = 0; i < _vertices.length; i++) { + final vertex = _vertices[i]; _globalVertices[i] ..setFrom(vertex) - ..sub(_topLeft) ..multiply(scale) ..add(position) ..rotate(angle, center: position); - }); + } if (scale.y.isNegative || scale.x.isNegative) { // Since the list will be clockwise we have to reverse it for it to // become counterclockwise. @@ -255,11 +254,7 @@ class PolygonComponent extends ShapeComponent { @override bool containsLocalPoint(Vector2 point) { - // Take anchor into consideration. - final localPoint = - anchor.toOtherAnchorPosition(point, Anchor.topLeft, size); - - return _containsPoint(localPoint, _vertices); + return _containsPoint(point, _vertices); } /// Return all vertices as [LineSegment]s that intersect [rect], if [rect] diff --git a/packages/flame/test/components/shape_component_test.dart b/packages/flame/test/components/shape_component_test.dart index 7a6fb170834..a24153da7f3 100644 --- a/packages/flame/test/components/shape_component_test.dart +++ b/packages/flame/test/components/shape_component_test.dart @@ -52,8 +52,34 @@ void main() { Vector2(1.5, 0.5), ], ); - expect(polygon.containsLocalPoint(Vector2(0.25, 0.25)), isFalse); + expect(polygon.containsLocalPoint(Vector2(0.0, 0.0)), isTrue); + expect(polygon.containsLocalPoint(Vector2(0.25, 0.25)), isTrue); expect(polygon.containsLocalPoint(Vector2(0.75, 0.75)), isTrue); + expect(polygon.containsLocalPoint(Vector2(1.0, 1.0)), isTrue); + expect(polygon.containsLocalPoint(Vector2(1.0, 0.0)), isTrue); + expect(polygon.containsLocalPoint(Vector2(0.0, 1.0)), isTrue); + expect(polygon.containsLocalPoint(Vector2(0.0, 1.0001)), isFalse); + expect(polygon.containsLocalPoint(Vector2(-0.0001, 0.0)), isFalse); + }); + + test('polygon contains point in local with anchor', () { + final polygon = PolygonComponent( + [ + Vector2(0.5, 0.5), + Vector2(0.5, 1.5), + Vector2(1.5, 1.5), + Vector2(1.5, 0.5), + ], + anchor: Anchor.center, + ); + expect(polygon.containsLocalPoint(Vector2(0.0, 0.0)), isTrue); + expect(polygon.containsLocalPoint(Vector2(0.25, 0.25)), isTrue); + expect(polygon.containsLocalPoint(Vector2(0.75, 0.75)), isTrue); + expect(polygon.containsLocalPoint(Vector2(1.0, 1.0)), isTrue); + expect(polygon.containsLocalPoint(Vector2(1.0, 0.0)), isTrue); + expect(polygon.containsLocalPoint(Vector2(0.0, 1.0)), isTrue); + expect(polygon.containsLocalPoint(Vector2(0.0, 1.0001)), isFalse); + expect(polygon.containsLocalPoint(Vector2(-0.0001, 0.0)), isFalse); }); test('rectangle contains point in local with anchor', () { From 7c3038becba91550eb47a033cbed7208d570e012 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Sat, 17 Feb 2024 06:04:44 +0100 Subject: [PATCH 02/79] fix: BodyComponent fixtures should test with global point (#3042) The previous solution didn't take the whole transform into consideration, this one does. Closes: #3039 --- .../flame_forge2d/lib/body_component.dart | 4 +- .../test/body_component_test.dart | 86 ++++++++++++++++++- 2 files changed, 85 insertions(+), 5 deletions(-) diff --git a/packages/flame_forge2d/lib/body_component.dart b/packages/flame_forge2d/lib/body_component.dart index 37d37ea251c..ae86a2f9f73 100644 --- a/packages/flame_forge2d/lib/body_component.dart +++ b/packages/flame_forge2d/lib/body_component.dart @@ -207,9 +207,7 @@ class BodyComponent extends Component @override bool containsLocalPoint(Vector2 point) { - _hitTestPoint - ..setFrom(body.position) - ..add(point); + _transform.localToGlobal(point, output: _hitTestPoint); return body.fixtures.any((fixture) => fixture.testPoint(_hitTestPoint)); } diff --git a/packages/flame_forge2d/test/body_component_test.dart b/packages/flame_forge2d/test/body_component_test.dart index afff0a25eeb..33b73b4ef7e 100644 --- a/packages/flame_forge2d/test/body_component_test.dart +++ b/packages/flame_forge2d/test/body_component_test.dart @@ -1,5 +1,12 @@ -import 'package:flame/components.dart' show ComponentKey, PositionComponent; +// ignore_for_file: invalid_use_of_internal_member + +import 'dart:math'; + +import 'package:flame/components.dart' + show Anchor, ComponentKey, PositionComponent; +import 'package:flame/events.dart'; import 'package:flame/extensions.dart'; +import 'package:flame/src/events/flame_game_mixins/multi_tap_dispatcher.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flame_test/flame_test.dart'; import 'package:flutter/material.dart'; @@ -8,12 +15,19 @@ import 'package:mocktail/mocktail.dart'; import 'helpers/mocks.dart'; -class _TestBodyComponent extends BodyComponent { +class _TestBodyComponent extends BodyComponent with TapCallbacks { + int tapCount = 0; + @override Body createBody() => body; @override void noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); + + @override + void onTapDown(TapDownEvent _) { + tapCount++; + } } class _MockCanvas extends Mock implements Canvas {} @@ -350,6 +364,7 @@ void main() { }, ); }); + group('createBody', () { test('should throw an error if bodyDef is null', () { final bodyComponent = BodyComponent(); @@ -399,5 +414,72 @@ void main() { ); }); }); + + group('containsLocalPoint', () { + testWithGame('with rotation', Forge2DGame.new, (game) async { + game.camera.viewfinder.anchor = Anchor.topLeft; + final zoom = game.camera.viewfinder.zoom; + final position = Vector2.all(10); + final body = game.world.createBody( + BodyDef(position: position, angle: pi / 2), + ); + + body.createFixtureFromShape( + CircleShape() + ..radius = 1 + ..position.setFrom(Vector2(3, 0)), + ); + body.createFixtureFromShape( + CircleShape() + ..radius = 1 + ..position.setFrom(Vector2(-3, 0)), + ); + final component = _TestBodyComponent()..body = body; + + await game.world.ensureAdd(component); + game.update(0); + final tapDispatcher = game.firstChild()!; + + tapDispatcher.handleTapDown( + 1, + TapDownDetails( + globalPosition: position.toOffset() * zoom + Offset(0, 3 * zoom), + ), + ); + expect(component.tapCount, 1); + + tapDispatcher.handleTapDown( + 1, + TapDownDetails( + globalPosition: position.toOffset() * zoom + Offset(3 * zoom, 0), + ), + ); + expect(component.tapCount, 1); + + tapDispatcher.handleTapDown( + 1, + TapDownDetails( + globalPosition: position.toOffset() * zoom + Offset(0, -3 * zoom), + ), + ); + expect(component.tapCount, 2); + + tapDispatcher.handleTapDown( + 1, + TapDownDetails( + globalPosition: position.toOffset() * zoom + Offset(-3 * zoom, 0), + ), + ); + expect(component.tapCount, 2); + + tapDispatcher.handleTapDown( + 1, + TapDownDetails( + globalPosition: position.toOffset() * zoom, + ), + ); + expect(component.tapCount, 2); + }); + }); }); } From d40919330072b904a34bac455e2ebb73817fecf3 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Sat, 17 Feb 2024 11:15:05 +0100 Subject: [PATCH 03/79] chore(release): Publish Flame v1.16.0 et. al (#3044) ``` Package Name Current Version Updated Version Update Reason flame 1.15.0 1.16.0 manual versioning flame_audio 2.1.8 2.10.0 manual versioning flame_bloc 1.10.10 1.11.0 manual versioning flame_fire_atlas 1.4.8 1.5.0 manual versioning flame_rive 1.9.11 1.10.0 manual versioning flame_riverpod 5.2.0 5.3.0 manual versioning flame_svg 1.9.0 1.10.0 manual versioning flame_test 1.15.4 1.16.0 manual versioning flame_texturepacker 3.0.0 3.1.0 manual versioning flame_tiled 1.18.4 1.19.0 manual versioning flame_forge2d 0.16.0+5 0.17.0 updated with major changes flame_isolate 0.5.1 0.6.0 updated with major changes flame_lottie 0.3.0+8 0.4.0 updated with major changes flame_markdown 0.1.1+8 0.2.0 updated with major changes flame_network_assets 0.2.0+13 0.3.0 updated with major changes flame_noise 0.2.0 0.3.0 updated with major changes flame_oxygen 0.1.9+8 0.2.0 updated with major changes flame_spine 0.1.1+10 0.2.0 updated with major changes flame_splash_screen 0.2.0 0.3.0 updated with major changes jenny 1.2.1 1.3.0 updated with minor changes ``` --- CHANGELOG.md | 119 ++++++++++++++++++ doc/flame/examples/pubspec.yaml | 6 +- doc/tutorials/klondike/app/pubspec.yaml | 2 +- doc/tutorials/platformer/app/pubspec.yaml | 4 +- doc/tutorials/space_shooter/app/pubspec.yaml | 2 +- examples/games/padracing/pubspec.yaml | 4 +- examples/games/rogue_shooter/pubspec.yaml | 4 +- examples/games/trex/pubspec.yaml | 4 +- examples/pubspec.yaml | 20 +-- melos.yaml | 2 +- packages/flame/CHANGELOG.md | 8 ++ packages/flame/example/pubspec.yaml | 4 +- packages/flame/pubspec.yaml | 6 +- packages/flame_audio/CHANGELOG.md | 6 + packages/flame_audio/example/pubspec.yaml | 4 +- packages/flame_audio/pubspec.yaml | 6 +- packages/flame_bloc/CHANGELOG.md | 6 + packages/flame_bloc/example/pubspec.yaml | 6 +- packages/flame_bloc/pubspec.yaml | 8 +- packages/flame_fire_atlas/CHANGELOG.md | 6 + .../flame_fire_atlas/example/pubspec.yaml | 4 +- packages/flame_fire_atlas/pubspec.yaml | 6 +- packages/flame_forge2d/CHANGELOG.md | 7 ++ packages/flame_forge2d/example/pubspec.yaml | 6 +- packages/flame_forge2d/pubspec.yaml | 8 +- packages/flame_isolate/CHANGELOG.md | 6 + packages/flame_isolate/example/pubspec.yaml | 6 +- packages/flame_isolate/pubspec.yaml | 8 +- packages/flame_jenny/jenny/CHANGELOG.md | 4 + packages/flame_jenny/jenny/pubspec.yaml | 2 +- packages/flame_jenny/pubspec.yaml | 6 +- packages/flame_lottie/CHANGELOG.md | 6 + packages/flame_lottie/example/pubspec.yaml | 4 +- packages/flame_lottie/pubspec.yaml | 8 +- packages/flame_markdown/CHANGELOG.md | 6 + packages/flame_markdown/example/pubspec.yaml | 4 +- packages/flame_markdown/pubspec.yaml | 6 +- packages/flame_network_assets/CHANGELOG.md | 6 + .../flame_network_assets/example/pubspec.yaml | 4 +- packages/flame_network_assets/pubspec.yaml | 6 +- packages/flame_noise/CHANGELOG.md | 6 + packages/flame_noise/pubspec.yaml | 8 +- packages/flame_oxygen/CHANGELOG.md | 6 + packages/flame_oxygen/example/pubspec.yaml | 4 +- packages/flame_oxygen/pubspec.yaml | 6 +- packages/flame_rive/CHANGELOG.md | 6 + packages/flame_rive/example/pubspec.yaml | 4 +- packages/flame_rive/pubspec.yaml | 8 +- packages/flame_riverpod/CHANGELOG.md | 6 + packages/flame_riverpod/example/pubspec.yaml | 4 +- packages/flame_riverpod/pubspec.yaml | 6 +- packages/flame_spine/CHANGELOG.md | 6 + packages/flame_spine/example/pubspec.yaml | 4 +- packages/flame_spine/pubspec.yaml | 6 +- packages/flame_splash_screen/CHANGELOG.md | 6 + .../flame_splash_screen/example/pubspec.yaml | 4 +- packages/flame_splash_screen/pubspec.yaml | 4 +- packages/flame_studio/pubspec.yaml | 4 +- packages/flame_svg/CHANGELOG.md | 6 + packages/flame_svg/example/pubspec.yaml | 4 +- packages/flame_svg/pubspec.yaml | 6 +- packages/flame_test/CHANGELOG.md | 6 + packages/flame_test/example/pubspec.yaml | 4 +- packages/flame_test/pubspec.yaml | 6 +- packages/flame_texturepacker/CHANGELOG.md | 6 + .../flame_texturepacker/example/pubspec.yaml | 6 +- packages/flame_texturepacker/pubspec.yaml | 6 +- packages/flame_tiled/CHANGELOG.md | 7 ++ packages/flame_tiled/example/pubspec.yaml | 4 +- packages/flame_tiled/pubspec.yaml | 6 +- 70 files changed, 373 insertions(+), 132 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 906058d5625..1e0b8e728cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,125 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2024-02-17 + +### Changes + +--- + +Packages with breaking changes: + + - [`flame` - `v1.16.0`](#flame---v1160) + - [`flame_audio` - `v2.10.0`](#flame_audio---v2100) + - [`flame_bloc` - `v1.11.0`](#flame_bloc---v1110) + - [`flame_fire_atlas` - `v1.5.0`](#flame_fire_atlas---v150) + - [`flame_rive` - `v1.10.0`](#flame_rive---v1100) + - [`flame_riverpod` - `v5.3.0`](#flame_riverpod---v530) + - [`flame_svg` - `v1.10.0`](#flame_svg---v1100) + - [`flame_test` - `v1.16.0`](#flame_test---v1160) + - [`flame_texturepacker` - `v3.1.0`](#flame_texturepacker---v310) + - [`flame_tiled` - `v1.19.0`](#flame_tiled---v1190) + - [`flame_forge2d` - `v0.17.0`](#flame_forge2d---v0170) + - [`flame_isolate` - `v0.6.0`](#flame_isolate---v060) + - [`flame_lottie` - `v0.4.0`](#flame_lottie---v040) + - [`flame_markdown` - `v0.2.0`](#flame_markdown---v020) + - [`flame_network_assets` - `v0.3.0`](#flame_network_assets---v030) + - [`flame_noise` - `v0.3.0`](#flame_noise---v030) + - [`flame_oxygen` - `v0.2.0`](#flame_oxygen---v020) + - [`flame_spine` - `v0.2.0`](#flame_spine---v020) + - [`flame_splash_screen` - `v0.3.0`](#flame_splash_screen---v030) + +Packages with other changes: + + - [`jenny` - `v1.3.0`](#jenny---v130) + +--- + +#### `flame` - `v1.16.0` + + - **REFACTOR**: Fix unrelated types reported by DCM ([#3023](https://github.com/flame-engine/flame/issues/3023)). ([1d020a52](https://github.com/flame-engine/flame/commit/1d020a525b81df1cb45345d3e36a9c4e9caf701e)) + - **FIX**: Vertices in `PolygonComponent` should subtract vertices positioning ([#3040](https://github.com/flame-engine/flame/issues/3040)). ([4f053ed7](https://github.com/flame-engine/flame/commit/4f053ed74c09d4e19a53694130b5d5c0d3e23aa6)) + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + +#### `flame_audio` - `v2.10.0` + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + +#### `flame_bloc` - `v1.11.0` + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + +#### `flame_fire_atlas` - `v1.5.0` + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + +#### `flame_rive` - `v1.10.0` + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + +#### `flame_riverpod` - `v5.3.0` + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + +#### `flame_svg` - `v1.10.0` + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + +#### `flame_test` - `v1.16.0` + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + +#### `flame_texturepacker` - `v3.1.0` + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + +#### `flame_tiled` - `v1.19.0` + + - **FEAT**: Add TiledObjectHealpers extension on TiledObject ([#3032](https://github.com/flame-engine/flame/issues/3032)). ([78380b9d](https://github.com/flame-engine/flame/commit/78380b9d3bb895e20f382c4a1227bcc11e5038b9)) + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + +#### `flame_forge2d` - `v0.17.0` + + - **FIX**: BodyComponent fixtures should test with global point ([#3042](https://github.com/flame-engine/flame/issues/3042)). ([7c3038be](https://github.com/flame-engine/flame/commit/7c3038becba91550eb47a033cbed7208d570e012)) + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + +#### `flame_isolate` - `v0.6.0` + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + +#### `flame_lottie` - `v0.4.0` + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + +#### `flame_markdown` - `v0.2.0` + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + +#### `flame_network_assets` - `v0.3.0` + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + +#### `flame_noise` - `v0.3.0` + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + +#### `flame_oxygen` - `v0.2.0` + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + +#### `flame_spine` - `v0.2.0` + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + +#### `flame_splash_screen` - `v0.3.0` + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + +#### `jenny` - `v1.3.0` + + - **FEAT**: Add new methods to CommandStorage to support more arguments ([#3035](https://github.com/flame-engine/flame/issues/3035)). ([21922620](https://github.com/flame-engine/flame/commit/219226201a8d0c6e301c388299277be95b585c0e)) + + ## 2024-02-11 ### Changes diff --git a/doc/flame/examples/pubspec.yaml b/doc/flame/examples/pubspec.yaml index 1f1eddc8707..2e87303d7a8 100644 --- a/doc/flame/examples/pubspec.yaml +++ b/doc/flame/examples/pubspec.yaml @@ -5,11 +5,11 @@ publish_to: none environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: - flame: ^1.15.0 - flame_rive: ^1.9.11 + flame: ^1.16.0 + flame_rive: ^1.10.0 flutter: sdk: flutter diff --git a/doc/tutorials/klondike/app/pubspec.yaml b/doc/tutorials/klondike/app/pubspec.yaml index a6c6171cfe9..988f00767bd 100644 --- a/doc/tutorials/klondike/app/pubspec.yaml +++ b/doc/tutorials/klondike/app/pubspec.yaml @@ -7,7 +7,7 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter diff --git a/doc/tutorials/platformer/app/pubspec.yaml b/doc/tutorials/platformer/app/pubspec.yaml index 209bf07b4a4..8040a36814a 100644 --- a/doc/tutorials/platformer/app/pubspec.yaml +++ b/doc/tutorials/platformer/app/pubspec.yaml @@ -5,10 +5,10 @@ version: 1.0.0+1 environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter diff --git a/doc/tutorials/space_shooter/app/pubspec.yaml b/doc/tutorials/space_shooter/app/pubspec.yaml index 611e3c55e47..7b678045a16 100644 --- a/doc/tutorials/space_shooter/app/pubspec.yaml +++ b/doc/tutorials/space_shooter/app/pubspec.yaml @@ -9,7 +9,7 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter diff --git a/examples/games/padracing/pubspec.yaml b/examples/games/padracing/pubspec.yaml index 84f26e1a50b..71a926e882d 100644 --- a/examples/games/padracing/pubspec.yaml +++ b/examples/games/padracing/pubspec.yaml @@ -8,8 +8,8 @@ environment: dependencies: collection: ^1.17.1 - flame: ^1.15.0 - flame_forge2d: ^0.16.0+5 + flame: ^1.16.0 + flame_forge2d: ^0.17.0 flutter: sdk: flutter google_fonts: ^4.0.4 diff --git a/examples/games/rogue_shooter/pubspec.yaml b/examples/games/rogue_shooter/pubspec.yaml index 509c3d44429..d8224be125a 100644 --- a/examples/games/rogue_shooter/pubspec.yaml +++ b/examples/games/rogue_shooter/pubspec.yaml @@ -7,10 +7,10 @@ version: 0.1.0 environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter diff --git a/examples/games/trex/pubspec.yaml b/examples/games/trex/pubspec.yaml index 88e4cf751c2..ce17c4e5fd1 100644 --- a/examples/games/trex/pubspec.yaml +++ b/examples/games/trex/pubspec.yaml @@ -7,11 +7,11 @@ version: 0.1.0 environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: collection: ^1.16.0 - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter diff --git a/examples/pubspec.yaml b/examples/pubspec.yaml index 90d8237e83d..abd00ba1663 100644 --- a/examples/pubspec.yaml +++ b/examples/pubspec.yaml @@ -7,19 +7,19 @@ version: 0.1.0 environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: dashbook: ^0.1.12 - flame: ^1.15.0 - flame_audio: ^2.1.8 - flame_forge2d: ^0.16.0+5 - flame_isolate: ^0.5.1 - flame_lottie: ^0.3.0+8 - flame_noise: ^0.2.0 - flame_spine: ^0.1.1+10 - flame_svg: ^1.9.0 - flame_tiled: ^1.18.4 + flame: ^1.16.0 + flame_audio: ^2.10.0 + flame_forge2d: ^0.17.0 + flame_isolate: ^0.6.0 + flame_lottie: ^0.4.0 + flame_noise: ^0.3.0 + flame_spine: ^0.2.0 + flame_svg: ^1.10.0 + flame_tiled: ^1.19.0 flutter: sdk: flutter google_fonts: ^4.0.4 diff --git a/melos.yaml b/melos.yaml index 2d5ecde702d..19ba0616396 100644 --- a/melos.yaml +++ b/melos.yaml @@ -16,7 +16,7 @@ command: bootstrap: environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: meta: ^1.9.1 vector_math: ^2.1.4 diff --git a/packages/flame/CHANGELOG.md b/packages/flame/CHANGELOG.md index b38f6bc2121..33a2472df8e 100644 --- a/packages/flame/CHANGELOG.md +++ b/packages/flame/CHANGELOG.md @@ -1,3 +1,11 @@ +## 1.16.0 + +> Note: This release has breaking changes. + + - **REFACTOR**: Fix unrelated types reported by DCM ([#3023](https://github.com/flame-engine/flame/issues/3023)). ([1d020a52](https://github.com/flame-engine/flame/commit/1d020a525b81df1cb45345d3e36a9c4e9caf701e)) + - **FIX**: Vertices in `PolygonComponent` should subtract vertices positioning ([#3040](https://github.com/flame-engine/flame/issues/3040)). ([4f053ed7](https://github.com/flame-engine/flame/commit/4f053ed74c09d4e19a53694130b5d5c0d3e23aa6)) + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + ## 1.15.0 - **REFACTOR**: Minimize `Vector2` creation in `IsometricTileMapComponent` ([#3018](https://github.com/flame-engine/flame/issues/3018)). ([5d3be313](https://github.com/flame-engine/flame/commit/5d3be3137a177c8900158fce10cffc01f729ed7a)) diff --git a/packages/flame/example/pubspec.yaml b/packages/flame/example/pubspec.yaml index 1ee19d9893b..0381ea19e72 100644 --- a/packages/flame/example/pubspec.yaml +++ b/packages/flame/example/pubspec.yaml @@ -5,10 +5,10 @@ publish_to: 'none' environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter diff --git a/packages/flame/pubspec.yaml b/packages/flame/pubspec.yaml index d9196bbcfb7..8b2c3a56ade 100644 --- a/packages/flame/pubspec.yaml +++ b/packages/flame/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: 1.15.0 +version: 1.16.0 homepage: https://github.com/flame-engine/flame funding: - https://opencollective.com/blue-fire @@ -9,7 +9,7 @@ funding: environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: collection: ^1.17.1 @@ -23,7 +23,7 @@ dev_dependencies: canvas_test: ^0.2.0 dartdoc: ^6.3.0 flame_lint: ^1.1.2 - flame_test: ^1.15.4 + flame_test: ^1.16.0 flutter_test: sdk: flutter mocktail: ^1.0.1 diff --git a/packages/flame_audio/CHANGELOG.md b/packages/flame_audio/CHANGELOG.md index af13df66066..ec48b276d0d 100644 --- a/packages/flame_audio/CHANGELOG.md +++ b/packages/flame_audio/CHANGELOG.md @@ -1,3 +1,9 @@ +## 2.10.0 + +> Note: This release has breaking changes. + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + ## 2.1.8 - Update a dependency to the latest release. diff --git a/packages/flame_audio/example/pubspec.yaml b/packages/flame_audio/example/pubspec.yaml index a6ac3b95a8f..8bdfdc7e54e 100644 --- a/packages/flame_audio/example/pubspec.yaml +++ b/packages/flame_audio/example/pubspec.yaml @@ -9,8 +9,8 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.15.0 - flame_audio: ^2.1.8 + flame: ^1.16.0 + flame_audio: ^2.10.0 flutter: sdk: flutter diff --git a/packages/flame_audio/pubspec.yaml b/packages/flame_audio/pubspec.yaml index c9c500bac32..0c9deb191a1 100644 --- a/packages/flame_audio/pubspec.yaml +++ b/packages/flame_audio/pubspec.yaml @@ -1,7 +1,7 @@ name: flame_audio description: | Audio support for the Flame game engine, basically a thin wrapper around the audioplayers package. -version: 2.1.8 +version: 2.10.0 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_audio funding: - https://opencollective.com/blue-fire @@ -10,11 +10,11 @@ funding: environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: audioplayers: ^5.0.0 - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter synchronized: ^3.1.0 diff --git a/packages/flame_bloc/CHANGELOG.md b/packages/flame_bloc/CHANGELOG.md index fcdde1e9d84..8088f6e2735 100644 --- a/packages/flame_bloc/CHANGELOG.md +++ b/packages/flame_bloc/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.11.0 + +> Note: This release has breaking changes. + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + ## 1.10.10 - Update a dependency to the latest release. diff --git a/packages/flame_bloc/example/pubspec.yaml b/packages/flame_bloc/example/pubspec.yaml index 795fc391e7c..3085ad3b533 100644 --- a/packages/flame_bloc/example/pubspec.yaml +++ b/packages/flame_bloc/example/pubspec.yaml @@ -7,12 +7,12 @@ version: 1.0.0+1 environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: equatable: ^2.0.5 - flame: ^1.15.0 - flame_bloc: ^1.10.10 + flame: ^1.16.0 + flame_bloc: ^1.11.0 flutter: sdk: flutter flutter_bloc: ^8.1.2 diff --git a/packages/flame_bloc/pubspec.yaml b/packages/flame_bloc/pubspec.yaml index 611df32c43b..9af93423d8f 100644 --- a/packages/flame_bloc/pubspec.yaml +++ b/packages/flame_bloc/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_bloc description: Integration for the Bloc state management library to Flame games. -version: 1.10.10 +version: 1.11.0 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_bloc funding: - https://opencollective.com/blue-fire @@ -9,11 +9,11 @@ funding: environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: bloc: ^8.1.1 - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter flutter_bloc: ^8.1.2 @@ -22,7 +22,7 @@ dependencies: dev_dependencies: dartdoc: ^6.3.0 flame_lint: ^1.1.2 - flame_test: ^1.15.4 + flame_test: ^1.16.0 flutter_lints: ^2.0.1 flutter_test: sdk: flutter diff --git a/packages/flame_fire_atlas/CHANGELOG.md b/packages/flame_fire_atlas/CHANGELOG.md index 642348bfa5f..ce92374c389 100644 --- a/packages/flame_fire_atlas/CHANGELOG.md +++ b/packages/flame_fire_atlas/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.5.0 + +> Note: This release has breaking changes. + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + ## 1.4.8 - Update a dependency to the latest release. diff --git a/packages/flame_fire_atlas/example/pubspec.yaml b/packages/flame_fire_atlas/example/pubspec.yaml index 05c93bde9d2..60b1dc1b23a 100644 --- a/packages/flame_fire_atlas/example/pubspec.yaml +++ b/packages/flame_fire_atlas/example/pubspec.yaml @@ -9,8 +9,8 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.15.0 - flame_fire_atlas: ^1.4.8 + flame: ^1.16.0 + flame_fire_atlas: ^1.5.0 flutter: sdk: flutter diff --git a/packages/flame_fire_atlas/pubspec.yaml b/packages/flame_fire_atlas/pubspec.yaml index bb27416751c..531de83ea10 100644 --- a/packages/flame_fire_atlas/pubspec.yaml +++ b/packages/flame_fire_atlas/pubspec.yaml @@ -1,7 +1,7 @@ name: flame_fire_atlas description: Easy to use texture atlases for the flame engine created with the fire atlas editor -version: 1.4.8 +version: 1.5.0 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_fire_atlas funding: - https://opencollective.com/blue-fire @@ -10,11 +10,11 @@ funding: environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: archive: ^3.3.9 - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter diff --git a/packages/flame_forge2d/CHANGELOG.md b/packages/flame_forge2d/CHANGELOG.md index afdf50ebd81..21d0415fb2e 100644 --- a/packages/flame_forge2d/CHANGELOG.md +++ b/packages/flame_forge2d/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.17.0 + +> Note: This release has breaking changes. + + - **FIX**: BodyComponent fixtures should test with global point ([#3042](https://github.com/flame-engine/flame/issues/3042)). ([7c3038be](https://github.com/flame-engine/flame/commit/7c3038becba91550eb47a033cbed7208d570e012)) + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + ## 0.16.0+5 - Update a dependency to the latest release. diff --git a/packages/flame_forge2d/example/pubspec.yaml b/packages/flame_forge2d/example/pubspec.yaml index 8d6d6e2f12a..e76a0eb0628 100644 --- a/packages/flame_forge2d/example/pubspec.yaml +++ b/packages/flame_forge2d/example/pubspec.yaml @@ -7,12 +7,12 @@ version: 1.0.0+1 environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: dashbook: ^0.1.12 - flame: ^1.15.0 - flame_forge2d: ^0.16.0+5 + flame: ^1.16.0 + flame_forge2d: ^0.17.0 flutter: sdk: flutter diff --git a/packages/flame_forge2d/pubspec.yaml b/packages/flame_forge2d/pubspec.yaml index 07a0942ce28..9980a3c5ddc 100644 --- a/packages/flame_forge2d/pubspec.yaml +++ b/packages/flame_forge2d/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_forge2d description: Forge2D (Box2D) support for the Flame game engine. This uses the forge2d package and provides wrappers and components to be used inside Flame. -version: 0.16.0+5 +version: 0.17.0 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_forge2d funding: - https://opencollective.com/blue-fire @@ -9,10 +9,10 @@ funding: environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter forge2d: ">=0.12.2 <0.13.0" @@ -20,7 +20,7 @@ dependencies: dev_dependencies: dartdoc: ^6.3.0 flame_lint: ^1.1.2 - flame_test: ^1.15.4 + flame_test: ^1.16.0 flutter_test: sdk: flutter mocktail: ^1.0.1 diff --git a/packages/flame_isolate/CHANGELOG.md b/packages/flame_isolate/CHANGELOG.md index c5204dd48f6..262c1317599 100644 --- a/packages/flame_isolate/CHANGELOG.md +++ b/packages/flame_isolate/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.6.0 + +> Note: This release has breaking changes. + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + ## 0.5.1 - **FEAT**: Bumped integral_isolates package for flame_isolate ([#2994](https://github.com/flame-engine/flame/issues/2994)). ([3c38ee60](https://github.com/flame-engine/flame/commit/3c38ee6058e7c8b7546c3fcdb1b08e3e40ba138b)) diff --git a/packages/flame_isolate/example/pubspec.yaml b/packages/flame_isolate/example/pubspec.yaml index be686130656..9ef5d97785d 100755 --- a/packages/flame_isolate/example/pubspec.yaml +++ b/packages/flame_isolate/example/pubspec.yaml @@ -7,12 +7,12 @@ version: 1.0.0+1 environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: collection: ^1.18.0 - flame: ^1.15.0 - flame_isolate: ^0.5.1 + flame: ^1.16.0 + flame_isolate: ^0.6.0 flutter: sdk: flutter quiver: ^3.2.1 diff --git a/packages/flame_isolate/pubspec.yaml b/packages/flame_isolate/pubspec.yaml index 8ea6c963898..cd531579cbc 100644 --- a/packages/flame_isolate/pubspec.yaml +++ b/packages/flame_isolate/pubspec.yaml @@ -1,21 +1,21 @@ name: flame_isolate description: Flame wrapper for integral_isolates making multi-threading easy in Flame -version: 0.5.1 +version: 0.6.0 repository: https://github.com/flame-engine/flame/blob/main/packages/flame_isolate environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter integral_isolates: ^0.5.1 dev_dependencies: flame_lint: ^1.1.2 - flame_test: ^1.15.4 + flame_test: ^1.16.0 flutter_test: sdk: flutter test: any diff --git a/packages/flame_jenny/jenny/CHANGELOG.md b/packages/flame_jenny/jenny/CHANGELOG.md index 02347a5e247..e511630254e 100644 --- a/packages/flame_jenny/jenny/CHANGELOG.md +++ b/packages/flame_jenny/jenny/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.0 + + - **FEAT**: Add new methods to CommandStorage to support more arguments ([#3035](https://github.com/flame-engine/flame/issues/3035)). ([21922620](https://github.com/flame-engine/flame/commit/219226201a8d0c6e301c388299277be95b585c0e)) + ## 1.2.1 - **FIX**: Minor issues due Flutter 3.16 ([#2856](https://github.com/flame-engine/flame/issues/2856)). ([d51cd584](https://github.com/flame-engine/flame/commit/d51cd584c71a27c242c2f4600282cf8359daaa17)) diff --git a/packages/flame_jenny/jenny/pubspec.yaml b/packages/flame_jenny/jenny/pubspec.yaml index 32718cb8ba9..292163e7528 100644 --- a/packages/flame_jenny/jenny/pubspec.yaml +++ b/packages/flame_jenny/jenny/pubspec.yaml @@ -1,6 +1,6 @@ name: jenny description: YarnSpinner equivalent for Dart. -version: 1.2.1 +version: 1.3.0 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_jenny/jenny funding: - https://opencollective.com/blue-fire diff --git a/packages/flame_jenny/pubspec.yaml b/packages/flame_jenny/pubspec.yaml index 41ed0c02249..0ba9fd71b4b 100644 --- a/packages/flame_jenny/pubspec.yaml +++ b/packages/flame_jenny/pubspec.yaml @@ -10,14 +10,14 @@ funding: environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: collection: ^1.17.1 - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter - jenny: ^1.2.1 + jenny: ^1.3.0 meta: ^1.9.1 dev_dependencies: diff --git a/packages/flame_lottie/CHANGELOG.md b/packages/flame_lottie/CHANGELOG.md index 462b87d3024..6ef21948a7a 100644 --- a/packages/flame_lottie/CHANGELOG.md +++ b/packages/flame_lottie/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.4.0 + +> Note: This release has breaking changes. + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + ## 0.3.0+8 - Update a dependency to the latest release. diff --git a/packages/flame_lottie/example/pubspec.yaml b/packages/flame_lottie/example/pubspec.yaml index 68e5699c2e4..6d47fe315d4 100644 --- a/packages/flame_lottie/example/pubspec.yaml +++ b/packages/flame_lottie/example/pubspec.yaml @@ -8,8 +8,8 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.15.0 - flame_lottie: ^0.3.0+8 + flame: ^1.16.0 + flame_lottie: ^0.4.0 flutter: sdk: flutter lottie: diff --git a/packages/flame_lottie/pubspec.yaml b/packages/flame_lottie/pubspec.yaml index d99d4b230fd..932941ebdfd 100644 --- a/packages/flame_lottie/pubspec.yaml +++ b/packages/flame_lottie/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_lottie description: Flame wrapper for Lottie by AirBnB. This package implements a bridge between Lottie and Flame, allowing to load and display Lottie animations. -version: 0.3.0+8 +version: 0.4.0 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_lottie funding: - https://opencollective.com/blue-fire @@ -9,17 +9,17 @@ funding: environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter lottie: ^2.3.2 dev_dependencies: flame_lint: ^1.1.2 - flame_test: ^1.15.4 + flame_test: ^1.16.0 flutter_test: sdk: flutter lint: ^2.1.2 diff --git a/packages/flame_markdown/CHANGELOG.md b/packages/flame_markdown/CHANGELOG.md index 7fbb045faf6..70f81bc17a2 100644 --- a/packages/flame_markdown/CHANGELOG.md +++ b/packages/flame_markdown/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.2.0 + +> Note: This release has breaking changes. + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + ## 0.1.1+8 - Update a dependency to the latest release. diff --git a/packages/flame_markdown/example/pubspec.yaml b/packages/flame_markdown/example/pubspec.yaml index 0b800f29efa..69b7f04d1a4 100644 --- a/packages/flame_markdown/example/pubspec.yaml +++ b/packages/flame_markdown/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.15.0 - flame_markdown: ^0.1.1+8 + flame: ^1.16.0 + flame_markdown: ^0.2.0 flutter: sdk: flutter diff --git a/packages/flame_markdown/pubspec.yaml b/packages/flame_markdown/pubspec.yaml index 1ea8fda7adf..244e0222c78 100644 --- a/packages/flame_markdown/pubspec.yaml +++ b/packages/flame_markdown/pubspec.yaml @@ -1,7 +1,7 @@ name: flame_markdown description: | Markdown support for the Flame game engine, bridging the markdown package into Flame's text rendering pipeline. -version: 0.1.1+8 +version: 0.2.0 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_markdown funding: - https://opencollective.com/blue-fire @@ -10,10 +10,10 @@ funding: environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter markdown: ^7.1.1 diff --git a/packages/flame_network_assets/CHANGELOG.md b/packages/flame_network_assets/CHANGELOG.md index cbf6734a7fa..a4896e9a5d6 100644 --- a/packages/flame_network_assets/CHANGELOG.md +++ b/packages/flame_network_assets/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.3.0 + +> Note: This release has breaking changes. + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + ## 0.2.0+13 - Update a dependency to the latest release. diff --git a/packages/flame_network_assets/example/pubspec.yaml b/packages/flame_network_assets/example/pubspec.yaml index 7ff28abc059..c15202c0765 100644 --- a/packages/flame_network_assets/example/pubspec.yaml +++ b/packages/flame_network_assets/example/pubspec.yaml @@ -8,8 +8,8 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.15.0 - flame_network_assets: ^0.2.0+13 + flame: ^1.16.0 + flame_network_assets: ^0.3.0 flutter: sdk: flutter diff --git a/packages/flame_network_assets/pubspec.yaml b/packages/flame_network_assets/pubspec.yaml index 2cf2b548515..4fc4d34192d 100644 --- a/packages/flame_network_assets/pubspec.yaml +++ b/packages/flame_network_assets/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_network_assets description: Network assets support for Flame. -version: 0.2.0+13 +version: 0.3.0 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_network_assets funding: - https://opencollective.com/blue-fire @@ -9,11 +9,11 @@ funding: environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: dev: ^1.0.0 - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter http: ^0.13.6 diff --git a/packages/flame_noise/CHANGELOG.md b/packages/flame_noise/CHANGELOG.md index 58afda1ff46..52e6eba141b 100644 --- a/packages/flame_noise/CHANGELOG.md +++ b/packages/flame_noise/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.3.0 + +> Note: This release has breaking changes. + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + ## 0.2.0 > Note: This release has breaking changes. diff --git a/packages/flame_noise/pubspec.yaml b/packages/flame_noise/pubspec.yaml index 5ac87e8c458..d2d798bca68 100644 --- a/packages/flame_noise/pubspec.yaml +++ b/packages/flame_noise/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_noise description: Integrate the fast_noise package into Flame -version: 0.2.0 +version: 0.3.0 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_noise funding: - https://opencollective.com/blue-fire @@ -9,16 +9,16 @@ funding: environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: fast_noise: ^2.0.0 - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter dev_dependencies: dartdoc: ^6.3.0 flame_lint: ^1.1.2 - flame_test: ^1.15.4 + flame_test: ^1.16.0 test: any \ No newline at end of file diff --git a/packages/flame_oxygen/CHANGELOG.md b/packages/flame_oxygen/CHANGELOG.md index c656f62a51d..c153f8c528b 100644 --- a/packages/flame_oxygen/CHANGELOG.md +++ b/packages/flame_oxygen/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.2.0 + +> Note: This release has breaking changes. + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + ## 0.1.9+8 - Update a dependency to the latest release. diff --git a/packages/flame_oxygen/example/pubspec.yaml b/packages/flame_oxygen/example/pubspec.yaml index 5699ad341cd..28dfd91e20e 100644 --- a/packages/flame_oxygen/example/pubspec.yaml +++ b/packages/flame_oxygen/example/pubspec.yaml @@ -9,8 +9,8 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.15.0 - flame_oxygen: ^0.1.9+8 + flame: ^1.16.0 + flame_oxygen: ^0.2.0 flutter: sdk: flutter diff --git a/packages/flame_oxygen/pubspec.yaml b/packages/flame_oxygen/pubspec.yaml index bd420fe4e36..2664ee352a2 100644 --- a/packages/flame_oxygen/pubspec.yaml +++ b/packages/flame_oxygen/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_oxygen description: Integrate the Oxygen ECS with the Flame Engine. -version: 0.1.9+8 +version: 0.2.0 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_oxygen funding: - https://opencollective.com/blue-fire @@ -9,10 +9,10 @@ funding: environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter oxygen: ^0.2.0 diff --git a/packages/flame_rive/CHANGELOG.md b/packages/flame_rive/CHANGELOG.md index d5749ad21ac..94b965c7d07 100644 --- a/packages/flame_rive/CHANGELOG.md +++ b/packages/flame_rive/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.10.0 + +> Note: This release has breaking changes. + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + ## 1.9.11 - Update a dependency to the latest release. diff --git a/packages/flame_rive/example/pubspec.yaml b/packages/flame_rive/example/pubspec.yaml index 7489c242878..b5be3cc310f 100644 --- a/packages/flame_rive/example/pubspec.yaml +++ b/packages/flame_rive/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.15.0 - flame_rive: ^1.9.11 + flame: ^1.16.0 + flame_rive: ^1.10.0 flutter: sdk: flutter rive: ^0.12.3 diff --git a/packages/flame_rive/pubspec.yaml b/packages/flame_rive/pubspec.yaml index 58addf2091f..e8ec5ccae95 100644 --- a/packages/flame_rive/pubspec.yaml +++ b/packages/flame_rive/pubspec.yaml @@ -1,7 +1,7 @@ name: flame_rive description: Rive support for the Flame game engine. This uses the rive package and provides wrappers and components to be used inside Flame. homepage: https://github.com/flame-engine/flame -version: 1.9.11 +version: 1.10.0 funding: - https://opencollective.com/blue-fire - https://github.com/sponsors/bluefireteam @@ -9,10 +9,10 @@ funding: environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter rive: ^0.12.3 @@ -20,6 +20,6 @@ dependencies: dev_dependencies: dartdoc: ^6.3.0 flame_lint: ^1.1.2 - flame_test: ^1.15.4 + flame_test: ^1.16.0 flutter_test: sdk: flutter diff --git a/packages/flame_riverpod/CHANGELOG.md b/packages/flame_riverpod/CHANGELOG.md index 7ab6b2bb3b5..acda8810a3b 100644 --- a/packages/flame_riverpod/CHANGELOG.md +++ b/packages/flame_riverpod/CHANGELOG.md @@ -1,3 +1,9 @@ +## 5.3.0 + +> Note: This release has breaking changes. + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + ## 5.2.0 - **FIX**: Add Template param to RiverpodGameMixin ([#2972](https://github.com/flame-engine/flame/issues/2972)). ([622c8553](https://github.com/flame-engine/flame/commit/622c855318b6c1731891b023ddc6429ba1f32329)) diff --git a/packages/flame_riverpod/example/pubspec.yaml b/packages/flame_riverpod/example/pubspec.yaml index 7229f4198a6..eb97b7d5e2c 100644 --- a/packages/flame_riverpod/example/pubspec.yaml +++ b/packages/flame_riverpod/example/pubspec.yaml @@ -5,8 +5,8 @@ version: 1.0.0+1 environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.15.0 - flame_riverpod: ^5.2.0 + flame: ^1.16.0 + flame_riverpod: ^5.3.0 flutter: sdk: flutter flutter_riverpod: ^2.1.3 diff --git a/packages/flame_riverpod/pubspec.yaml b/packages/flame_riverpod/pubspec.yaml index d991416ee1a..06fb6e26d21 100644 --- a/packages/flame_riverpod/pubspec.yaml +++ b/packages/flame_riverpod/pubspec.yaml @@ -1,13 +1,13 @@ name: flame_riverpod description: Helpers for using Riverpod - a reactive caching and data-binding framework, in conjunction with Flame. -version: 5.2.0 +version: 5.3.0 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_riverpod environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter flutter_riverpod: ^2.1.3 diff --git a/packages/flame_spine/CHANGELOG.md b/packages/flame_spine/CHANGELOG.md index a7b527567c9..9cf9f2cd0d7 100644 --- a/packages/flame_spine/CHANGELOG.md +++ b/packages/flame_spine/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.2.0 + +> Note: This release has breaking changes. + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + ## 0.1.1+10 - Update a dependency to the latest release. diff --git a/packages/flame_spine/example/pubspec.yaml b/packages/flame_spine/example/pubspec.yaml index 5982356e118..e0f75aa6e6d 100644 --- a/packages/flame_spine/example/pubspec.yaml +++ b/packages/flame_spine/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.15.0 - flame_spine: ^0.1.1+10 + flame: ^1.16.0 + flame_spine: ^0.2.0 flutter: sdk: flutter diff --git a/packages/flame_spine/pubspec.yaml b/packages/flame_spine/pubspec.yaml index 648d1b8ffed..a8e4ee33e19 100644 --- a/packages/flame_spine/pubspec.yaml +++ b/packages/flame_spine/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_spine description: Spine support for the Flame game engine. This uses the spine_flutter package and provides wrappers and components to be used inside Flame. -version: 0.1.1+10 +version: 0.2.0 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_sprine funding: - https://opencollective.com/blue-fire @@ -9,11 +9,11 @@ funding: environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: collection: ^1.17.1 - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter spine_flutter: ^4.2.18 diff --git a/packages/flame_splash_screen/CHANGELOG.md b/packages/flame_splash_screen/CHANGELOG.md index 4236c038b14..c98e4b646f2 100644 --- a/packages/flame_splash_screen/CHANGELOG.md +++ b/packages/flame_splash_screen/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.3.0 + +> Note: This release has breaking changes. + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + ## 0.2.0 - Added linter diff --git a/packages/flame_splash_screen/example/pubspec.yaml b/packages/flame_splash_screen/example/pubspec.yaml index 9ec589a585e..0f667bcd3e3 100644 --- a/packages/flame_splash_screen/example/pubspec.yaml +++ b/packages/flame_splash_screen/example/pubspec.yaml @@ -6,10 +6,10 @@ version: 1.0.0+1 environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: - flame_splash_screen: ^0.2.0 + flame_splash_screen: ^0.3.0 flutter: sdk: flutter diff --git a/packages/flame_splash_screen/pubspec.yaml b/packages/flame_splash_screen/pubspec.yaml index 98d7285a48d..29d19d70c2b 100644 --- a/packages/flame_splash_screen/pubspec.yaml +++ b/packages/flame_splash_screen/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_splash_screen description: Style your flame game with a beautiful splash screen with logo reveal. Simple to use but still customizable. -version: 0.2.0 +version: 0.3.0 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_splash_screen funding: - https://opencollective.com/blue-fire @@ -9,7 +9,7 @@ funding: environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: flutter: diff --git a/packages/flame_studio/pubspec.yaml b/packages/flame_studio/pubspec.yaml index 9396135dbbd..72875002ab8 100644 --- a/packages/flame_studio/pubspec.yaml +++ b/packages/flame_studio/pubspec.yaml @@ -10,11 +10,11 @@ funding: environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: collection: ^1.17.1 - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter flutter_riverpod: ^2.3.6 diff --git a/packages/flame_svg/CHANGELOG.md b/packages/flame_svg/CHANGELOG.md index 08d9aed308f..d2b4029f414 100644 --- a/packages/flame_svg/CHANGELOG.md +++ b/packages/flame_svg/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.10.0 + +> Note: This release has breaking changes. + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + ## 1.9.0 - **FEAT**: Add `loadFromString` to Svg class ([#3030](https://github.com/flame-engine/flame/issues/3030)). ([b0cafb2a](https://github.com/flame-engine/flame/commit/b0cafb2a5561de136af93eb7a09df37b93d38ce0)) diff --git a/packages/flame_svg/example/pubspec.yaml b/packages/flame_svg/example/pubspec.yaml index 9e6bc334daa..d25a2647efd 100644 --- a/packages/flame_svg/example/pubspec.yaml +++ b/packages/flame_svg/example/pubspec.yaml @@ -9,8 +9,8 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.15.0 - flame_svg: ^1.9.0 + flame: ^1.16.0 + flame_svg: ^1.10.0 flutter: sdk: flutter diff --git a/packages/flame_svg/pubspec.yaml b/packages/flame_svg/pubspec.yaml index 964c7862e17..cefc820a026 100644 --- a/packages/flame_svg/pubspec.yaml +++ b/packages/flame_svg/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_svg description: Package to add SVG rendering support for the Flame game engine -version: 1.9.0 +version: 1.10.0 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_svg funding: - https://opencollective.com/blue-fire @@ -9,10 +9,10 @@ funding: environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter flutter_svg: ^2.0.5 diff --git a/packages/flame_test/CHANGELOG.md b/packages/flame_test/CHANGELOG.md index c3304d2fa9b..29c2c0466e8 100644 --- a/packages/flame_test/CHANGELOG.md +++ b/packages/flame_test/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.16.0 + +> Note: This release has breaking changes. + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + ## 1.15.4 - **FIX**: Lifecycle completers to be called for FlameGame ([#3007](https://github.com/flame-engine/flame/issues/3007)). ([3804f524](https://github.com/flame-engine/flame/commit/3804f52434cf1bcaf28b501bf96858ecd3636164)) diff --git a/packages/flame_test/example/pubspec.yaml b/packages/flame_test/example/pubspec.yaml index 3133a49b3e2..8a7be8f7653 100644 --- a/packages/flame_test/example/pubspec.yaml +++ b/packages/flame_test/example/pubspec.yaml @@ -8,13 +8,13 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter dev_dependencies: flame_lint: ^1.1.2 - flame_test: ^1.15.4 + flame_test: ^1.16.0 flutter_test: sdk: flutter test: any diff --git a/packages/flame_test/pubspec.yaml b/packages/flame_test/pubspec.yaml index 17e0cd1d6ee..8decb077df1 100644 --- a/packages/flame_test/pubspec.yaml +++ b/packages/flame_test/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_test description: A package with classes to help testing applications using Flame -version: 1.15.4 +version: 1.16.0 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_test funding: - https://opencollective.com/blue-fire @@ -9,10 +9,10 @@ funding: environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter flutter_test: diff --git a/packages/flame_texturepacker/CHANGELOG.md b/packages/flame_texturepacker/CHANGELOG.md index f77236b6f04..4c282a3f5d7 100644 --- a/packages/flame_texturepacker/CHANGELOG.md +++ b/packages/flame_texturepacker/CHANGELOG.md @@ -1,3 +1,9 @@ +## 3.1.0 + +> Note: This release has breaking changes. + + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + ## 3.0.0 > Note: This release has breaking changes. diff --git a/packages/flame_texturepacker/example/pubspec.yaml b/packages/flame_texturepacker/example/pubspec.yaml index 9db04fd15f0..34bddea64e7 100644 --- a/packages/flame_texturepacker/example/pubspec.yaml +++ b/packages/flame_texturepacker/example/pubspec.yaml @@ -5,11 +5,11 @@ publish_to: none environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: - flame: ^1.15.0 - flame_texturepacker: ^3.0.0 + flame: ^1.16.0 + flame_texturepacker: ^3.1.0 flutter: sdk: flutter diff --git a/packages/flame_texturepacker/pubspec.yaml b/packages/flame_texturepacker/pubspec.yaml index 0abb68e8563..d41ec7267a2 100644 --- a/packages/flame_texturepacker/pubspec.yaml +++ b/packages/flame_texturepacker/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_texturepacker description: A simple plugin for the Flame Engine to import spritesheets generated by the TexturePacker tool. -version: 3.0.0 +version: 3.1.0 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_texturepacker funding: - https://opencollective.com/blue-fire @@ -9,11 +9,11 @@ funding: environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: collection: ^1.17.1 - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter diff --git a/packages/flame_tiled/CHANGELOG.md b/packages/flame_tiled/CHANGELOG.md index 1717a1b72fd..6699c920c4a 100644 --- a/packages/flame_tiled/CHANGELOG.md +++ b/packages/flame_tiled/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.19.0 + +> Note: This release has breaking changes. + + - **FEAT**: Add TiledObjectHealpers extension on TiledObject ([#3032](https://github.com/flame-engine/flame/issues/3032)). ([78380b9d](https://github.com/flame-engine/flame/commit/78380b9d3bb895e20f382c4a1227bcc11e5038b9)) + - **BREAKING** **FIX**: Migrate from `RawKeyEvent` to `KeyEvent` ([#3002](https://github.com/flame-engine/flame/issues/3002)). ([330862c9](https://github.com/flame-engine/flame/commit/330862c98ecc7ed8d94e7cae0c34cd5781da0007)) + ## 1.18.4 - Update a dependency to the latest release. diff --git a/packages/flame_tiled/example/pubspec.yaml b/packages/flame_tiled/example/pubspec.yaml index 79339f50017..a71b1ff4c9d 100644 --- a/packages/flame_tiled/example/pubspec.yaml +++ b/packages/flame_tiled/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.15.0 - flame_tiled: ^1.18.4 + flame: ^1.16.0 + flame_tiled: ^1.19.0 flutter: sdk: flutter diff --git a/packages/flame_tiled/pubspec.yaml b/packages/flame_tiled/pubspec.yaml index afec1ab5555..2d790dd575d 100644 --- a/packages/flame_tiled/pubspec.yaml +++ b/packages/flame_tiled/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_tiled description: Tiled support for the Flame game engine. This uses the tiled package and provides wrappers and components to be used inside Flame. -version: 1.18.4 +version: 1.19.0 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_tiled funding: - https://opencollective.com/blue-fire @@ -9,11 +9,11 @@ funding: environment: sdk: ">=3.0.0 <4.0.0" - flutter: ^3.19.0 + flutter: ">=3.19.0" dependencies: collection: ^1.17.1 - flame: ^1.15.0 + flame: ^1.16.0 flutter: sdk: flutter meta: ^1.9.1 From 6270353af9a6ec58ee9275ddfa6a8b26276a2c20 Mon Sep 17 00:00:00 2001 From: DevKage <33748002+ufrshubham@users.noreply.github.com> Date: Sun, 18 Feb 2024 23:23:29 +0530 Subject: [PATCH 04/79] feat: Add `HasPerformanceTracker` mixin on `Game` (#3043) This PR adds a `HasPerformanceTracker` mixin on `Game`. This mixin will allow for tracking the update and render time of the game. --- doc/flame/game.md | 15 ++++++ .../lib/components/bullet_component.dart | 2 +- .../lib/components/player_component.dart | 8 +--- .../rogue_shooter/lib/rogue_shooter_game.dart | 46 +++++++++++++------ packages/flame/lib/game.dart | 1 + .../game/mixins/has_performance_tracker.dart | 34 ++++++++++++++ .../mixins/has_performance_tracker_test.dart | 46 +++++++++++++++++++ 7 files changed, 130 insertions(+), 22 deletions(-) create mode 100644 packages/flame/lib/src/game/mixins/has_performance_tracker.dart create mode 100644 packages/flame/test/game/mixins/has_performance_tracker_test.dart diff --git a/doc/flame/game.md b/doc/flame/game.md index 51db73c5687..350c7bbb346 100644 --- a/doc/flame/game.md +++ b/doc/flame/game.md @@ -244,3 +244,18 @@ class MyGame extends FlameGame { On the current Flutter stable (3.13), this flag is effectively ignored on non-mobile platforms including the web. + + +## HasPerformanceTracker mixin + +While optimizing a game, it can be useful to track the time it took for the game to update and render +each frame. This data can help in detecting areas of the code that are running hot. It can also help +in detecting visual areas of the game that are taking the most time to render. + +To get the update and render times, just add the `HasPerformanceTracker` mixin to the game class. + +```dart +class MyGame extends FlameGame with HasPerformanceTracker { + // access `updateTime` and `renderTime` getters. +} +``` diff --git a/examples/games/rogue_shooter/lib/components/bullet_component.dart b/examples/games/rogue_shooter/lib/components/bullet_component.dart index 5630c29c760..f4d714693a1 100644 --- a/examples/games/rogue_shooter/lib/components/bullet_component.dart +++ b/examples/games/rogue_shooter/lib/components/bullet_component.dart @@ -9,7 +9,7 @@ class BulletComponent extends SpriteAnimationComponent final Vector2 deltaPosition = Vector2.zero(); BulletComponent({required super.position, super.angle}) - : super(size: Vector2(10, 20)); + : super(size: Vector2(10, 20), anchor: Anchor.center); @override Future onLoad() async { diff --git a/examples/games/rogue_shooter/lib/components/player_component.dart b/examples/games/rogue_shooter/lib/components/player_component.dart index 46b79ef0ffd..0bd242a5989 100644 --- a/examples/games/rogue_shooter/lib/components/player_component.dart +++ b/examples/games/rogue_shooter/lib/components/player_component.dart @@ -8,15 +8,11 @@ class PlayerComponent extends SpriteAnimationComponent with HasGameRef, CollisionCallbacks { late TimerComponent bulletCreator; - PlayerComponent() - : super( - size: Vector2(50, 75), - position: Vector2(100, 500), - anchor: Anchor.center, - ); + PlayerComponent() : super(size: Vector2(50, 75), anchor: Anchor.center); @override Future onLoad() async { + position = game.size / 2; add(CircleHitbox()); add( bulletCreator = TimerComponent( diff --git a/examples/games/rogue_shooter/lib/rogue_shooter_game.dart b/examples/games/rogue_shooter/lib/rogue_shooter_game.dart index 3c73f4f36bd..1bd2436ea2c 100644 --- a/examples/games/rogue_shooter/lib/rogue_shooter_game.dart +++ b/examples/games/rogue_shooter/lib/rogue_shooter_game.dart @@ -6,32 +6,44 @@ import 'package:rogue_shooter/components/player_component.dart'; import 'package:rogue_shooter/components/star_background_creator.dart'; class RogueShooterGame extends FlameGame - with PanDetector, HasCollisionDetection { + with PanDetector, HasCollisionDetection, HasPerformanceTracker { static const String description = ''' A simple space shooter game used for testing performance of the collision detection system in Flame. '''; - late final PlayerComponent player; - late final TextComponent componentCounter; - late final TextComponent scoreText; + late final PlayerComponent _player; + late final TextComponent _componentCounter; + late final TextComponent _scoreText; - int score = 0; + final _updateTime = TextComponent( + text: 'Update time: 0ms', + position: Vector2(0, 0), + priority: 1, + ); + + final TextComponent _renderTime = TextComponent( + text: 'Render time: 0ms', + position: Vector2(0, 25), + priority: 1, + ); + + int _score = 0; @override Future onLoad() async { - add(player = PlayerComponent()); + add(_player = PlayerComponent()); addAll([ FpsTextComponent( position: size - Vector2(0, 50), anchor: Anchor.bottomRight, ), - scoreText = TextComponent( + _scoreText = TextComponent( position: size - Vector2(0, 25), anchor: Anchor.bottomRight, priority: 1, ), - componentCounter = TextComponent( + _componentCounter = TextComponent( position: size, anchor: Anchor.bottomRight, priority: 1, @@ -40,36 +52,40 @@ class RogueShooterGame extends FlameGame add(EnemyCreator()); add(StarBackGroundCreator()); + + addAll([_updateTime, _renderTime]); } @override void update(double dt) { super.update(dt); - scoreText.text = 'Score: $score'; - componentCounter.text = 'Components: ${children.length}'; + _scoreText.text = 'Score: $_score'; + _componentCounter.text = 'Components: ${children.length}'; + _updateTime.text = 'Update time: $updateTime ms'; + _renderTime.text = 'Render time: $renderTime ms'; } @override void onPanStart(_) { - player.beginFire(); + _player.beginFire(); } @override void onPanEnd(_) { - player.stopFire(); + _player.stopFire(); } @override void onPanCancel() { - player.stopFire(); + _player.stopFire(); } @override void onPanUpdate(DragUpdateInfo info) { - player.position += info.delta.global; + _player.position += info.delta.global; } void increaseScore() { - score++; + _score++; } } diff --git a/packages/flame/lib/game.dart b/packages/flame/lib/game.dart index 27fdf508e02..b9f26f89876 100644 --- a/packages/flame/lib/game.dart +++ b/packages/flame/lib/game.dart @@ -11,6 +11,7 @@ export 'src/extensions/vector2.dart'; export 'src/game/flame_game.dart'; export 'src/game/game.dart'; export 'src/game/game_widget/game_widget.dart'; +export 'src/game/mixins/has_performance_tracker.dart'; export 'src/game/mixins/single_game_instance.dart'; export 'src/game/notifying_vector2.dart'; export 'src/game/transform2d.dart'; diff --git a/packages/flame/lib/src/game/mixins/has_performance_tracker.dart b/packages/flame/lib/src/game/mixins/has_performance_tracker.dart new file mode 100644 index 00000000000..afc1f881e73 --- /dev/null +++ b/packages/flame/lib/src/game/mixins/has_performance_tracker.dart @@ -0,0 +1,34 @@ +import 'dart:ui'; + +import 'package:flame/game.dart'; + +/// A mixin that adds performance tracking to a game. +mixin HasPerformanceTracker on Game { + int _updateTime = 0; + int _renderTime = 0; + final _stopwatch = Stopwatch(); + + /// The time it took to update the game in milliseconds. + int get updateTime => _updateTime; + + /// The time it took to render the game in milliseconds. + int get renderTime => _renderTime; + + @override + void update(double dt) { + _stopwatch.reset(); + _stopwatch.start(); + super.update(dt); + _stopwatch.stop(); + _updateTime = _stopwatch.elapsedMilliseconds; + } + + @override + void render(Canvas canvas) { + _stopwatch.reset(); + _stopwatch.start(); + super.render(canvas); + _stopwatch.stop(); + _renderTime = _stopwatch.elapsedMilliseconds; + } +} diff --git a/packages/flame/test/game/mixins/has_performance_tracker_test.dart b/packages/flame/test/game/mixins/has_performance_tracker_test.dart new file mode 100644 index 00000000000..8c89e6fc7fa --- /dev/null +++ b/packages/flame/test/game/mixins/has_performance_tracker_test.dart @@ -0,0 +1,46 @@ +import 'dart:io'; +import 'dart:ui'; + +import 'package:flame/components.dart'; +import 'package:flame/game.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + testWidgets( + 'tracks update and render times.', + (widgetTester) async { + final game = _GameWithPerformanceTracker( + children: [_SlowComponent()], + ); + + expect(game.updateTime, 0); + expect(game.renderTime, 0); + + await widgetTester.pumpFrames( + GameWidget(game: game), + const Duration(seconds: 1), + ); + + expect( + game.updateTime, + greaterThanOrEqualTo(_SlowComponent.duration.inMilliseconds), + ); + expect( + game.renderTime, + greaterThanOrEqualTo(_SlowComponent.duration.inMilliseconds), + ); + }, + ); +} + +class _GameWithPerformanceTracker extends FlameGame with HasPerformanceTracker { + _GameWithPerformanceTracker({super.children}); +} + +class _SlowComponent extends Component { + static const duration = Duration(milliseconds: 8); + @override + void update(double dt) => sleep(duration); + @override + void render(Canvas canvas) => sleep(duration); +} From 892052b99a21a8e371c4163e1e1918fd187c6e11 Mon Sep 17 00:00:00 2001 From: Matthias Nehlsen Date: Tue, 20 Feb 2024 09:35:06 +0100 Subject: [PATCH 05/79] feat(flame_texturepacker): Expose TexturePackerAtlas (#3047) Closes #3046 --------- Co-authored-by: Lukas Klingsbo --- packages/flame_texturepacker/lib/flame_texturepacker.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/flame_texturepacker/lib/flame_texturepacker.dart b/packages/flame_texturepacker/lib/flame_texturepacker.dart index 4194342cf43..ad214bd1040 100644 --- a/packages/flame_texturepacker/lib/flame_texturepacker.dart +++ b/packages/flame_texturepacker/lib/flame_texturepacker.dart @@ -3,6 +3,7 @@ library flame_texturepacker; import 'package:flame/game.dart'; import 'package:flame_texturepacker/src/texture_packer_atlas.dart'; +export 'package:flame_texturepacker/src/texture_packer_atlas.dart'; export 'package:flame_texturepacker/src/texture_packer_sprite.dart'; extension TexturepackerLoader on Game { From 3a24a51d108b1138ac3dd735956f4276f16b2974 Mon Sep 17 00:00:00 2001 From: DevKage <33748002+ufrshubham@users.noreply.github.com> Date: Sun, 25 Feb 2024 16:32:20 +0530 Subject: [PATCH 06/79] fix: Check for removing state while adding a child (#3050) Adding a child component to a parent which is in `removing` state, caused the lifecycle processing to go into a cyclic dependency when the parent is re-added. It happens because, while processing the lifecycle events, child's add event causes itself and the parent to get added to the blocked list. As a result of this, when the parent's add event is processed next, it gets skipped due to being in the blocked list. This PR makes sure that the child does not get enqueued when parent is about to be removed. --- .../lib/src/components/core/component.dart | 2 +- .../flame/test/components/component_test.dart | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/flame/lib/src/components/core/component.dart b/packages/flame/lib/src/components/core/component.dart index 0097139dea6..d16ddf6a0b2 100644 --- a/packages/flame/lib/src/components/core/component.dart +++ b/packages/flame/lib/src/components/core/component.dart @@ -594,7 +594,7 @@ class Component { _clearRemovingBit(); } game.enqueueMove(child, this); - } else if (isMounted && !child.isMounted) { + } else if (isMounted && !isRemoving && !child.isMounted) { child._parent = this; game.enqueueAdd(child, this); } else { diff --git a/packages/flame/test/components/component_test.dart b/packages/flame/test/components/component_test.dart index 3dd96e61cbc..1eb61d6aa81 100644 --- a/packages/flame/test/components/component_test.dart +++ b/packages/flame/test/components/component_test.dart @@ -556,6 +556,27 @@ void main() { expect(wrapper.contains(child), true); }, ); + + testWithFlameGame('when parent is in removing state', (game) async { + final parent = Component(); + final child = Component(); + + await game.add(parent); + await game.ready(); + + // Remove the parent and add the child in the same tick. + parent.removeFromParent(); + await parent.add(child); + + // Timeout is added because processLifecycleEvents of ComponentTreeRoot + // gets blocked in such cases. + expect(game.ready().timeout(const Duration(seconds: 2)), completes); + + // Adding the parent again should eventually mount the child as well. + await game.add(parent); + await game.ready(); + expect(child.isMounted, true); + }); }); group('Removing components', () { From 41e9e4e38c643b07a3a7269b1cd8d3fa60cbeebb Mon Sep 17 00:00:00 2001 From: DevKage <33748002+ufrshubham@users.noreply.github.com> Date: Sun, 25 Feb 2024 16:38:14 +0530 Subject: [PATCH 07/79] feat: Export `TileAtlas` from `flame_tiled` package (#3049) `TileAtlas` has a `clearCache` method which the users might need to call from their code. This is recommended in our docs here: https://docs.flame-engine.org/latest/bridge_packages/flame_tiled/flame_tiled.html#clearing-images-cache --------- Co-authored-by: Lukas Klingsbo --- packages/flame_tiled/lib/flame_tiled.dart | 1 + .../lib/src/renderable_layers/tile_layers/tile_layer.dart | 1 - packages/flame_tiled/test/tile_atlas_test.dart | 1 - packages/flame_tiled/test/tiled_test.dart | 1 - 4 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/flame_tiled/lib/flame_tiled.dart b/packages/flame_tiled/lib/flame_tiled.dart index 78ce6d27479..42813d3421b 100644 --- a/packages/flame_tiled/lib/flame_tiled.dart +++ b/packages/flame_tiled/lib/flame_tiled.dart @@ -6,4 +6,5 @@ export 'src/extensions.dart'; export 'src/flame_tsx_provider.dart'; export 'src/renderable_tile_map.dart'; export 'src/simple_flips.dart'; +export 'src/tile_atlas.dart'; export 'src/tiled_component.dart'; diff --git a/packages/flame_tiled/lib/src/renderable_layers/tile_layers/tile_layer.dart b/packages/flame_tiled/lib/src/renderable_layers/tile_layers/tile_layer.dart index 710a2bbec98..d2a5597281f 100644 --- a/packages/flame_tiled/lib/src/renderable_layers/tile_layers/tile_layer.dart +++ b/packages/flame_tiled/lib/src/renderable_layers/tile_layers/tile_layer.dart @@ -10,7 +10,6 @@ import 'package:flame_tiled/src/renderable_layers/tile_layers/isometric_tile_lay import 'package:flame_tiled/src/renderable_layers/tile_layers/orthogonal_tile_layer.dart'; import 'package:flame_tiled/src/renderable_layers/tile_layers/staggered_tile_layer.dart'; import 'package:flame_tiled/src/tile_animation.dart'; -import 'package:flame_tiled/src/tile_atlas.dart'; import 'package:flutter/painting.dart'; import 'package:meta/meta.dart'; diff --git a/packages/flame_tiled/test/tile_atlas_test.dart b/packages/flame_tiled/test/tile_atlas_test.dart index 45058472096..fce7539f3ca 100644 --- a/packages/flame_tiled/test/tile_atlas_test.dart +++ b/packages/flame_tiled/test/tile_atlas_test.dart @@ -1,7 +1,6 @@ import 'package:flame/cache.dart'; import 'package:flame/components.dart'; import 'package:flame_tiled/flame_tiled.dart'; -import 'package:flame_tiled/src/tile_atlas.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/packages/flame_tiled/test/tiled_test.dart b/packages/flame_tiled/test/tiled_test.dart index adadda99172..28d8feb2d7c 100644 --- a/packages/flame_tiled/test/tiled_test.dart +++ b/packages/flame_tiled/test/tiled_test.dart @@ -7,7 +7,6 @@ import 'package:flame/flame.dart'; import 'package:flame/game.dart'; import 'package:flame_tiled/flame_tiled.dart'; import 'package:flame_tiled/src/renderable_layers/tile_layers/tile_layer.dart'; -import 'package:flame_tiled/src/tile_atlas.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; From e434bafb15fc486c51b43aaa9d9190b8b7e783cb Mon Sep 17 00:00:00 2001 From: Jochum van der Ploeg Date: Mon, 26 Feb 2024 15:52:33 +0100 Subject: [PATCH 08/79] feat(flame_3d): initial implementation of 3D support (#3012) Co-authored-by: Lukas Klingsbo --- packages/flame_3d/.metadata | 10 + packages/flame_3d/CHANGELOG.md | 3 + packages/flame_3d/CONTRIBUTING.md | 48 ++++ packages/flame_3d/LICENSE | 22 ++ packages/flame_3d/README.md | 139 ++++++++++++ packages/flame_3d/ROADMAP.md | 50 +++++ packages/flame_3d/analysis_options.yaml | 1 + .../shaders/standard_material.shaderbundle | Bin 0 -> 10304 bytes packages/flame_3d/bin/build_shaders.dart | 62 +++++ packages/flame_3d/example/.metadata | 45 ++++ packages/flame_3d/example/README.md | 3 + .../flame_3d/example/analysis_options.yaml | 1 + .../flame_3d/example/assets/images/crate.jpg | Bin 0 -> 37566 bytes packages/flame_3d/example/lib/crate.dart | 29 +++ .../lib/keyboard_controlled_camera.dart | 196 ++++++++++++++++ packages/flame_3d/example/lib/main.dart | 142 ++++++++++++ packages/flame_3d/example/lib/player_box.dart | 29 +++ packages/flame_3d/example/lib/simple_hud.dart | 76 +++++++ packages/flame_3d/example/pubspec.yaml | 22 ++ packages/flame_3d/lib/camera.dart | 4 + packages/flame_3d/lib/components.dart | 2 + packages/flame_3d/lib/extensions.dart | 6 + packages/flame_3d/lib/game.dart | 6 + packages/flame_3d/lib/graphics.dart | 1 + packages/flame_3d/lib/resources.dart | 12 + .../lib/src/camera/camera_component_3d.dart | 207 +++++++++++++++++ .../flame_3d/lib/src/camera/world_3d.dart | 48 ++++ .../lib/src/components/component_3d.dart | 113 ++++++++++ .../lib/src/components/mesh_component.dart | 42 ++++ .../flame_3d/lib/src/extensions/aabb3.dart | 15 ++ .../flame_3d/lib/src/extensions/color.dart | 8 + .../flame_3d/lib/src/extensions/matrix4.dart | 31 +++ .../flame_3d/lib/src/extensions/vector2.dart | 9 + .../flame_3d/lib/src/extensions/vector3.dart | 9 + .../flame_3d/lib/src/extensions/vector4.dart | 9 + .../flame_3d/lib/src/game/flame_game_3d.dart | 18 ++ .../lib/src/game/notifying_quaternion.dart | 174 +++++++++++++++ .../lib/src/game/notifying_vector3.dart | 211 ++++++++++++++++++ .../flame_3d/lib/src/game/transform_3d.dart | 147 ++++++++++++ .../lib/src/graphics/graphics_device.dart | 190 ++++++++++++++++ .../flame_3d/lib/src/resources/material.dart | 2 + .../lib/src/resources/material/material.dart | 68 ++++++ .../resources/material/standard_material.dart | 48 ++++ packages/flame_3d/lib/src/resources/mesh.dart | 6 + .../lib/src/resources/mesh/cuboid_mesh.dart | 64 ++++++ .../flame_3d/lib/src/resources/mesh/mesh.dart | 67 ++++++ .../lib/src/resources/mesh/plane_mesh.dart | 23 ++ .../lib/src/resources/mesh/sphere_mesh.dart | 53 +++++ .../lib/src/resources/mesh/surface.dart | 96 ++++++++ .../lib/src/resources/mesh/vertex.dart | 57 +++++ .../flame_3d/lib/src/resources/resource.dart | 19 ++ .../flame_3d/lib/src/resources/texture.dart | 3 + .../src/resources/texture/color_texture.dart | 20 ++ .../src/resources/texture/image_texture.dart | 17 ++ .../lib/src/resources/texture/texture.dart | 42 ++++ packages/flame_3d/pubspec.yaml | 28 +++ .../flame_3d/shaders/standard_material.frag | 16 ++ .../flame_3d/shaders/standard_material.vert | 16 ++ 58 files changed, 2785 insertions(+) create mode 100644 packages/flame_3d/.metadata create mode 100644 packages/flame_3d/CHANGELOG.md create mode 100644 packages/flame_3d/CONTRIBUTING.md create mode 100644 packages/flame_3d/LICENSE create mode 100644 packages/flame_3d/README.md create mode 100644 packages/flame_3d/ROADMAP.md create mode 100644 packages/flame_3d/analysis_options.yaml create mode 100644 packages/flame_3d/assets/shaders/standard_material.shaderbundle create mode 100644 packages/flame_3d/bin/build_shaders.dart create mode 100644 packages/flame_3d/example/.metadata create mode 100644 packages/flame_3d/example/README.md create mode 100644 packages/flame_3d/example/analysis_options.yaml create mode 100644 packages/flame_3d/example/assets/images/crate.jpg create mode 100644 packages/flame_3d/example/lib/crate.dart create mode 100644 packages/flame_3d/example/lib/keyboard_controlled_camera.dart create mode 100644 packages/flame_3d/example/lib/main.dart create mode 100644 packages/flame_3d/example/lib/player_box.dart create mode 100644 packages/flame_3d/example/lib/simple_hud.dart create mode 100644 packages/flame_3d/example/pubspec.yaml create mode 100644 packages/flame_3d/lib/camera.dart create mode 100644 packages/flame_3d/lib/components.dart create mode 100644 packages/flame_3d/lib/extensions.dart create mode 100644 packages/flame_3d/lib/game.dart create mode 100644 packages/flame_3d/lib/graphics.dart create mode 100644 packages/flame_3d/lib/resources.dart create mode 100644 packages/flame_3d/lib/src/camera/camera_component_3d.dart create mode 100644 packages/flame_3d/lib/src/camera/world_3d.dart create mode 100644 packages/flame_3d/lib/src/components/component_3d.dart create mode 100644 packages/flame_3d/lib/src/components/mesh_component.dart create mode 100644 packages/flame_3d/lib/src/extensions/aabb3.dart create mode 100644 packages/flame_3d/lib/src/extensions/color.dart create mode 100644 packages/flame_3d/lib/src/extensions/matrix4.dart create mode 100644 packages/flame_3d/lib/src/extensions/vector2.dart create mode 100644 packages/flame_3d/lib/src/extensions/vector3.dart create mode 100644 packages/flame_3d/lib/src/extensions/vector4.dart create mode 100644 packages/flame_3d/lib/src/game/flame_game_3d.dart create mode 100644 packages/flame_3d/lib/src/game/notifying_quaternion.dart create mode 100644 packages/flame_3d/lib/src/game/notifying_vector3.dart create mode 100644 packages/flame_3d/lib/src/game/transform_3d.dart create mode 100644 packages/flame_3d/lib/src/graphics/graphics_device.dart create mode 100644 packages/flame_3d/lib/src/resources/material.dart create mode 100644 packages/flame_3d/lib/src/resources/material/material.dart create mode 100644 packages/flame_3d/lib/src/resources/material/standard_material.dart create mode 100644 packages/flame_3d/lib/src/resources/mesh.dart create mode 100644 packages/flame_3d/lib/src/resources/mesh/cuboid_mesh.dart create mode 100644 packages/flame_3d/lib/src/resources/mesh/mesh.dart create mode 100644 packages/flame_3d/lib/src/resources/mesh/plane_mesh.dart create mode 100644 packages/flame_3d/lib/src/resources/mesh/sphere_mesh.dart create mode 100644 packages/flame_3d/lib/src/resources/mesh/surface.dart create mode 100644 packages/flame_3d/lib/src/resources/mesh/vertex.dart create mode 100644 packages/flame_3d/lib/src/resources/resource.dart create mode 100644 packages/flame_3d/lib/src/resources/texture.dart create mode 100644 packages/flame_3d/lib/src/resources/texture/color_texture.dart create mode 100644 packages/flame_3d/lib/src/resources/texture/image_texture.dart create mode 100644 packages/flame_3d/lib/src/resources/texture/texture.dart create mode 100644 packages/flame_3d/pubspec.yaml create mode 100644 packages/flame_3d/shaders/standard_material.frag create mode 100644 packages/flame_3d/shaders/standard_material.vert diff --git a/packages/flame_3d/.metadata b/packages/flame_3d/.metadata new file mode 100644 index 00000000000..18428991e0b --- /dev/null +++ b/packages/flame_3d/.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: "1b197762c51e993cb77d7fafe9729ef2506e2bf7" + channel: "beta" + +project_type: package diff --git a/packages/flame_3d/CHANGELOG.md b/packages/flame_3d/CHANGELOG.md new file mode 100644 index 00000000000..6ef630e4a42 --- /dev/null +++ b/packages/flame_3d/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.1.0-dev.1 + +- Initial experimental release of `flame_3d`. diff --git a/packages/flame_3d/CONTRIBUTING.md b/packages/flame_3d/CONTRIBUTING.md new file mode 100644 index 00000000000..a16aea724ca --- /dev/null +++ b/packages/flame_3d/CONTRIBUTING.md @@ -0,0 +1,48 @@ +# Contribution Guidelines + +Read the main [Flame Contribution Guidelines](https://github.com/flame-engine/flame/blob/main/CONTRIBUTING.md) +first and then come back to this one. + +## How To Contribute + + +### Environment Setup + +First follow the steps described in the main [Flame Contribution Guidelines](https://github.com/flame-engine/flame/blob/main/CONTRIBUTING.md#environment-setup) + +After you have followed those steps you have to setup Flutter to use the specific build that this +package is built against: + +```sh +cd $(dirname $(which flutter)) && git checkout 8a5509ea6a277d48c15e5965163b08bd4ad4816a -q && echo "Engine commit: $(cat internal/engine.version)" && cd - >/dev/null +``` + +This will check out the GIT repo of your Flutter installation to the specific commit that we require +and also gets us t he the commit SHA of the Flutter Engine that you need to use in setting up the +Flutter GPU. For that you can follow the steps described in the +[Flutter Wiki](https://github.com/flutter/flutter/wiki/Flutter-GPU#try-out-flutter-gpu). + +Once you have cloned the Flutter engine you can add the `flutter_gpu` as an override dependency +to the `pubspec_overrides.yaml` file in the `flame_3d` directory and it's example: + +```yaml +dependency_overrides: + ... # Melos related overrides + flutter_gpu: + path: /lib/gpu +``` + +After all of that you should run `flutter pub get` one more time to ensure all dependencies are +set up correctly. + + +### Shader changes + +If you have added/changed/removed any of the shaders in the `shaders` directory make sure to run the +build script for shaders: + +```sh +dart bin/build_shaders.dart +``` + +This is currently a manual process until Flutter provides bundling support. \ No newline at end of file diff --git a/packages/flame_3d/LICENSE b/packages/flame_3d/LICENSE new file mode 100644 index 00000000000..f7831247594 --- /dev/null +++ b/packages/flame_3d/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2024 Blue Fire + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/packages/flame_3d/README.md b/packages/flame_3d/README.md new file mode 100644 index 00000000000..de7c155786d --- /dev/null +++ b/packages/flame_3d/README.md @@ -0,0 +1,139 @@ + +

+ + flame + +

+ +

+Adds 3D support for Flame using the Flutter GPU. +

+ +

+ + + + +

+ +--- + + + +# flame_3d + +This package provides an experimental implementation of 3D support for Flame. The main focus is to +explore the potential capabilities of 3D for Flame while providing a familiar API to existing Flame +developers. + +Supported platforms: + +| Platform | Supported | +| -------- | --------- | +| Android | ❌ | +| iOS | ❌ | +| macOS | ✅ | +| Windows | ❌ | +| Linux | ❌ | +| Web | ❌ | + +## Prologue + +**STOP**, we know you are hyped up and want to start coding some funky 3D stuff but we first have to +set your expectations and clarify some things. So turn down your music, put away the coffee and make +some tea instead because you have to do some reading first! + +This package provides 3D support for Flame but it depends on the still experimental +[Flutter GPU](https://github.com/flutter/flutter/wiki/Flutter-GPU) which in turn depends on +Impeller. The Flutter GPU is currently not shipped with Flutter so this package wont work without +following the prerequisites steps. + +Because we depend on Flutter GPU this package is also highly experimental. Our long term goal is to +eventually deprecate this package and integrate it into the core `flame` package, for more +information on this see the [Roadmap](https://github.com/flame-engine/flame/blob/main/packages/flame_3d/ROADMAP.md). + +This package does not guarantee that it will follow correct [semver](https://semver.org/) versioning +rules nor does it assure that it's APIs wont break. Be ready to constantly have to refactor your +code if you are planning on using this package in a semi-production environment, which we do not +recommend. + +Documentation and tests might be lacking for quite a while because of the potential constant changes +of the API. Where possible we will try to provide in-code documentation and code examples to help +developers but our main goal for now is to enable the usage of 3D rendering within a Flame +ecosystem. + + +## Prerequisites + +Before you can get started with using this package a few steps have to happen first. Step one is +switching to a specific commit on the Flutter tooling. Because this package is still experimental +some of the features it requires are still being worked on from the Flutter side. + +So to make sure you are using the same build that we use while developing you have to manually +checkout a specific Flutter build. Thankfully we were able to simplify that process into a +one-liner: + +```sh +cd $(dirname $(which flutter)) && && git fetch && git checkout bcdd1b2c481bca0647beff690238efaae68ca5ac -q && echo "Engine commit: $(cat internal/engine.version)" && cd - >/dev/null +``` + +This will check out the GIT repo of your Flutter installation to the specific commit that we require +and also return the commit SHA of the Flutter Engine that it was build with. We need for step two. + +Step two is setting up the Flutter GPU. You can follow the steps described in the [Flutter Wiki](https://github.com/flutter/flutter/wiki/Flutter-GPU#try-out-flutter-gpu). +The engine commit that you should use is the one we got in step one. + +Once you have cloned the Flutter engine you can add the `flutter_gpu` as an override dependency +to your `pubspec.yaml` or in a `pubspec_overrides.yaml` file: + +```yaml +dependency_overrides: + flutter_gpu: + path: /lib/gpu +``` + +Step three would be to enable impeller for the macOS platform, add the following to the +`Info.plist` in your `macos/` directory: + +```xml + + ... + FLTEnableImpeller + + +``` + +Now everything is set up you can start doing some 3D magic! You can check out the +[example](https://github.com/flame-engine/flame/tree/main/packages/flame_3d/example) to see how you +can set up a simple 3D environment using Flame. + + +## Building shaders + +You can write your own shaders and use them on Materials. Currently Flutter does not do the bundling +of shaders for us so this package provides a simple dart script. Create your fragment and vertex +shader in a `shaders` directory, make sure the file names are identical. Like so: + +- `my_custom_shader`.frag +- `my_custom_shader`.vert + +You can then run `dart pub run flame_3d:build_shaders` to bundle the shaders. They will +automatically be placed in `assets/shaders`. + +You can check out the +[default shaders](https://github.com/flame-engine/flame/tree/main/packages/flame_3d/shaders) if you +want to have some examples. + + +## Contributing + +Have you found a bug or have a suggestion of how to enhance the 3D APIs? Open an issue and we will +take a look at it as soon as possible. + +Do you want to contribute with a PR? PRs are always welcome, just make sure to create it from the +correct branch (main) and follow the [checklist](.github/pull_request_template.md) which will +appear when you open the PR. + +For bigger changes, or if in doubt, make sure to talk about your contribution to the team. Either +via an issue, GitHub discussion, or reach out to the team using the +[Discord server](https://discord.gg/pxrBmy4). \ No newline at end of file diff --git a/packages/flame_3d/ROADMAP.md b/packages/flame_3d/ROADMAP.md new file mode 100644 index 00000000000..b225bec5ad5 --- /dev/null +++ b/packages/flame_3d/ROADMAP.md @@ -0,0 +1,50 @@ +# Roadmap + +In the interest of transparency, we provide a high-level detail of the roadmap for adding 3D +support to Flame. We hope this roadmap will help others in making plans and priorities based on the +work we are doing and potentially contribute back to the project itself. + +The goal of the package can be split up into two sections, the primary goal is to provide an API for +Flame developers so they can create 3D environments without having to learn new Flame concepts. This +means the package will tie into the existing [FCS](https://docs.flame-engine.org/latest/flame/components.html#component) +and provide the tools needed, like a [`CameraComponent`](https://docs.flame-engine.org/latest/flame/camera_component.html), +`World` and similar components. + +In a perfect world this API does not depend or even know about the Flutter GPU, which brings us +to our secondary goal: to abstract the Flutter GPU into an API that is user-friendly for 3D +development. That includes simplifying things like creating render targets, setting up the color +and depth textures and configuring depth stencils. But it also includes higher level APIs like +geometric shapes, texture/material rendering and creating Meshes that can use those shapes and +materials. + +## Goals + +### Abstracting the Flutter GPU into a user-friendly API for 3D + +- [x] Abstract the GPU setup into a class that represents the graphics device + - [ ] Setup binding logic for meshes, geometry and materials. +- [ ] Provide a `Mesh` API + - [x] Provide `Surface`s that can hold geometric shapes. + - [x] Provide a `Material` API + - [x] Define a `Texture` API to be used with the `Material` API + - [x] Support images as textures + - [x] Support single color textures + - [x] Support generated textures + - [x] Provide a standard `Material` + - [ ] Support custom shaders + - [ ] Add a more dev friendly way to set uniforms + - [x] Support multiple `Material`s by defining surfaces on a mesh. + + +### Providing a familiar API for developers to use 3D with Flame + +- [x] Use the existing `CameraComponent` API for 3D rendering + - [x] Provide a custom `World` + - [x] Support existing and custom viewports + - [ ] Support existing and custom viewfinders +- [x] Create a new core component for 3D rendering (`Component3D`) + - [x] Implement a `Transform3D` for 3D transformations + - [x] Implement a notifying `Vector3` and `Quaternion` for 3D positioning and rotation + - [ ] Add support for gesture event callbacks +- [x] Create a component that can show meshes (`MeshComponent`) + - [x] Ensure materials can be set outside of construction (in the `onLoad` for instance) \ No newline at end of file diff --git a/packages/flame_3d/analysis_options.yaml b/packages/flame_3d/analysis_options.yaml new file mode 100644 index 00000000000..92aae2f2499 --- /dev/null +++ b/packages/flame_3d/analysis_options.yaml @@ -0,0 +1 @@ +include: package:flame_lint/analysis_options_with_dcm.yaml diff --git a/packages/flame_3d/assets/shaders/standard_material.shaderbundle b/packages/flame_3d/assets/shaders/standard_material.shaderbundle new file mode 100644 index 0000000000000000000000000000000000000000..37d2f9e01b7d2cf0d2cf87dfb1f1822561945461 GIT binary patch literal 10304 zcmeI2&u?8v6~}LWG)Z6F#HDVUQa6m_5}s4{@nRmR!i}+8i?mV}hFGCeYMB?mYx|1# z!@M79peo9u?6Lp}Ar>sU=z<06szP1x2Xx7T1q%?Y3PKe~P@q7{8 z9_hTf=gc{0&di)SGjr^rD2iT~yYj3ml_Sxy=&*hx{YKG2LFGaB{nnql-IBgfKM+O7 z?vJ8dV!Ct4wGI5W+ZF49cZ6RS40-x7)rSs_9*qtih>k}OL{Er`@}M*yP<>oIQD3@z z<#M6bt`th2FVcP@lAsE0C#^-UpISMoLzfxR!-5gPpm?$MsNj;mWL|VuKnXZ}(;i3m zjDSKrdIJ7@bYJv{ZHb~$Utf}bXv_utkE%}V2S@*mZ|56*2LumE3b_&KU_^YM(iih< z1dm7`c8B?XG`c^^c^vt43HW1@KduJ&jN}JA6SPT>GY1s(pHz*0`i6f{HM*d~56+xG zqkTvOaJPy2$_242>hf;}IIa-ZspqB8yy0>%!`_&yIv*0i1ARs``hQ%2&Dez; ze5@bz?|QjU=^I(-f#Ki`jQ?iaZgZ80D^t6C+Vf*mEyItmVT0oh$zs~M* z^?F=s%*Qv|on|b0kQtQBi^7dyMnDNQ>laGkKlPh#m$kr0LVKv0C)dw&jcTK5{pZWg z@=7hPw_m6)H_*j6TJ3VZQf^ijYvp#_Ov=^8WzQuF+wdQ5&(9x>qF<@w*9DC42dYPJ z#LZUHsGAED#oTDJT#1*>rOS&mUwwA5wOXzu^_9hHxxUgVuf&U`iQ-y$=^MFGjXJJd zscl%z7fmz%W+!RJ5~^2{Js(~x3nm1}F&xH&QF_4xG>$BlCHTN(_VOjvO>J=bV7E0gJ_l5MiHjZ7n{7-ld( z=1p9wE@Jp>xm~_iTrd|+zU@3n28097J zB!{I3oi7QDU`9X*b%<-wwDdLx9r=B?OKjgL{=v6bG4Svm=Yzk{Vf2z(p4OQ4T50XH;%2_uSgJe4glFG1 zp*Qs1^>Z1xvuEsX<~~zf-Gw|HntmwmeT+i%_}D@`2>GW!S6l>u$qN zpB7NKzhw*)9(eyC-Z|miZMNF~r{2By=g*+5IBH|ufa24TjZv8Tp7#Fgek_n*?8k!r zSa3eXj%{OsyEhEl^HUiHd;0GrF1Y)G@p1#&iSE9zlQ=Q;$9o?qc!w%*@}lFGPs~)T z7?!<^k;rk{#*Q~mMbVG+Sba-_zODSqdwSS%m$=Od=9<+r#2{_Ur&jF518b=;n*Yk+HiiT&4>$OiKwnL*1 ze8@mk812#chQ|2G$)L~ac6kJ$>c#PM_oIxu%IXL--uL(#I-sEg`?2+`fD-T#hgzI@ zfQPc1ybk(}^m7|#3?a7x&YVJ{J)DW59X!knc^uBgkSBtlJO;AR$-RKH20G!8)yTtgWL~&(vBVA_zg7rA-7@#=%pWU z@$6K$+R$T4A~5nwmth97%J1jggo_h|vPeMMf3 zU7ztZRXtkX)387Ajd>dLFemTAmh%GS;isK3eqVZNds0B(@Q?$;Z^i|z8TMg6IDG4K zSFiuM+np61Uz!$#f<3I?ci!*6yQY0(s6knm+Kn~q>sRBZF2FA11pT&PT7aI{)Q?fk z98*)^q0kovyOm~=j=4rFX)D{LaZ0WvI&#bh#n@k`m(L)NUx&h)I$iddis~snf!}!M zpf}L*fl&H3g{!j5BYyO%?t1f?v}jH9*46-TN%^pVIXJ2M?bp_TGZYv3C<7YfBO_YO;m7rre86NRFLvec(C z_{;9qgwNp{dHua*R`q84@W=;uzYpJ#-f02-@OK@fdbj)V&A;r;KIBv>$r886j_E8K zR*W3CXHC)D74{)^QnYPs3G}c(?{;qvXfE$aDf{wmDP>-Ms=B{7m17K9!>hfZw!d+D zJLBWuIQRnV_VvGSy>F(JU*N96-D_GvnYO>~XQ$`atokt$+3mi0_iuZ%Zwl%^oP%K> zU=KxZY)hbr{Q>cA_efFm_7hDofB&5qFxStk?&mu9BnSGD-Q}`}H&aK`rin@yjqQQE zKJ&RZc}ja|@P~y`I&v#_x8|=W+vZZ!CT6oI>kl<)?HzhPOWW&yV%>3;;dLq19&hF# z%`i^%a<9&+4YI0fbICJqdCA!z>zbC|GUs}=7gW#rvDvd$_NMZ!n`cGS{a`1M&55qN z4k&x+Wct?2zf5Qnz9kN+p7C-569eQ)9! zSs5&JS*Srf-@lW=zub>+`|+*+4-u)zvLD~{S0MNJxy$&*j^l4CAubGP_YvpjEIoS< zBL;+c=Q64Nct;*%qx+k-?xwkix79W;Kz2wkj9>%%pEn168NsgOUw3cfAMc>2Wz|OS Wppv)ie-RhSAL&pem+cN^;r|5~ViJV_ literal 0 HcmV?d00001 diff --git a/packages/flame_3d/bin/build_shaders.dart b/packages/flame_3d/bin/build_shaders.dart new file mode 100644 index 00000000000..0cefe877f75 --- /dev/null +++ b/packages/flame_3d/bin/build_shaders.dart @@ -0,0 +1,62 @@ +import 'dart:convert'; +import 'dart:io'; + +/// Bundle a shader (.frag & .vert) into a single shader bundle and +/// store it in the assets directory. +/// +/// This script is just a temporary way to bundle shaders. In the long run +/// Flutter might support auto-bundling themselves but until then we have to +/// do it manually. +/// +/// Note: this script should be run from the root of the package: +/// packages/flame_3d +void main() async { + final root = Directory.current; + + final assets = Directory.fromUri(root.uri.resolve('assets/shaders')); + // Delete all the bundled shaders so we can replace them with new ones. + if (assets.existsSync()) { + assets.deleteSync(recursive: true); + } + // Create if not exists. + assets.createSync(recursive: true); + + // Directory where our unbundled shaders are stored. + final shaders = Directory.fromUri(root.uri.resolve('shaders')); + if (!shaders.existsSync()) { + return stderr.writeln('Missing shader directory'); + } + + // Get a list of unique shader names. Each shader should have a .frag and + // .vert with the same basename to be considered a bundle. + final uniqueShaders = shaders + .listSync() + .whereType() + .map((f) => f.path.split('/').last.split('.').first) + .toSet(); + + for (final name in uniqueShaders) { + final bundle = { + 'TextureFragment': { + 'type': 'fragment', + 'file': '${root.path}/shaders/$name.frag', + }, + 'TextureVertex': { + 'type': 'vertex', + 'file': '${root.path}/shaders/$name.vert', + }, + }; + + final result = await Process.run(impellerC, [ + '--sl=${assets.path}/$name.shaderbundle', + '--shader-bundle=${jsonEncode(bundle)}', + ]); + + if (result.exitCode != 0) { + return stderr.writeln(result.stderr); + } + } +} + +final impellerC = + '${Platform.environment['FLUTTER_HOME']}/bin/cache/artifacts/engine/darwin-x64/impellerc'; diff --git a/packages/flame_3d/example/.metadata b/packages/flame_3d/example/.metadata new file mode 100644 index 00000000000..a2eed5f2b7c --- /dev/null +++ b/packages/flame_3d/example/.metadata @@ -0,0 +1,45 @@ +# 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: "1b197762c51e993cb77d7fafe9729ef2506e2bf7" + channel: "beta" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 + base_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 + - platform: android + create_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 + base_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 + - platform: ios + create_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 + base_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 + - platform: linux + create_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 + base_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 + - platform: macos + create_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 + base_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 + - platform: web + create_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 + base_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 + - platform: windows + create_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 + base_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/packages/flame_3d/example/README.md b/packages/flame_3d/example/README.md new file mode 100644 index 00000000000..e6a8c4c9085 --- /dev/null +++ b/packages/flame_3d/example/README.md @@ -0,0 +1,3 @@ +# flame_3d example + +An example for using the `flame_3d` package. \ No newline at end of file diff --git a/packages/flame_3d/example/analysis_options.yaml b/packages/flame_3d/example/analysis_options.yaml new file mode 100644 index 00000000000..92aae2f2499 --- /dev/null +++ b/packages/flame_3d/example/analysis_options.yaml @@ -0,0 +1 @@ +include: package:flame_lint/analysis_options_with_dcm.yaml diff --git a/packages/flame_3d/example/assets/images/crate.jpg b/packages/flame_3d/example/assets/images/crate.jpg new file mode 100644 index 0000000000000000000000000000000000000000..eaebeba17865fe93f90e2c4a6858b0009b49210d GIT binary patch literal 37566 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%0D;@YS4s~A`2k#!%?wYO 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 onLoad() async { + final crateTexture = await Flame.images.loadTexture('crate.jpg'); + mesh.addMaterialToSurface(0, StandardMaterial(albedoTexture: crateTexture)); + } + + double direction = 0.1; + + @override + void update(double dt) { + if (scale.x >= 1.19 || scale.x <= 0.99) { + direction *= -1; + } + scale.add(Vector3.all(direction * dt)); + } +} diff --git a/packages/flame_3d/example/lib/keyboard_controlled_camera.dart b/packages/flame_3d/example/lib/keyboard_controlled_camera.dart new file mode 100644 index 00000000000..936e8685631 --- /dev/null +++ b/packages/flame_3d/example/lib/keyboard_controlled_camera.dart @@ -0,0 +1,196 @@ +import 'package:flame/components.dart' show KeyboardHandler; +import 'package:flame_3d/camera.dart'; +import 'package:flame_3d/game.dart'; +import 'package:flutter/gestures.dart' show kMiddleMouseButton; +import 'package:flutter/services.dart' + show KeyEvent, KeyRepeatEvent, LogicalKeyboardKey, PointerEvent; + +class KeyboardControlledCamera extends CameraComponent3D with KeyboardHandler { + KeyboardControlledCamera({ + super.world, + super.viewport, + super.viewfinder, + super.backdrop, + super.hudComponents, + }) : super( + projection: CameraProjection.perspective, + mode: CameraMode.firstPerson, + position: Vector3(0, 2, 4), + target: Vector3(0, 2, 0), + up: Vector3(0, 1, 0), + fovY: 60, + ); + + final double moveSpeed = 0.9; + final double rotationSpeed = 0.3; + final double panSpeed = 2; + final double orbitalSpeed = 0.5; + + Set _keysDown = {}; + PointerEvent? pointerEvent; + double scrollMove = 0; + + final Matrix4 _orbitalMatrix = Matrix4.identity(); + + @override + bool onKeyEvent(KeyEvent event, Set keysPressed) { + _keysDown = keysPressed; + + // Switch camera mode + if (isKeyDown(Key.digit1)) { + mode = CameraMode.free; + up = Vector3(0, 1, 0); // Reset roll + } else if (isKeyDown(Key.digit2)) { + mode = CameraMode.firstPerson; + up = Vector3(0, 1, 0); // Reset roll + } else if (isKeyDown(Key.digit3)) { + mode = CameraMode.thirdPerson; + up = Vector3(0, 1, 0); // Reset roll + } else if (isKeyDown(Key.digit4)) { + mode = CameraMode.orbital; + up = Vector3(0, 1, 0); // Reset roll + } + + if (isKeyDown(Key.keyP) && event is! KeyRepeatEvent) { + if (projection == CameraProjection.perspective) { + // Create an isometric view. + mode = CameraMode.thirdPerson; + projection = CameraProjection.orthographic; + + position = Vector3(0, 2, -100); + target = Vector3(0, 2, 0); + up = Vector3(0, 1, 0); + fovY = 20; + + yaw(-135 * degrees2Radians, rotateAroundTarget: true); + pitch(-45 * degrees2Radians, lockView: true, rotateAroundTarget: true); + } else if (projection == CameraProjection.orthographic) { + // Reset to default view. + mode = CameraMode.thirdPerson; + projection = CameraProjection.perspective; + + position = Vector3(0, 2, 10); + target = Vector3(0, 2, 0); + up = Vector3(0, 1, 0); + fovY = 60; + } + } + + return false; + } + + @override + void update(double dt) { + final moveInWorldPlane = switch (mode) { + CameraMode.firstPerson || CameraMode.thirdPerson => true, + _ => false, + }; + final rotateAroundTarget = switch (mode) { + CameraMode.thirdPerson || CameraMode.orbital => true, + _ => false, + }; + final lockView = switch (mode) { + CameraMode.free || CameraMode.firstPerson || CameraMode.orbital => true, + _ => false, + }; + + if (mode == CameraMode.orbital) { + final rotation = _orbitalMatrix + ..setIdentity() + ..rotate(up, orbitalSpeed * dt); + final view = rotation.transform3(position - target); + position = target + view; + } else { + // Camera rotation + if (isKeyDown(Key.arrowDown)) { + pitch( + -rotationSpeed * dt, + lockView: lockView, + rotateAroundTarget: rotateAroundTarget, + ); + } else if (isKeyDown(Key.arrowUp)) { + pitch( + rotationSpeed * dt, + lockView: lockView, + rotateAroundTarget: rotateAroundTarget, + ); + } + if (isKeyDown(Key.arrowRight)) { + yaw(-rotationSpeed * dt, rotateAroundTarget: rotateAroundTarget); + } else if (isKeyDown(Key.arrowLeft)) { + yaw(rotationSpeed * dt, rotateAroundTarget: rotateAroundTarget); + } + if (isKeyDown(Key.keyQ)) { + roll(-rotationSpeed * dt); + } else if (isKeyDown(Key.keyE)) { + roll(rotationSpeed * dt); + } + + // Camera movement, if mode is free and mouse button is down we pan the + // camera. + if (pointerEvent != null) { + if (mode == CameraMode.free && + pointerEvent?.buttons == kMiddleMouseButton) { + final mouseDelta = pointerEvent!.delta; + if (mouseDelta.dx > 0) { + moveRight(panSpeed * dt, moveInWorldPlane: moveInWorldPlane); + } else if (mouseDelta.dx < 0) { + moveRight(-panSpeed * dt, moveInWorldPlane: moveInWorldPlane); + } + if (mouseDelta.dy > 0) { + moveUp(-panSpeed * dt); + } else if (mouseDelta.dy < 0) { + moveUp(panSpeed * dt); + } + } else { + const mouseMoveSensitivity = 0.003; + yaw( + (pointerEvent?.delta.dx ?? 0) * mouseMoveSensitivity, + rotateAroundTarget: rotateAroundTarget, + ); + pitch( + (pointerEvent?.delta.dy ?? 0) * mouseMoveSensitivity, + lockView: lockView, + rotateAroundTarget: rotateAroundTarget, + ); + } + pointerEvent = null; + } + + // Keyboard movement + if (isKeyDown(Key.keyW)) { + moveForward(moveSpeed * dt); + } else if (isKeyDown(Key.keyS)) { + moveForward(-moveSpeed * dt); + } + if (isKeyDown(Key.keyA)) { + moveRight(-moveSpeed * dt); + } else if (isKeyDown(Key.keyD)) { + moveRight(moveSpeed * dt); + } + + if (mode == CameraMode.free) { + if (isKeyDown(Key.space)) { + moveUp(moveSpeed * dt); + } else if (isKeyDown(Key.controlLeft)) { + moveUp(-moveSpeed * dt); + } + } + } + + // if (mode == CameraMode.thirdPerson || + // mode == CameraMode.orbital || + // mode == CameraMode.free) { + // moveToTarget(-scrollMove); + // if (isKeyDown(Key.numpadSubtract)) { + // moveToTarget(2 * dt); + // } else if (isKeyDown(Key.numpadAdd)) { + // moveToTarget(-2 * dt); + // } + // } + } + + bool isKeyDown(Key key) => _keysDown.contains(key); +} + +typedef Key = LogicalKeyboardKey; diff --git a/packages/flame_3d/example/lib/main.dart b/packages/flame_3d/example/lib/main.dart new file mode 100644 index 00000000000..843d71fcc1a --- /dev/null +++ b/packages/flame_3d/example/lib/main.dart @@ -0,0 +1,142 @@ +import 'dart:async'; +import 'dart:math'; +import 'dart:ui'; + +import 'package:example/crate.dart'; +import 'package:example/keyboard_controlled_camera.dart'; +import 'package:example/player_box.dart'; +import 'package:example/simple_hud.dart'; +import 'package:flame/events.dart'; +import 'package:flame/extensions.dart' as v64 show Vector2; +import 'package:flame/game.dart' show FlameGame, GameWidget; +import 'package:flame_3d/camera.dart'; +import 'package:flame_3d/components.dart'; +import 'package:flame_3d/game.dart'; +import 'package:flame_3d/resources.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart' show runApp, Color, Colors, Listener; + +class ExampleGame3D extends FlameGame + with HasKeyboardHandlerComponents { + ExampleGame3D() + : super( + world: World3D(clearColor: const Color(0xFFFFFFFF)), + camera: KeyboardControlledCamera( + viewport: FixedResolutionViewport( + resolution: v64.Vector2(800, 600), + ), + hudComponents: [SimpleHud()], + ), + ); + + @override + KeyboardControlledCamera get camera => + super.camera as KeyboardControlledCamera; + + @override + FutureOr onLoad() async { + world.addAll([ + // Add a player box + PlayerBox(), + + // Floating crate + Crate(size: Vector3.all(1), position: Vector3(0, 5, 0)), + + // Floating sphere + MeshComponent( + position: Vector3(5, 5, 5), + mesh: SphereMesh( + radius: 1, + material: StandardMaterial( + albedoTexture: ColorTexture(Colors.purple), + ), + ), + ), + + // Floor + MeshComponent( + mesh: PlaneMesh( + size: Vector2(32, 32), + material: StandardMaterial(albedoTexture: ColorTexture(Colors.grey)), + ), + ), + + // Front wall + MeshComponent( + position: Vector3(16.5, 2.5, 0), + mesh: CuboidMesh( + size: Vector3(1, 5, 32), + material: + StandardMaterial(albedoTexture: ColorTexture(Colors.yellow)), + ), + ), + + // Left wall + MeshComponent( + position: Vector3(0, 2.5, 16.5), + mesh: CuboidMesh( + size: Vector3(32, 5, 1), + material: StandardMaterial(albedoTexture: ColorTexture(Colors.blue)), + ), + ), + + // Right wall + MeshComponent( + position: Vector3(0, 2.5, -16.5), + mesh: CuboidMesh( + size: Vector3(32, 5, 1), + material: StandardMaterial(albedoTexture: ColorTexture(Colors.lime)), + ), + ), + ]); + + final rnd = Random(); + for (var i = 0; i < 20; i++) { + final height = rnd.range(1, 12); + + world.add( + MeshComponent( + position: Vector3(rnd.range(-15, 15), height / 2, rnd.range(-15, 15)), + mesh: CuboidMesh( + size: Vector3(1, height, 1), + material: StandardMaterial( + albedoTexture: ColorTexture( + Color.fromRGBO(rnd.iRange(20, 255), rnd.iRange(10, 55), 30, 1), + ), + ), + ), + ), + ); + } + } +} + +void main() { + final example = ExampleGame3D(); + + runApp( + Listener( + onPointerMove: (event) { + if (!event.down) { + return; + } + example.camera.pointerEvent = event; + }, + onPointerSignal: (event) { + if (event is! PointerScrollEvent || !event.down) { + return; + } + example.camera.scrollMove = event.delta.dy / 3000; + }, + onPointerUp: (event) => example.camera.pointerEvent = null, + onPointerCancel: (event) => example.camera.pointerEvent = null, + child: GameWidget(game: example), + ), + ); +} + +extension on Random { + double range(num min, num max) => nextDouble() * (max - min) + min; + + int iRange(int min, int max) => range(min, max).toInt(); +} diff --git a/packages/flame_3d/example/lib/player_box.dart b/packages/flame_3d/example/lib/player_box.dart new file mode 100644 index 00000000000..fc42d7f75bb --- /dev/null +++ b/packages/flame_3d/example/lib/player_box.dart @@ -0,0 +1,29 @@ +import 'dart:ui'; + +import 'package:example/main.dart'; +import 'package:flame/components.dart' show HasGameReference; +import 'package:flame_3d/camera.dart'; +import 'package:flame_3d/components.dart'; +import 'package:flame_3d/game.dart'; +import 'package:flame_3d/resources.dart'; +import 'package:flutter/material.dart' show Colors; + +class PlayerBox extends MeshComponent with HasGameReference { + PlayerBox() + : super( + mesh: CuboidMesh( + size: Vector3.all(0.5), + material: + StandardMaterial(albedoTexture: ColorTexture(Colors.purple)), + ), + ); + + @override + void renderTree(Canvas canvas) { + // Only show the box if we are in third person mode. + if (game.camera.mode == CameraMode.thirdPerson) { + position.setFrom(game.camera.target); + super.renderTree(canvas); + } + } +} diff --git a/packages/flame_3d/example/lib/simple_hud.dart b/packages/flame_3d/example/lib/simple_hud.dart new file mode 100644 index 00000000000..757a70a34a1 --- /dev/null +++ b/packages/flame_3d/example/lib/simple_hud.dart @@ -0,0 +1,76 @@ +import 'dart:ui'; + +import 'package:example/main.dart'; +import 'package:flame/components.dart'; +import 'package:flame/text.dart'; +import 'package:flame_3d/camera.dart'; + +const _width = 1.2; +const _color = Color(0xFFFFFFFF); + +final _style = TextStyle( + color: const Color(0xFF000000), + shadows: [ + for (var x = 1; x < _width + 5; x++) + for (var y = 1; y < _width + 5; y++) ...[ + Shadow(offset: Offset(-_width / x, -_width / y), color: _color), + Shadow(offset: Offset(-_width / x, _width / y), color: _color), + Shadow(offset: Offset(_width / x, -_width / y), color: _color), + Shadow(offset: Offset(_width / x, _width / y), color: _color), + ], + ], +); + +class SimpleHud extends Component with HasGameReference { + SimpleHud() : super(children: [FpsComponent()]); + + String get fps => + children.query().firstOrNull?.fps.toStringAsFixed(2) ?? '0'; + + final _textLeft = TextPaint(style: _style); + + final _textCenter = TextPaint(style: _style.copyWith(fontSize: 20)); + + final _textRight = TextPaint(style: _style, textDirection: TextDirection.rtl); + + @override + void render(Canvas canvas) { + final CameraComponent3D(:position, :target, :up) = game.camera; + + _textLeft.render( + canvas, + ''' +Camera controls: +- Move using W, A, S, D, Space, Left-Ctrl +- Look around with arrow keys or mouse +- Change camera mode with 1, 2, 3 or 4 +- Change camera projection with P +- Zoom in and out with scroll +''', + Vector2.all(8), + ); + + _textCenter.render( + canvas, + 'Welcome to the 3D world', + Vector2(game.size.x / 2, game.size.y - 8), + anchor: Anchor.bottomCenter, + ); + + _textRight.render( + canvas, + ''' +FPS: $fps +Mode: ${game.camera.mode.name} +Projection: ${game.camera.projection.name} +Culled: ${game.world.culled} + +Position: ${position.x.toStringAsFixed(2)}, ${position.y.toStringAsFixed(2)}, ${position.z.toStringAsFixed(2)} +Target: ${target.x.toStringAsFixed(2)}, ${target.y.toStringAsFixed(2)}, ${target.z.toStringAsFixed(2)} +Up: ${up.x.toStringAsFixed(2)}, ${up.y.toStringAsFixed(2)}, ${up.z.toStringAsFixed(2)} +''', + Vector2(game.size.x - 8, 8), + anchor: Anchor.topRight, + ); + } +} diff --git a/packages/flame_3d/example/pubspec.yaml b/packages/flame_3d/example/pubspec.yaml new file mode 100644 index 00000000000..497c039c6fa --- /dev/null +++ b/packages/flame_3d/example/pubspec.yaml @@ -0,0 +1,22 @@ +name: example +description: An example for flame_3d. The example shows how to set up 3D support in a flame game. +version: 0.0.1+1 +publish_to: none + +environment: + sdk: ">=3.0.0 <4.0.0" + +dependencies: + flame: ^1.16.0 + flame_3d: ^0.1.0 + flutter: + sdk: flutter + +dev_dependencies: + flame_lint: ^1.1.2 + +flutter: + uses-material-design: true + + assets: + - assets/images/ diff --git a/packages/flame_3d/lib/camera.dart b/packages/flame_3d/lib/camera.dart new file mode 100644 index 00000000000..0459754995e --- /dev/null +++ b/packages/flame_3d/lib/camera.dart @@ -0,0 +1,4 @@ +export 'package:flame/camera.dart'; + +export 'src/camera/camera_component_3d.dart'; +export 'src/camera/world_3d.dart'; diff --git a/packages/flame_3d/lib/components.dart b/packages/flame_3d/lib/components.dart new file mode 100644 index 00000000000..d3c590b1d53 --- /dev/null +++ b/packages/flame_3d/lib/components.dart @@ -0,0 +1,2 @@ +export 'src/components/component_3d.dart'; +export 'src/components/mesh_component.dart'; diff --git a/packages/flame_3d/lib/extensions.dart b/packages/flame_3d/lib/extensions.dart new file mode 100644 index 00000000000..7a262a03afb --- /dev/null +++ b/packages/flame_3d/lib/extensions.dart @@ -0,0 +1,6 @@ +export 'src/extensions/aabb3.dart'; +export 'src/extensions/color.dart'; +export 'src/extensions/matrix4.dart'; +export 'src/extensions/vector2.dart'; +export 'src/extensions/vector3.dart'; +export 'src/extensions/vector4.dart'; diff --git a/packages/flame_3d/lib/game.dart b/packages/flame_3d/lib/game.dart new file mode 100644 index 00000000000..b79118633a3 --- /dev/null +++ b/packages/flame_3d/lib/game.dart @@ -0,0 +1,6 @@ +export 'package:vector_math/vector_math.dart' hide Colors; + +export 'src/game/flame_game_3d.dart'; +export 'src/game/notifying_quaternion.dart'; +export 'src/game/notifying_vector3.dart'; +export 'src/game/transform_3d.dart'; diff --git a/packages/flame_3d/lib/graphics.dart b/packages/flame_3d/lib/graphics.dart new file mode 100644 index 00000000000..ab2eee25192 --- /dev/null +++ b/packages/flame_3d/lib/graphics.dart @@ -0,0 +1 @@ +export 'src/graphics/graphics_device.dart'; diff --git a/packages/flame_3d/lib/resources.dart b/packages/flame_3d/lib/resources.dart new file mode 100644 index 00000000000..b6ba8d86973 --- /dev/null +++ b/packages/flame_3d/lib/resources.dart @@ -0,0 +1,12 @@ +import 'package:flame/cache.dart'; +import 'package:flame_3d/resources.dart'; + +export 'src/resources/material.dart'; +export 'src/resources/mesh.dart'; +export 'src/resources/resource.dart'; +export 'src/resources/texture.dart'; + +extension TextureCache on Images { + Future loadTexture(String path) => + load('crate.jpg').then(ImageTexture.create); +} diff --git a/packages/flame_3d/lib/src/camera/camera_component_3d.dart b/packages/flame_3d/lib/src/camera/camera_component_3d.dart new file mode 100644 index 00000000000..d747e1f7644 --- /dev/null +++ b/packages/flame_3d/lib/src/camera/camera_component_3d.dart @@ -0,0 +1,207 @@ +import 'package:flame_3d/camera.dart'; +import 'package:flame_3d/extensions.dart'; +import 'package:flame_3d/game.dart'; + +enum CameraProjection { perspective, orthographic } + +enum CameraMode { custom, free, orbital, firstPerson, thirdPerson } + +/// {@template camera_component_3d} +/// [CameraComponent3D] is a component through which a [World3D] is observed. +/// {@endtemplate} +class CameraComponent3D extends CameraComponent { + /// {@macro camera_component_3d} + CameraComponent3D({ + this.fovY = 60, + Vector3? position, + Vector3? target, + Vector3? up, + this.projection = CameraProjection.perspective, + this.mode = CameraMode.free, + World3D? super.world, + super.viewport, + super.viewfinder, + super.backdrop, + super.hudComponents, + }) : position = position?.clone() ?? Vector3.zero(), + target = target?.clone() ?? Vector3.zero(), + _up = up?.clone() ?? Vector3(0, 1, 0); + + @override + World3D? get world => super.world as World3D?; + + @override + set world(covariant World3D? world) => super.world = world; + + /// The [fovY] is the field of view in Y (degrees) when the [projection] is + /// [CameraProjection.perspective] otherwise it is used as the near plane when + /// the [projection] is [CameraProjection.orthographic]. + double fovY; + + /// The position of the camera in 3D space. + /// + /// Often also referred to as the "eye". + Vector3 position; + + /// The target in 3D space that the camera is looking at. + Vector3 target; + + /// The forward direction relative to the camera. + Vector3 get forward => target - position; + + /// The right direction relative to the camera. + Vector3 get right => forward.cross(up); + + /// The up direction relative to the camera. + Vector3 get up => _up.normalized(); + set up(Vector3 up) => _up.setFrom(up); + final Vector3 _up; + + /// The current camera projection. + CameraProjection projection; + + /// The current camera mode. + CameraMode mode; + + /// The view matrix of the camera, this is without any projection applied on + /// it. + Matrix4 get viewMatrix => _viewMatrix..setAsViewMatrix(position, target, up); + final Matrix4 _viewMatrix = Matrix4.zero(); + + /// The projection matrix of the camera. + Matrix4 get projectionMatrix { + final aspectRatio = viewport.virtualSize.x / viewport.virtualSize.y; + return switch (projection) { + CameraProjection.perspective => _projectionMatrix + ..setAsPerspective(fovY, aspectRatio, distanceNear, distanceFar), + CameraProjection.orthographic => _projectionMatrix + ..setAsOrthographic(fovY, aspectRatio, distanceNear, distanceFar) + } + ..multiply(viewMatrix); + } + + final Matrix4 _projectionMatrix = Matrix4.zero(); + final Frustum _frustum = Frustum(); + + Frustum get frustum => _frustum..setFromMatrix(_projectionMatrix); + + void moveForward(double distance, {bool moveInWorldPlane = false}) { + final forward = this.forward..scale(distance); + + if (moveInWorldPlane) { + forward.y = 0; + forward.normalize(); + } + + position.add(forward); + target.add(forward); + } + + void moveUp(double distance) { + final up = this.up..scale(distance); + position.add(up); + target.add(up); + } + + void moveRight(double distance, {bool moveInWorldPlane = false}) { + final right = this.right..scale(distance); + + if (moveInWorldPlane) { + right.y = 0; + right.normalize(); + } + + position.add(right); + target.add(right); + } + + void moveToTarget(double delta) { + var distance = position.distanceTo(target); + distance += delta; + + if (distance <= 0) { + distance = 0.001; + } + + final forward = this.forward; + position.setValues( + target.x + (forward.x * -distance), + target.y + (forward.y * -distance), + target.z + (forward.z * -distance), + ); + } + + void yaw(double angle, {bool rotateAroundTarget = false}) { + final targetPosition = (target - position)..applyAxisAngle(up, angle); + + if (rotateAroundTarget) { + position.setValues( + target.x - targetPosition.x, + target.y - targetPosition.y, + target.z - targetPosition.z, + ); + } else { + target.setValues( + position.x + targetPosition.x, + position.y + targetPosition.y, + position.z + targetPosition.z, + ); + } + } + + void pitch( + double angle, { + bool lockView = false, + bool rotateAroundTarget = false, + bool rotateUp = false, + }) { + var localAngle = angle; + final up = this.up; + final targetPosition = target - position; + + if (lockView) { + final maxAngleUp = up.angleTo(targetPosition); + if (localAngle > maxAngleUp) { + localAngle = maxAngleUp; + } + + var maxAngleDown = (-up).angleTo(targetPosition); + maxAngleDown *= -1.0; + + if (localAngle < maxAngleDown) { + localAngle = maxAngleDown; + } + } + + final right = this.right; + targetPosition.applyAxisAngle(right, localAngle); + + if (rotateAroundTarget) { + position.setValues( + target.x - targetPosition.x, + target.y - targetPosition.y, + target.z - targetPosition.z, + ); + } else { + target.setValues( + position.x + targetPosition.x, + position.y + targetPosition.y, + position.z + targetPosition.z, + ); + } + + if (rotateUp) { + _up.applyAxisAngle(right, angle); + } + } + + void roll(double angle) { + _up.applyAxisAngle(forward, angle); + } + + static CameraComponent3D? get currentCamera => + CameraComponent.currentCamera as CameraComponent3D?; + + static const distanceNear = 0.01; + static const distanceFar = 1000.0; +} diff --git a/packages/flame_3d/lib/src/camera/world_3d.dart b/packages/flame_3d/lib/src/camera/world_3d.dart new file mode 100644 index 00000000000..6497a7d1c0a --- /dev/null +++ b/packages/flame_3d/lib/src/camera/world_3d.dart @@ -0,0 +1,48 @@ +import 'dart:ui'; + +import 'package:flame/components.dart' as flame; +import 'package:flame_3d/camera.dart'; +import 'package:flame_3d/components.dart'; +import 'package:flame_3d/graphics.dart'; + +/// {@template world_3d} +/// The root component for all 3D world elements. +/// +/// The primary feature of this component is that it allows [Component3D]s to +/// render directly to a [GraphicsDevice] instead of the regular rendering. +/// {@endtemplate} +class World3D extends flame.World { + /// {@macro world_3d} + World3D({ + super.children, + super.priority, + Color clearColor = const Color(0x00000000), + }) : graphics = GraphicsDevice(clearValue: clearColor); + + /// The graphical device attached to this world. + final GraphicsDevice graphics; + + final _paint = Paint(); + + @override + void renderFromCamera(Canvas canvas) { + final camera = CameraComponent3D.currentCamera!; + + final viewport = camera.viewport; + graphics.begin( + Size(viewport.virtualSize.x, viewport.virtualSize.y), + transformMatrix: camera.projectionMatrix, + ); + + culled = 0; + // ignore: invalid_use_of_internal_member + super.renderFromCamera(canvas); + + final image = graphics.end(); + canvas.drawImage(image, (-viewport.virtualSize / 2).toOffset(), _paint); + image.dispose(); + } + + // TODO(wolfen): this is only here for testing purposes + int culled = 0; +} diff --git a/packages/flame_3d/lib/src/components/component_3d.dart b/packages/flame_3d/lib/src/components/component_3d.dart new file mode 100644 index 00000000000..d381999dab2 --- /dev/null +++ b/packages/flame_3d/lib/src/components/component_3d.dart @@ -0,0 +1,113 @@ +import 'dart:ui'; + +import 'package:flame/components.dart' show Component, HasWorldReference; +import 'package:flame/game.dart' show FlameGame; +import 'package:flame_3d/camera.dart'; +import 'package:flame_3d/components.dart'; +import 'package:flame_3d/game.dart'; +import 'package:flame_3d/graphics.dart'; +import 'package:flame_3d/resources.dart'; + +/// {@template component_3d} +/// [Component3D]s are the basic building blocks for a 3D [FlameGame]. +/// +/// It is a [Component] implementation that represents a 3D object that can be +/// freely moved around in 3D space, rotated, and scaled. +/// +/// The [Component3D] class has no visual representation of its own (except in +/// debug mode). It is common, therefore, to derive from this class +/// and implement a specific rendering logic. +/// +/// The base [Component3D] class can also be used as a container +/// for several other components. In this case, changing the position, +/// rotating or scaling the [Component3D] will affect the whole +/// group as if it was a single entity. +/// +/// The main property of this class is the [transform] (which combines +/// the [position], [rotation], and [scale]). Thus, the [Component3D] can be +/// seen as an object in 3D space where you can change its perceived +/// visualization. +/// +/// See the [MeshComponent] for a [Component3D] that has a visual representation +/// by using [Mesh]es +/// {@endtemplate} +class Component3D extends Component with HasWorldReference { + /// {@macro component_3d} + Component3D({ + Vector3? position, + Quaternion? rotation, + }) : transform = Transform3D() + ..position = position ?? Vector3.zero() + ..rotation = rotation ?? Quaternion.euler(0, 0, 0) + ..scale = Vector3.all(1); + + final Transform3D transform; + + /// The total transformation matrix for the component. This matrix combines + /// translation, rotation and scale transforms into a single entity. The + /// matrix is cached and gets recalculated only as necessary. + Matrix4 get transformMatrix => transform.transformMatrix; + + /// The position of this component's anchor on the screen. + NotifyingVector3 get position => transform.position; + set position(Vector3 position) => transform.position = position; + + /// X position of this component's anchor on the screen. + double get x => transform.x; + set x(double x) => transform.x = x; + + /// Y position of this component's anchor on the screen. + double get y => transform.y; + set y(double y) => transform.y = y; + + /// Z position of this component's anchor on the screen. + double get z => transform.z; + set z(double z) => transform.z = z; + + /// The rotation of this component. + NotifyingQuaternion get rotation => transform.rotation; + set rotation(NotifyingQuaternion rotation) => transform.rotation = rotation; + + /// The scale factor of this component. The scale can be different along + /// the X, Y and Z dimensions. A scale greater than 1 makes the component + /// bigger along that axis, and less than 1 smaller. The scale can also be negative, + /// which results in a mirror reflection along the corresponding axis. + NotifyingVector3 get scale => transform.scale; + set scale(Vector3 scale) => transform.scale = scale; + + /// Measure the distance (in parent's coordinate space) between this + /// component's anchor and the [other] component's anchor. + double distance(Component3D other) => position.distanceTo(other.position); + + @override + void renderTree(Canvas canvas) { + super.renderTree(canvas); + final camera = CameraComponent3D.currentCamera; + assert( + camera != null, + '''Component is either not part of a World3D or the render is being called outside of the camera rendering''', + ); + if (!shouldCull(camera!)) { + world.culled++; + return; + } + + // We set the priority to the distance between the camera and the object. + // This ensures that our rendering is done in a specific order allowing for + // alpha blending. + // + // Note(wolfen): we should optimize this in the long run it currently sucks. + priority = -(CameraComponent3D.currentCamera!.position - position) + .length + .abs() + .toInt(); + + bind(world.graphics); + } + + void bind(GraphicsDevice device) {} + + bool shouldCull(CameraComponent3D camera) { + return camera.frustum.containsVector3(position); + } +} diff --git a/packages/flame_3d/lib/src/components/mesh_component.dart b/packages/flame_3d/lib/src/components/mesh_component.dart new file mode 100644 index 00000000000..4c9e8ae6003 --- /dev/null +++ b/packages/flame_3d/lib/src/components/mesh_component.dart @@ -0,0 +1,42 @@ +import 'package:flame_3d/components.dart'; +import 'package:flame_3d/game.dart'; +import 'package:flame_3d/resources.dart'; +import 'package:flame_3d/src/camera/camera_component_3d.dart'; +import 'package:flame_3d/src/extensions/aabb3.dart'; +import 'package:flame_3d/src/graphics/graphics_device.dart'; + +/// {@template mesh_component} +/// A [Component3D] that renders a [Mesh] at the [position] with the [rotation] +/// and [scale] applied. +/// +/// This is a commonly used subclass of [Component3D]. +/// {@endtemplate} +class MeshComponent extends Component3D { + /// {@macro mesh_component} + MeshComponent({ + required Mesh mesh, + super.position, + super.rotation, + }) : _mesh = mesh; + + /// The mesh resource. + Mesh get mesh => _mesh; + final Mesh _mesh; + + Aabb3 get aabb => _aabb + ..setFrom(mesh.aabb) + ..transform(transformMatrix); + final Aabb3 _aabb = Aabb3(); + + @override + void bind(GraphicsDevice device) { + world.graphics + ..setViewModel(transformMatrix) + ..bindMesh(mesh); + } + + @override + bool shouldCull(CameraComponent3D camera) { + return camera.frustum.intersectsWithAabb3(aabb); + } +} diff --git a/packages/flame_3d/lib/src/extensions/aabb3.dart b/packages/flame_3d/lib/src/extensions/aabb3.dart new file mode 100644 index 00000000000..1fc56a27269 --- /dev/null +++ b/packages/flame_3d/lib/src/extensions/aabb3.dart @@ -0,0 +1,15 @@ +import 'package:flame_3d/game.dart'; + +extension Aabb3Extension on Aabb3 { + /// Set the min and max from the [other]. + void setFrom(Aabb3 other) { + min.setFrom(other.min); + max.setFrom(other.max); + } + + /// Set the min and max to zero. + void setZero() { + min.setZero(); + max.setZero(); + } +} diff --git a/packages/flame_3d/lib/src/extensions/color.dart b/packages/flame_3d/lib/src/extensions/color.dart new file mode 100644 index 00000000000..b8579e1446f --- /dev/null +++ b/packages/flame_3d/lib/src/extensions/color.dart @@ -0,0 +1,8 @@ +import 'dart:typed_data'; +import 'dart:ui'; + +extension ColorExtension on Color { + /// Returns a Float32List that represents the color as a vector. + Float32List get storage => + Float32List.fromList([red / 255, green / 255, blue / 255, opacity]); +} diff --git a/packages/flame_3d/lib/src/extensions/matrix4.dart b/packages/flame_3d/lib/src/extensions/matrix4.dart new file mode 100644 index 00000000000..d7c18ad50b8 --- /dev/null +++ b/packages/flame_3d/lib/src/extensions/matrix4.dart @@ -0,0 +1,31 @@ +import 'package:flame_3d/game.dart'; + +extension Matrix4Extension on Matrix4 { + /// Set the matrix to be a view matrix. + void setAsViewMatrix(Vector3 position, Vector3 target, Vector3 up) { + setViewMatrix(this, position, target, up); + } + + /// Set the matrix to use a projection view. + void setAsPerspective( + double fovy, + double aspectRatio, + double zNear, + double zFar, + ) { + final fovYRadians = fovy * degrees2Radians; + setPerspectiveMatrix(this, fovYRadians, aspectRatio, zNear, zFar); + } + + /// Set the matrix to use a orthographic view. + void setAsOrthographic( + double nearPlaneWidth, + double aspectRatio, + double zNear, + double zFar, + ) { + final top = nearPlaneWidth / 2.0; + final right = top * aspectRatio; + setOrthographicMatrix(this, -right, right, -top, top, zNear, zFar); + } +} diff --git a/packages/flame_3d/lib/src/extensions/vector2.dart b/packages/flame_3d/lib/src/extensions/vector2.dart new file mode 100644 index 00000000000..dc1c46d3cc4 --- /dev/null +++ b/packages/flame_3d/lib/src/extensions/vector2.dart @@ -0,0 +1,9 @@ +import 'package:flame_3d/game.dart'; + +/// Represents an immutable [Vector2]. +typedef ImmutableVector2 = ({double x, double y}); + +extension Vector2Extension on Vector2 { + /// Returns an immutable representation of the vector. + ImmutableVector2 get immutable => (x: x, y: y); +} diff --git a/packages/flame_3d/lib/src/extensions/vector3.dart b/packages/flame_3d/lib/src/extensions/vector3.dart new file mode 100644 index 00000000000..a577ed007d3 --- /dev/null +++ b/packages/flame_3d/lib/src/extensions/vector3.dart @@ -0,0 +1,9 @@ +import 'package:flame_3d/game.dart'; + +/// Represents an immutable [Vector3]. +typedef ImmutableVector3 = ({double x, double y, double z}); + +extension Vector3Extension on Vector3 { + /// Returns an immutable representation of the vector. + ImmutableVector3 get immutable => (x: x, y: y, z: z); +} diff --git a/packages/flame_3d/lib/src/extensions/vector4.dart b/packages/flame_3d/lib/src/extensions/vector4.dart new file mode 100644 index 00000000000..cadee0da270 --- /dev/null +++ b/packages/flame_3d/lib/src/extensions/vector4.dart @@ -0,0 +1,9 @@ +import 'package:flame_3d/game.dart'; + +/// Represents an immutable [Vector3]. +typedef ImmutableVector4 = ({double x, double y, double z, double w}); + +extension Vector4Extension on Vector4 { + /// Returns an immutable representation of the vector. + ImmutableVector4 get immutable => (x: x, y: y, z: z, w: w); +} diff --git a/packages/flame_3d/lib/src/game/flame_game_3d.dart b/packages/flame_3d/lib/src/game/flame_game_3d.dart new file mode 100644 index 00000000000..ec3fa7d8ec9 --- /dev/null +++ b/packages/flame_3d/lib/src/game/flame_game_3d.dart @@ -0,0 +1,18 @@ +import 'dart:ui'; + +import 'package:flame/game.dart'; +import 'package:flame_3d/camera.dart'; + +class FlameGame3D extends FlameGame { + FlameGame3D({ + super.children, + W? world, + CameraComponent3D? camera, + }) : super( + world: world ?? World3D(clearColor: const Color(0xFFFFFFFF)) as W, + camera: camera ?? CameraComponent3D(), + ); + + @override + CameraComponent3D get camera => super.camera as CameraComponent3D; +} diff --git a/packages/flame_3d/lib/src/game/notifying_quaternion.dart b/packages/flame_3d/lib/src/game/notifying_quaternion.dart new file mode 100644 index 00000000000..29385889976 --- /dev/null +++ b/packages/flame_3d/lib/src/game/notifying_quaternion.dart @@ -0,0 +1,174 @@ +import 'dart:math'; +import 'dart:typed_data'; + +import 'package:flame_3d/game.dart'; +import 'package:flutter/widgets.dart'; + +/// {@template notifying_quaternion} +/// Extension of the standard [Quaternion] class, implementing the +/// [ChangeNotifier] functionality. This allows any interested party to be +/// notified when the value of this quaternion changes. +/// +/// This class can be used as a regular [Quaternion] class. However, if you do +/// subscribe to notifications, don't forget to eventually unsubscribe in +/// order to avoid resource leaks. +/// +/// Direct modification of this quaternion's [storage] is not allowed. +/// {@endtemplate} +class NotifyingQuaternion extends Quaternion with ChangeNotifier { + /// {@macro notifying_quaternion} + /// + /// Constructs a quaternion using the raw values [x], [y], [z], and [w]. + factory NotifyingQuaternion(double x, double y, double z, double w) => + NotifyingQuaternion._()..setValues(x, y, z, w); + NotifyingQuaternion._() : super.fromFloat32List(Float32List(4)); + + /// {@macro notifying_quaternion} + /// + /// Constructs a quaternion from a rotation matrix [rotationMatrix]. + factory NotifyingQuaternion.fromRotation(Matrix3 rotationMatrix) => + NotifyingQuaternion._()..setFromRotation(rotationMatrix); + + /// {@macro notifying_quaternion} + /// + /// Constructs a quaternion from a rotation of [angle] around [axis]. + factory NotifyingQuaternion.axisAngle(Vector3 axis, double angle) => + NotifyingQuaternion._()..setAxisAngle(axis, angle); + + /// {@macro notifying_quaternion} + /// + /// Constructs a quaternion as a copy of [other]. + factory NotifyingQuaternion.copy(Quaternion other) => + NotifyingQuaternion._()..setFrom(other); + + /// {@macro notifying_quaternion} + /// + /// Constructs a quaternion from time derivative of [q] with angular + /// velocity [omega]. + factory NotifyingQuaternion.dq(Quaternion q, Vector3 omega) => + NotifyingQuaternion._()..setDQ(q, omega); + + /// {@macro notifying_quaternion} + /// + /// Constructs a quaternion from [yaw], [pitch] and [roll]. + factory NotifyingQuaternion.euler(double yaw, double pitch, double roll) => + NotifyingQuaternion._()..setEuler(yaw, pitch, roll); + + @override + void setValues(double x, double y, double z, double w) { + super.setValues(x, y, z, w); + notifyListeners(); + } + + @override + void setAxisAngle(Vector3 axis, double radians) { + super.setAxisAngle(axis, radians); + notifyListeners(); + } + + @override + void setDQ(Quaternion q, Vector3 omega) { + super.setDQ(q, omega); + notifyListeners(); + } + + @override + void setEuler(double yaw, double pitch, double roll) { + super.setEuler(yaw, pitch, roll); + notifyListeners(); + } + + @override + void setFromRotation(Matrix3 rotationMatrix) { + super.setFromRotation(rotationMatrix); + notifyListeners(); + } + + @override + void setFromTwoVectors(Vector3 a, Vector3 b) { + super.setFromTwoVectors(a, b); + notifyListeners(); + } + + @override + void setRandom(Random rn) { + super.setRandom(rn); + notifyListeners(); + } + + @override + void setFrom(Quaternion source) { + super.setFrom(source); + notifyListeners(); + } + + @override + void operator []=(int i, double arg) { + super[i] = arg; + notifyListeners(); + } + + @override + double normalize() { + final l = super.normalize(); + notifyListeners(); + return l; + } + + @override + void add(Quaternion arg) { + super.add(arg); + notifyListeners(); + } + + @override + void sub(Quaternion arg) { + super.sub(arg); + notifyListeners(); + } + + @override + void scale(double scale) { + super.scale(scale); + notifyListeners(); + } + + @override + set x(double x) { + super.x = x; + notifyListeners(); + } + + @override + set y(double y) { + super.y = y; + notifyListeners(); + } + + @override + set z(double z) { + super.z = z; + notifyListeners(); + } + + @override + set w(double w) { + super.w = w; + notifyListeners(); + } + + @override + void conjugate() { + super.conjugate(); + notifyListeners(); + } + + @override + void inverse() { + super.inverse(); + notifyListeners(); + } + + @override + Float32List get storage => UnmodifiableFloat32ListView(super.storage); +} diff --git a/packages/flame_3d/lib/src/game/notifying_vector3.dart b/packages/flame_3d/lib/src/game/notifying_vector3.dart new file mode 100644 index 00000000000..ce62b22db66 --- /dev/null +++ b/packages/flame_3d/lib/src/game/notifying_vector3.dart @@ -0,0 +1,211 @@ +import 'dart:typed_data'; + +import 'package:flame_3d/game.dart'; +import 'package:flutter/widgets.dart'; + +/// {@template notifying_vector_3} +/// Extension of the standard [Vector3] class, implementing the [ChangeNotifier] +/// functionality. This allows any interested party to be notified when the +/// value of this vector changes. +/// +/// This class can be used as a regular [Vector3] class. However, if you do +/// subscribe to notifications, don't forget to eventually unsubscribe in +/// order to avoid resource leaks. +/// +/// Direct modification of this vector's [storage] is not allowed. +/// {@endtemplate} +class NotifyingVector3 extends Vector3 with ChangeNotifier { + /// {@macro notifying_vector_3} + /// + /// Constructs a vector using the raw values [x], [y], and [z]. + factory NotifyingVector3(double x, double y, double z) => + NotifyingVector3.zero()..setValues(x, y, z); + + /// {@macro notifying_vector_3} + /// + /// Create an empty vector. + NotifyingVector3.zero() : super.zero(); + + /// {@macro notifying_vector_3} + /// + /// Create an vector whose values are all [v]. + factory NotifyingVector3.all(double v) => NotifyingVector3.zero()..splat(v); + + /// {@macro notifying_vector_3} + /// + /// Create a copy of the [other] vector. + factory NotifyingVector3.copy(Vector3 other) => + NotifyingVector3.zero()..setFrom(other); + + @override + void setValues(double x, double y, double z) { + super.setValues(x, y, z); + notifyListeners(); + } + + @override + void setFrom(Vector3 other) { + super.setFrom(other); + notifyListeners(); + } + + @override + void setZero() { + super.setZero(); + notifyListeners(); + } + + @override + void splat(double arg) { + super.splat(arg); + notifyListeners(); + } + + @override + void operator []=(int i, double v) { + super[i] = v; + notifyListeners(); + } + + @override + set length(double l) { + super.length = l; + notifyListeners(); + } + + @override + double normalize() { + final l = super.normalize(); + notifyListeners(); + return l; + } + + @override + void postmultiply(Matrix3 arg) { + super.postmultiply(arg); + notifyListeners(); + } + + @override + void add(Vector3 arg) { + super.add(arg); + notifyListeners(); + } + + @override + void addScaled(Vector3 arg, double factor) { + super.addScaled(arg, factor); + notifyListeners(); + } + + @override + void sub(Vector3 arg) { + super.sub(arg); + notifyListeners(); + } + + @override + void multiply(Vector3 arg) { + super.multiply(arg); + notifyListeners(); + } + + @override + void divide(Vector3 arg) { + super.divide(arg); + notifyListeners(); + } + + @override + void scale(double arg) { + super.scale(arg); + notifyListeners(); + } + + @override + void negate() { + super.negate(); + notifyListeners(); + } + + @override + void absolute() { + super.absolute(); + notifyListeners(); + } + + @override + void clamp(Vector3 min, Vector3 max) { + super.clamp(min, max); + notifyListeners(); + } + + @override + void clampScalar(double min, double max) { + super.clampScalar(min, max); + notifyListeners(); + } + + @override + void floor() { + super.floor(); + notifyListeners(); + } + + @override + void ceil() { + super.ceil(); + notifyListeners(); + } + + @override + void round() { + super.round(); + notifyListeners(); + } + + @override + void roundToZero() { + super.roundToZero(); + notifyListeners(); + } + + @override + void copyFromArray(List array, [int offset = 0]) { + super.copyFromArray(array, offset); + notifyListeners(); + } + + @override + set xy(Vector2 arg) { + super.xy = arg; + notifyListeners(); + } + + @override + set yx(Vector2 arg) { + super.yx = arg; + notifyListeners(); + } + + @override + set x(double x) { + super.x = x; + notifyListeners(); + } + + @override + set y(double y) { + super.y = y; + notifyListeners(); + } + + @override + set z(double z) { + super.z = z; + notifyListeners(); + } + + @override + Float32List get storage => UnmodifiableFloat32ListView(super.storage); +} diff --git a/packages/flame_3d/lib/src/game/transform_3d.dart b/packages/flame_3d/lib/src/game/transform_3d.dart new file mode 100644 index 00000000000..4fc09af2642 --- /dev/null +++ b/packages/flame_3d/lib/src/game/transform_3d.dart @@ -0,0 +1,147 @@ +import 'package:flame_3d/game.dart'; +import 'package:flutter/widgets.dart' show ChangeNotifier; + +/// {@template transform_3d} +/// This class describes a generic 3D transform, which is a combination of +/// translations, rotations and scaling. These transforms are combined into a +/// single matrix, that can be either applied to a graphical device like the +/// canvas, composed with another transform, or used directly to convert +/// coordinates. +/// +/// The transform can be visualized as 2 reference frames: a "global" and +/// a "local". At first, these two reference frames coincide. Then, the +/// following sequence of transforms is applied: +/// - translation to point [position]; +/// - rotate using the [rotation]; +/// - scaling in X, Y and Z directions by [scale] factors. +/// +/// The class is optimized for repeated use: the transform matrix is cached +/// and then recalculated only when the underlying properties change. Moreover, +/// recalculation of the transform is postponed until the matrix is actually +/// requested by the user. Thus, modifying multiple properties at once does +/// not incur the penalty of unnecessary recalculations. +/// +/// This class implements the [ChangeNotifier] API, allowing you to subscribe +/// for notifications whenever the transform matrix changes. In addition, you +/// can subscribe to get notified when individual components of the transform +/// change: [position], [scale], and [rotation]. +/// {@endtemplate} +class Transform3D extends ChangeNotifier { + /// {@macro transform_3d} + Transform3D() + : _recalculate = true, + _rotation = NotifyingQuaternion(0, 0, 0, 0), + _position = NotifyingVector3.zero(), + _scale = NotifyingVector3.all(1), + _transformMatrix = Matrix4.zero() { + _position.addListener(_markAsModified); + _scale.addListener(_markAsModified); + _rotation.addListener(_markAsModified); + } + + /// {@macro transform_3d} + /// + /// Create a copy of the [other] transform. + factory Transform3D.copy(Transform3D other) => Transform3D()..setFrom(other); + + /// {@macro transform_3d} + /// + /// Create an instance of [Transform3D] and apply the [matrix] on it. + factory Transform3D.fromMatrix4(Matrix4 matrix) { + final transform = Transform3D(); + matrix.decompose(transform.position, transform.rotation, transform.scale); + return transform; + } + + /// Clone of this. + Transform3D clone() => Transform3D.copy(this); + + /// The translation part of the transform. This translation is applied + /// relative to the global coordinate space. + /// + /// The returned vector can be modified by the user, and the changes + /// will be propagated back to the transform matrix. + NotifyingVector3 get position => _position; + set position(Vector3 position) => _position.setFrom(position); + final NotifyingVector3 _position; + + /// X coordinate of the translation transform. + double get x => _position.x; + set x(double x) => _position.x = x; + + /// Y coordinate of the translation transform. + double get y => _position.y; + set y(double y) => _position.y = y; + + /// Z coordinate of the translation transform. + double get z => _position.z; + set z(double y) => _position.z = z; + + NotifyingQuaternion get rotation => _rotation; + set rotation(Quaternion rotation) => _rotation.setFrom(rotation); + final NotifyingQuaternion _rotation; + + /// The scale part of the transform. The default scale factor is (1, 1, 1), + /// a scale greater than 1 corresponds to expansion, and less than 1 is + /// contraction. A negative scale is also allowed, and it corresponds + /// to a mirror reflection around the corresponding axis. + /// Scale factors can be different for X, Y and Z directions. + /// + /// The returned vector can be modified by the user, and the changes + /// will be propagated back to the transform matrix. + NotifyingVector3 get scale => _scale; + set scale(Vector3 scale) => _scale.setFrom(scale); + final NotifyingVector3 _scale; + + /// The total transformation matrix for the component. This matrix combines + /// translation, rotation and scale transforms into a single entity. The + /// matrix is cached and gets recalculated only when necessary. + /// + /// The returned matrix must not be modified by the user. + Matrix4 get transformMatrix { + if (_recalculate) { + _transformMatrix.setFromTranslationRotationScale( + _position, + _rotation, + _scale, + ); + _recalculate = false; + } + return _transformMatrix; + } + + final Matrix4 _transformMatrix; + bool _recalculate; + + /// Set this to the values of the [other] [Transform3D]. + void setFrom(Transform3D other) { + rotation.setFrom(other.rotation); + position.setFrom(other.position); + scale.setFrom(other.scale); + } + + /// Check whether this transform is equal to [other], up to the given + /// [tolerance]. Setting tolerance to zero will check for exact equality. + /// Transforms are considered equal if their rotation angles are the same + /// or differ by a multiple of 2π, and if all other transform parameters: + /// translation, scale, and offset are the same. + /// + /// The [tolerance] parameter is in absolute units, not relative. + bool closeTo(Transform3D other, {double tolerance = 1e-10}) { + return (position.x - other.position.x).abs() <= tolerance && + (position.y - other.position.y).abs() <= tolerance && + (position.z - other.position.z).abs() <= tolerance && + (rotation.x - other.rotation.x).abs() <= tolerance && + (rotation.y - other.rotation.y).abs() <= tolerance && + (rotation.z - other.rotation.z).abs() <= tolerance && + (rotation.w - other.rotation.w).abs() <= tolerance && + (scale.x - other.scale.x).abs() <= tolerance && + (scale.y - other.scale.y).abs() <= tolerance && + (scale.z - other.scale.z).abs() <= tolerance; + } + + void _markAsModified() { + _recalculate = true; + notifyListeners(); + } +} diff --git a/packages/flame_3d/lib/src/graphics/graphics_device.dart b/packages/flame_3d/lib/src/graphics/graphics_device.dart new file mode 100644 index 00000000000..a609bbd8d65 --- /dev/null +++ b/packages/flame_3d/lib/src/graphics/graphics_device.dart @@ -0,0 +1,190 @@ +import 'dart:typed_data'; +import 'dart:ui'; + +import 'package:flame_3d/game.dart'; +import 'package:flame_3d/resources.dart'; +import 'package:flutter_gpu/gpu.dart' as gpu; + +enum BlendState { + additive, + alphaBlend, + opaque, +} + +enum DepthStencilState { + standard, + depthRead, + none, +} + +/// {@template graphics_device} +/// The Graphical Device provides a way for developers to interact with the GPU +/// by binding different resources to it. +/// +/// A single render call starts with a call to [begin] and only ends when [end] +/// is called. Anything that gets binded to the device in between will be +/// uploaded to the GPU and returns as an [Image] in [end]. +/// {@endtemplate} +class GraphicsDevice { + /// {@macro graphics_device} + GraphicsDevice({this.clearValue = const Color(0x00000000)}); + + /// The clear value, used to clear out the screen. + final Color clearValue; + + late gpu.CommandBuffer _commandBuffer; + late gpu.HostBuffer _hostBuffer; + late gpu.RenderPass _renderPass; + late gpu.RenderTarget _renderTarget; + final _transformMatrix = Matrix4.identity(); + final _viewModelMatrix = Matrix4.identity(); + + Size _previousSize = Size.zero; + + /// Begin a new rendering batch. + /// + /// After [begin] is called the graphics device can be used to bind resources + /// like [Mesh]s, [Material]s and [Texture]s. + /// + /// Once you have executed all your bindings you can submit the batch to the + /// GPU with [end]. + void begin( + Size size, { + // TODO(wolfen): unused at the moment + BlendState blendState = BlendState.alphaBlend, + // TODO(wolfen): used incorrectly + DepthStencilState depthStencilState = DepthStencilState.depthRead, + Matrix4? transformMatrix, + }) { + _commandBuffer = gpu.gpuContext.createCommandBuffer(); + _hostBuffer = gpu.gpuContext.createHostBuffer(); + _renderPass = _commandBuffer.createRenderPass(_getRenderTarget(size)) + ..setColorBlendEnable(true) + ..setColorBlendEquation( + gpu.ColorBlendEquation( + sourceAlphaBlendFactor: blendState == BlendState.alphaBlend + ? gpu.BlendFactor.oneMinusSourceAlpha + : gpu.BlendFactor.one, + ), + ) + ..setDepthWriteEnable(depthStencilState == DepthStencilState.depthRead) + ..setDepthCompareOperation( + // TODO(wolfen): this is not correctly implemented AT all. + switch (depthStencilState) { + DepthStencilState.none => gpu.CompareFunction.never, + DepthStencilState.standard => gpu.CompareFunction.always, + DepthStencilState.depthRead => gpu.CompareFunction.less, + }, + ); + _transformMatrix.setFrom(transformMatrix ?? Matrix4.identity()); + } + + /// Submit the rendering batch and it's the commands to the GPU and return + /// the result. + Image end() { + _commandBuffer.submit(); + return _renderTarget.colorAttachments[0].texture.asImage(); + } + + void clearBindings() { + _renderPass.clearBindings(); + } + + void setViewModel(Matrix4 mvp) => _viewModelMatrix.setFrom(mvp); + + /// Bind a [mesh]. + void bindMesh(Mesh mesh) { + _renderPass.clearBindings(); + mesh.bind(this); + _renderPass.draw(); + } + + /// Bind a [surface]. + void bindSurface(Surface surface) { + _renderPass.clearBindings(); + if (surface.material != null) { + bindMaterial(surface.material!); + } + + _renderPass.bindVertexBuffer( + gpu.BufferView( + surface.resource!, + offsetInBytes: 0, + lengthInBytes: surface.verticesBytes, + ), + surface.vertexCount, + ); + + _renderPass.bindIndexBuffer( + gpu.BufferView( + surface.resource!, + offsetInBytes: surface.verticesBytes, + lengthInBytes: surface.indicesBytes, + ), + gpu.IndexType.int16, + surface.indexCount, + ); + + _renderPass.draw(); + } + + /// Bind a [material] and set up the buffer correctly. + void bindMaterial(Material material) { + _renderPass.bindPipeline(material.resource); + material.vertexBuffer + ..clear() + ..addMatrix4(_transformMatrix.multiplied(_viewModelMatrix)); + material.fragmentBuffer.clear(); + material.bind(this); + } + + /// Bind a [shader] with the given [buffer]. + void bindShader(gpu.Shader shader, ShaderBuffer buffer) { + bindUniform( + shader, + buffer.slot, + buffer.bytes.asByteData(), + ); + } + + /// Bind a uniform slot of [name] with the [data] on the [shader]. + void bindUniform(gpu.Shader shader, String name, ByteData data) { + _renderPass.bindUniform( + shader.getUniformSlot(name), + _hostBuffer.emplace(data), + ); + } + + void bindTexture(gpu.Shader shader, String name, Texture texture) { + _renderPass.bindTexture(shader.getUniformSlot(name), texture.resource); + } + + gpu.RenderTarget _getRenderTarget(Size size) { + if (_previousSize != size) { + _previousSize = size; + + final colorTexture = gpu.gpuContext.createTexture( + gpu.StorageMode.devicePrivate, + size.width.toInt(), + size.height.toInt(), + ); + + final depthTexture = gpu.gpuContext.createTexture( + gpu.StorageMode.deviceTransient, + size.width.toInt(), + size.height.toInt(), + format: gpu.gpuContext.defaultDepthStencilFormat, + ); + + _renderTarget = gpu.RenderTarget.singleColor( + gpu.ColorAttachment(texture: colorTexture!, clearValue: clearValue), + depthStencilAttachment: gpu.DepthStencilAttachment( + texture: depthTexture!, + depthClearValue: 1.0, + ), + ); + } + + return _renderTarget; + } +} diff --git a/packages/flame_3d/lib/src/resources/material.dart b/packages/flame_3d/lib/src/resources/material.dart new file mode 100644 index 00000000000..dab1184d5dc --- /dev/null +++ b/packages/flame_3d/lib/src/resources/material.dart @@ -0,0 +1,2 @@ +export 'material/material.dart'; +export 'material/standard_material.dart'; diff --git a/packages/flame_3d/lib/src/resources/material/material.dart b/packages/flame_3d/lib/src/resources/material/material.dart new file mode 100644 index 00000000000..5d9706fef34 --- /dev/null +++ b/packages/flame_3d/lib/src/resources/material/material.dart @@ -0,0 +1,68 @@ +import 'dart:typed_data'; + +import 'package:flame_3d/game.dart'; +import 'package:flame_3d/graphics.dart'; +import 'package:flame_3d/src/resources/resource.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter_gpu/gpu.dart' as gpu; + +/// {@template material} +/// Base material [Resource], it holds the shader library that should be used +/// for the texture. +/// {@endtemplate} +abstract class Material extends Resource { + /// {@macro material} + Material(gpu.ShaderLibrary library) + : super( + gpu.gpuContext.createRenderPipeline( + library['TextureVertex']!, + library['TextureFragment']!, + ), + ); + + final _vertexBuffer = ShaderBuffer('VertexInfo'); + final _fragmentBuffer = ShaderBuffer('FragmentInfo'); + + /// The vertex shader being used. + gpu.Shader get vertexShader => resource.vertexShader; + ShaderBuffer get vertexBuffer => _vertexBuffer; + + /// The fragment shader being used. + gpu.Shader get fragmentShader => resource.fragmentShader; + ShaderBuffer get fragmentBuffer => _fragmentBuffer; + + @mustCallSuper + void bind(GraphicsDevice device) { + device.bindShader(vertexShader, _vertexBuffer); + device.bindShader(fragmentShader, fragmentBuffer); + } +} + +/// {@template shader_buffer} +/// Class that buffers all the float uniforms that have to be uploaded to a +/// shader. +/// {@endtemplate} +class ShaderBuffer { + /// {@macro shader_buffer} + ShaderBuffer(this.slot); + + final String slot; + + final List _storage = []; + ByteBuffer get bytes => Float32List.fromList(_storage).buffer; + + /// Add a [Vector2] to the buffer. + void addVector2(Vector2 vector) => _storage.addAll(vector.storage); + + /// Add a [Vector3] to the buffer. + void addVector3(Vector3 vector) => _storage.addAll(vector.storage); + + /// Add a [Vector4] to the buffer. + void addVector4(Vector4 vector) => _storage.addAll(vector.storage); + + /// Add a [Matrix4] to the buffer. + void addMatrix4(Matrix4 matrix) => _storage.addAll(matrix.storage); + + /// Clear the buffer. + void clear() => _storage.clear(); +} diff --git a/packages/flame_3d/lib/src/resources/material/standard_material.dart b/packages/flame_3d/lib/src/resources/material/standard_material.dart new file mode 100644 index 00000000000..854045c9e5d --- /dev/null +++ b/packages/flame_3d/lib/src/resources/material/standard_material.dart @@ -0,0 +1,48 @@ +import 'dart:ui'; + +import 'package:flame_3d/game.dart'; +import 'package:flame_3d/graphics.dart'; +import 'package:flame_3d/resources.dart'; +import 'package:flutter_gpu/gpu.dart' as gpu; + +/// {@template standard_material} +/// The standard material, it applies the [albedoColor] to the [albedoTexture]. +/// {@endtemplate} +class StandardMaterial extends Material { + /// {@macro standard_material} + StandardMaterial({ + Texture? albedoTexture, + Color? albedoColor, + }) : albedoTexture = albedoTexture ?? Texture.standard, + _albedoColorCache = Vector4.zero(), + super(_library) { + this.albedoColor = albedoColor ?? const Color(0xFFFFFFFF); + } + + Texture albedoTexture; + + Color get albedoColor => _albedoColor; + set albedoColor(Color color) { + _albedoColor = color; + _albedoColorCache.setValues( + color.red / 255, + color.green / 255, + color.blue / 255, + color.alpha / 255, + ); + } + + late Color _albedoColor; + final Vector4 _albedoColorCache; + + @override + void bind(GraphicsDevice device) { + fragmentBuffer.addVector4(_albedoColorCache); + device.bindTexture(fragmentShader, 'albedoTexture', albedoTexture); + return super.bind(device); + } + + static final _library = gpu.ShaderLibrary.fromAsset( + 'packages/flame_3d/assets/shaders/standard_material.shaderbundle', + )!; +} diff --git a/packages/flame_3d/lib/src/resources/mesh.dart b/packages/flame_3d/lib/src/resources/mesh.dart new file mode 100644 index 00000000000..3ae45920121 --- /dev/null +++ b/packages/flame_3d/lib/src/resources/mesh.dart @@ -0,0 +1,6 @@ +export 'mesh/cuboid_mesh.dart'; +export 'mesh/mesh.dart'; +export 'mesh/plane_mesh.dart'; +export 'mesh/sphere_mesh.dart'; +export 'mesh/surface.dart'; +export 'mesh/vertex.dart'; diff --git a/packages/flame_3d/lib/src/resources/mesh/cuboid_mesh.dart b/packages/flame_3d/lib/src/resources/mesh/cuboid_mesh.dart new file mode 100644 index 00000000000..988730c1910 --- /dev/null +++ b/packages/flame_3d/lib/src/resources/mesh/cuboid_mesh.dart @@ -0,0 +1,64 @@ +import 'package:flame_3d/game.dart'; +import 'package:flame_3d/resources.dart'; + +/// {@template cuboid_mesh} +/// Represents a Cuboid's geometry with a single surface. +/// {@endtemplate} +class CuboidMesh extends Mesh { + /// {@macro cuboid_mesh} + CuboidMesh({ + required Vector3 size, + Material? material, + }) { + final Vector3(:x, :y, :z) = size / 2; + + final vertices = [ + // Face 1 (front) + Vertex(position: Vector3(-x, -y, -z), texCoord: Vector2(0, 0)), + Vertex(position: Vector3(x, -y, -z), texCoord: Vector2(1, 0)), + Vertex(position: Vector3(x, y, -z), texCoord: Vector2(1, 1)), + Vertex(position: Vector3(-x, y, -z), texCoord: Vector2(0, 1)), + + // Face 2 (back) + Vertex(position: Vector3(-x, -y, z), texCoord: Vector2(0, 0)), + Vertex(position: Vector3(x, -y, z), texCoord: Vector2(1, 0)), + Vertex(position: Vector3(x, y, z), texCoord: Vector2(1, 1)), + Vertex(position: Vector3(-x, y, z), texCoord: Vector2(0, 1)), + + // Face 3 (left) + Vertex(position: Vector3(-x, -y, z), texCoord: Vector2(0, 0)), + Vertex(position: Vector3(-x, -y, -z), texCoord: Vector2(1, 0)), + Vertex(position: Vector3(-x, y, -z), texCoord: Vector2(1, 1)), + Vertex(position: Vector3(-x, y, z), texCoord: Vector2(0, 1)), + + // Face 4 (right) + Vertex(position: Vector3(x, -y, -z), texCoord: Vector2(0, 0)), + Vertex(position: Vector3(x, -y, z), texCoord: Vector2(1, 0)), + Vertex(position: Vector3(x, y, z), texCoord: Vector2(1, 1)), + Vertex(position: Vector3(x, y, -z), texCoord: Vector2(0, 1)), + + // Face 5 (top) + Vertex(position: Vector3(-x, y, -z), texCoord: Vector2(0, 0)), + Vertex(position: Vector3(x, y, -z), texCoord: Vector2(1, 0)), + Vertex(position: Vector3(x, y, z), texCoord: Vector2(1, 1)), + Vertex(position: Vector3(-x, y, z), texCoord: Vector2(0, 1)), + + // Face 6 (bottom) + Vertex(position: Vector3(-x, -y, z), texCoord: Vector2(0, 0)), + Vertex(position: Vector3(x, -y, z), texCoord: Vector2(1, 0)), + Vertex(position: Vector3(x, -y, -z), texCoord: Vector2(1, 1)), + Vertex(position: Vector3(-x, -y, -z), texCoord: Vector2(0, 1)), + ]; + + final indices = [ + 0, 1, 2, 2, 3, 0, // Face 1 + 4, 5, 6, 6, 7, 4, // Face 2 + 8, 9, 10, 10, 11, 8, // Face 3 + 12, 13, 14, 14, 15, 12, // Face 4 + 16, 17, 18, 18, 19, 16, // Face 5 + 20, 21, 22, 22, 23, 20, // Face 6 + ]; + + addSurface(vertices, indices, material: material); + } +} diff --git a/packages/flame_3d/lib/src/resources/mesh/mesh.dart b/packages/flame_3d/lib/src/resources/mesh/mesh.dart new file mode 100644 index 00000000000..c3366bfb2aa --- /dev/null +++ b/packages/flame_3d/lib/src/resources/mesh/mesh.dart @@ -0,0 +1,67 @@ +import 'package:flame_3d/game.dart'; +import 'package:flame_3d/graphics.dart'; +import 'package:flame_3d/resources.dart'; + +/// {@template mesh} +/// A [Resource] that represents a geometric shape that is divided up in one or +/// more [Surface]s. +/// +/// This class isn't a true resource, it does not upload it self to the GPU. +/// Instead it uploads [Surface]s, it acts as a proxy. +/// {@endtemplate} +class Mesh extends Resource { + /// {@macro mesh} + Mesh() + : _surfaces = [], + super(null); + + /// The AABB of the mesh. + /// + /// This is the sum of all the AABB's of the surfaces it contains. + Aabb3 get aabb { + if (_aabb == null) { + var aabb = Aabb3(); + for (var i = 0; i < _surfaces.length; i++) { + if (i == 0) { + aabb = _surfaces[i].aabb; + } else { + aabb.hull(_surfaces[i].aabb); + } + } + _aabb = aabb; + } + return _aabb!; + } + + Aabb3? _aabb; + + final List _surfaces; + + /// The total surface count of the mesh. + int get surfaceCount => _surfaces.length; + + void bind(GraphicsDevice device) { + for (final surface in _surfaces) { + device.bindSurface(surface); + } + } + + /// Add a new surface represented by [vertices], [indices] and a material. + void addSurface( + List vertices, + List indices, { + Material? material, + }) { + _surfaces.add(Surface(vertices, indices, material)); + } + + /// Add a material to the surface at [index]. + void addMaterialToSurface(int index, Material material) { + _surfaces[index].material = material; + } + + /// Get a material from the surface at [index]. + Material? getMaterialToSurface(int index) { + return _surfaces[index].material; + } +} diff --git a/packages/flame_3d/lib/src/resources/mesh/plane_mesh.dart b/packages/flame_3d/lib/src/resources/mesh/plane_mesh.dart new file mode 100644 index 00000000000..f84a2be90ef --- /dev/null +++ b/packages/flame_3d/lib/src/resources/mesh/plane_mesh.dart @@ -0,0 +1,23 @@ +import 'package:flame_3d/game.dart'; +import 'package:flame_3d/resources.dart'; + +/// {@template plane_mesh} +/// Represents a 2D Plane's geometry with a single surface. +/// {@endtemplate} +class PlaneMesh extends Mesh { + /// {@macro plane_mesh} + PlaneMesh({ + required Vector2 size, + Material? material, + }) { + final Vector2(:x, :y) = size / 2; + + final vertices = [ + Vertex(position: Vector3(-x, 0, -y), texCoord: Vector2(0, 0)), + Vertex(position: Vector3(x, 0, -y), texCoord: Vector2(1, 0)), + Vertex(position: Vector3(x, 0, y), texCoord: Vector2(1, 1)), + Vertex(position: Vector3(-x, 0, y), texCoord: Vector2(0, 1)), + ]; + addSurface(vertices, [0, 1, 2, 2, 3, 0], material: material); + } +} diff --git a/packages/flame_3d/lib/src/resources/mesh/sphere_mesh.dart b/packages/flame_3d/lib/src/resources/mesh/sphere_mesh.dart new file mode 100644 index 00000000000..dafca4b8ba7 --- /dev/null +++ b/packages/flame_3d/lib/src/resources/mesh/sphere_mesh.dart @@ -0,0 +1,53 @@ +import 'dart:math' as math; + +import 'package:flame_3d/game.dart'; +import 'package:flame_3d/resources.dart'; + +/// {@template sphere_mesh} +/// Represents a Sphere's geometry with a single surface. +/// {@endtemplate} +class SphereMesh extends Mesh { + /// {@macro sphere_mesh} + SphereMesh({ + required double radius, + int segments = 64, + Material? material, + }) { + final vertices = []; + for (var i = 0; i <= segments; i++) { + final theta = i * (2 * math.pi) / segments; + for (var j = 0; j <= segments; j++) { + final phi = j * math.pi / segments; + + final x = radius * math.sin(phi) * math.cos(theta); + final y = radius * math.cos(phi); + final z = radius * math.sin(phi) * math.sin(theta); + + final u = theta / (2 * math.pi); + final v = phi / math.pi; + + vertices.add( + Vertex(position: Vector3(x, y, z), texCoord: Vector2(u, v)), + ); + } + } + + final indices = []; + for (var i = 0; i < segments; i++) { + for (var j = 0; j < segments; j++) { + final first = i * (segments + 1) + j; + final second = first + segments + 1; + + indices.add(first); + indices.add(second); + indices.add(first + 1); + + indices.add(second); + indices.add(second + 1); + indices.add(first + 1); + } + } + + addSurface(vertices, indices, material: material); + } +} diff --git a/packages/flame_3d/lib/src/resources/mesh/surface.dart b/packages/flame_3d/lib/src/resources/mesh/surface.dart new file mode 100644 index 00000000000..52f591d0872 --- /dev/null +++ b/packages/flame_3d/lib/src/resources/mesh/surface.dart @@ -0,0 +1,96 @@ +import 'dart:math' as math; +import 'dart:typed_data'; + +import 'package:flame_3d/game.dart'; +import 'package:flame_3d/resources.dart'; +import 'package:flutter_gpu/gpu.dart' as gpu; + +enum PrimitiveType { + triangles, +} + +/// {@template surface} +/// Base surface [Resource], it describes a single surface to be rendered. +/// {@endtemplate} +class Surface extends Resource { + /// {@macro surface} + Surface( + List vertices, + List indices, [ + this.material, + ]) : super(null) { + // `TODO`(bdero): This should have an attribute map instead and be fully SoA + // but vertex attributes in Impeller aren't flexible enough yet. + // See also https://github.com/flutter/flutter/issues/116168. + _vertices = Float32List.fromList( + vertices.fold([], (p, v) => p..addAll(v.storage)), + ).buffer; + _vertexCount = _vertices.lengthInBytes ~/ (vertices.length * 9); + + _indices = Uint16List.fromList(indices).buffer; + _indexCount = _indices.lengthInBytes ~/ 2; + + _calculateAabb(vertices); + } + + Material? material; + + Aabb3 get aabb => _aabb; + late Aabb3 _aabb; + + int get verticesBytes => _vertices.lengthInBytes; + late ByteBuffer _vertices; + + int get vertexCount => _vertexCount; + late int _vertexCount; + + int get indicesBytes => _indices.lengthInBytes; + late ByteBuffer _indices; + + int get indexCount => _indexCount; + late int _indexCount; + + @override + gpu.DeviceBuffer? get resource { + var resource = super.resource; + final sizeInBytes = _vertices.lengthInBytes + _indices.lengthInBytes; + if (resource?.sizeInBytes != sizeInBytes) { + // Store the device buffer in the resource parent. + resource = super.resource = gpu.gpuContext.createDeviceBuffer( + gpu.StorageMode.hostVisible, + sizeInBytes, + ); + + resource + ?..overwrite(_vertices.asByteData()) + ..overwrite( + _indices.asByteData(), + destinationOffsetInBytes: _vertices.lengthInBytes, + ); + } + return resource; + } + + void _calculateAabb(List vertices) { + var minX = double.infinity; + var minY = double.infinity; + var minZ = double.infinity; + var maxX = double.negativeInfinity; + var maxY = double.negativeInfinity; + var maxZ = double.negativeInfinity; + + for (final vertex in vertices) { + minX = math.min(minX, vertex.position.x); + minY = math.min(minY, vertex.position.y); + minZ = math.min(minZ, vertex.position.z); + maxX = math.max(maxX, vertex.position.x); + maxY = math.max(maxY, vertex.position.y); + maxZ = math.max(maxZ, vertex.position.z); + } + + _aabb = Aabb3.minMax( + Vector3(minX, minY, minZ), + Vector3(maxX, maxY, maxZ), + ); + } +} diff --git a/packages/flame_3d/lib/src/resources/mesh/vertex.dart b/packages/flame_3d/lib/src/resources/mesh/vertex.dart new file mode 100644 index 00000000000..b278095df65 --- /dev/null +++ b/packages/flame_3d/lib/src/resources/mesh/vertex.dart @@ -0,0 +1,57 @@ +import 'dart:typed_data'; + +import 'package:flame_3d/extensions.dart'; +import 'package:flame_3d/game.dart'; +import 'package:flutter/widgets.dart'; + +/// {@template vertex} +/// Represents a vertex in 3D space. +/// +/// A vertex consists out of space coordinates, UV/texture coordinates and a +/// color. +/// {@endtemplate} +@immutable +class Vertex { + /// {@macro vertex} + Vertex({ + required Vector3 position, + required Vector2 texCoord, + Vector3? normal, + this.color = const Color(0xFFFFFFFF), + }) : position = position.immutable, + texCoord = texCoord.immutable, + normal = (normal ?? Vector3.zero()).immutable, + _storage = Float32List.fromList([ + ...position.storage, + ...texCoord.storage, + // `TODO`(wolfen): uhh normals fuck shit up, I should read up on it + // ...(normal ?? Vector3.zero()).storage, + ...color.storage, + ]); + + Float32List get storage => _storage; + final Float32List _storage; + + /// The position of the vertex in 3D space. + final ImmutableVector3 position; + + /// The UV coordinates of the texture to map. + final ImmutableVector2 texCoord; + + /// The normal vector of the vertex. + final ImmutableVector3 normal; + + /// The color on the vertex. + final Color color; + + @override + bool operator ==(Object other) => + other is Vertex && + position == other.position && + texCoord == other.texCoord && + normal == other.normal && + color == other.color; + + @override + int get hashCode => Object.hashAll([position, texCoord, normal, color]); +} diff --git a/packages/flame_3d/lib/src/resources/resource.dart b/packages/flame_3d/lib/src/resources/resource.dart new file mode 100644 index 00000000000..068a0227b56 --- /dev/null +++ b/packages/flame_3d/lib/src/resources/resource.dart @@ -0,0 +1,19 @@ +import 'package:flutter/foundation.dart'; + +// TODO(wolfen): in the long run it would be nice of we can make it +// automatically refer to same type of objects to prevent memory leaks + +/// {@template resource} +/// A Resource is the base class for any resource typed classes. The primary +/// use case is to be a data container. +/// {@endtemplate} +class Resource { + /// {@macro resource} + Resource(this._resource); + + /// The resource data. + R get resource => _resource; + @protected + set resource(R resource) => _resource = resource; + R _resource; +} diff --git a/packages/flame_3d/lib/src/resources/texture.dart b/packages/flame_3d/lib/src/resources/texture.dart new file mode 100644 index 00000000000..aad730afa8c --- /dev/null +++ b/packages/flame_3d/lib/src/resources/texture.dart @@ -0,0 +1,3 @@ +export 'texture/color_texture.dart'; +export 'texture/image_texture.dart'; +export 'texture/texture.dart'; diff --git a/packages/flame_3d/lib/src/resources/texture/color_texture.dart b/packages/flame_3d/lib/src/resources/texture/color_texture.dart new file mode 100644 index 00000000000..2ef6a490e7e --- /dev/null +++ b/packages/flame_3d/lib/src/resources/texture/color_texture.dart @@ -0,0 +1,20 @@ +import 'dart:typed_data'; +import 'dart:ui'; + +import 'package:flame_3d/resources.dart'; + +/// {@template color_texture} +/// A texture that holds a single color. By default it creates a 1x1 texture. +/// {@endtemplate} +class ColorTexture extends Texture { + /// {@macro color_texture} + ColorTexture(Color color, {int width = 1, int height = 1}) + : super( + Uint32List.fromList( + List.filled(width * height, color.value), + ).buffer.asByteData(), + width: width, + height: height, + format: PixelFormat.bgra8888, + ); +} diff --git a/packages/flame_3d/lib/src/resources/texture/image_texture.dart b/packages/flame_3d/lib/src/resources/texture/image_texture.dart new file mode 100644 index 00000000000..4f395577ff5 --- /dev/null +++ b/packages/flame_3d/lib/src/resources/texture/image_texture.dart @@ -0,0 +1,17 @@ +import 'dart:ui'; + +import 'package:flame_3d/resources.dart'; + +/// {@template image_texture} +/// A texture that holds an image as it's render-able texture. +/// {@endtemplate} +class ImageTexture extends Texture { + /// {@macro image_texture} + ImageTexture(super.source, {required super.width, required super.height}); + + /// Create a [ImageTexture] from the given [image]. + static Future create(Image image) async { + final Image(:toByteData, :width, :height) = image; + return ImageTexture((await toByteData())!, width: width, height: height); + } +} diff --git a/packages/flame_3d/lib/src/resources/texture/texture.dart b/packages/flame_3d/lib/src/resources/texture/texture.dart new file mode 100644 index 00000000000..8f4c840fea6 --- /dev/null +++ b/packages/flame_3d/lib/src/resources/texture/texture.dart @@ -0,0 +1,42 @@ +import 'dart:typed_data'; +import 'dart:ui'; + +import 'package:flame_3d/resources.dart'; +import 'package:flutter_gpu/gpu.dart' as gpu; + +/// {@template texture} +/// Base texture [Resource], represents an image/texture on the GPU. +/// {@endtemplate} +class Texture extends Resource { + /// {@macro texture} + Texture( + ByteData sourceData, { + required int width, + required int height, + PixelFormat format = PixelFormat.rgba8888, + }) : super( + gpu.gpuContext.createTexture( + gpu.StorageMode.hostVisible, + width, + height, + format: switch (format) { + PixelFormat.rgba8888 => gpu.PixelFormat.r8g8b8a8UNormInt, + PixelFormat.bgra8888 => gpu.PixelFormat.b8g8r8a8UNormInt, + PixelFormat.rgbaFloat32 => gpu.PixelFormat.r32g32b32a32Float, + }, + )! + ..overwrite(sourceData), + ); + + int get width => resource.width; + + int get height => resource.height; + + Image toImage() => resource.asImage(); + + /// A transparent single pixel texture. + static final empty = ColorTexture(const Color(0x00000000)); + + /// A white single pixel texture. + static final standard = ColorTexture(const Color(0xFFFFFFFF)); +} diff --git a/packages/flame_3d/pubspec.yaml b/packages/flame_3d/pubspec.yaml new file mode 100644 index 00000000000..44e71ff7131 --- /dev/null +++ b/packages/flame_3d/pubspec.yaml @@ -0,0 +1,28 @@ +name: flame_3d +description: Experimental 3D support for the Flame Engine +version: 0.1.0-dev.1 +homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_3d +funding: + - https://opencollective.com/blue-fire + - https://github.com/sponsors/bluefireteam + - https://patreon.com/bluefireoss + +environment: + sdk: '>=3.3.0-279.2.beta <4.0.0' + flutter: ">=3.13.0" + +dependencies: + flame: ^1.16.0 + flutter: + sdk: flutter + flutter_gpu: + +dev_dependencies: + flame_lint: ^1.1.2 + flame_test: ^1.15.3 + flutter_test: + sdk: flutter + +flutter: + assets: + - assets/shaders/ \ No newline at end of file diff --git a/packages/flame_3d/shaders/standard_material.frag b/packages/flame_3d/shaders/standard_material.frag new file mode 100644 index 00000000000..8253fe6945c --- /dev/null +++ b/packages/flame_3d/shaders/standard_material.frag @@ -0,0 +1,16 @@ + +in vec2 fragTexCoord; +in vec4 fragColor; + +out vec4 outColor; + +uniform sampler2D albedoTexture; + +uniform FragmentInfo { + vec4 albedoColor; +} fragment_info; + +void main() { + vec4 texelColor = texture(albedoTexture, fragTexCoord); + outColor = texelColor * fragment_info.albedoColor * fragColor; +} diff --git a/packages/flame_3d/shaders/standard_material.vert b/packages/flame_3d/shaders/standard_material.vert new file mode 100644 index 00000000000..d93ce85ecc6 --- /dev/null +++ b/packages/flame_3d/shaders/standard_material.vert @@ -0,0 +1,16 @@ +in vec3 vertexPosition; +in vec2 vertexTexCoord; +in vec4 vertexColor; + +out vec2 fragTexCoord; +out vec4 fragColor; + +uniform VertexInfo { + mat4 mvp; +} vertex_info; + +void main() { + fragTexCoord = vertexTexCoord; + fragColor = vertexColor; + gl_Position = vertex_info.mvp * vec4(vertexPosition, 1.0); +} From 741d9384dbfea7bb692f181a7689a7b10a947ef0 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Fri, 1 Mar 2024 21:48:40 +0100 Subject: [PATCH 09/79] fix: Revert "feat(flame_3d): initial implementation of 3D support" (#3060) This reverts commit e434bafb15fc486c51b43aaa9d9190b8b7e783cb (flame_3d) for the time being so that we can get the pipeline back up running. --- packages/flame_3d/.metadata | 10 - packages/flame_3d/CHANGELOG.md | 3 - packages/flame_3d/CONTRIBUTING.md | 48 ---- packages/flame_3d/LICENSE | 22 -- packages/flame_3d/README.md | 139 ------------ packages/flame_3d/ROADMAP.md | 50 ----- packages/flame_3d/analysis_options.yaml | 1 - .../shaders/standard_material.shaderbundle | Bin 10304 -> 0 bytes packages/flame_3d/bin/build_shaders.dart | 62 ----- packages/flame_3d/example/.metadata | 45 ---- packages/flame_3d/example/README.md | 3 - .../flame_3d/example/analysis_options.yaml | 1 - .../flame_3d/example/assets/images/crate.jpg | Bin 37566 -> 0 bytes packages/flame_3d/example/lib/crate.dart | 29 --- .../lib/keyboard_controlled_camera.dart | 196 ---------------- packages/flame_3d/example/lib/main.dart | 142 ------------ packages/flame_3d/example/lib/player_box.dart | 29 --- packages/flame_3d/example/lib/simple_hud.dart | 76 ------- packages/flame_3d/example/pubspec.yaml | 22 -- packages/flame_3d/lib/camera.dart | 4 - packages/flame_3d/lib/components.dart | 2 - packages/flame_3d/lib/extensions.dart | 6 - packages/flame_3d/lib/game.dart | 6 - packages/flame_3d/lib/graphics.dart | 1 - packages/flame_3d/lib/resources.dart | 12 - .../lib/src/camera/camera_component_3d.dart | 207 ----------------- .../flame_3d/lib/src/camera/world_3d.dart | 48 ---- .../lib/src/components/component_3d.dart | 113 ---------- .../lib/src/components/mesh_component.dart | 42 ---- .../flame_3d/lib/src/extensions/aabb3.dart | 15 -- .../flame_3d/lib/src/extensions/color.dart | 8 - .../flame_3d/lib/src/extensions/matrix4.dart | 31 --- .../flame_3d/lib/src/extensions/vector2.dart | 9 - .../flame_3d/lib/src/extensions/vector3.dart | 9 - .../flame_3d/lib/src/extensions/vector4.dart | 9 - .../flame_3d/lib/src/game/flame_game_3d.dart | 18 -- .../lib/src/game/notifying_quaternion.dart | 174 --------------- .../lib/src/game/notifying_vector3.dart | 211 ------------------ .../flame_3d/lib/src/game/transform_3d.dart | 147 ------------ .../lib/src/graphics/graphics_device.dart | 190 ---------------- .../flame_3d/lib/src/resources/material.dart | 2 - .../lib/src/resources/material/material.dart | 68 ------ .../resources/material/standard_material.dart | 48 ---- packages/flame_3d/lib/src/resources/mesh.dart | 6 - .../lib/src/resources/mesh/cuboid_mesh.dart | 64 ------ .../flame_3d/lib/src/resources/mesh/mesh.dart | 67 ------ .../lib/src/resources/mesh/plane_mesh.dart | 23 -- .../lib/src/resources/mesh/sphere_mesh.dart | 53 ----- .../lib/src/resources/mesh/surface.dart | 96 -------- .../lib/src/resources/mesh/vertex.dart | 57 ----- .../flame_3d/lib/src/resources/resource.dart | 19 -- .../flame_3d/lib/src/resources/texture.dart | 3 - .../src/resources/texture/color_texture.dart | 20 -- .../src/resources/texture/image_texture.dart | 17 -- .../lib/src/resources/texture/texture.dart | 42 ---- packages/flame_3d/pubspec.yaml | 28 --- .../flame_3d/shaders/standard_material.frag | 16 -- .../flame_3d/shaders/standard_material.vert | 16 -- 58 files changed, 2785 deletions(-) delete mode 100644 packages/flame_3d/.metadata delete mode 100644 packages/flame_3d/CHANGELOG.md delete mode 100644 packages/flame_3d/CONTRIBUTING.md delete mode 100644 packages/flame_3d/LICENSE delete mode 100644 packages/flame_3d/README.md delete mode 100644 packages/flame_3d/ROADMAP.md delete mode 100644 packages/flame_3d/analysis_options.yaml delete mode 100644 packages/flame_3d/assets/shaders/standard_material.shaderbundle delete mode 100644 packages/flame_3d/bin/build_shaders.dart delete mode 100644 packages/flame_3d/example/.metadata delete mode 100644 packages/flame_3d/example/README.md delete mode 100644 packages/flame_3d/example/analysis_options.yaml delete mode 100644 packages/flame_3d/example/assets/images/crate.jpg delete mode 100644 packages/flame_3d/example/lib/crate.dart delete mode 100644 packages/flame_3d/example/lib/keyboard_controlled_camera.dart delete mode 100644 packages/flame_3d/example/lib/main.dart delete mode 100644 packages/flame_3d/example/lib/player_box.dart delete mode 100644 packages/flame_3d/example/lib/simple_hud.dart delete mode 100644 packages/flame_3d/example/pubspec.yaml delete mode 100644 packages/flame_3d/lib/camera.dart delete mode 100644 packages/flame_3d/lib/components.dart delete mode 100644 packages/flame_3d/lib/extensions.dart delete mode 100644 packages/flame_3d/lib/game.dart delete mode 100644 packages/flame_3d/lib/graphics.dart delete mode 100644 packages/flame_3d/lib/resources.dart delete mode 100644 packages/flame_3d/lib/src/camera/camera_component_3d.dart delete mode 100644 packages/flame_3d/lib/src/camera/world_3d.dart delete mode 100644 packages/flame_3d/lib/src/components/component_3d.dart delete mode 100644 packages/flame_3d/lib/src/components/mesh_component.dart delete mode 100644 packages/flame_3d/lib/src/extensions/aabb3.dart delete mode 100644 packages/flame_3d/lib/src/extensions/color.dart delete mode 100644 packages/flame_3d/lib/src/extensions/matrix4.dart delete mode 100644 packages/flame_3d/lib/src/extensions/vector2.dart delete mode 100644 packages/flame_3d/lib/src/extensions/vector3.dart delete mode 100644 packages/flame_3d/lib/src/extensions/vector4.dart delete mode 100644 packages/flame_3d/lib/src/game/flame_game_3d.dart delete mode 100644 packages/flame_3d/lib/src/game/notifying_quaternion.dart delete mode 100644 packages/flame_3d/lib/src/game/notifying_vector3.dart delete mode 100644 packages/flame_3d/lib/src/game/transform_3d.dart delete mode 100644 packages/flame_3d/lib/src/graphics/graphics_device.dart delete mode 100644 packages/flame_3d/lib/src/resources/material.dart delete mode 100644 packages/flame_3d/lib/src/resources/material/material.dart delete mode 100644 packages/flame_3d/lib/src/resources/material/standard_material.dart delete mode 100644 packages/flame_3d/lib/src/resources/mesh.dart delete mode 100644 packages/flame_3d/lib/src/resources/mesh/cuboid_mesh.dart delete mode 100644 packages/flame_3d/lib/src/resources/mesh/mesh.dart delete mode 100644 packages/flame_3d/lib/src/resources/mesh/plane_mesh.dart delete mode 100644 packages/flame_3d/lib/src/resources/mesh/sphere_mesh.dart delete mode 100644 packages/flame_3d/lib/src/resources/mesh/surface.dart delete mode 100644 packages/flame_3d/lib/src/resources/mesh/vertex.dart delete mode 100644 packages/flame_3d/lib/src/resources/resource.dart delete mode 100644 packages/flame_3d/lib/src/resources/texture.dart delete mode 100644 packages/flame_3d/lib/src/resources/texture/color_texture.dart delete mode 100644 packages/flame_3d/lib/src/resources/texture/image_texture.dart delete mode 100644 packages/flame_3d/lib/src/resources/texture/texture.dart delete mode 100644 packages/flame_3d/pubspec.yaml delete mode 100644 packages/flame_3d/shaders/standard_material.frag delete mode 100644 packages/flame_3d/shaders/standard_material.vert diff --git a/packages/flame_3d/.metadata b/packages/flame_3d/.metadata deleted file mode 100644 index 18428991e0b..00000000000 --- a/packages/flame_3d/.metadata +++ /dev/null @@ -1,10 +0,0 @@ -# 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: "1b197762c51e993cb77d7fafe9729ef2506e2bf7" - channel: "beta" - -project_type: package diff --git a/packages/flame_3d/CHANGELOG.md b/packages/flame_3d/CHANGELOG.md deleted file mode 100644 index 6ef630e4a42..00000000000 --- a/packages/flame_3d/CHANGELOG.md +++ /dev/null @@ -1,3 +0,0 @@ -## 0.1.0-dev.1 - -- Initial experimental release of `flame_3d`. diff --git a/packages/flame_3d/CONTRIBUTING.md b/packages/flame_3d/CONTRIBUTING.md deleted file mode 100644 index a16aea724ca..00000000000 --- a/packages/flame_3d/CONTRIBUTING.md +++ /dev/null @@ -1,48 +0,0 @@ -# Contribution Guidelines - -Read the main [Flame Contribution Guidelines](https://github.com/flame-engine/flame/blob/main/CONTRIBUTING.md) -first and then come back to this one. - -## How To Contribute - - -### Environment Setup - -First follow the steps described in the main [Flame Contribution Guidelines](https://github.com/flame-engine/flame/blob/main/CONTRIBUTING.md#environment-setup) - -After you have followed those steps you have to setup Flutter to use the specific build that this -package is built against: - -```sh -cd $(dirname $(which flutter)) && git checkout 8a5509ea6a277d48c15e5965163b08bd4ad4816a -q && echo "Engine commit: $(cat internal/engine.version)" && cd - >/dev/null -``` - -This will check out the GIT repo of your Flutter installation to the specific commit that we require -and also gets us t he the commit SHA of the Flutter Engine that you need to use in setting up the -Flutter GPU. For that you can follow the steps described in the -[Flutter Wiki](https://github.com/flutter/flutter/wiki/Flutter-GPU#try-out-flutter-gpu). - -Once you have cloned the Flutter engine you can add the `flutter_gpu` as an override dependency -to the `pubspec_overrides.yaml` file in the `flame_3d` directory and it's example: - -```yaml -dependency_overrides: - ... # Melos related overrides - flutter_gpu: - path: /lib/gpu -``` - -After all of that you should run `flutter pub get` one more time to ensure all dependencies are -set up correctly. - - -### Shader changes - -If you have added/changed/removed any of the shaders in the `shaders` directory make sure to run the -build script for shaders: - -```sh -dart bin/build_shaders.dart -``` - -This is currently a manual process until Flutter provides bundling support. \ No newline at end of file diff --git a/packages/flame_3d/LICENSE b/packages/flame_3d/LICENSE deleted file mode 100644 index f7831247594..00000000000 --- a/packages/flame_3d/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -MIT License - -Copyright (c) 2024 Blue Fire - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/packages/flame_3d/README.md b/packages/flame_3d/README.md deleted file mode 100644 index de7c155786d..00000000000 --- a/packages/flame_3d/README.md +++ /dev/null @@ -1,139 +0,0 @@ - -

- - flame - -

- -

-Adds 3D support for Flame using the Flutter GPU. -

- -

- - - - -

- ---- - - - -# flame_3d - -This package provides an experimental implementation of 3D support for Flame. The main focus is to -explore the potential capabilities of 3D for Flame while providing a familiar API to existing Flame -developers. - -Supported platforms: - -| Platform | Supported | -| -------- | --------- | -| Android | ❌ | -| iOS | ❌ | -| macOS | ✅ | -| Windows | ❌ | -| Linux | ❌ | -| Web | ❌ | - -## Prologue - -**STOP**, we know you are hyped up and want to start coding some funky 3D stuff but we first have to -set your expectations and clarify some things. So turn down your music, put away the coffee and make -some tea instead because you have to do some reading first! - -This package provides 3D support for Flame but it depends on the still experimental -[Flutter GPU](https://github.com/flutter/flutter/wiki/Flutter-GPU) which in turn depends on -Impeller. The Flutter GPU is currently not shipped with Flutter so this package wont work without -following the prerequisites steps. - -Because we depend on Flutter GPU this package is also highly experimental. Our long term goal is to -eventually deprecate this package and integrate it into the core `flame` package, for more -information on this see the [Roadmap](https://github.com/flame-engine/flame/blob/main/packages/flame_3d/ROADMAP.md). - -This package does not guarantee that it will follow correct [semver](https://semver.org/) versioning -rules nor does it assure that it's APIs wont break. Be ready to constantly have to refactor your -code if you are planning on using this package in a semi-production environment, which we do not -recommend. - -Documentation and tests might be lacking for quite a while because of the potential constant changes -of the API. Where possible we will try to provide in-code documentation and code examples to help -developers but our main goal for now is to enable the usage of 3D rendering within a Flame -ecosystem. - - -## Prerequisites - -Before you can get started with using this package a few steps have to happen first. Step one is -switching to a specific commit on the Flutter tooling. Because this package is still experimental -some of the features it requires are still being worked on from the Flutter side. - -So to make sure you are using the same build that we use while developing you have to manually -checkout a specific Flutter build. Thankfully we were able to simplify that process into a -one-liner: - -```sh -cd $(dirname $(which flutter)) && && git fetch && git checkout bcdd1b2c481bca0647beff690238efaae68ca5ac -q && echo "Engine commit: $(cat internal/engine.version)" && cd - >/dev/null -``` - -This will check out the GIT repo of your Flutter installation to the specific commit that we require -and also return the commit SHA of the Flutter Engine that it was build with. We need for step two. - -Step two is setting up the Flutter GPU. You can follow the steps described in the [Flutter Wiki](https://github.com/flutter/flutter/wiki/Flutter-GPU#try-out-flutter-gpu). -The engine commit that you should use is the one we got in step one. - -Once you have cloned the Flutter engine you can add the `flutter_gpu` as an override dependency -to your `pubspec.yaml` or in a `pubspec_overrides.yaml` file: - -```yaml -dependency_overrides: - flutter_gpu: - path: /lib/gpu -``` - -Step three would be to enable impeller for the macOS platform, add the following to the -`Info.plist` in your `macos/` directory: - -```xml - - ... - FLTEnableImpeller - - -``` - -Now everything is set up you can start doing some 3D magic! You can check out the -[example](https://github.com/flame-engine/flame/tree/main/packages/flame_3d/example) to see how you -can set up a simple 3D environment using Flame. - - -## Building shaders - -You can write your own shaders and use them on Materials. Currently Flutter does not do the bundling -of shaders for us so this package provides a simple dart script. Create your fragment and vertex -shader in a `shaders` directory, make sure the file names are identical. Like so: - -- `my_custom_shader`.frag -- `my_custom_shader`.vert - -You can then run `dart pub run flame_3d:build_shaders` to bundle the shaders. They will -automatically be placed in `assets/shaders`. - -You can check out the -[default shaders](https://github.com/flame-engine/flame/tree/main/packages/flame_3d/shaders) if you -want to have some examples. - - -## Contributing - -Have you found a bug or have a suggestion of how to enhance the 3D APIs? Open an issue and we will -take a look at it as soon as possible. - -Do you want to contribute with a PR? PRs are always welcome, just make sure to create it from the -correct branch (main) and follow the [checklist](.github/pull_request_template.md) which will -appear when you open the PR. - -For bigger changes, or if in doubt, make sure to talk about your contribution to the team. Either -via an issue, GitHub discussion, or reach out to the team using the -[Discord server](https://discord.gg/pxrBmy4). \ No newline at end of file diff --git a/packages/flame_3d/ROADMAP.md b/packages/flame_3d/ROADMAP.md deleted file mode 100644 index b225bec5ad5..00000000000 --- a/packages/flame_3d/ROADMAP.md +++ /dev/null @@ -1,50 +0,0 @@ -# Roadmap - -In the interest of transparency, we provide a high-level detail of the roadmap for adding 3D -support to Flame. We hope this roadmap will help others in making plans and priorities based on the -work we are doing and potentially contribute back to the project itself. - -The goal of the package can be split up into two sections, the primary goal is to provide an API for -Flame developers so they can create 3D environments without having to learn new Flame concepts. This -means the package will tie into the existing [FCS](https://docs.flame-engine.org/latest/flame/components.html#component) -and provide the tools needed, like a [`CameraComponent`](https://docs.flame-engine.org/latest/flame/camera_component.html), -`World` and similar components. - -In a perfect world this API does not depend or even know about the Flutter GPU, which brings us -to our secondary goal: to abstract the Flutter GPU into an API that is user-friendly for 3D -development. That includes simplifying things like creating render targets, setting up the color -and depth textures and configuring depth stencils. But it also includes higher level APIs like -geometric shapes, texture/material rendering and creating Meshes that can use those shapes and -materials. - -## Goals - -### Abstracting the Flutter GPU into a user-friendly API for 3D - -- [x] Abstract the GPU setup into a class that represents the graphics device - - [ ] Setup binding logic for meshes, geometry and materials. -- [ ] Provide a `Mesh` API - - [x] Provide `Surface`s that can hold geometric shapes. - - [x] Provide a `Material` API - - [x] Define a `Texture` API to be used with the `Material` API - - [x] Support images as textures - - [x] Support single color textures - - [x] Support generated textures - - [x] Provide a standard `Material` - - [ ] Support custom shaders - - [ ] Add a more dev friendly way to set uniforms - - [x] Support multiple `Material`s by defining surfaces on a mesh. - - -### Providing a familiar API for developers to use 3D with Flame - -- [x] Use the existing `CameraComponent` API for 3D rendering - - [x] Provide a custom `World` - - [x] Support existing and custom viewports - - [ ] Support existing and custom viewfinders -- [x] Create a new core component for 3D rendering (`Component3D`) - - [x] Implement a `Transform3D` for 3D transformations - - [x] Implement a notifying `Vector3` and `Quaternion` for 3D positioning and rotation - - [ ] Add support for gesture event callbacks -- [x] Create a component that can show meshes (`MeshComponent`) - - [x] Ensure materials can be set outside of construction (in the `onLoad` for instance) \ No newline at end of file diff --git a/packages/flame_3d/analysis_options.yaml b/packages/flame_3d/analysis_options.yaml deleted file mode 100644 index 92aae2f2499..00000000000 --- a/packages/flame_3d/analysis_options.yaml +++ /dev/null @@ -1 +0,0 @@ -include: package:flame_lint/analysis_options_with_dcm.yaml diff --git a/packages/flame_3d/assets/shaders/standard_material.shaderbundle b/packages/flame_3d/assets/shaders/standard_material.shaderbundle deleted file mode 100644 index 37d2f9e01b7d2cf0d2cf87dfb1f1822561945461..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10304 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 Wppv)ie-RhSAL&pem+cN^;r|5~ViJV_ diff --git a/packages/flame_3d/bin/build_shaders.dart b/packages/flame_3d/bin/build_shaders.dart deleted file mode 100644 index 0cefe877f75..00000000000 --- a/packages/flame_3d/bin/build_shaders.dart +++ /dev/null @@ -1,62 +0,0 @@ -import 'dart:convert'; -import 'dart:io'; - -/// Bundle a shader (.frag & .vert) into a single shader bundle and -/// store it in the assets directory. -/// -/// This script is just a temporary way to bundle shaders. In the long run -/// Flutter might support auto-bundling themselves but until then we have to -/// do it manually. -/// -/// Note: this script should be run from the root of the package: -/// packages/flame_3d -void main() async { - final root = Directory.current; - - final assets = Directory.fromUri(root.uri.resolve('assets/shaders')); - // Delete all the bundled shaders so we can replace them with new ones. - if (assets.existsSync()) { - assets.deleteSync(recursive: true); - } - // Create if not exists. - assets.createSync(recursive: true); - - // Directory where our unbundled shaders are stored. - final shaders = Directory.fromUri(root.uri.resolve('shaders')); - if (!shaders.existsSync()) { - return stderr.writeln('Missing shader directory'); - } - - // Get a list of unique shader names. Each shader should have a .frag and - // .vert with the same basename to be considered a bundle. - final uniqueShaders = shaders - .listSync() - .whereType() - .map((f) => f.path.split('/').last.split('.').first) - .toSet(); - - for (final name in uniqueShaders) { - final bundle = { - 'TextureFragment': { - 'type': 'fragment', - 'file': '${root.path}/shaders/$name.frag', - }, - 'TextureVertex': { - 'type': 'vertex', - 'file': '${root.path}/shaders/$name.vert', - }, - }; - - final result = await Process.run(impellerC, [ - '--sl=${assets.path}/$name.shaderbundle', - '--shader-bundle=${jsonEncode(bundle)}', - ]); - - if (result.exitCode != 0) { - return stderr.writeln(result.stderr); - } - } -} - -final impellerC = - '${Platform.environment['FLUTTER_HOME']}/bin/cache/artifacts/engine/darwin-x64/impellerc'; diff --git a/packages/flame_3d/example/.metadata b/packages/flame_3d/example/.metadata deleted file mode 100644 index a2eed5f2b7c..00000000000 --- a/packages/flame_3d/example/.metadata +++ /dev/null @@ -1,45 +0,0 @@ -# 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: "1b197762c51e993cb77d7fafe9729ef2506e2bf7" - channel: "beta" - -project_type: app - -# Tracks metadata for the flutter migrate command -migration: - platforms: - - platform: root - create_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 - base_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 - - platform: android - create_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 - base_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 - - platform: ios - create_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 - base_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 - - platform: linux - create_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 - base_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 - - platform: macos - create_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 - base_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 - - platform: web - create_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 - base_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 - - platform: windows - create_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 - base_revision: 1b197762c51e993cb77d7fafe9729ef2506e2bf7 - - # User provided section - - # List of Local paths (relative to this file) that should be - # ignored by the migrate tool. - # - # Files that are not part of the templates will be ignored by default. - unmanaged_files: - - 'lib/main.dart' - - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/packages/flame_3d/example/README.md b/packages/flame_3d/example/README.md deleted file mode 100644 index e6a8c4c9085..00000000000 --- a/packages/flame_3d/example/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# flame_3d example - -An example for using the `flame_3d` package. \ No newline at end of file diff --git a/packages/flame_3d/example/analysis_options.yaml b/packages/flame_3d/example/analysis_options.yaml deleted file mode 100644 index 92aae2f2499..00000000000 --- a/packages/flame_3d/example/analysis_options.yaml +++ /dev/null @@ -1 +0,0 @@ -include: package:flame_lint/analysis_options_with_dcm.yaml diff --git a/packages/flame_3d/example/assets/images/crate.jpg b/packages/flame_3d/example/assets/images/crate.jpg deleted file mode 100644 index eaebeba17865fe93f90e2c4a6858b0009b49210d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37566 zcmeFXWmFu&);2o0y9C$4eQs;8f-{nYO6y{G%n=AQ!qCRj#Z1_1R|n4y>ffIo)-EomQHD*!-A z3BU*d01yGNP(%Q@w;I&jPXvnizv?nj^Z=NDv_k^`&^Z69|3&?y{AK%l&Oi5mZUD@x zHqIW-?l#UY6r8N=06qzMC0N*hKru+5^Z+o#G_oXbcxV9Z+bmE+Y&<+%1lZV|+*wU6 zoXsp*&7B?Dd`w-~I9S=)079ZZE~e)8mL3#lme#gT!gOEy2I(klErjW`xs}+JTqG@R zY~}piEY*#@{Rqifz|ennV-|t!qVc6iJiv`#KL98 z&B?;Y!wzEMFyrImu`)F^1DSFDFV6pQ`u|aue=7CnL~riI_Fqo zz`?-6!otA4ZQ$VG;1N&}5#9<03JMY`76vvp76uj;4nD~{99$wiEGz;_0wPjUa&mH< zcT_+sG9U>VIoV$lsJBxQ;1SRf5z)zTv2e-$?eb>`fQ1NU17!mPg$01df`Y+<`ZER~ zdCRQe-mb2Z<7QdzV(`80-&H_;Ghu@Q4rA);h|yv9s*#o;NY<-ImFcv zaB!(iU0bL@5+Nxi!%K*G_?!?kx6stq!*@VhNp*AgG#V~$kFfO8vhud}k>xu&9w})J zO^a||8LiRdd&?Co&!e|Nh@b#4e-p?5p29x{frEeR<9?ee6bv*h95fuv+cf_|-a4^3 zuqk0d;%Yc=qla+bQA?zhv_OWJaJeK8?}282wgIRxP;Vx}U;#t{m#ymV)yY|6zN-~1 z6hPp6Kyd|UQeGXzZ~wf7V0_fJbDeg!))AY$LLtD;)pNPI){`ahnponI#_e*1e}xU> z5D;;1y%r@UGrKwr%-U_blw!(rrffw>pCzB@4GyP$r+-UKvBEC`C?6f2L9Jcr=8_WU z;6Y~5IJa9VKlQf zM=tc#|JiQMAQWYi#?6is-hV(|5n6fUe2W5YP5XH+PlOu>YAws%)-d93x z01hiM7JG9LxY+JHS_Fz!b$e_wm+xspjeh5yR3lYDcUeRO7%-K{R^4Y?g$+0 z=x<3l4f~pWC;FniKY*BkZ_B)KtY?dTXtkaX@&+>dkyqTa_Lnw{o?V2A8nJ`6O zj#O?vVZWEy1?q_PZ%HYsJimpeu)ivAGL{*NR~{SGtkG8`WH%+^Xp7fl2APlt2Sr)o z5Pj)}Q(T=!^O^V^5?a2Lua1QCRlZtb0qVgtLzfw9m_yxm-o}cw3asc%7C3xZ64;zq zEmU%-G^IgK6gXFcmM3A4js<#!TFEyJur)he3_o@Exp#~Dyok{V-(&QHC!O7KIc7lN zCIkmo8;YVjv38x@P{H^o^wNho1u{R^9qGu-F0JjX2ziK`sz4}GETm4@Mt4L2EN_ij zLyIKS0JMt#hDFq>w|N)WlAhMnz!`w&{BVw2$ljajQ%o;cfz+7dJi|=&vUemeLVGw7{gmk$(Z(^rw zbHjX{ifH|5ZWxZexZH82!Ci{dBIazTu99r-fHrn(vI-1@BA$5+>n^WyB^9SaTS_&< z127dOh>7*oBl+cqeEU5~G+KTaTp?P|(XY~%C)Qt?L6GXlfrId|nG4!z=7UTy?nqCR z_(@|&scZ~ZdRRH61HfNkIM376M=XEKF`6n71%Y)`sk*agEiL3Vad~Hq!tV*Nt z1LIE$-R5f=vZip60DDdcpZi|-&ktjcbIsxOb{*ecL*a5dahbr~e%+J2fpg{)#sT~e ztmA`wbEZ&@(q@Ad_4cp36ETF|8c)0IB1(5Y_0WP1LB8K*25TBFkaVf@4_>U`zO3?m z!!&KQuaeg*b1;>cwjaki<`@tkG~Y}Gjj6=Iah<7`%=)-@uO2 zwhfnW9=V3XC&8RSX1uMNQC|aq!HCfaw^Tm{mzs(!nkUk|5z|0Tl9$7FyRrw}0C#W< z(=YCnuE_x2P>#MfaIAjP+6+7VqCUpE&balstd}mlXcP81dO6**G)+Z;(Q?p^Q;IdB z{ZZ=bYs=wu=t#;_mrx}wdkF)~zUFZ~;8!7iG3n6w6Zflxyo=4YI?EKI@!AV-@+XnV5}oqP%7v=$n^0Hg^GV!dl`m4L{yVB_ybUY1%$u%Q1V+ffj>H=W8Zv%=SYH|yhFG; z*xW#lC4(LaH-S!XjI7bVI);@xs+rP!rsAGu6GEL65|d%)o-gsZuY?L`;;Qj5y_e~B zprw3PFT8liorGgN&RBq(;I1S7{z*aDif3HNCF~QuuL&oTM%t(DfR;w{>B=7nhUNrd zWdEbjM2A9%Nx zH|<3PHBCXSR||;Oc;m9S9dw;1l;o)$O)2MtRWwLxSADp|YCM}|4ybLv^E8PqZ*HX1 zT|_gm9t;*6sBXR_L8OTP*2Tji-FpcY-td+5mZc1PDoQ4oF&!K*sHrwP;osJIvLAVB z5Gx5Q6won9tO*`XSAV`IaLPDRkuiG*z9v=aIam&+60%FE@Zzc3g>2iat_1P%7={F^ z!MBf0-VY&$=cX^UC~b{9tYg+_Owo%NYoNTqkC>_99xW?h9~(Y$e~>`dA^R51sM5^b z7nfl2qhY0#r)m>l;vK#llJgXdK2N$&!)Phseth*O{3MA=kaYJ(U_zHGhX9id)=5aM zVVLEvRKp*@6i*R}Bjnni_2?+r-FkxPfxDD~t!QeaeyBgef-(I@_`ccC9{zzl8Omun zWLzcjokoI%v}P4^&M>fM%M>In8DR49q`~yt{B|$&{f9U~V1^#(aN<4OFoa^oJGBqC zQy8 zP?*mnT#@@2k0@@g=WDXihlD{FIlGP{@#hhQtY+_9QnhE?kafz&KA4~*RKUr$Jok+^w>No3oGzdX59!#Xo>QT4cl<)K4JNDjUl6X**-!=4Uza zrBxm*-6U=;m!9lcnDg&Iv3mUhR94J1cnQ1?c>e*cAeBYwn$xKr!sZNM;?w8Vc}7UP zcjf;9d>g-e@{aoPlBX%1PLXp6TMabyua@U}-E}#C$wtn?NH7krHn{S_oxO`q2K2pC z<0pCTb+^7_7ZN~ex^{FAL?-?+f_B}5w$-Tb4U%xg&#SXC)bgww{~-kc%R!*vBTHG( z$@0_eB>4NbKMDqL?$n*5qdQ6r zCc|pw`h9qQYta$$Nw=Fvym z?Y>RXKB?lWgVp)LbVZu7EsVpLLKRd8HV$vv%dBG@7%+U2s^MX!1`u+i1pO99m5*}e z@{k3wioV5vnhf?iaf;^y#V!DQm>dr$gm$M#Q37TSBCY9~d>Idi$i&Dgt%V ziel+Rh%mPyWZWcOYRs=YpNi|r-4U3YZbyR;!|yJRwXa8gAK_-c1T8WSpuJNnYEybC z6Y$Wo{*}YuFXg=V`V9{ujK*?c%bD$DI6(m8YcQ=_buZdpA(pfBNvESAt<0(JLmQ8o zs#T9>PXsmod)yLD;S}4u)iOLf=ClOesV%B+dfwkBkkz~z4@Un0&JDPKTk-Gmc|FJO zm+FvdR*XQ4(Ow(osut}{aFGuUyOg{dcfE!PBo!Oxp}tW%Lt6^xDFt88=8)2#w)$qAe+wWIXbLD0cFs3`uLy6U;IF zDLl%o?Sb!=tKLR-HE5`1YJtyD!oV0|Y6Okt{IlVp|7*&Ij8+Ak^KFFv{J;z70W988 zS|j1=h&!b=*0qQ4v_(_9V5^}jhrCFi#1U!t^YvG3#iHdFd@iz@0}!Ywzg$2uV!Iot zk5%tmN4BXjH#Nv46rLIdNySCi4ds2DkjYtTOQop=jq)cv9n>04=kv@(Z}C7jw6h6w z)PEyCbHz>9rL#s=R0s-X;0NxQ+ToTg{9GElk}t^AVx_q)V|3Ic!fA!CWa^k|)t1gs zkyo`l@)Cbbn(Huqn0p(Pc6a!{qpo&MqJR}7-HK_#yoyxFBKG%je z?lgehHuXGSsM{ipbp3-v@hW`T+{O$ZB?@pCoe~Xy2&`s~(w?_{?8vO4meZyM*`%KAM&zL@8jcAgUUcC-fMP*s5XzoGzN9=fTf`LcEAeJ8unTvV5Gwh+_QJ zkO-Yk+b$CaXs<9If1lG3vbY8Nuxh(+qEwP^lrA22P z%=E-!SWRX#~~ER6H0`0)06op zsk_0UA}AYvXK7CQER9CPj+%~iG)e`dN8fI?NIknFz&uxOrZ>z2JjMHwC>X&i`-!R*K;$V{q-?0?V>T$ye~y*g z5V2bzCSfNpixDG{iBaZlN~aPBVP1SgOl6#@qX^eS!({ZC4q4Kiw4&w*$ZZ|X(M)leXhLiS~9!uVaCQ$C<8wOYhMMcxA=j$nzF zdo0`%2iPJ#sJcGP+u`-g3r7cV0Ia%2$bSbOsl4_?RD3(Vd0oYxS~1J4@ifmO?J|MSOU6Lt^cB5Q4@g5WbE|CIE_kt)WMDEzJN0bJfi-AB zP+^KRdCIVu*JAn>eh2r0w>hiKIK||Ox$F!&_7V%&ULs`+d)&Itsc%c zhpLrX5Rb4MSH7t3O^Dd{e{4oWYu-10te>#P>8JYr;I_Q2_(7e^o#Sa#?%>K}*Gnzs zW5R0F!@y<-cME?jQ-i4{`eNf|K~#?}d!lRQ7bz4pcm9!3(WSiu0d(0vfZpia!*@p{ z9nUD2t?91qn<*+liGXE7Q$l;Ubu)>143XyK+yXz!8u95#oQynrC%D<%LG{ai{0IEG zPmZ3ZVJUeOugd$?pWTu$NLyv*%LI4(&{|gycPALnvi>xOsf?EqW7WvGKgbw3)YW$I5OzSS=+F%Q3WVw}w&ZmQSVg@d} zPR%fdaq;f#c+<~qgH$^IBVPyB9o`NKGdw@&-S#(>?isLR7s>Idypm=F)qAZ=1Yauet%m(QZ?HTrgaxfrGBZpqV?QgzQo|Ag7nt ziP%bHNn>f~%B;XOsY9cK38(B|R_M6ft~Is}2lhT}%9fD{J5reX~%0D;@YS4s~A`2k#!%?wYO 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 onLoad() async { - final crateTexture = await Flame.images.loadTexture('crate.jpg'); - mesh.addMaterialToSurface(0, StandardMaterial(albedoTexture: crateTexture)); - } - - double direction = 0.1; - - @override - void update(double dt) { - if (scale.x >= 1.19 || scale.x <= 0.99) { - direction *= -1; - } - scale.add(Vector3.all(direction * dt)); - } -} diff --git a/packages/flame_3d/example/lib/keyboard_controlled_camera.dart b/packages/flame_3d/example/lib/keyboard_controlled_camera.dart deleted file mode 100644 index 936e8685631..00000000000 --- a/packages/flame_3d/example/lib/keyboard_controlled_camera.dart +++ /dev/null @@ -1,196 +0,0 @@ -import 'package:flame/components.dart' show KeyboardHandler; -import 'package:flame_3d/camera.dart'; -import 'package:flame_3d/game.dart'; -import 'package:flutter/gestures.dart' show kMiddleMouseButton; -import 'package:flutter/services.dart' - show KeyEvent, KeyRepeatEvent, LogicalKeyboardKey, PointerEvent; - -class KeyboardControlledCamera extends CameraComponent3D with KeyboardHandler { - KeyboardControlledCamera({ - super.world, - super.viewport, - super.viewfinder, - super.backdrop, - super.hudComponents, - }) : super( - projection: CameraProjection.perspective, - mode: CameraMode.firstPerson, - position: Vector3(0, 2, 4), - target: Vector3(0, 2, 0), - up: Vector3(0, 1, 0), - fovY: 60, - ); - - final double moveSpeed = 0.9; - final double rotationSpeed = 0.3; - final double panSpeed = 2; - final double orbitalSpeed = 0.5; - - Set _keysDown = {}; - PointerEvent? pointerEvent; - double scrollMove = 0; - - final Matrix4 _orbitalMatrix = Matrix4.identity(); - - @override - bool onKeyEvent(KeyEvent event, Set keysPressed) { - _keysDown = keysPressed; - - // Switch camera mode - if (isKeyDown(Key.digit1)) { - mode = CameraMode.free; - up = Vector3(0, 1, 0); // Reset roll - } else if (isKeyDown(Key.digit2)) { - mode = CameraMode.firstPerson; - up = Vector3(0, 1, 0); // Reset roll - } else if (isKeyDown(Key.digit3)) { - mode = CameraMode.thirdPerson; - up = Vector3(0, 1, 0); // Reset roll - } else if (isKeyDown(Key.digit4)) { - mode = CameraMode.orbital; - up = Vector3(0, 1, 0); // Reset roll - } - - if (isKeyDown(Key.keyP) && event is! KeyRepeatEvent) { - if (projection == CameraProjection.perspective) { - // Create an isometric view. - mode = CameraMode.thirdPerson; - projection = CameraProjection.orthographic; - - position = Vector3(0, 2, -100); - target = Vector3(0, 2, 0); - up = Vector3(0, 1, 0); - fovY = 20; - - yaw(-135 * degrees2Radians, rotateAroundTarget: true); - pitch(-45 * degrees2Radians, lockView: true, rotateAroundTarget: true); - } else if (projection == CameraProjection.orthographic) { - // Reset to default view. - mode = CameraMode.thirdPerson; - projection = CameraProjection.perspective; - - position = Vector3(0, 2, 10); - target = Vector3(0, 2, 0); - up = Vector3(0, 1, 0); - fovY = 60; - } - } - - return false; - } - - @override - void update(double dt) { - final moveInWorldPlane = switch (mode) { - CameraMode.firstPerson || CameraMode.thirdPerson => true, - _ => false, - }; - final rotateAroundTarget = switch (mode) { - CameraMode.thirdPerson || CameraMode.orbital => true, - _ => false, - }; - final lockView = switch (mode) { - CameraMode.free || CameraMode.firstPerson || CameraMode.orbital => true, - _ => false, - }; - - if (mode == CameraMode.orbital) { - final rotation = _orbitalMatrix - ..setIdentity() - ..rotate(up, orbitalSpeed * dt); - final view = rotation.transform3(position - target); - position = target + view; - } else { - // Camera rotation - if (isKeyDown(Key.arrowDown)) { - pitch( - -rotationSpeed * dt, - lockView: lockView, - rotateAroundTarget: rotateAroundTarget, - ); - } else if (isKeyDown(Key.arrowUp)) { - pitch( - rotationSpeed * dt, - lockView: lockView, - rotateAroundTarget: rotateAroundTarget, - ); - } - if (isKeyDown(Key.arrowRight)) { - yaw(-rotationSpeed * dt, rotateAroundTarget: rotateAroundTarget); - } else if (isKeyDown(Key.arrowLeft)) { - yaw(rotationSpeed * dt, rotateAroundTarget: rotateAroundTarget); - } - if (isKeyDown(Key.keyQ)) { - roll(-rotationSpeed * dt); - } else if (isKeyDown(Key.keyE)) { - roll(rotationSpeed * dt); - } - - // Camera movement, if mode is free and mouse button is down we pan the - // camera. - if (pointerEvent != null) { - if (mode == CameraMode.free && - pointerEvent?.buttons == kMiddleMouseButton) { - final mouseDelta = pointerEvent!.delta; - if (mouseDelta.dx > 0) { - moveRight(panSpeed * dt, moveInWorldPlane: moveInWorldPlane); - } else if (mouseDelta.dx < 0) { - moveRight(-panSpeed * dt, moveInWorldPlane: moveInWorldPlane); - } - if (mouseDelta.dy > 0) { - moveUp(-panSpeed * dt); - } else if (mouseDelta.dy < 0) { - moveUp(panSpeed * dt); - } - } else { - const mouseMoveSensitivity = 0.003; - yaw( - (pointerEvent?.delta.dx ?? 0) * mouseMoveSensitivity, - rotateAroundTarget: rotateAroundTarget, - ); - pitch( - (pointerEvent?.delta.dy ?? 0) * mouseMoveSensitivity, - lockView: lockView, - rotateAroundTarget: rotateAroundTarget, - ); - } - pointerEvent = null; - } - - // Keyboard movement - if (isKeyDown(Key.keyW)) { - moveForward(moveSpeed * dt); - } else if (isKeyDown(Key.keyS)) { - moveForward(-moveSpeed * dt); - } - if (isKeyDown(Key.keyA)) { - moveRight(-moveSpeed * dt); - } else if (isKeyDown(Key.keyD)) { - moveRight(moveSpeed * dt); - } - - if (mode == CameraMode.free) { - if (isKeyDown(Key.space)) { - moveUp(moveSpeed * dt); - } else if (isKeyDown(Key.controlLeft)) { - moveUp(-moveSpeed * dt); - } - } - } - - // if (mode == CameraMode.thirdPerson || - // mode == CameraMode.orbital || - // mode == CameraMode.free) { - // moveToTarget(-scrollMove); - // if (isKeyDown(Key.numpadSubtract)) { - // moveToTarget(2 * dt); - // } else if (isKeyDown(Key.numpadAdd)) { - // moveToTarget(-2 * dt); - // } - // } - } - - bool isKeyDown(Key key) => _keysDown.contains(key); -} - -typedef Key = LogicalKeyboardKey; diff --git a/packages/flame_3d/example/lib/main.dart b/packages/flame_3d/example/lib/main.dart deleted file mode 100644 index 843d71fcc1a..00000000000 --- a/packages/flame_3d/example/lib/main.dart +++ /dev/null @@ -1,142 +0,0 @@ -import 'dart:async'; -import 'dart:math'; -import 'dart:ui'; - -import 'package:example/crate.dart'; -import 'package:example/keyboard_controlled_camera.dart'; -import 'package:example/player_box.dart'; -import 'package:example/simple_hud.dart'; -import 'package:flame/events.dart'; -import 'package:flame/extensions.dart' as v64 show Vector2; -import 'package:flame/game.dart' show FlameGame, GameWidget; -import 'package:flame_3d/camera.dart'; -import 'package:flame_3d/components.dart'; -import 'package:flame_3d/game.dart'; -import 'package:flame_3d/resources.dart'; -import 'package:flutter/gestures.dart'; -import 'package:flutter/material.dart' show runApp, Color, Colors, Listener; - -class ExampleGame3D extends FlameGame - with HasKeyboardHandlerComponents { - ExampleGame3D() - : super( - world: World3D(clearColor: const Color(0xFFFFFFFF)), - camera: KeyboardControlledCamera( - viewport: FixedResolutionViewport( - resolution: v64.Vector2(800, 600), - ), - hudComponents: [SimpleHud()], - ), - ); - - @override - KeyboardControlledCamera get camera => - super.camera as KeyboardControlledCamera; - - @override - FutureOr onLoad() async { - world.addAll([ - // Add a player box - PlayerBox(), - - // Floating crate - Crate(size: Vector3.all(1), position: Vector3(0, 5, 0)), - - // Floating sphere - MeshComponent( - position: Vector3(5, 5, 5), - mesh: SphereMesh( - radius: 1, - material: StandardMaterial( - albedoTexture: ColorTexture(Colors.purple), - ), - ), - ), - - // Floor - MeshComponent( - mesh: PlaneMesh( - size: Vector2(32, 32), - material: StandardMaterial(albedoTexture: ColorTexture(Colors.grey)), - ), - ), - - // Front wall - MeshComponent( - position: Vector3(16.5, 2.5, 0), - mesh: CuboidMesh( - size: Vector3(1, 5, 32), - material: - StandardMaterial(albedoTexture: ColorTexture(Colors.yellow)), - ), - ), - - // Left wall - MeshComponent( - position: Vector3(0, 2.5, 16.5), - mesh: CuboidMesh( - size: Vector3(32, 5, 1), - material: StandardMaterial(albedoTexture: ColorTexture(Colors.blue)), - ), - ), - - // Right wall - MeshComponent( - position: Vector3(0, 2.5, -16.5), - mesh: CuboidMesh( - size: Vector3(32, 5, 1), - material: StandardMaterial(albedoTexture: ColorTexture(Colors.lime)), - ), - ), - ]); - - final rnd = Random(); - for (var i = 0; i < 20; i++) { - final height = rnd.range(1, 12); - - world.add( - MeshComponent( - position: Vector3(rnd.range(-15, 15), height / 2, rnd.range(-15, 15)), - mesh: CuboidMesh( - size: Vector3(1, height, 1), - material: StandardMaterial( - albedoTexture: ColorTexture( - Color.fromRGBO(rnd.iRange(20, 255), rnd.iRange(10, 55), 30, 1), - ), - ), - ), - ), - ); - } - } -} - -void main() { - final example = ExampleGame3D(); - - runApp( - Listener( - onPointerMove: (event) { - if (!event.down) { - return; - } - example.camera.pointerEvent = event; - }, - onPointerSignal: (event) { - if (event is! PointerScrollEvent || !event.down) { - return; - } - example.camera.scrollMove = event.delta.dy / 3000; - }, - onPointerUp: (event) => example.camera.pointerEvent = null, - onPointerCancel: (event) => example.camera.pointerEvent = null, - child: GameWidget(game: example), - ), - ); -} - -extension on Random { - double range(num min, num max) => nextDouble() * (max - min) + min; - - int iRange(int min, int max) => range(min, max).toInt(); -} diff --git a/packages/flame_3d/example/lib/player_box.dart b/packages/flame_3d/example/lib/player_box.dart deleted file mode 100644 index fc42d7f75bb..00000000000 --- a/packages/flame_3d/example/lib/player_box.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'dart:ui'; - -import 'package:example/main.dart'; -import 'package:flame/components.dart' show HasGameReference; -import 'package:flame_3d/camera.dart'; -import 'package:flame_3d/components.dart'; -import 'package:flame_3d/game.dart'; -import 'package:flame_3d/resources.dart'; -import 'package:flutter/material.dart' show Colors; - -class PlayerBox extends MeshComponent with HasGameReference { - PlayerBox() - : super( - mesh: CuboidMesh( - size: Vector3.all(0.5), - material: - StandardMaterial(albedoTexture: ColorTexture(Colors.purple)), - ), - ); - - @override - void renderTree(Canvas canvas) { - // Only show the box if we are in third person mode. - if (game.camera.mode == CameraMode.thirdPerson) { - position.setFrom(game.camera.target); - super.renderTree(canvas); - } - } -} diff --git a/packages/flame_3d/example/lib/simple_hud.dart b/packages/flame_3d/example/lib/simple_hud.dart deleted file mode 100644 index 757a70a34a1..00000000000 --- a/packages/flame_3d/example/lib/simple_hud.dart +++ /dev/null @@ -1,76 +0,0 @@ -import 'dart:ui'; - -import 'package:example/main.dart'; -import 'package:flame/components.dart'; -import 'package:flame/text.dart'; -import 'package:flame_3d/camera.dart'; - -const _width = 1.2; -const _color = Color(0xFFFFFFFF); - -final _style = TextStyle( - color: const Color(0xFF000000), - shadows: [ - for (var x = 1; x < _width + 5; x++) - for (var y = 1; y < _width + 5; y++) ...[ - Shadow(offset: Offset(-_width / x, -_width / y), color: _color), - Shadow(offset: Offset(-_width / x, _width / y), color: _color), - Shadow(offset: Offset(_width / x, -_width / y), color: _color), - Shadow(offset: Offset(_width / x, _width / y), color: _color), - ], - ], -); - -class SimpleHud extends Component with HasGameReference { - SimpleHud() : super(children: [FpsComponent()]); - - String get fps => - children.query().firstOrNull?.fps.toStringAsFixed(2) ?? '0'; - - final _textLeft = TextPaint(style: _style); - - final _textCenter = TextPaint(style: _style.copyWith(fontSize: 20)); - - final _textRight = TextPaint(style: _style, textDirection: TextDirection.rtl); - - @override - void render(Canvas canvas) { - final CameraComponent3D(:position, :target, :up) = game.camera; - - _textLeft.render( - canvas, - ''' -Camera controls: -- Move using W, A, S, D, Space, Left-Ctrl -- Look around with arrow keys or mouse -- Change camera mode with 1, 2, 3 or 4 -- Change camera projection with P -- Zoom in and out with scroll -''', - Vector2.all(8), - ); - - _textCenter.render( - canvas, - 'Welcome to the 3D world', - Vector2(game.size.x / 2, game.size.y - 8), - anchor: Anchor.bottomCenter, - ); - - _textRight.render( - canvas, - ''' -FPS: $fps -Mode: ${game.camera.mode.name} -Projection: ${game.camera.projection.name} -Culled: ${game.world.culled} - -Position: ${position.x.toStringAsFixed(2)}, ${position.y.toStringAsFixed(2)}, ${position.z.toStringAsFixed(2)} -Target: ${target.x.toStringAsFixed(2)}, ${target.y.toStringAsFixed(2)}, ${target.z.toStringAsFixed(2)} -Up: ${up.x.toStringAsFixed(2)}, ${up.y.toStringAsFixed(2)}, ${up.z.toStringAsFixed(2)} -''', - Vector2(game.size.x - 8, 8), - anchor: Anchor.topRight, - ); - } -} diff --git a/packages/flame_3d/example/pubspec.yaml b/packages/flame_3d/example/pubspec.yaml deleted file mode 100644 index 497c039c6fa..00000000000 --- a/packages/flame_3d/example/pubspec.yaml +++ /dev/null @@ -1,22 +0,0 @@ -name: example -description: An example for flame_3d. The example shows how to set up 3D support in a flame game. -version: 0.0.1+1 -publish_to: none - -environment: - sdk: ">=3.0.0 <4.0.0" - -dependencies: - flame: ^1.16.0 - flame_3d: ^0.1.0 - flutter: - sdk: flutter - -dev_dependencies: - flame_lint: ^1.1.2 - -flutter: - uses-material-design: true - - assets: - - assets/images/ diff --git a/packages/flame_3d/lib/camera.dart b/packages/flame_3d/lib/camera.dart deleted file mode 100644 index 0459754995e..00000000000 --- a/packages/flame_3d/lib/camera.dart +++ /dev/null @@ -1,4 +0,0 @@ -export 'package:flame/camera.dart'; - -export 'src/camera/camera_component_3d.dart'; -export 'src/camera/world_3d.dart'; diff --git a/packages/flame_3d/lib/components.dart b/packages/flame_3d/lib/components.dart deleted file mode 100644 index d3c590b1d53..00000000000 --- a/packages/flame_3d/lib/components.dart +++ /dev/null @@ -1,2 +0,0 @@ -export 'src/components/component_3d.dart'; -export 'src/components/mesh_component.dart'; diff --git a/packages/flame_3d/lib/extensions.dart b/packages/flame_3d/lib/extensions.dart deleted file mode 100644 index 7a262a03afb..00000000000 --- a/packages/flame_3d/lib/extensions.dart +++ /dev/null @@ -1,6 +0,0 @@ -export 'src/extensions/aabb3.dart'; -export 'src/extensions/color.dart'; -export 'src/extensions/matrix4.dart'; -export 'src/extensions/vector2.dart'; -export 'src/extensions/vector3.dart'; -export 'src/extensions/vector4.dart'; diff --git a/packages/flame_3d/lib/game.dart b/packages/flame_3d/lib/game.dart deleted file mode 100644 index b79118633a3..00000000000 --- a/packages/flame_3d/lib/game.dart +++ /dev/null @@ -1,6 +0,0 @@ -export 'package:vector_math/vector_math.dart' hide Colors; - -export 'src/game/flame_game_3d.dart'; -export 'src/game/notifying_quaternion.dart'; -export 'src/game/notifying_vector3.dart'; -export 'src/game/transform_3d.dart'; diff --git a/packages/flame_3d/lib/graphics.dart b/packages/flame_3d/lib/graphics.dart deleted file mode 100644 index ab2eee25192..00000000000 --- a/packages/flame_3d/lib/graphics.dart +++ /dev/null @@ -1 +0,0 @@ -export 'src/graphics/graphics_device.dart'; diff --git a/packages/flame_3d/lib/resources.dart b/packages/flame_3d/lib/resources.dart deleted file mode 100644 index b6ba8d86973..00000000000 --- a/packages/flame_3d/lib/resources.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'package:flame/cache.dart'; -import 'package:flame_3d/resources.dart'; - -export 'src/resources/material.dart'; -export 'src/resources/mesh.dart'; -export 'src/resources/resource.dart'; -export 'src/resources/texture.dart'; - -extension TextureCache on Images { - Future loadTexture(String path) => - load('crate.jpg').then(ImageTexture.create); -} diff --git a/packages/flame_3d/lib/src/camera/camera_component_3d.dart b/packages/flame_3d/lib/src/camera/camera_component_3d.dart deleted file mode 100644 index d747e1f7644..00000000000 --- a/packages/flame_3d/lib/src/camera/camera_component_3d.dart +++ /dev/null @@ -1,207 +0,0 @@ -import 'package:flame_3d/camera.dart'; -import 'package:flame_3d/extensions.dart'; -import 'package:flame_3d/game.dart'; - -enum CameraProjection { perspective, orthographic } - -enum CameraMode { custom, free, orbital, firstPerson, thirdPerson } - -/// {@template camera_component_3d} -/// [CameraComponent3D] is a component through which a [World3D] is observed. -/// {@endtemplate} -class CameraComponent3D extends CameraComponent { - /// {@macro camera_component_3d} - CameraComponent3D({ - this.fovY = 60, - Vector3? position, - Vector3? target, - Vector3? up, - this.projection = CameraProjection.perspective, - this.mode = CameraMode.free, - World3D? super.world, - super.viewport, - super.viewfinder, - super.backdrop, - super.hudComponents, - }) : position = position?.clone() ?? Vector3.zero(), - target = target?.clone() ?? Vector3.zero(), - _up = up?.clone() ?? Vector3(0, 1, 0); - - @override - World3D? get world => super.world as World3D?; - - @override - set world(covariant World3D? world) => super.world = world; - - /// The [fovY] is the field of view in Y (degrees) when the [projection] is - /// [CameraProjection.perspective] otherwise it is used as the near plane when - /// the [projection] is [CameraProjection.orthographic]. - double fovY; - - /// The position of the camera in 3D space. - /// - /// Often also referred to as the "eye". - Vector3 position; - - /// The target in 3D space that the camera is looking at. - Vector3 target; - - /// The forward direction relative to the camera. - Vector3 get forward => target - position; - - /// The right direction relative to the camera. - Vector3 get right => forward.cross(up); - - /// The up direction relative to the camera. - Vector3 get up => _up.normalized(); - set up(Vector3 up) => _up.setFrom(up); - final Vector3 _up; - - /// The current camera projection. - CameraProjection projection; - - /// The current camera mode. - CameraMode mode; - - /// The view matrix of the camera, this is without any projection applied on - /// it. - Matrix4 get viewMatrix => _viewMatrix..setAsViewMatrix(position, target, up); - final Matrix4 _viewMatrix = Matrix4.zero(); - - /// The projection matrix of the camera. - Matrix4 get projectionMatrix { - final aspectRatio = viewport.virtualSize.x / viewport.virtualSize.y; - return switch (projection) { - CameraProjection.perspective => _projectionMatrix - ..setAsPerspective(fovY, aspectRatio, distanceNear, distanceFar), - CameraProjection.orthographic => _projectionMatrix - ..setAsOrthographic(fovY, aspectRatio, distanceNear, distanceFar) - } - ..multiply(viewMatrix); - } - - final Matrix4 _projectionMatrix = Matrix4.zero(); - final Frustum _frustum = Frustum(); - - Frustum get frustum => _frustum..setFromMatrix(_projectionMatrix); - - void moveForward(double distance, {bool moveInWorldPlane = false}) { - final forward = this.forward..scale(distance); - - if (moveInWorldPlane) { - forward.y = 0; - forward.normalize(); - } - - position.add(forward); - target.add(forward); - } - - void moveUp(double distance) { - final up = this.up..scale(distance); - position.add(up); - target.add(up); - } - - void moveRight(double distance, {bool moveInWorldPlane = false}) { - final right = this.right..scale(distance); - - if (moveInWorldPlane) { - right.y = 0; - right.normalize(); - } - - position.add(right); - target.add(right); - } - - void moveToTarget(double delta) { - var distance = position.distanceTo(target); - distance += delta; - - if (distance <= 0) { - distance = 0.001; - } - - final forward = this.forward; - position.setValues( - target.x + (forward.x * -distance), - target.y + (forward.y * -distance), - target.z + (forward.z * -distance), - ); - } - - void yaw(double angle, {bool rotateAroundTarget = false}) { - final targetPosition = (target - position)..applyAxisAngle(up, angle); - - if (rotateAroundTarget) { - position.setValues( - target.x - targetPosition.x, - target.y - targetPosition.y, - target.z - targetPosition.z, - ); - } else { - target.setValues( - position.x + targetPosition.x, - position.y + targetPosition.y, - position.z + targetPosition.z, - ); - } - } - - void pitch( - double angle, { - bool lockView = false, - bool rotateAroundTarget = false, - bool rotateUp = false, - }) { - var localAngle = angle; - final up = this.up; - final targetPosition = target - position; - - if (lockView) { - final maxAngleUp = up.angleTo(targetPosition); - if (localAngle > maxAngleUp) { - localAngle = maxAngleUp; - } - - var maxAngleDown = (-up).angleTo(targetPosition); - maxAngleDown *= -1.0; - - if (localAngle < maxAngleDown) { - localAngle = maxAngleDown; - } - } - - final right = this.right; - targetPosition.applyAxisAngle(right, localAngle); - - if (rotateAroundTarget) { - position.setValues( - target.x - targetPosition.x, - target.y - targetPosition.y, - target.z - targetPosition.z, - ); - } else { - target.setValues( - position.x + targetPosition.x, - position.y + targetPosition.y, - position.z + targetPosition.z, - ); - } - - if (rotateUp) { - _up.applyAxisAngle(right, angle); - } - } - - void roll(double angle) { - _up.applyAxisAngle(forward, angle); - } - - static CameraComponent3D? get currentCamera => - CameraComponent.currentCamera as CameraComponent3D?; - - static const distanceNear = 0.01; - static const distanceFar = 1000.0; -} diff --git a/packages/flame_3d/lib/src/camera/world_3d.dart b/packages/flame_3d/lib/src/camera/world_3d.dart deleted file mode 100644 index 6497a7d1c0a..00000000000 --- a/packages/flame_3d/lib/src/camera/world_3d.dart +++ /dev/null @@ -1,48 +0,0 @@ -import 'dart:ui'; - -import 'package:flame/components.dart' as flame; -import 'package:flame_3d/camera.dart'; -import 'package:flame_3d/components.dart'; -import 'package:flame_3d/graphics.dart'; - -/// {@template world_3d} -/// The root component for all 3D world elements. -/// -/// The primary feature of this component is that it allows [Component3D]s to -/// render directly to a [GraphicsDevice] instead of the regular rendering. -/// {@endtemplate} -class World3D extends flame.World { - /// {@macro world_3d} - World3D({ - super.children, - super.priority, - Color clearColor = const Color(0x00000000), - }) : graphics = GraphicsDevice(clearValue: clearColor); - - /// The graphical device attached to this world. - final GraphicsDevice graphics; - - final _paint = Paint(); - - @override - void renderFromCamera(Canvas canvas) { - final camera = CameraComponent3D.currentCamera!; - - final viewport = camera.viewport; - graphics.begin( - Size(viewport.virtualSize.x, viewport.virtualSize.y), - transformMatrix: camera.projectionMatrix, - ); - - culled = 0; - // ignore: invalid_use_of_internal_member - super.renderFromCamera(canvas); - - final image = graphics.end(); - canvas.drawImage(image, (-viewport.virtualSize / 2).toOffset(), _paint); - image.dispose(); - } - - // TODO(wolfen): this is only here for testing purposes - int culled = 0; -} diff --git a/packages/flame_3d/lib/src/components/component_3d.dart b/packages/flame_3d/lib/src/components/component_3d.dart deleted file mode 100644 index d381999dab2..00000000000 --- a/packages/flame_3d/lib/src/components/component_3d.dart +++ /dev/null @@ -1,113 +0,0 @@ -import 'dart:ui'; - -import 'package:flame/components.dart' show Component, HasWorldReference; -import 'package:flame/game.dart' show FlameGame; -import 'package:flame_3d/camera.dart'; -import 'package:flame_3d/components.dart'; -import 'package:flame_3d/game.dart'; -import 'package:flame_3d/graphics.dart'; -import 'package:flame_3d/resources.dart'; - -/// {@template component_3d} -/// [Component3D]s are the basic building blocks for a 3D [FlameGame]. -/// -/// It is a [Component] implementation that represents a 3D object that can be -/// freely moved around in 3D space, rotated, and scaled. -/// -/// The [Component3D] class has no visual representation of its own (except in -/// debug mode). It is common, therefore, to derive from this class -/// and implement a specific rendering logic. -/// -/// The base [Component3D] class can also be used as a container -/// for several other components. In this case, changing the position, -/// rotating or scaling the [Component3D] will affect the whole -/// group as if it was a single entity. -/// -/// The main property of this class is the [transform] (which combines -/// the [position], [rotation], and [scale]). Thus, the [Component3D] can be -/// seen as an object in 3D space where you can change its perceived -/// visualization. -/// -/// See the [MeshComponent] for a [Component3D] that has a visual representation -/// by using [Mesh]es -/// {@endtemplate} -class Component3D extends Component with HasWorldReference { - /// {@macro component_3d} - Component3D({ - Vector3? position, - Quaternion? rotation, - }) : transform = Transform3D() - ..position = position ?? Vector3.zero() - ..rotation = rotation ?? Quaternion.euler(0, 0, 0) - ..scale = Vector3.all(1); - - final Transform3D transform; - - /// The total transformation matrix for the component. This matrix combines - /// translation, rotation and scale transforms into a single entity. The - /// matrix is cached and gets recalculated only as necessary. - Matrix4 get transformMatrix => transform.transformMatrix; - - /// The position of this component's anchor on the screen. - NotifyingVector3 get position => transform.position; - set position(Vector3 position) => transform.position = position; - - /// X position of this component's anchor on the screen. - double get x => transform.x; - set x(double x) => transform.x = x; - - /// Y position of this component's anchor on the screen. - double get y => transform.y; - set y(double y) => transform.y = y; - - /// Z position of this component's anchor on the screen. - double get z => transform.z; - set z(double z) => transform.z = z; - - /// The rotation of this component. - NotifyingQuaternion get rotation => transform.rotation; - set rotation(NotifyingQuaternion rotation) => transform.rotation = rotation; - - /// The scale factor of this component. The scale can be different along - /// the X, Y and Z dimensions. A scale greater than 1 makes the component - /// bigger along that axis, and less than 1 smaller. The scale can also be negative, - /// which results in a mirror reflection along the corresponding axis. - NotifyingVector3 get scale => transform.scale; - set scale(Vector3 scale) => transform.scale = scale; - - /// Measure the distance (in parent's coordinate space) between this - /// component's anchor and the [other] component's anchor. - double distance(Component3D other) => position.distanceTo(other.position); - - @override - void renderTree(Canvas canvas) { - super.renderTree(canvas); - final camera = CameraComponent3D.currentCamera; - assert( - camera != null, - '''Component is either not part of a World3D or the render is being called outside of the camera rendering''', - ); - if (!shouldCull(camera!)) { - world.culled++; - return; - } - - // We set the priority to the distance between the camera and the object. - // This ensures that our rendering is done in a specific order allowing for - // alpha blending. - // - // Note(wolfen): we should optimize this in the long run it currently sucks. - priority = -(CameraComponent3D.currentCamera!.position - position) - .length - .abs() - .toInt(); - - bind(world.graphics); - } - - void bind(GraphicsDevice device) {} - - bool shouldCull(CameraComponent3D camera) { - return camera.frustum.containsVector3(position); - } -} diff --git a/packages/flame_3d/lib/src/components/mesh_component.dart b/packages/flame_3d/lib/src/components/mesh_component.dart deleted file mode 100644 index 4c9e8ae6003..00000000000 --- a/packages/flame_3d/lib/src/components/mesh_component.dart +++ /dev/null @@ -1,42 +0,0 @@ -import 'package:flame_3d/components.dart'; -import 'package:flame_3d/game.dart'; -import 'package:flame_3d/resources.dart'; -import 'package:flame_3d/src/camera/camera_component_3d.dart'; -import 'package:flame_3d/src/extensions/aabb3.dart'; -import 'package:flame_3d/src/graphics/graphics_device.dart'; - -/// {@template mesh_component} -/// A [Component3D] that renders a [Mesh] at the [position] with the [rotation] -/// and [scale] applied. -/// -/// This is a commonly used subclass of [Component3D]. -/// {@endtemplate} -class MeshComponent extends Component3D { - /// {@macro mesh_component} - MeshComponent({ - required Mesh mesh, - super.position, - super.rotation, - }) : _mesh = mesh; - - /// The mesh resource. - Mesh get mesh => _mesh; - final Mesh _mesh; - - Aabb3 get aabb => _aabb - ..setFrom(mesh.aabb) - ..transform(transformMatrix); - final Aabb3 _aabb = Aabb3(); - - @override - void bind(GraphicsDevice device) { - world.graphics - ..setViewModel(transformMatrix) - ..bindMesh(mesh); - } - - @override - bool shouldCull(CameraComponent3D camera) { - return camera.frustum.intersectsWithAabb3(aabb); - } -} diff --git a/packages/flame_3d/lib/src/extensions/aabb3.dart b/packages/flame_3d/lib/src/extensions/aabb3.dart deleted file mode 100644 index 1fc56a27269..00000000000 --- a/packages/flame_3d/lib/src/extensions/aabb3.dart +++ /dev/null @@ -1,15 +0,0 @@ -import 'package:flame_3d/game.dart'; - -extension Aabb3Extension on Aabb3 { - /// Set the min and max from the [other]. - void setFrom(Aabb3 other) { - min.setFrom(other.min); - max.setFrom(other.max); - } - - /// Set the min and max to zero. - void setZero() { - min.setZero(); - max.setZero(); - } -} diff --git a/packages/flame_3d/lib/src/extensions/color.dart b/packages/flame_3d/lib/src/extensions/color.dart deleted file mode 100644 index b8579e1446f..00000000000 --- a/packages/flame_3d/lib/src/extensions/color.dart +++ /dev/null @@ -1,8 +0,0 @@ -import 'dart:typed_data'; -import 'dart:ui'; - -extension ColorExtension on Color { - /// Returns a Float32List that represents the color as a vector. - Float32List get storage => - Float32List.fromList([red / 255, green / 255, blue / 255, opacity]); -} diff --git a/packages/flame_3d/lib/src/extensions/matrix4.dart b/packages/flame_3d/lib/src/extensions/matrix4.dart deleted file mode 100644 index d7c18ad50b8..00000000000 --- a/packages/flame_3d/lib/src/extensions/matrix4.dart +++ /dev/null @@ -1,31 +0,0 @@ -import 'package:flame_3d/game.dart'; - -extension Matrix4Extension on Matrix4 { - /// Set the matrix to be a view matrix. - void setAsViewMatrix(Vector3 position, Vector3 target, Vector3 up) { - setViewMatrix(this, position, target, up); - } - - /// Set the matrix to use a projection view. - void setAsPerspective( - double fovy, - double aspectRatio, - double zNear, - double zFar, - ) { - final fovYRadians = fovy * degrees2Radians; - setPerspectiveMatrix(this, fovYRadians, aspectRatio, zNear, zFar); - } - - /// Set the matrix to use a orthographic view. - void setAsOrthographic( - double nearPlaneWidth, - double aspectRatio, - double zNear, - double zFar, - ) { - final top = nearPlaneWidth / 2.0; - final right = top * aspectRatio; - setOrthographicMatrix(this, -right, right, -top, top, zNear, zFar); - } -} diff --git a/packages/flame_3d/lib/src/extensions/vector2.dart b/packages/flame_3d/lib/src/extensions/vector2.dart deleted file mode 100644 index dc1c46d3cc4..00000000000 --- a/packages/flame_3d/lib/src/extensions/vector2.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'package:flame_3d/game.dart'; - -/// Represents an immutable [Vector2]. -typedef ImmutableVector2 = ({double x, double y}); - -extension Vector2Extension on Vector2 { - /// Returns an immutable representation of the vector. - ImmutableVector2 get immutable => (x: x, y: y); -} diff --git a/packages/flame_3d/lib/src/extensions/vector3.dart b/packages/flame_3d/lib/src/extensions/vector3.dart deleted file mode 100644 index a577ed007d3..00000000000 --- a/packages/flame_3d/lib/src/extensions/vector3.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'package:flame_3d/game.dart'; - -/// Represents an immutable [Vector3]. -typedef ImmutableVector3 = ({double x, double y, double z}); - -extension Vector3Extension on Vector3 { - /// Returns an immutable representation of the vector. - ImmutableVector3 get immutable => (x: x, y: y, z: z); -} diff --git a/packages/flame_3d/lib/src/extensions/vector4.dart b/packages/flame_3d/lib/src/extensions/vector4.dart deleted file mode 100644 index cadee0da270..00000000000 --- a/packages/flame_3d/lib/src/extensions/vector4.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'package:flame_3d/game.dart'; - -/// Represents an immutable [Vector3]. -typedef ImmutableVector4 = ({double x, double y, double z, double w}); - -extension Vector4Extension on Vector4 { - /// Returns an immutable representation of the vector. - ImmutableVector4 get immutable => (x: x, y: y, z: z, w: w); -} diff --git a/packages/flame_3d/lib/src/game/flame_game_3d.dart b/packages/flame_3d/lib/src/game/flame_game_3d.dart deleted file mode 100644 index ec3fa7d8ec9..00000000000 --- a/packages/flame_3d/lib/src/game/flame_game_3d.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'dart:ui'; - -import 'package:flame/game.dart'; -import 'package:flame_3d/camera.dart'; - -class FlameGame3D extends FlameGame { - FlameGame3D({ - super.children, - W? world, - CameraComponent3D? camera, - }) : super( - world: world ?? World3D(clearColor: const Color(0xFFFFFFFF)) as W, - camera: camera ?? CameraComponent3D(), - ); - - @override - CameraComponent3D get camera => super.camera as CameraComponent3D; -} diff --git a/packages/flame_3d/lib/src/game/notifying_quaternion.dart b/packages/flame_3d/lib/src/game/notifying_quaternion.dart deleted file mode 100644 index 29385889976..00000000000 --- a/packages/flame_3d/lib/src/game/notifying_quaternion.dart +++ /dev/null @@ -1,174 +0,0 @@ -import 'dart:math'; -import 'dart:typed_data'; - -import 'package:flame_3d/game.dart'; -import 'package:flutter/widgets.dart'; - -/// {@template notifying_quaternion} -/// Extension of the standard [Quaternion] class, implementing the -/// [ChangeNotifier] functionality. This allows any interested party to be -/// notified when the value of this quaternion changes. -/// -/// This class can be used as a regular [Quaternion] class. However, if you do -/// subscribe to notifications, don't forget to eventually unsubscribe in -/// order to avoid resource leaks. -/// -/// Direct modification of this quaternion's [storage] is not allowed. -/// {@endtemplate} -class NotifyingQuaternion extends Quaternion with ChangeNotifier { - /// {@macro notifying_quaternion} - /// - /// Constructs a quaternion using the raw values [x], [y], [z], and [w]. - factory NotifyingQuaternion(double x, double y, double z, double w) => - NotifyingQuaternion._()..setValues(x, y, z, w); - NotifyingQuaternion._() : super.fromFloat32List(Float32List(4)); - - /// {@macro notifying_quaternion} - /// - /// Constructs a quaternion from a rotation matrix [rotationMatrix]. - factory NotifyingQuaternion.fromRotation(Matrix3 rotationMatrix) => - NotifyingQuaternion._()..setFromRotation(rotationMatrix); - - /// {@macro notifying_quaternion} - /// - /// Constructs a quaternion from a rotation of [angle] around [axis]. - factory NotifyingQuaternion.axisAngle(Vector3 axis, double angle) => - NotifyingQuaternion._()..setAxisAngle(axis, angle); - - /// {@macro notifying_quaternion} - /// - /// Constructs a quaternion as a copy of [other]. - factory NotifyingQuaternion.copy(Quaternion other) => - NotifyingQuaternion._()..setFrom(other); - - /// {@macro notifying_quaternion} - /// - /// Constructs a quaternion from time derivative of [q] with angular - /// velocity [omega]. - factory NotifyingQuaternion.dq(Quaternion q, Vector3 omega) => - NotifyingQuaternion._()..setDQ(q, omega); - - /// {@macro notifying_quaternion} - /// - /// Constructs a quaternion from [yaw], [pitch] and [roll]. - factory NotifyingQuaternion.euler(double yaw, double pitch, double roll) => - NotifyingQuaternion._()..setEuler(yaw, pitch, roll); - - @override - void setValues(double x, double y, double z, double w) { - super.setValues(x, y, z, w); - notifyListeners(); - } - - @override - void setAxisAngle(Vector3 axis, double radians) { - super.setAxisAngle(axis, radians); - notifyListeners(); - } - - @override - void setDQ(Quaternion q, Vector3 omega) { - super.setDQ(q, omega); - notifyListeners(); - } - - @override - void setEuler(double yaw, double pitch, double roll) { - super.setEuler(yaw, pitch, roll); - notifyListeners(); - } - - @override - void setFromRotation(Matrix3 rotationMatrix) { - super.setFromRotation(rotationMatrix); - notifyListeners(); - } - - @override - void setFromTwoVectors(Vector3 a, Vector3 b) { - super.setFromTwoVectors(a, b); - notifyListeners(); - } - - @override - void setRandom(Random rn) { - super.setRandom(rn); - notifyListeners(); - } - - @override - void setFrom(Quaternion source) { - super.setFrom(source); - notifyListeners(); - } - - @override - void operator []=(int i, double arg) { - super[i] = arg; - notifyListeners(); - } - - @override - double normalize() { - final l = super.normalize(); - notifyListeners(); - return l; - } - - @override - void add(Quaternion arg) { - super.add(arg); - notifyListeners(); - } - - @override - void sub(Quaternion arg) { - super.sub(arg); - notifyListeners(); - } - - @override - void scale(double scale) { - super.scale(scale); - notifyListeners(); - } - - @override - set x(double x) { - super.x = x; - notifyListeners(); - } - - @override - set y(double y) { - super.y = y; - notifyListeners(); - } - - @override - set z(double z) { - super.z = z; - notifyListeners(); - } - - @override - set w(double w) { - super.w = w; - notifyListeners(); - } - - @override - void conjugate() { - super.conjugate(); - notifyListeners(); - } - - @override - void inverse() { - super.inverse(); - notifyListeners(); - } - - @override - Float32List get storage => UnmodifiableFloat32ListView(super.storage); -} diff --git a/packages/flame_3d/lib/src/game/notifying_vector3.dart b/packages/flame_3d/lib/src/game/notifying_vector3.dart deleted file mode 100644 index ce62b22db66..00000000000 --- a/packages/flame_3d/lib/src/game/notifying_vector3.dart +++ /dev/null @@ -1,211 +0,0 @@ -import 'dart:typed_data'; - -import 'package:flame_3d/game.dart'; -import 'package:flutter/widgets.dart'; - -/// {@template notifying_vector_3} -/// Extension of the standard [Vector3] class, implementing the [ChangeNotifier] -/// functionality. This allows any interested party to be notified when the -/// value of this vector changes. -/// -/// This class can be used as a regular [Vector3] class. However, if you do -/// subscribe to notifications, don't forget to eventually unsubscribe in -/// order to avoid resource leaks. -/// -/// Direct modification of this vector's [storage] is not allowed. -/// {@endtemplate} -class NotifyingVector3 extends Vector3 with ChangeNotifier { - /// {@macro notifying_vector_3} - /// - /// Constructs a vector using the raw values [x], [y], and [z]. - factory NotifyingVector3(double x, double y, double z) => - NotifyingVector3.zero()..setValues(x, y, z); - - /// {@macro notifying_vector_3} - /// - /// Create an empty vector. - NotifyingVector3.zero() : super.zero(); - - /// {@macro notifying_vector_3} - /// - /// Create an vector whose values are all [v]. - factory NotifyingVector3.all(double v) => NotifyingVector3.zero()..splat(v); - - /// {@macro notifying_vector_3} - /// - /// Create a copy of the [other] vector. - factory NotifyingVector3.copy(Vector3 other) => - NotifyingVector3.zero()..setFrom(other); - - @override - void setValues(double x, double y, double z) { - super.setValues(x, y, z); - notifyListeners(); - } - - @override - void setFrom(Vector3 other) { - super.setFrom(other); - notifyListeners(); - } - - @override - void setZero() { - super.setZero(); - notifyListeners(); - } - - @override - void splat(double arg) { - super.splat(arg); - notifyListeners(); - } - - @override - void operator []=(int i, double v) { - super[i] = v; - notifyListeners(); - } - - @override - set length(double l) { - super.length = l; - notifyListeners(); - } - - @override - double normalize() { - final l = super.normalize(); - notifyListeners(); - return l; - } - - @override - void postmultiply(Matrix3 arg) { - super.postmultiply(arg); - notifyListeners(); - } - - @override - void add(Vector3 arg) { - super.add(arg); - notifyListeners(); - } - - @override - void addScaled(Vector3 arg, double factor) { - super.addScaled(arg, factor); - notifyListeners(); - } - - @override - void sub(Vector3 arg) { - super.sub(arg); - notifyListeners(); - } - - @override - void multiply(Vector3 arg) { - super.multiply(arg); - notifyListeners(); - } - - @override - void divide(Vector3 arg) { - super.divide(arg); - notifyListeners(); - } - - @override - void scale(double arg) { - super.scale(arg); - notifyListeners(); - } - - @override - void negate() { - super.negate(); - notifyListeners(); - } - - @override - void absolute() { - super.absolute(); - notifyListeners(); - } - - @override - void clamp(Vector3 min, Vector3 max) { - super.clamp(min, max); - notifyListeners(); - } - - @override - void clampScalar(double min, double max) { - super.clampScalar(min, max); - notifyListeners(); - } - - @override - void floor() { - super.floor(); - notifyListeners(); - } - - @override - void ceil() { - super.ceil(); - notifyListeners(); - } - - @override - void round() { - super.round(); - notifyListeners(); - } - - @override - void roundToZero() { - super.roundToZero(); - notifyListeners(); - } - - @override - void copyFromArray(List array, [int offset = 0]) { - super.copyFromArray(array, offset); - notifyListeners(); - } - - @override - set xy(Vector2 arg) { - super.xy = arg; - notifyListeners(); - } - - @override - set yx(Vector2 arg) { - super.yx = arg; - notifyListeners(); - } - - @override - set x(double x) { - super.x = x; - notifyListeners(); - } - - @override - set y(double y) { - super.y = y; - notifyListeners(); - } - - @override - set z(double z) { - super.z = z; - notifyListeners(); - } - - @override - Float32List get storage => UnmodifiableFloat32ListView(super.storage); -} diff --git a/packages/flame_3d/lib/src/game/transform_3d.dart b/packages/flame_3d/lib/src/game/transform_3d.dart deleted file mode 100644 index 4fc09af2642..00000000000 --- a/packages/flame_3d/lib/src/game/transform_3d.dart +++ /dev/null @@ -1,147 +0,0 @@ -import 'package:flame_3d/game.dart'; -import 'package:flutter/widgets.dart' show ChangeNotifier; - -/// {@template transform_3d} -/// This class describes a generic 3D transform, which is a combination of -/// translations, rotations and scaling. These transforms are combined into a -/// single matrix, that can be either applied to a graphical device like the -/// canvas, composed with another transform, or used directly to convert -/// coordinates. -/// -/// The transform can be visualized as 2 reference frames: a "global" and -/// a "local". At first, these two reference frames coincide. Then, the -/// following sequence of transforms is applied: -/// - translation to point [position]; -/// - rotate using the [rotation]; -/// - scaling in X, Y and Z directions by [scale] factors. -/// -/// The class is optimized for repeated use: the transform matrix is cached -/// and then recalculated only when the underlying properties change. Moreover, -/// recalculation of the transform is postponed until the matrix is actually -/// requested by the user. Thus, modifying multiple properties at once does -/// not incur the penalty of unnecessary recalculations. -/// -/// This class implements the [ChangeNotifier] API, allowing you to subscribe -/// for notifications whenever the transform matrix changes. In addition, you -/// can subscribe to get notified when individual components of the transform -/// change: [position], [scale], and [rotation]. -/// {@endtemplate} -class Transform3D extends ChangeNotifier { - /// {@macro transform_3d} - Transform3D() - : _recalculate = true, - _rotation = NotifyingQuaternion(0, 0, 0, 0), - _position = NotifyingVector3.zero(), - _scale = NotifyingVector3.all(1), - _transformMatrix = Matrix4.zero() { - _position.addListener(_markAsModified); - _scale.addListener(_markAsModified); - _rotation.addListener(_markAsModified); - } - - /// {@macro transform_3d} - /// - /// Create a copy of the [other] transform. - factory Transform3D.copy(Transform3D other) => Transform3D()..setFrom(other); - - /// {@macro transform_3d} - /// - /// Create an instance of [Transform3D] and apply the [matrix] on it. - factory Transform3D.fromMatrix4(Matrix4 matrix) { - final transform = Transform3D(); - matrix.decompose(transform.position, transform.rotation, transform.scale); - return transform; - } - - /// Clone of this. - Transform3D clone() => Transform3D.copy(this); - - /// The translation part of the transform. This translation is applied - /// relative to the global coordinate space. - /// - /// The returned vector can be modified by the user, and the changes - /// will be propagated back to the transform matrix. - NotifyingVector3 get position => _position; - set position(Vector3 position) => _position.setFrom(position); - final NotifyingVector3 _position; - - /// X coordinate of the translation transform. - double get x => _position.x; - set x(double x) => _position.x = x; - - /// Y coordinate of the translation transform. - double get y => _position.y; - set y(double y) => _position.y = y; - - /// Z coordinate of the translation transform. - double get z => _position.z; - set z(double y) => _position.z = z; - - NotifyingQuaternion get rotation => _rotation; - set rotation(Quaternion rotation) => _rotation.setFrom(rotation); - final NotifyingQuaternion _rotation; - - /// The scale part of the transform. The default scale factor is (1, 1, 1), - /// a scale greater than 1 corresponds to expansion, and less than 1 is - /// contraction. A negative scale is also allowed, and it corresponds - /// to a mirror reflection around the corresponding axis. - /// Scale factors can be different for X, Y and Z directions. - /// - /// The returned vector can be modified by the user, and the changes - /// will be propagated back to the transform matrix. - NotifyingVector3 get scale => _scale; - set scale(Vector3 scale) => _scale.setFrom(scale); - final NotifyingVector3 _scale; - - /// The total transformation matrix for the component. This matrix combines - /// translation, rotation and scale transforms into a single entity. The - /// matrix is cached and gets recalculated only when necessary. - /// - /// The returned matrix must not be modified by the user. - Matrix4 get transformMatrix { - if (_recalculate) { - _transformMatrix.setFromTranslationRotationScale( - _position, - _rotation, - _scale, - ); - _recalculate = false; - } - return _transformMatrix; - } - - final Matrix4 _transformMatrix; - bool _recalculate; - - /// Set this to the values of the [other] [Transform3D]. - void setFrom(Transform3D other) { - rotation.setFrom(other.rotation); - position.setFrom(other.position); - scale.setFrom(other.scale); - } - - /// Check whether this transform is equal to [other], up to the given - /// [tolerance]. Setting tolerance to zero will check for exact equality. - /// Transforms are considered equal if their rotation angles are the same - /// or differ by a multiple of 2π, and if all other transform parameters: - /// translation, scale, and offset are the same. - /// - /// The [tolerance] parameter is in absolute units, not relative. - bool closeTo(Transform3D other, {double tolerance = 1e-10}) { - return (position.x - other.position.x).abs() <= tolerance && - (position.y - other.position.y).abs() <= tolerance && - (position.z - other.position.z).abs() <= tolerance && - (rotation.x - other.rotation.x).abs() <= tolerance && - (rotation.y - other.rotation.y).abs() <= tolerance && - (rotation.z - other.rotation.z).abs() <= tolerance && - (rotation.w - other.rotation.w).abs() <= tolerance && - (scale.x - other.scale.x).abs() <= tolerance && - (scale.y - other.scale.y).abs() <= tolerance && - (scale.z - other.scale.z).abs() <= tolerance; - } - - void _markAsModified() { - _recalculate = true; - notifyListeners(); - } -} diff --git a/packages/flame_3d/lib/src/graphics/graphics_device.dart b/packages/flame_3d/lib/src/graphics/graphics_device.dart deleted file mode 100644 index a609bbd8d65..00000000000 --- a/packages/flame_3d/lib/src/graphics/graphics_device.dart +++ /dev/null @@ -1,190 +0,0 @@ -import 'dart:typed_data'; -import 'dart:ui'; - -import 'package:flame_3d/game.dart'; -import 'package:flame_3d/resources.dart'; -import 'package:flutter_gpu/gpu.dart' as gpu; - -enum BlendState { - additive, - alphaBlend, - opaque, -} - -enum DepthStencilState { - standard, - depthRead, - none, -} - -/// {@template graphics_device} -/// The Graphical Device provides a way for developers to interact with the GPU -/// by binding different resources to it. -/// -/// A single render call starts with a call to [begin] and only ends when [end] -/// is called. Anything that gets binded to the device in between will be -/// uploaded to the GPU and returns as an [Image] in [end]. -/// {@endtemplate} -class GraphicsDevice { - /// {@macro graphics_device} - GraphicsDevice({this.clearValue = const Color(0x00000000)}); - - /// The clear value, used to clear out the screen. - final Color clearValue; - - late gpu.CommandBuffer _commandBuffer; - late gpu.HostBuffer _hostBuffer; - late gpu.RenderPass _renderPass; - late gpu.RenderTarget _renderTarget; - final _transformMatrix = Matrix4.identity(); - final _viewModelMatrix = Matrix4.identity(); - - Size _previousSize = Size.zero; - - /// Begin a new rendering batch. - /// - /// After [begin] is called the graphics device can be used to bind resources - /// like [Mesh]s, [Material]s and [Texture]s. - /// - /// Once you have executed all your bindings you can submit the batch to the - /// GPU with [end]. - void begin( - Size size, { - // TODO(wolfen): unused at the moment - BlendState blendState = BlendState.alphaBlend, - // TODO(wolfen): used incorrectly - DepthStencilState depthStencilState = DepthStencilState.depthRead, - Matrix4? transformMatrix, - }) { - _commandBuffer = gpu.gpuContext.createCommandBuffer(); - _hostBuffer = gpu.gpuContext.createHostBuffer(); - _renderPass = _commandBuffer.createRenderPass(_getRenderTarget(size)) - ..setColorBlendEnable(true) - ..setColorBlendEquation( - gpu.ColorBlendEquation( - sourceAlphaBlendFactor: blendState == BlendState.alphaBlend - ? gpu.BlendFactor.oneMinusSourceAlpha - : gpu.BlendFactor.one, - ), - ) - ..setDepthWriteEnable(depthStencilState == DepthStencilState.depthRead) - ..setDepthCompareOperation( - // TODO(wolfen): this is not correctly implemented AT all. - switch (depthStencilState) { - DepthStencilState.none => gpu.CompareFunction.never, - DepthStencilState.standard => gpu.CompareFunction.always, - DepthStencilState.depthRead => gpu.CompareFunction.less, - }, - ); - _transformMatrix.setFrom(transformMatrix ?? Matrix4.identity()); - } - - /// Submit the rendering batch and it's the commands to the GPU and return - /// the result. - Image end() { - _commandBuffer.submit(); - return _renderTarget.colorAttachments[0].texture.asImage(); - } - - void clearBindings() { - _renderPass.clearBindings(); - } - - void setViewModel(Matrix4 mvp) => _viewModelMatrix.setFrom(mvp); - - /// Bind a [mesh]. - void bindMesh(Mesh mesh) { - _renderPass.clearBindings(); - mesh.bind(this); - _renderPass.draw(); - } - - /// Bind a [surface]. - void bindSurface(Surface surface) { - _renderPass.clearBindings(); - if (surface.material != null) { - bindMaterial(surface.material!); - } - - _renderPass.bindVertexBuffer( - gpu.BufferView( - surface.resource!, - offsetInBytes: 0, - lengthInBytes: surface.verticesBytes, - ), - surface.vertexCount, - ); - - _renderPass.bindIndexBuffer( - gpu.BufferView( - surface.resource!, - offsetInBytes: surface.verticesBytes, - lengthInBytes: surface.indicesBytes, - ), - gpu.IndexType.int16, - surface.indexCount, - ); - - _renderPass.draw(); - } - - /// Bind a [material] and set up the buffer correctly. - void bindMaterial(Material material) { - _renderPass.bindPipeline(material.resource); - material.vertexBuffer - ..clear() - ..addMatrix4(_transformMatrix.multiplied(_viewModelMatrix)); - material.fragmentBuffer.clear(); - material.bind(this); - } - - /// Bind a [shader] with the given [buffer]. - void bindShader(gpu.Shader shader, ShaderBuffer buffer) { - bindUniform( - shader, - buffer.slot, - buffer.bytes.asByteData(), - ); - } - - /// Bind a uniform slot of [name] with the [data] on the [shader]. - void bindUniform(gpu.Shader shader, String name, ByteData data) { - _renderPass.bindUniform( - shader.getUniformSlot(name), - _hostBuffer.emplace(data), - ); - } - - void bindTexture(gpu.Shader shader, String name, Texture texture) { - _renderPass.bindTexture(shader.getUniformSlot(name), texture.resource); - } - - gpu.RenderTarget _getRenderTarget(Size size) { - if (_previousSize != size) { - _previousSize = size; - - final colorTexture = gpu.gpuContext.createTexture( - gpu.StorageMode.devicePrivate, - size.width.toInt(), - size.height.toInt(), - ); - - final depthTexture = gpu.gpuContext.createTexture( - gpu.StorageMode.deviceTransient, - size.width.toInt(), - size.height.toInt(), - format: gpu.gpuContext.defaultDepthStencilFormat, - ); - - _renderTarget = gpu.RenderTarget.singleColor( - gpu.ColorAttachment(texture: colorTexture!, clearValue: clearValue), - depthStencilAttachment: gpu.DepthStencilAttachment( - texture: depthTexture!, - depthClearValue: 1.0, - ), - ); - } - - return _renderTarget; - } -} diff --git a/packages/flame_3d/lib/src/resources/material.dart b/packages/flame_3d/lib/src/resources/material.dart deleted file mode 100644 index dab1184d5dc..00000000000 --- a/packages/flame_3d/lib/src/resources/material.dart +++ /dev/null @@ -1,2 +0,0 @@ -export 'material/material.dart'; -export 'material/standard_material.dart'; diff --git a/packages/flame_3d/lib/src/resources/material/material.dart b/packages/flame_3d/lib/src/resources/material/material.dart deleted file mode 100644 index 5d9706fef34..00000000000 --- a/packages/flame_3d/lib/src/resources/material/material.dart +++ /dev/null @@ -1,68 +0,0 @@ -import 'dart:typed_data'; - -import 'package:flame_3d/game.dart'; -import 'package:flame_3d/graphics.dart'; -import 'package:flame_3d/src/resources/resource.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter_gpu/gpu.dart' as gpu; - -/// {@template material} -/// Base material [Resource], it holds the shader library that should be used -/// for the texture. -/// {@endtemplate} -abstract class Material extends Resource { - /// {@macro material} - Material(gpu.ShaderLibrary library) - : super( - gpu.gpuContext.createRenderPipeline( - library['TextureVertex']!, - library['TextureFragment']!, - ), - ); - - final _vertexBuffer = ShaderBuffer('VertexInfo'); - final _fragmentBuffer = ShaderBuffer('FragmentInfo'); - - /// The vertex shader being used. - gpu.Shader get vertexShader => resource.vertexShader; - ShaderBuffer get vertexBuffer => _vertexBuffer; - - /// The fragment shader being used. - gpu.Shader get fragmentShader => resource.fragmentShader; - ShaderBuffer get fragmentBuffer => _fragmentBuffer; - - @mustCallSuper - void bind(GraphicsDevice device) { - device.bindShader(vertexShader, _vertexBuffer); - device.bindShader(fragmentShader, fragmentBuffer); - } -} - -/// {@template shader_buffer} -/// Class that buffers all the float uniforms that have to be uploaded to a -/// shader. -/// {@endtemplate} -class ShaderBuffer { - /// {@macro shader_buffer} - ShaderBuffer(this.slot); - - final String slot; - - final List _storage = []; - ByteBuffer get bytes => Float32List.fromList(_storage).buffer; - - /// Add a [Vector2] to the buffer. - void addVector2(Vector2 vector) => _storage.addAll(vector.storage); - - /// Add a [Vector3] to the buffer. - void addVector3(Vector3 vector) => _storage.addAll(vector.storage); - - /// Add a [Vector4] to the buffer. - void addVector4(Vector4 vector) => _storage.addAll(vector.storage); - - /// Add a [Matrix4] to the buffer. - void addMatrix4(Matrix4 matrix) => _storage.addAll(matrix.storage); - - /// Clear the buffer. - void clear() => _storage.clear(); -} diff --git a/packages/flame_3d/lib/src/resources/material/standard_material.dart b/packages/flame_3d/lib/src/resources/material/standard_material.dart deleted file mode 100644 index 854045c9e5d..00000000000 --- a/packages/flame_3d/lib/src/resources/material/standard_material.dart +++ /dev/null @@ -1,48 +0,0 @@ -import 'dart:ui'; - -import 'package:flame_3d/game.dart'; -import 'package:flame_3d/graphics.dart'; -import 'package:flame_3d/resources.dart'; -import 'package:flutter_gpu/gpu.dart' as gpu; - -/// {@template standard_material} -/// The standard material, it applies the [albedoColor] to the [albedoTexture]. -/// {@endtemplate} -class StandardMaterial extends Material { - /// {@macro standard_material} - StandardMaterial({ - Texture? albedoTexture, - Color? albedoColor, - }) : albedoTexture = albedoTexture ?? Texture.standard, - _albedoColorCache = Vector4.zero(), - super(_library) { - this.albedoColor = albedoColor ?? const Color(0xFFFFFFFF); - } - - Texture albedoTexture; - - Color get albedoColor => _albedoColor; - set albedoColor(Color color) { - _albedoColor = color; - _albedoColorCache.setValues( - color.red / 255, - color.green / 255, - color.blue / 255, - color.alpha / 255, - ); - } - - late Color _albedoColor; - final Vector4 _albedoColorCache; - - @override - void bind(GraphicsDevice device) { - fragmentBuffer.addVector4(_albedoColorCache); - device.bindTexture(fragmentShader, 'albedoTexture', albedoTexture); - return super.bind(device); - } - - static final _library = gpu.ShaderLibrary.fromAsset( - 'packages/flame_3d/assets/shaders/standard_material.shaderbundle', - )!; -} diff --git a/packages/flame_3d/lib/src/resources/mesh.dart b/packages/flame_3d/lib/src/resources/mesh.dart deleted file mode 100644 index 3ae45920121..00000000000 --- a/packages/flame_3d/lib/src/resources/mesh.dart +++ /dev/null @@ -1,6 +0,0 @@ -export 'mesh/cuboid_mesh.dart'; -export 'mesh/mesh.dart'; -export 'mesh/plane_mesh.dart'; -export 'mesh/sphere_mesh.dart'; -export 'mesh/surface.dart'; -export 'mesh/vertex.dart'; diff --git a/packages/flame_3d/lib/src/resources/mesh/cuboid_mesh.dart b/packages/flame_3d/lib/src/resources/mesh/cuboid_mesh.dart deleted file mode 100644 index 988730c1910..00000000000 --- a/packages/flame_3d/lib/src/resources/mesh/cuboid_mesh.dart +++ /dev/null @@ -1,64 +0,0 @@ -import 'package:flame_3d/game.dart'; -import 'package:flame_3d/resources.dart'; - -/// {@template cuboid_mesh} -/// Represents a Cuboid's geometry with a single surface. -/// {@endtemplate} -class CuboidMesh extends Mesh { - /// {@macro cuboid_mesh} - CuboidMesh({ - required Vector3 size, - Material? material, - }) { - final Vector3(:x, :y, :z) = size / 2; - - final vertices = [ - // Face 1 (front) - Vertex(position: Vector3(-x, -y, -z), texCoord: Vector2(0, 0)), - Vertex(position: Vector3(x, -y, -z), texCoord: Vector2(1, 0)), - Vertex(position: Vector3(x, y, -z), texCoord: Vector2(1, 1)), - Vertex(position: Vector3(-x, y, -z), texCoord: Vector2(0, 1)), - - // Face 2 (back) - Vertex(position: Vector3(-x, -y, z), texCoord: Vector2(0, 0)), - Vertex(position: Vector3(x, -y, z), texCoord: Vector2(1, 0)), - Vertex(position: Vector3(x, y, z), texCoord: Vector2(1, 1)), - Vertex(position: Vector3(-x, y, z), texCoord: Vector2(0, 1)), - - // Face 3 (left) - Vertex(position: Vector3(-x, -y, z), texCoord: Vector2(0, 0)), - Vertex(position: Vector3(-x, -y, -z), texCoord: Vector2(1, 0)), - Vertex(position: Vector3(-x, y, -z), texCoord: Vector2(1, 1)), - Vertex(position: Vector3(-x, y, z), texCoord: Vector2(0, 1)), - - // Face 4 (right) - Vertex(position: Vector3(x, -y, -z), texCoord: Vector2(0, 0)), - Vertex(position: Vector3(x, -y, z), texCoord: Vector2(1, 0)), - Vertex(position: Vector3(x, y, z), texCoord: Vector2(1, 1)), - Vertex(position: Vector3(x, y, -z), texCoord: Vector2(0, 1)), - - // Face 5 (top) - Vertex(position: Vector3(-x, y, -z), texCoord: Vector2(0, 0)), - Vertex(position: Vector3(x, y, -z), texCoord: Vector2(1, 0)), - Vertex(position: Vector3(x, y, z), texCoord: Vector2(1, 1)), - Vertex(position: Vector3(-x, y, z), texCoord: Vector2(0, 1)), - - // Face 6 (bottom) - Vertex(position: Vector3(-x, -y, z), texCoord: Vector2(0, 0)), - Vertex(position: Vector3(x, -y, z), texCoord: Vector2(1, 0)), - Vertex(position: Vector3(x, -y, -z), texCoord: Vector2(1, 1)), - Vertex(position: Vector3(-x, -y, -z), texCoord: Vector2(0, 1)), - ]; - - final indices = [ - 0, 1, 2, 2, 3, 0, // Face 1 - 4, 5, 6, 6, 7, 4, // Face 2 - 8, 9, 10, 10, 11, 8, // Face 3 - 12, 13, 14, 14, 15, 12, // Face 4 - 16, 17, 18, 18, 19, 16, // Face 5 - 20, 21, 22, 22, 23, 20, // Face 6 - ]; - - addSurface(vertices, indices, material: material); - } -} diff --git a/packages/flame_3d/lib/src/resources/mesh/mesh.dart b/packages/flame_3d/lib/src/resources/mesh/mesh.dart deleted file mode 100644 index c3366bfb2aa..00000000000 --- a/packages/flame_3d/lib/src/resources/mesh/mesh.dart +++ /dev/null @@ -1,67 +0,0 @@ -import 'package:flame_3d/game.dart'; -import 'package:flame_3d/graphics.dart'; -import 'package:flame_3d/resources.dart'; - -/// {@template mesh} -/// A [Resource] that represents a geometric shape that is divided up in one or -/// more [Surface]s. -/// -/// This class isn't a true resource, it does not upload it self to the GPU. -/// Instead it uploads [Surface]s, it acts as a proxy. -/// {@endtemplate} -class Mesh extends Resource { - /// {@macro mesh} - Mesh() - : _surfaces = [], - super(null); - - /// The AABB of the mesh. - /// - /// This is the sum of all the AABB's of the surfaces it contains. - Aabb3 get aabb { - if (_aabb == null) { - var aabb = Aabb3(); - for (var i = 0; i < _surfaces.length; i++) { - if (i == 0) { - aabb = _surfaces[i].aabb; - } else { - aabb.hull(_surfaces[i].aabb); - } - } - _aabb = aabb; - } - return _aabb!; - } - - Aabb3? _aabb; - - final List _surfaces; - - /// The total surface count of the mesh. - int get surfaceCount => _surfaces.length; - - void bind(GraphicsDevice device) { - for (final surface in _surfaces) { - device.bindSurface(surface); - } - } - - /// Add a new surface represented by [vertices], [indices] and a material. - void addSurface( - List vertices, - List indices, { - Material? material, - }) { - _surfaces.add(Surface(vertices, indices, material)); - } - - /// Add a material to the surface at [index]. - void addMaterialToSurface(int index, Material material) { - _surfaces[index].material = material; - } - - /// Get a material from the surface at [index]. - Material? getMaterialToSurface(int index) { - return _surfaces[index].material; - } -} diff --git a/packages/flame_3d/lib/src/resources/mesh/plane_mesh.dart b/packages/flame_3d/lib/src/resources/mesh/plane_mesh.dart deleted file mode 100644 index f84a2be90ef..00000000000 --- a/packages/flame_3d/lib/src/resources/mesh/plane_mesh.dart +++ /dev/null @@ -1,23 +0,0 @@ -import 'package:flame_3d/game.dart'; -import 'package:flame_3d/resources.dart'; - -/// {@template plane_mesh} -/// Represents a 2D Plane's geometry with a single surface. -/// {@endtemplate} -class PlaneMesh extends Mesh { - /// {@macro plane_mesh} - PlaneMesh({ - required Vector2 size, - Material? material, - }) { - final Vector2(:x, :y) = size / 2; - - final vertices = [ - Vertex(position: Vector3(-x, 0, -y), texCoord: Vector2(0, 0)), - Vertex(position: Vector3(x, 0, -y), texCoord: Vector2(1, 0)), - Vertex(position: Vector3(x, 0, y), texCoord: Vector2(1, 1)), - Vertex(position: Vector3(-x, 0, y), texCoord: Vector2(0, 1)), - ]; - addSurface(vertices, [0, 1, 2, 2, 3, 0], material: material); - } -} diff --git a/packages/flame_3d/lib/src/resources/mesh/sphere_mesh.dart b/packages/flame_3d/lib/src/resources/mesh/sphere_mesh.dart deleted file mode 100644 index dafca4b8ba7..00000000000 --- a/packages/flame_3d/lib/src/resources/mesh/sphere_mesh.dart +++ /dev/null @@ -1,53 +0,0 @@ -import 'dart:math' as math; - -import 'package:flame_3d/game.dart'; -import 'package:flame_3d/resources.dart'; - -/// {@template sphere_mesh} -/// Represents a Sphere's geometry with a single surface. -/// {@endtemplate} -class SphereMesh extends Mesh { - /// {@macro sphere_mesh} - SphereMesh({ - required double radius, - int segments = 64, - Material? material, - }) { - final vertices = []; - for (var i = 0; i <= segments; i++) { - final theta = i * (2 * math.pi) / segments; - for (var j = 0; j <= segments; j++) { - final phi = j * math.pi / segments; - - final x = radius * math.sin(phi) * math.cos(theta); - final y = radius * math.cos(phi); - final z = radius * math.sin(phi) * math.sin(theta); - - final u = theta / (2 * math.pi); - final v = phi / math.pi; - - vertices.add( - Vertex(position: Vector3(x, y, z), texCoord: Vector2(u, v)), - ); - } - } - - final indices = []; - for (var i = 0; i < segments; i++) { - for (var j = 0; j < segments; j++) { - final first = i * (segments + 1) + j; - final second = first + segments + 1; - - indices.add(first); - indices.add(second); - indices.add(first + 1); - - indices.add(second); - indices.add(second + 1); - indices.add(first + 1); - } - } - - addSurface(vertices, indices, material: material); - } -} diff --git a/packages/flame_3d/lib/src/resources/mesh/surface.dart b/packages/flame_3d/lib/src/resources/mesh/surface.dart deleted file mode 100644 index 52f591d0872..00000000000 --- a/packages/flame_3d/lib/src/resources/mesh/surface.dart +++ /dev/null @@ -1,96 +0,0 @@ -import 'dart:math' as math; -import 'dart:typed_data'; - -import 'package:flame_3d/game.dart'; -import 'package:flame_3d/resources.dart'; -import 'package:flutter_gpu/gpu.dart' as gpu; - -enum PrimitiveType { - triangles, -} - -/// {@template surface} -/// Base surface [Resource], it describes a single surface to be rendered. -/// {@endtemplate} -class Surface extends Resource { - /// {@macro surface} - Surface( - List vertices, - List indices, [ - this.material, - ]) : super(null) { - // `TODO`(bdero): This should have an attribute map instead and be fully SoA - // but vertex attributes in Impeller aren't flexible enough yet. - // See also https://github.com/flutter/flutter/issues/116168. - _vertices = Float32List.fromList( - vertices.fold([], (p, v) => p..addAll(v.storage)), - ).buffer; - _vertexCount = _vertices.lengthInBytes ~/ (vertices.length * 9); - - _indices = Uint16List.fromList(indices).buffer; - _indexCount = _indices.lengthInBytes ~/ 2; - - _calculateAabb(vertices); - } - - Material? material; - - Aabb3 get aabb => _aabb; - late Aabb3 _aabb; - - int get verticesBytes => _vertices.lengthInBytes; - late ByteBuffer _vertices; - - int get vertexCount => _vertexCount; - late int _vertexCount; - - int get indicesBytes => _indices.lengthInBytes; - late ByteBuffer _indices; - - int get indexCount => _indexCount; - late int _indexCount; - - @override - gpu.DeviceBuffer? get resource { - var resource = super.resource; - final sizeInBytes = _vertices.lengthInBytes + _indices.lengthInBytes; - if (resource?.sizeInBytes != sizeInBytes) { - // Store the device buffer in the resource parent. - resource = super.resource = gpu.gpuContext.createDeviceBuffer( - gpu.StorageMode.hostVisible, - sizeInBytes, - ); - - resource - ?..overwrite(_vertices.asByteData()) - ..overwrite( - _indices.asByteData(), - destinationOffsetInBytes: _vertices.lengthInBytes, - ); - } - return resource; - } - - void _calculateAabb(List vertices) { - var minX = double.infinity; - var minY = double.infinity; - var minZ = double.infinity; - var maxX = double.negativeInfinity; - var maxY = double.negativeInfinity; - var maxZ = double.negativeInfinity; - - for (final vertex in vertices) { - minX = math.min(minX, vertex.position.x); - minY = math.min(minY, vertex.position.y); - minZ = math.min(minZ, vertex.position.z); - maxX = math.max(maxX, vertex.position.x); - maxY = math.max(maxY, vertex.position.y); - maxZ = math.max(maxZ, vertex.position.z); - } - - _aabb = Aabb3.minMax( - Vector3(minX, minY, minZ), - Vector3(maxX, maxY, maxZ), - ); - } -} diff --git a/packages/flame_3d/lib/src/resources/mesh/vertex.dart b/packages/flame_3d/lib/src/resources/mesh/vertex.dart deleted file mode 100644 index b278095df65..00000000000 --- a/packages/flame_3d/lib/src/resources/mesh/vertex.dart +++ /dev/null @@ -1,57 +0,0 @@ -import 'dart:typed_data'; - -import 'package:flame_3d/extensions.dart'; -import 'package:flame_3d/game.dart'; -import 'package:flutter/widgets.dart'; - -/// {@template vertex} -/// Represents a vertex in 3D space. -/// -/// A vertex consists out of space coordinates, UV/texture coordinates and a -/// color. -/// {@endtemplate} -@immutable -class Vertex { - /// {@macro vertex} - Vertex({ - required Vector3 position, - required Vector2 texCoord, - Vector3? normal, - this.color = const Color(0xFFFFFFFF), - }) : position = position.immutable, - texCoord = texCoord.immutable, - normal = (normal ?? Vector3.zero()).immutable, - _storage = Float32List.fromList([ - ...position.storage, - ...texCoord.storage, - // `TODO`(wolfen): uhh normals fuck shit up, I should read up on it - // ...(normal ?? Vector3.zero()).storage, - ...color.storage, - ]); - - Float32List get storage => _storage; - final Float32List _storage; - - /// The position of the vertex in 3D space. - final ImmutableVector3 position; - - /// The UV coordinates of the texture to map. - final ImmutableVector2 texCoord; - - /// The normal vector of the vertex. - final ImmutableVector3 normal; - - /// The color on the vertex. - final Color color; - - @override - bool operator ==(Object other) => - other is Vertex && - position == other.position && - texCoord == other.texCoord && - normal == other.normal && - color == other.color; - - @override - int get hashCode => Object.hashAll([position, texCoord, normal, color]); -} diff --git a/packages/flame_3d/lib/src/resources/resource.dart b/packages/flame_3d/lib/src/resources/resource.dart deleted file mode 100644 index 068a0227b56..00000000000 --- a/packages/flame_3d/lib/src/resources/resource.dart +++ /dev/null @@ -1,19 +0,0 @@ -import 'package:flutter/foundation.dart'; - -// TODO(wolfen): in the long run it would be nice of we can make it -// automatically refer to same type of objects to prevent memory leaks - -/// {@template resource} -/// A Resource is the base class for any resource typed classes. The primary -/// use case is to be a data container. -/// {@endtemplate} -class Resource { - /// {@macro resource} - Resource(this._resource); - - /// The resource data. - R get resource => _resource; - @protected - set resource(R resource) => _resource = resource; - R _resource; -} diff --git a/packages/flame_3d/lib/src/resources/texture.dart b/packages/flame_3d/lib/src/resources/texture.dart deleted file mode 100644 index aad730afa8c..00000000000 --- a/packages/flame_3d/lib/src/resources/texture.dart +++ /dev/null @@ -1,3 +0,0 @@ -export 'texture/color_texture.dart'; -export 'texture/image_texture.dart'; -export 'texture/texture.dart'; diff --git a/packages/flame_3d/lib/src/resources/texture/color_texture.dart b/packages/flame_3d/lib/src/resources/texture/color_texture.dart deleted file mode 100644 index 2ef6a490e7e..00000000000 --- a/packages/flame_3d/lib/src/resources/texture/color_texture.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'dart:typed_data'; -import 'dart:ui'; - -import 'package:flame_3d/resources.dart'; - -/// {@template color_texture} -/// A texture that holds a single color. By default it creates a 1x1 texture. -/// {@endtemplate} -class ColorTexture extends Texture { - /// {@macro color_texture} - ColorTexture(Color color, {int width = 1, int height = 1}) - : super( - Uint32List.fromList( - List.filled(width * height, color.value), - ).buffer.asByteData(), - width: width, - height: height, - format: PixelFormat.bgra8888, - ); -} diff --git a/packages/flame_3d/lib/src/resources/texture/image_texture.dart b/packages/flame_3d/lib/src/resources/texture/image_texture.dart deleted file mode 100644 index 4f395577ff5..00000000000 --- a/packages/flame_3d/lib/src/resources/texture/image_texture.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'dart:ui'; - -import 'package:flame_3d/resources.dart'; - -/// {@template image_texture} -/// A texture that holds an image as it's render-able texture. -/// {@endtemplate} -class ImageTexture extends Texture { - /// {@macro image_texture} - ImageTexture(super.source, {required super.width, required super.height}); - - /// Create a [ImageTexture] from the given [image]. - static Future create(Image image) async { - final Image(:toByteData, :width, :height) = image; - return ImageTexture((await toByteData())!, width: width, height: height); - } -} diff --git a/packages/flame_3d/lib/src/resources/texture/texture.dart b/packages/flame_3d/lib/src/resources/texture/texture.dart deleted file mode 100644 index 8f4c840fea6..00000000000 --- a/packages/flame_3d/lib/src/resources/texture/texture.dart +++ /dev/null @@ -1,42 +0,0 @@ -import 'dart:typed_data'; -import 'dart:ui'; - -import 'package:flame_3d/resources.dart'; -import 'package:flutter_gpu/gpu.dart' as gpu; - -/// {@template texture} -/// Base texture [Resource], represents an image/texture on the GPU. -/// {@endtemplate} -class Texture extends Resource { - /// {@macro texture} - Texture( - ByteData sourceData, { - required int width, - required int height, - PixelFormat format = PixelFormat.rgba8888, - }) : super( - gpu.gpuContext.createTexture( - gpu.StorageMode.hostVisible, - width, - height, - format: switch (format) { - PixelFormat.rgba8888 => gpu.PixelFormat.r8g8b8a8UNormInt, - PixelFormat.bgra8888 => gpu.PixelFormat.b8g8r8a8UNormInt, - PixelFormat.rgbaFloat32 => gpu.PixelFormat.r32g32b32a32Float, - }, - )! - ..overwrite(sourceData), - ); - - int get width => resource.width; - - int get height => resource.height; - - Image toImage() => resource.asImage(); - - /// A transparent single pixel texture. - static final empty = ColorTexture(const Color(0x00000000)); - - /// A white single pixel texture. - static final standard = ColorTexture(const Color(0xFFFFFFFF)); -} diff --git a/packages/flame_3d/pubspec.yaml b/packages/flame_3d/pubspec.yaml deleted file mode 100644 index 44e71ff7131..00000000000 --- a/packages/flame_3d/pubspec.yaml +++ /dev/null @@ -1,28 +0,0 @@ -name: flame_3d -description: Experimental 3D support for the Flame Engine -version: 0.1.0-dev.1 -homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_3d -funding: - - https://opencollective.com/blue-fire - - https://github.com/sponsors/bluefireteam - - https://patreon.com/bluefireoss - -environment: - sdk: '>=3.3.0-279.2.beta <4.0.0' - flutter: ">=3.13.0" - -dependencies: - flame: ^1.16.0 - flutter: - sdk: flutter - flutter_gpu: - -dev_dependencies: - flame_lint: ^1.1.2 - flame_test: ^1.15.3 - flutter_test: - sdk: flutter - -flutter: - assets: - - assets/shaders/ \ No newline at end of file diff --git a/packages/flame_3d/shaders/standard_material.frag b/packages/flame_3d/shaders/standard_material.frag deleted file mode 100644 index 8253fe6945c..00000000000 --- a/packages/flame_3d/shaders/standard_material.frag +++ /dev/null @@ -1,16 +0,0 @@ - -in vec2 fragTexCoord; -in vec4 fragColor; - -out vec4 outColor; - -uniform sampler2D albedoTexture; - -uniform FragmentInfo { - vec4 albedoColor; -} fragment_info; - -void main() { - vec4 texelColor = texture(albedoTexture, fragTexCoord); - outColor = texelColor * fragment_info.albedoColor * fragColor; -} diff --git a/packages/flame_3d/shaders/standard_material.vert b/packages/flame_3d/shaders/standard_material.vert deleted file mode 100644 index d93ce85ecc6..00000000000 --- a/packages/flame_3d/shaders/standard_material.vert +++ /dev/null @@ -1,16 +0,0 @@ -in vec3 vertexPosition; -in vec2 vertexTexCoord; -in vec4 vertexColor; - -out vec2 fragTexCoord; -out vec4 fragColor; - -uniform VertexInfo { - mat4 mvp; -} vertex_info; - -void main() { - fragTexCoord = vertexTexCoord; - fragColor = vertexColor; - gl_Position = vertex_info.mvp * vec4(vertexPosition, 1.0); -} From 2ed71a3c89b3c2182828f2812d8515811483f4d5 Mon Sep 17 00:00:00 2001 From: Ahmad Fakhri <105256764+fa-fifi@users.noreply.github.com> Date: Sat, 2 Mar 2024 05:01:53 +0800 Subject: [PATCH 10/79] fix: Size for `SpriteComponent.fromImage` should be nullable (#3054) I received an assertion error after I set `autoResize` to true when I am using `SpriteComponent.fromImage` component. It's kinda weird for me that the message tells me **"If size is set, autoResize should be false or size should be null when autoResize is true.''**, but the thing is I never set the size for that image yet. Then, I check the code and I found out that the size will never be null anyway, so the `autoresize` should always be false. In this PR, I just remove all the fallback value for `size`, so it would not give an assertion error when `size` is not being set yet while the `autoresize` is true. --------- Co-authored-by: Lukas Klingsbo --- .../flame/lib/src/components/sprite_component.dart | 3 +-- .../flame/test/components/sprite_component_test.dart | 12 ++++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/flame/lib/src/components/sprite_component.dart b/packages/flame/lib/src/components/sprite_component.dart index c647f8eed5b..5f50a371d91 100644 --- a/packages/flame/lib/src/components/sprite_component.dart +++ b/packages/flame/lib/src/components/sprite_component.dart @@ -2,7 +2,6 @@ import 'dart:ui'; import 'package:flame/components.dart'; import 'package:flame/src/effects/provider_interfaces.dart'; -import 'package:flame/src/extensions/image.dart'; import 'package:meta/meta.dart'; export '../sprite.dart'; @@ -75,7 +74,7 @@ class SpriteComponent extends PositionComponent autoResize: autoResize, paint: paint, position: position, - size: size ?? srcSize ?? image.size, + size: size, scale: scale, angle: angle, anchor: anchor, diff --git a/packages/flame/test/components/sprite_component_test.dart b/packages/flame/test/components/sprite_component_test.dart index 3b438de8e68..8cb0952e1ad 100644 --- a/packages/flame/test/components/sprite_component_test.dart +++ b/packages/flame/test/components/sprite_component_test.dart @@ -44,8 +44,20 @@ Future main() async { () => SpriteComponent(autoResize: true, size: Vector2.all(2)), throwsAssertionError, ); + expect( + () => SpriteComponent.fromImage( + image, + autoResize: true, + size: Vector2.all(2), + ), + throwsAssertionError, + ); expect(() => SpriteComponent(autoResize: false), throwsAssertionError); + expect( + () => SpriteComponent.fromImage(image, autoResize: false), + throwsAssertionError, + ); }); test('default value set correctly when not provided explicitly', () { From 72678c676020480beae1d944ee687fd73eac9cf7 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Sat, 2 Mar 2024 00:42:54 +0100 Subject: [PATCH 11/79] fix: FutureOr return type of ComponentViewportMargin.onLoad (#3059) Closes #3058 --- .../lib/src/components/mixins/component_viewport_margin.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/flame/lib/src/components/mixins/component_viewport_margin.dart b/packages/flame/lib/src/components/mixins/component_viewport_margin.dart index 666b0a7d43b..04b913353c0 100644 --- a/packages/flame/lib/src/components/mixins/component_viewport_margin.dart +++ b/packages/flame/lib/src/components/mixins/component_viewport_margin.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flame/camera.dart'; import 'package:flame/components.dart'; import 'package:flame/effects.dart'; @@ -29,7 +31,7 @@ mixin ComponentViewportMargin @override @mustCallSuper - Future onLoad() async { + FutureOr onLoad() async { super.onLoad(); assert(parent is ReadOnlySizeProvider, 'The parent must provide a size.'); // If margin is not null we will update the position `onGameResize` instead From 30fde805b4650cc802f9908f9a1149dae19669d4 Mon Sep 17 00:00:00 2001 From: DevKage <33748002+ufrshubham@users.noreply.github.com> Date: Sun, 3 Mar 2024 17:47:54 +0530 Subject: [PATCH 12/79] refactor!: Use HasTimeScale for Route (#3064) This PR replaces the `Route.timeSpeed` with `HasTimeScale.timeScale`. --- packages/flame/lib/src/components/route.dart | 18 ++++++------------ packages/flame/test/components/route_test.dart | 6 +++--- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/packages/flame/lib/src/components/route.dart b/packages/flame/lib/src/components/route.dart index cc0ed666062..6319bcdcfb3 100644 --- a/packages/flame/lib/src/components/route.dart +++ b/packages/flame/lib/src/components/route.dart @@ -20,7 +20,8 @@ import 'package:meta/meta.dart'; /// any potentially costly initialization operations. /// /// Routes are managed by the [RouterComponent] component. -class Route extends PositionComponent with ParentIsA { +class Route extends PositionComponent + with ParentIsA, HasTimeScale { Route( Component Function()? builder, { this.transparent = false, @@ -82,13 +83,6 @@ class Route extends PositionComponent with ParentIsA { return _builder!(); } - /// The time "speed" factor. - /// - /// The value of 1 means that the time on this page runs normally. The value - /// less than 1 corresponds to time running slower than normal. The speed of - /// zero means the time on this page is stopped. - double timeSpeed = 1.0; - /// Completely stops time for the managed page. /// /// When the time is stopped, the [updateTree] method of the page is not @@ -96,11 +90,11 @@ class Route extends PositionComponent with ParentIsA { /// means that the lifecycle events on the page will not be processed, and /// therefore no components will be able to be added or removed from the /// page. - void stopTime() => timeSpeed = 0; + void stopTime() => timeScale = 0; /// Resumes normal time progression for the page, if it was previously slowed /// down or stopped. - void resumeTime() => timeSpeed = 1.0; + void resumeTime() => timeScale = 1.0; /// Applies the provided [Decorator] to the page. /// @@ -157,8 +151,8 @@ class Route extends PositionComponent with ParentIsA { @override void updateTree(double dt) { - if (timeSpeed > 0) { - super.updateTree(dt * timeSpeed); + if (timeScale > 0) { + super.updateTree(dt); } } diff --git a/packages/flame/test/components/route_test.dart b/packages/flame/test/components/route_test.dart index 8d9bfe019af..5933b88c526 100644 --- a/packages/flame/test/components/route_test.dart +++ b/packages/flame/test/components/route_test.dart @@ -274,19 +274,19 @@ void main() { router.pushNamed('pause'); await game.ready(); expect(router.currentRoute.name, 'pause'); - expect(router.previousRoute!.timeSpeed, 0); + expect(router.previousRoute!.timeScale, 0); game.update(10); expect(timer.elapsedTime, 1); - router.previousRoute!.timeSpeed = 0.1; + router.previousRoute!.timeScale = 0.1; game.update(10); expect(timer.elapsedTime, 2); router.pop(); await game.ready(); expect(router.currentRoute.name, 'start'); - expect(router.currentRoute.timeSpeed, 1); + expect(router.currentRoute.timeScale, 1); game.update(10); expect(timer.elapsedTime, 12); From c92910c688f5dc4463e129132759102e7ebf2e36 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Tue, 5 Mar 2024 01:04:43 +0100 Subject: [PATCH 13/79] feat: Initial functionality of flame_devtools (#3061) ![image](https://github.com/flame-engine/flame/assets/744771/4ca93f5f-369e-4644-b7fb-1d7790b962e2) This adds a structure and some basic functionality for the Flame devtools extension. Later I will add a pre/post-hook for publishing to Melos so that it can build the devtools extension before publishing (and remove the directory afterwards), since it isn't committed to this repository. For now one has to run `melos devtools-build` before publishing. --------- Co-authored-by: Renan <6718144+renancaraujo@users.noreply.github.com> Co-authored-by: Erick --- .gitignore | 4 +- examples/devtools_options.yaml | 2 + melos.yaml | 6 ++ packages/flame/extension/devtools/config.yaml | 4 + packages/flame/lib/debug.dart | 1 + .../connectors/component_count_connector.dart | 29 +++++++ .../connectors/debug_mode_connector.dart | 63 ++++++++++++++ .../connectors/game_loop_connector.dart | 75 +++++++++++++++++ .../lib/src/devtools/dev_tools_connector.dart | 32 +++++++ .../lib/src/devtools/dev_tools_service.dart | 55 ++++++++++++ packages/flame/lib/src/game/flame_game.dart | 7 ++ packages/flame_devtools/.metadata | 30 +++++++ packages/flame_devtools/README.md | 20 +++++ packages/flame_devtools/analysis_options.yaml | 1 + packages/flame_devtools/lib/main.dart | 41 +++++++++ packages/flame_devtools/lib/repository.dart | 55 ++++++++++++ .../lib/widgets/component_counter.dart | 43 ++++++++++ .../lib/widgets/debug_mode_button.dart | 40 +++++++++ .../lib/widgets/game_loop_controls.dart | 84 +++++++++++++++++++ packages/flame_devtools/pubspec.yaml | 21 +++++ packages/flame_devtools/web/index.html | 55 ++++++++++++ packages/flame_devtools/web/manifest.json | 12 +++ 22 files changed, 677 insertions(+), 3 deletions(-) create mode 100644 examples/devtools_options.yaml create mode 100644 packages/flame/extension/devtools/config.yaml create mode 100644 packages/flame/lib/src/devtools/connectors/component_count_connector.dart create mode 100644 packages/flame/lib/src/devtools/connectors/debug_mode_connector.dart create mode 100644 packages/flame/lib/src/devtools/connectors/game_loop_connector.dart create mode 100644 packages/flame/lib/src/devtools/dev_tools_connector.dart create mode 100644 packages/flame/lib/src/devtools/dev_tools_service.dart create mode 100644 packages/flame_devtools/.metadata create mode 100644 packages/flame_devtools/README.md create mode 100644 packages/flame_devtools/analysis_options.yaml create mode 100644 packages/flame_devtools/lib/main.dart create mode 100644 packages/flame_devtools/lib/repository.dart create mode 100644 packages/flame_devtools/lib/widgets/component_counter.dart create mode 100644 packages/flame_devtools/lib/widgets/debug_mode_button.dart create mode 100644 packages/flame_devtools/lib/widgets/game_loop_controls.dart create mode 100644 packages/flame_devtools/pubspec.yaml create mode 100644 packages/flame_devtools/web/index.html create mode 100644 packages/flame_devtools/web/manifest.json diff --git a/.gitignore b/.gitignore index def41f1c70e..7452d7de590 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ -pubspec.lock - # Miscellaneous *.class *.bak @@ -35,7 +33,7 @@ macos/ windows/ linux/ desktop/ -build/ +**/build/ coverage/ pubspec.lock pubspec_overrides.yaml diff --git a/examples/devtools_options.yaml b/examples/devtools_options.yaml new file mode 100644 index 00000000000..091108c4a96 --- /dev/null +++ b/examples/devtools_options.yaml @@ -0,0 +1,2 @@ +extensions: + - flame: true \ No newline at end of file diff --git a/melos.yaml b/melos.yaml index 19ba0616396..2e29ea1b08d 100644 --- a/melos.yaml +++ b/melos.yaml @@ -112,3 +112,9 @@ scripts: packageFilters: dirExists: test description: Re-generate all golden test files + + devtools-build: + run: melos exec -- dart run devtools_extensions build_and_copy --source=. --dest=../flame/extension/devtools + packageFilters: + scope: flame_devtools + description: Builds the devtools and copies the build directory to the Flame package. diff --git a/packages/flame/extension/devtools/config.yaml b/packages/flame/extension/devtools/config.yaml new file mode 100644 index 00000000000..7841a31d64d --- /dev/null +++ b/packages/flame/extension/devtools/config.yaml @@ -0,0 +1,4 @@ +name: flame +issueTracker: https://github.com/flame-engine/flame/issues +version: 0.1.0 +materialIconCodePoint: '0xe392' diff --git a/packages/flame/lib/debug.dart b/packages/flame/lib/debug.dart index 4e9d3047b03..61f8eae7716 100644 --- a/packages/flame/lib/debug.dart +++ b/packages/flame/lib/debug.dart @@ -2,3 +2,4 @@ export 'src/components/debug/child_counter_component.dart'; export 'src/components/debug/time_track_component.dart'; export 'src/components/fps_component.dart'; export 'src/components/fps_text_component.dart'; +export 'src/devtools/dev_tools_service.dart'; diff --git a/packages/flame/lib/src/devtools/connectors/component_count_connector.dart b/packages/flame/lib/src/devtools/connectors/component_count_connector.dart new file mode 100644 index 00000000000..3384618410a --- /dev/null +++ b/packages/flame/lib/src/devtools/connectors/component_count_connector.dart @@ -0,0 +1,29 @@ +import 'dart:convert'; +import 'dart:developer'; + +import 'package:flame/src/devtools/dev_tools_connector.dart'; + +/// The [ComponentCountConnector] is responsible for reporting the component +/// count of the game to the devtools extension. +class ComponentCountConnector extends DevToolsConnector { + @override + void init() { + // Get the amount of components in the tree. + registerExtension( + 'ext.flame_devtools.getComponentCount', + (method, parameters) async { + var componentCount = 0; + game.propagateToChildren((_) { + componentCount++; + return true; + }); + + return ServiceExtensionResponse.result( + json.encode({ + 'component_count': componentCount, + }), + ); + }, + ); + } +} diff --git a/packages/flame/lib/src/devtools/connectors/debug_mode_connector.dart b/packages/flame/lib/src/devtools/connectors/debug_mode_connector.dart new file mode 100644 index 00000000000..8a2a3ca12e6 --- /dev/null +++ b/packages/flame/lib/src/devtools/connectors/debug_mode_connector.dart @@ -0,0 +1,63 @@ +import 'dart:convert'; +import 'dart:developer'; + +import 'package:flame/components.dart'; +import 'package:flame/game.dart'; +import 'package:flame/src/devtools/dev_tools_connector.dart'; +import 'package:flutter/foundation.dart'; + +/// The [DebugModeConnector] is responsible for reporting and setting the +/// `debugMode` of the game from the devtools extension. +class DebugModeConnector extends DevToolsConnector { + var _debugModeNotifier = ValueNotifier(false); + + @override + void init() { + // Get the current `debugMode`. + registerExtension( + 'ext.flame_devtools.getDebugMode', + (method, parameters) async { + return ServiceExtensionResponse.result( + json.encode({ + 'debug_mode': _debugModeNotifier.value, + }), + ); + }, + ); + + // Set the `debugMode` for all components in the tree. + registerExtension( + 'ext.flame_devtools.setDebugMode', + (method, parameters) async { + final debugMode = bool.parse(parameters['debug_mode'] ?? 'false'); + _debugModeNotifier.value = debugMode; + return ServiceExtensionResponse.result( + json.encode({ + 'debug_mode': debugMode, + }), + ); + }, + ); + } + + @override + void initGame(FlameGame game) { + super.initGame(game); + _debugModeNotifier = ValueNotifier(game.debugMode); + _debugModeNotifier.addListener(() { + final newDebugMode = _debugModeNotifier.value; + game.propagateToChildren( + (c) { + c.debugMode = newDebugMode; + return true; + }, + includeSelf: true, + ); + }); + } + + @override + void disposeGame() { + _debugModeNotifier.dispose(); + } +} diff --git a/packages/flame/lib/src/devtools/connectors/game_loop_connector.dart b/packages/flame/lib/src/devtools/connectors/game_loop_connector.dart new file mode 100644 index 00000000000..be2caa8e199 --- /dev/null +++ b/packages/flame/lib/src/devtools/connectors/game_loop_connector.dart @@ -0,0 +1,75 @@ +import 'dart:convert'; +import 'dart:developer'; + +import 'package:flame/game.dart'; +import 'package:flame/src/devtools/dev_tools_connector.dart'; +import 'package:flutter/foundation.dart'; + +/// The [GameLoopConnector] is responsible for reporting and setting the +/// pause/running state of the game and stepping the game forwards or backwards +/// from the devtools extension. +class GameLoopConnector extends DevToolsConnector { + var _pauseNotifier = ValueNotifier(true); + + @override + void init() { + // Get the current `debugMode`. + registerExtension( + 'ext.flame_devtools.getPaused', + (method, parameters) async { + return ServiceExtensionResponse.result( + json.encode({ + 'paused': _pauseNotifier.value, + }), + ); + }, + ); + + // Set whether the game should be paused or not. + registerExtension( + 'ext.flame_devtools.setPaused', + (method, parameters) async { + final shouldPause = bool.parse(parameters['paused'] ?? 'false'); + _pauseNotifier.value = shouldPause; + return ServiceExtensionResponse.result( + json.encode({ + 'paused': shouldPause, + }), + ); + }, + ); + + // Set whether the game should be paused or not. + registerExtension( + 'ext.flame_devtools.step', + (method, parameters) async { + final stepTime = double.parse(parameters['step_time'] ?? '0'); + game.stepEngine(stepTime: stepTime); + return ServiceExtensionResponse.result( + json.encode({ + 'step_time': stepTime, + }), + ); + }, + ); + } + + @override + void initGame(FlameGame game) { + super.initGame(game); + _pauseNotifier = ValueNotifier(game.paused); + _pauseNotifier.addListener(() { + final newPaused = _pauseNotifier.value; + if (newPaused) { + game.pauseEngine(); + } else { + game.resumeEngine(); + } + }); + } + + @override + void disposeGame() { + _pauseNotifier.dispose(); + } +} diff --git a/packages/flame/lib/src/devtools/dev_tools_connector.dart b/packages/flame/lib/src/devtools/dev_tools_connector.dart new file mode 100644 index 00000000000..d2ca9659488 --- /dev/null +++ b/packages/flame/lib/src/devtools/dev_tools_connector.dart @@ -0,0 +1,32 @@ +import 'dart:developer'; + +import 'package:flame/debug.dart'; +import 'package:flame/game.dart'; +import 'package:flutter/foundation.dart'; + +/// When a [DevToolsConnector] is initialized by the [DevToolsService] it will +/// call the [init] method the first time, where you should will register +/// service extensions which makes it possible for the devtools extension to +/// communicate with your interface. Then the [initGame] method will be called +/// every time a new game is set in the service. +abstract class DevToolsConnector { + DevToolsConnector() { + init(); + } + + late FlameGame game; + + /// In this method, you should register service extensions using + /// [registerExtension] from dart:developer + /// (see https://api.flutter.dev/flutter/dart-developer/registerExtension.html). + void init(); + + @mustCallSuper + // ignore: use_setters_to_change_properties + void initGame(FlameGame game) { + this.game = game; + } + + /// Here you can do clean-up before a new game is set in the connector. + void disposeGame() {} +} diff --git a/packages/flame/lib/src/devtools/dev_tools_service.dart b/packages/flame/lib/src/devtools/dev_tools_service.dart new file mode 100644 index 00000000000..d56bd4a56fc --- /dev/null +++ b/packages/flame/lib/src/devtools/dev_tools_service.dart @@ -0,0 +1,55 @@ +import 'package:flame/game.dart'; +import 'package:flame/src/devtools/connectors/component_count_connector.dart'; +import 'package:flame/src/devtools/connectors/debug_mode_connector.dart'; +import 'package:flame/src/devtools/connectors/game_loop_connector.dart'; +import 'package:flame/src/devtools/dev_tools_connector.dart'; + +/// When [DevToolsService] is initialized by the [FlameGame] it will call +/// the `init` method for all [DevToolsConnector]s so that they can register +/// service extensions which are the ones that makes it possible for the +/// devtools extension to communicate with the game. +/// +/// Do note that if you have multiple games in your app, only the last one +/// created will be connected to the devtools. If you want to change it to +/// another game instance you can call [DevToolsService.initWithGame] with +/// the game instance that you want to observe. +class DevToolsService { + DevToolsService._(); + + static final instance = DevToolsService._(); + + /// Initializes the service with the given game instance. + factory DevToolsService.initWithGame(FlameGame game) { + instance.initGame(game); + return instance; + } + + FlameGame? _game; + FlameGame get game => _game!; + + /// The list of available connectors, remember to add your connector here if + /// you create a new one. + final connectors = [ + DebugModeConnector(), + ComponentCountConnector(), + GameLoopConnector(), + ]; + + /// This method is called every time a new game is set in the service and it + /// is responsible for calling the [DevToolsConnector.initGame] method in all + /// the connectors. It is also responsible for calling + /// [DevToolsConnector.disposeGame] of all connectors when a new game is set, + /// if there was a game set previously. + void initGame(FlameGame game) { + if (_game != null) { + for (final connector in connectors) { + connector.disposeGame(); + } + } + + _game = game; + for (final connector in connectors) { + connector.initGame(game); + } + } +} diff --git a/packages/flame/lib/src/game/flame_game.dart b/packages/flame/lib/src/game/flame_game.dart index bd8127f118c..5fa988ba697 100644 --- a/packages/flame/lib/src/game/flame_game.dart +++ b/packages/flame/lib/src/game/flame_game.dart @@ -3,8 +3,10 @@ import 'dart:ui'; import 'package:flame/components.dart'; import 'package:flame/src/components/core/component_tree_root.dart'; +import 'package:flame/src/devtools/dev_tools_service.dart'; import 'package:flame/src/effects/provider_interfaces.dart'; import 'package:flame/src/game/game.dart'; +import 'package:flutter/foundation.dart'; import 'package:meta/meta.dart'; /// This is a more complete and opinionated implementation of [Game]. @@ -33,6 +35,11 @@ class FlameGame extends ComponentTreeRoot '$this instantiated, while another game ${Component.staticGameInstance} ' 'declares itself to be a singleton', ); + + if (kDebugMode) { + DevToolsService.initWithGame(this); + } + _camera.world = _world; add(_camera); add(_world); diff --git a/packages/flame_devtools/.metadata b/packages/flame_devtools/.metadata new file mode 100644 index 00000000000..bcd1a600883 --- /dev/null +++ b/packages/flame_devtools/.metadata @@ -0,0 +1,30 @@ +# 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: "78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9" + channel: "stable" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9 + base_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9 + - platform: web + create_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9 + base_revision: 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/packages/flame_devtools/README.md b/packages/flame_devtools/README.md new file mode 100644 index 00000000000..012490dcaea --- /dev/null +++ b/packages/flame_devtools/README.md @@ -0,0 +1,20 @@ +# flame_devtools + +A DevTools extension for Flame games. To use it you just have to run your +Flame game in debug mode and open the DevTools in your browser, and it should +ask you if you want to add the Flame DevTools extension as a separate tab. + + +## Development + +To run it locally, make sure to run `melos devtools-build` to build the +extension so that it can be loaded in the browser (the build files are not +committed to the repository). + +After you have done any changes, make sure to run `melos devtools-build` to +build and copy the changes to `packages/flame/extension/build`. + +To develop things from the Flame side, create a new `DevToolsConnector` which +registers the new extension end points so that you can communicate with Flame +from the devtools extension. Don't forget to add the new connector to the +list of connectors in the `DevToolsService` class. diff --git a/packages/flame_devtools/analysis_options.yaml b/packages/flame_devtools/analysis_options.yaml new file mode 100644 index 00000000000..85732fa02fd --- /dev/null +++ b/packages/flame_devtools/analysis_options.yaml @@ -0,0 +1 @@ +include: package:flame_lint/analysis_options.yaml diff --git a/packages/flame_devtools/lib/main.dart b/packages/flame_devtools/lib/main.dart new file mode 100644 index 00000000000..91a7878898d --- /dev/null +++ b/packages/flame_devtools/lib/main.dart @@ -0,0 +1,41 @@ +import 'package:devtools_extensions/devtools_extensions.dart'; +import 'package:flame_devtools/widgets/component_counter.dart'; +import 'package:flame_devtools/widgets/debug_mode_button.dart'; +import 'package:flame_devtools/widgets/game_loop_controls.dart'; +import 'package:flutter/material.dart'; + +void main() { + runApp(const FlameDevTools()); +} + +class FlameDevTools extends StatelessWidget { + const FlameDevTools({super.key}); + + @override + Widget build(BuildContext context) { + return DevToolsExtension( + child: Column( + children: [ + const GameLoopControls(), + Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + const ComponentCounter(), + const DebugModeButton(), + ].withSpacing(), + ), + ].withSpacing(), + ), + ); + } +} + +extension on List { + List withSpacing() { + return expand((item) sync* { + yield const SizedBox(width: 16, height: 16); + yield item; + }).skip(1).toList(); + } +} diff --git a/packages/flame_devtools/lib/repository.dart b/packages/flame_devtools/lib/repository.dart new file mode 100644 index 00000000000..2f657f9d5ab --- /dev/null +++ b/packages/flame_devtools/lib/repository.dart @@ -0,0 +1,55 @@ +import 'package:devtools_extensions/devtools_extensions.dart'; + +sealed class Repository { + Repository._(); + + static Future getComponentCount() async { + final componentCountResponse = + await serviceManager.callServiceExtensionOnMainIsolate( + 'ext.flame_devtools.getComponentCount', + ); + return componentCountResponse.json!['component_count'] as int; + } + + static Future swapDebugMode() async { + final nextDebugMode = !(await getDebugMode()); + await serviceManager.callServiceExtensionOnMainIsolate( + 'ext.flame_devtools.setDebugMode', + args: {'debug_mode': nextDebugMode}, + ); + return nextDebugMode; + } + + static Future getDebugMode() async { + final debugModeResponse = + await serviceManager.callServiceExtensionOnMainIsolate( + 'ext.flame_devtools.getDebugMode', + ); + return debugModeResponse.json!['debug_mode'] as bool; + } + + // ignore: avoid_positional_boolean_parameters + static Future setPaused(bool shouldPause) async { + await serviceManager.callServiceExtensionOnMainIsolate( + 'ext.flame_devtools.setPaused', + args: {'paused': shouldPause}, + ); + return shouldPause; + } + + static Future getPaused() async { + final getPausedResponse = + await serviceManager.callServiceExtensionOnMainIsolate( + 'ext.flame_devtools.getPaused', + ); + return getPausedResponse.json!['paused'] as bool; + } + + static Future step({required double stepTime}) async { + final stepResponse = await serviceManager.callServiceExtensionOnMainIsolate( + 'ext.flame_devtools.step', + args: {'step_time': stepTime.toString()}, + ); + return stepResponse.json!['step_time'] as double; + } +} diff --git a/packages/flame_devtools/lib/widgets/component_counter.dart b/packages/flame_devtools/lib/widgets/component_counter.dart new file mode 100644 index 00000000000..66a9c162f0e --- /dev/null +++ b/packages/flame_devtools/lib/widgets/component_counter.dart @@ -0,0 +1,43 @@ +import 'package:flame_devtools/repository.dart'; +import 'package:flutter/material.dart'; + +class ComponentCounter extends StatefulWidget { + const ComponentCounter({super.key}); + + @override + State createState() => _ComponentCounterState(); +} + +class _ComponentCounterState extends State { + Future? _componentCount; + + @override + void initState() { + _componentCount = Repository.getComponentCount(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: _componentCount, + builder: (context, value) { + return Column( + children: [ + Text( + value.hasData + ? '${value.data} Components in the tree' + : 'Loading...', + ), + ElevatedButton( + onPressed: () => setState(() { + _componentCount = Repository.getComponentCount(); + }), + child: const Text('Update count'), + ), + ], + ); + }, + ); + } +} diff --git a/packages/flame_devtools/lib/widgets/debug_mode_button.dart b/packages/flame_devtools/lib/widgets/debug_mode_button.dart new file mode 100644 index 00000000000..d79f9424156 --- /dev/null +++ b/packages/flame_devtools/lib/widgets/debug_mode_button.dart @@ -0,0 +1,40 @@ +import 'package:flame_devtools/repository.dart'; +import 'package:flutter/material.dart'; + +class DebugModeButton extends StatefulWidget { + const DebugModeButton({super.key}); + + @override + State createState() => _DebugModeButtonState(); +} + +class _DebugModeButtonState extends State { + Future? _debugMode; + + @override + void initState() { + _debugMode = Repository.getDebugMode(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: _debugMode, + builder: (context, value) { + final buttonPrefix = switch (value.data) { + null => 'Loading', + true => 'Disable', + false => 'Enable', + }; + + return ElevatedButton( + onPressed: value.data == null + ? null + : () => setState(() => _debugMode = Repository.swapDebugMode()), + child: Text('$buttonPrefix Debug Mode'), + ); + }, + ); + } +} diff --git a/packages/flame_devtools/lib/widgets/game_loop_controls.dart b/packages/flame_devtools/lib/widgets/game_loop_controls.dart new file mode 100644 index 00000000000..5ecff67c555 --- /dev/null +++ b/packages/flame_devtools/lib/widgets/game_loop_controls.dart @@ -0,0 +1,84 @@ +import 'package:flame_devtools/repository.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class GameLoopControls extends StatefulWidget { + const GameLoopControls({super.key}); + + @override + State createState() => _GameLoopControlsState(); +} + +class _GameLoopControlsState extends State { + Future? _paused; + final _stepTimeController = TextEditingController(); + double get stepTime => double.tryParse(_stepTimeController.text) ?? 0; + + @override + void initState() { + _paused = Repository.getPaused(); + _stepTimeController.text = (1 / 60).toStringAsFixed(3); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: _paused, + builder: (context, value) { + final isPaused = value.data; + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text('Step time:'), + Container( + width: 60, + padding: const EdgeInsets.symmetric(horizontal: 8), + child: TextField( + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d*')), + ], + textAlign: TextAlign.end, + controller: _stepTimeController, + ), + ), + IconButton( + onPressed: (isPaused == null || !isPaused) + ? null + : () => setState( + () => Repository.step(stepTime: -stepTime), + ), + icon: const Icon(Icons.skip_previous), + ), + IconButton( + onPressed: (isPaused == null || isPaused) + ? null + : () => setState(() => _paused = Repository.setPaused(true)), + icon: const Icon(Icons.pause), + ), + IconButton( + onPressed: (isPaused == null || !isPaused) + ? null + : () => setState(() => _paused = Repository.setPaused(false)), + icon: const Icon(Icons.play_arrow), + ), + IconButton( + onPressed: (isPaused == null || !isPaused) + ? null + : () => setState( + () => Repository.step(stepTime: stepTime), + ), + icon: const Icon(Icons.skip_next), + ), + ], + ); + }, + ); + } + + @override + void dispose() { + _stepTimeController.dispose(); + super.dispose(); + } +} diff --git a/packages/flame_devtools/pubspec.yaml b/packages/flame_devtools/pubspec.yaml new file mode 100644 index 00000000000..8dae46f7a4d --- /dev/null +++ b/packages/flame_devtools/pubspec.yaml @@ -0,0 +1,21 @@ +name: flame_devtools +description: "The DevTools extension for Flame" +publish_to: 'none' +version: 0.1.0 + +environment: + sdk: ">=3.0.0 <4.0.0" + +dependencies: + devtools_app_shared: ^0.0.9 + devtools_extensions: ^0.0.13 + flutter: + sdk: flutter + +dev_dependencies: + flame_lint: ^1.1.2 + flutter_test: + sdk: flutter + +flutter: + uses-material-design: true diff --git a/packages/flame_devtools/web/index.html b/packages/flame_devtools/web/index.html new file mode 100644 index 00000000000..0628956658d --- /dev/null +++ b/packages/flame_devtools/web/index.html @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + flame_devtools + + + + + + + + + + diff --git a/packages/flame_devtools/web/manifest.json b/packages/flame_devtools/web/manifest.json new file mode 100644 index 00000000000..79d84823518 --- /dev/null +++ b/packages/flame_devtools/web/manifest.json @@ -0,0 +1,12 @@ +{ + "name": "flame_devtools", + "short_name": "flame_devtools", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "The devtools extensions for Flame.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [] +} From 1c51334e865ae7000f93832574e24707e8c9dfa0 Mon Sep 17 00:00:00 2001 From: DevKage <33748002+ufrshubham@users.noreply.github.com> Date: Tue, 5 Mar 2024 14:19:46 +0530 Subject: [PATCH 14/79] feat: Add initial version of `flame_sprite_fusion` package (#3062) This PR adds a new package which makes it easier to parse and render tilemaps exported from [Sprite Fusion](https://www.spritefusion.com/). --- doc/flame/structure.md | 13 +- packages/flame_sprite_fusion/.metadata | 10 + packages/flame_sprite_fusion/CHANGELOG.md | 0 packages/flame_sprite_fusion/LICENSE | 21 + packages/flame_sprite_fusion/README.md | 63 ++ .../flame_sprite_fusion/analysis_options.yaml | 1 + .../flame_sprite_fusion/example/.metadata | 30 + .../example/analysis_options.yaml | 1 + .../example/assets/images/spritesheet.png | Bin 0 -> 2784 bytes .../example/assets/tiles/map.json | 651 ++++++++++++++++++ .../flame_sprite_fusion/example/lib/main.dart | 43 ++ .../flame_sprite_fusion/example/pubspec.yaml | 24 + .../lib/flame_sprite_fusion.dart | 6 + .../lib/src/sprite_fusion_layer_data.dart | 34 + .../lib/src/sprite_fusion_tile_data.dart | 30 + .../src/sprite_fusion_tilemap_component.dart | 109 +++ .../lib/src/sprite_fusion_tilemap_data.dart | 39 ++ packages/flame_sprite_fusion/pubspec.yaml | 23 + .../flame_sprite_fusion/test/assets/map.json | 651 ++++++++++++++++++ .../test/assets/spritesheet.png | Bin 0 -> 2784 bytes .../goldens/sprite_fusion_anchor_test.png | Bin 0 -> 2738 bytes .../test/goldens/sprite_fusion_angle_test.png | Bin 0 -> 4833 bytes .../goldens/sprite_fusion_position_test.png | Bin 0 -> 2292 bytes .../goldens/sprite_fusion_render_test.png | Bin 0 -> 5018 bytes .../test/goldens/sprite_fusion_scale_test.png | Bin 0 -> 2962 bytes .../test/sprite_fusion_data_test.dart | 126 ++++ .../sprite_fusion_tilemap_component_test.dart | 179 +++++ .../test/test_asset_bundle.dart | 63 ++ 28 files changed, 2114 insertions(+), 3 deletions(-) create mode 100644 packages/flame_sprite_fusion/.metadata create mode 100644 packages/flame_sprite_fusion/CHANGELOG.md create mode 100644 packages/flame_sprite_fusion/LICENSE create mode 100644 packages/flame_sprite_fusion/README.md create mode 100644 packages/flame_sprite_fusion/analysis_options.yaml create mode 100644 packages/flame_sprite_fusion/example/.metadata create mode 100644 packages/flame_sprite_fusion/example/analysis_options.yaml create mode 100644 packages/flame_sprite_fusion/example/assets/images/spritesheet.png create mode 100644 packages/flame_sprite_fusion/example/assets/tiles/map.json create mode 100644 packages/flame_sprite_fusion/example/lib/main.dart create mode 100644 packages/flame_sprite_fusion/example/pubspec.yaml create mode 100644 packages/flame_sprite_fusion/lib/flame_sprite_fusion.dart create mode 100644 packages/flame_sprite_fusion/lib/src/sprite_fusion_layer_data.dart create mode 100644 packages/flame_sprite_fusion/lib/src/sprite_fusion_tile_data.dart create mode 100644 packages/flame_sprite_fusion/lib/src/sprite_fusion_tilemap_component.dart create mode 100644 packages/flame_sprite_fusion/lib/src/sprite_fusion_tilemap_data.dart create mode 100644 packages/flame_sprite_fusion/pubspec.yaml create mode 100644 packages/flame_sprite_fusion/test/assets/map.json create mode 100644 packages/flame_sprite_fusion/test/assets/spritesheet.png create mode 100644 packages/flame_sprite_fusion/test/goldens/sprite_fusion_anchor_test.png create mode 100644 packages/flame_sprite_fusion/test/goldens/sprite_fusion_angle_test.png create mode 100644 packages/flame_sprite_fusion/test/goldens/sprite_fusion_position_test.png create mode 100644 packages/flame_sprite_fusion/test/goldens/sprite_fusion_render_test.png create mode 100644 packages/flame_sprite_fusion/test/goldens/sprite_fusion_scale_test.png create mode 100644 packages/flame_sprite_fusion/test/sprite_fusion_data_test.dart create mode 100644 packages/flame_sprite_fusion/test/sprite_fusion_tilemap_component_test.dart create mode 100644 packages/flame_sprite_fusion/test/test_asset_bundle.dart diff --git a/doc/flame/structure.md b/doc/flame/structure.md index e5239e8af8d..6f0358ab873 100644 --- a/doc/flame/structure.md +++ b/doc/flame/structure.md @@ -12,7 +12,12 @@ void main() { Flame.images.load('player.png'); Flame.images.load('enemy.png'); - TiledComponent.load('level.tmx', tileSize); + final map1 = TiledComponent.load('level.tmx', tileSize); + + final map2 = await SpriteFusionTilemapComponent.load( + mapJsonFile: 'map.json', + spriteSheetFile: 'spritesheet.png' + ); } ``` @@ -25,9 +30,11 @@ The following file structure is where Flame would expect to find the files: │ └── explosion.mp3 ├── images │ ├── enemy.png - │ └── player.png + │ ├── player.png + │ └── spritesheet.png └── tiles - └── level.tmx + ├── level.tmx + └── map.json ``` Optionally you can split your `audio` folder into two subfolders, one for `music` and one for `sfx`. diff --git a/packages/flame_sprite_fusion/.metadata b/packages/flame_sprite_fusion/.metadata new file mode 100644 index 00000000000..2b377030c00 --- /dev/null +++ b/packages/flame_sprite_fusion/.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: "7482962148e8d758338d8a28f589f317e1e42ba4" + channel: "stable" + +project_type: package diff --git a/packages/flame_sprite_fusion/CHANGELOG.md b/packages/flame_sprite_fusion/CHANGELOG.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/flame_sprite_fusion/LICENSE b/packages/flame_sprite_fusion/LICENSE new file mode 100644 index 00000000000..0cf87ff4640 --- /dev/null +++ b/packages/flame_sprite_fusion/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Blue Fire + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/flame_sprite_fusion/README.md b/packages/flame_sprite_fusion/README.md new file mode 100644 index 00000000000..2205472ec14 --- /dev/null +++ b/packages/flame_sprite_fusion/README.md @@ -0,0 +1,63 @@ + +

+ + flame + +

+ +

+Adds support for parsing and rendering tilemap exported from Sprite Fusion directly in Flame engine. +

+ +

+ + + + +

+ +--- + + + +## Features + +Provides a component called `SpriteFusionTilemapComponent` to easily load json exports from Sprite Fusion. +This component works exactly like any other Flame component and plays nicely with rest of the Flame +Component System (a.k.a FCS). + + +## Getting started + +- To get started, first add `flame_sprite_fusion` as a dependency in your flutter project. + + ```bash + flutter pub add flame_sprite_fusion + ``` + +- Then place the `map.json` and `spritesheet.png` exported from Sprite Fusion into the `assets/tiles/` +and `assets/images/` directory of your project respectively. + +- Finally load the map and spritesheet using `SpriteFusionTilemapComponent` in your game. + + +## Usage + + +```dart +// Load the map. +final map = await SpriteFusionTilemapComponent.load( + mapJsonFile: 'map.json', + spriteSheetFile: 'spritesheet.png' +); + +//Add it to the game world. +world.add(map); +``` + + +## Additional information + + +> :warning: Under the current sprite batch implementation, you might experience extra lines while +rendering due to a bug in Flutter, see [this issue](https://github.com/flame-engine/flame/issues/1152). diff --git a/packages/flame_sprite_fusion/analysis_options.yaml b/packages/flame_sprite_fusion/analysis_options.yaml new file mode 100644 index 00000000000..85732fa02fd --- /dev/null +++ b/packages/flame_sprite_fusion/analysis_options.yaml @@ -0,0 +1 @@ +include: package:flame_lint/analysis_options.yaml diff --git a/packages/flame_sprite_fusion/example/.metadata b/packages/flame_sprite_fusion/example/.metadata new file mode 100644 index 00000000000..357f8d93c32 --- /dev/null +++ b/packages/flame_sprite_fusion/example/.metadata @@ -0,0 +1,30 @@ +# 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: "7482962148e8d758338d8a28f589f317e1e42ba4" + channel: "stable" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 + base_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 + - platform: web + create_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 + base_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/packages/flame_sprite_fusion/example/analysis_options.yaml b/packages/flame_sprite_fusion/example/analysis_options.yaml new file mode 100644 index 00000000000..85732fa02fd --- /dev/null +++ b/packages/flame_sprite_fusion/example/analysis_options.yaml @@ -0,0 +1 @@ +include: package:flame_lint/analysis_options.yaml diff --git a/packages/flame_sprite_fusion/example/assets/images/spritesheet.png b/packages/flame_sprite_fusion/example/assets/images/spritesheet.png new file mode 100644 index 0000000000000000000000000000000000000000..7746ef1abe5b99cc52ec38218cc17caa48ebeed9 GIT binary patch literal 2784 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 PlatformerGame( + camera: CameraComponent.withFixedResolution(width: 320, height: 180), + ), + ), + ); + } +} + +class PlatformerGame extends FlameGame { + PlatformerGame({super.camera}); + + @override + Color backgroundColor() => Colors.white70; + + @override + Future onLoad() async { + final map = await SpriteFusionTilemapComponent.load( + mapJsonFile: 'map.json', + spriteSheetFile: 'spritesheet.png', + ); + await world.add(map); + + camera.moveTo(map.size * 0.5); + } +} diff --git a/packages/flame_sprite_fusion/example/pubspec.yaml b/packages/flame_sprite_fusion/example/pubspec.yaml new file mode 100644 index 00000000000..064206fadba --- /dev/null +++ b/packages/flame_sprite_fusion/example/pubspec.yaml @@ -0,0 +1,24 @@ +name: flame_sprite_fusion_example +description: "An example for the SpriteFusionTilemapComponent." + +publish_to: "none" + +version: 1.0.0+1 + +environment: + sdk: ">=3.0.0 <4.0.0" + +dependencies: + flame: ^1.16.0 + flame_sprite_fusion: ^0.1.0 + flutter: + sdk: flutter + +dev_dependencies: + flame_lint: ^1.1.2 + +flutter: + uses-material-design: true + assets: + - assets/images/ + - assets/tiles/ diff --git a/packages/flame_sprite_fusion/lib/flame_sprite_fusion.dart b/packages/flame_sprite_fusion/lib/flame_sprite_fusion.dart new file mode 100644 index 00000000000..d802cb69434 --- /dev/null +++ b/packages/flame_sprite_fusion/lib/flame_sprite_fusion.dart @@ -0,0 +1,6 @@ +library flame_sprite_fusion; + +export 'src/sprite_fusion_layer_data.dart'; +export 'src/sprite_fusion_tile_data.dart'; +export 'src/sprite_fusion_tilemap_component.dart'; +export 'src/sprite_fusion_tilemap_data.dart'; diff --git a/packages/flame_sprite_fusion/lib/src/sprite_fusion_layer_data.dart b/packages/flame_sprite_fusion/lib/src/sprite_fusion_layer_data.dart new file mode 100644 index 00000000000..36c8fcd7f8d --- /dev/null +++ b/packages/flame_sprite_fusion/lib/src/sprite_fusion_layer_data.dart @@ -0,0 +1,34 @@ +import 'package:flame_sprite_fusion/flame_sprite_fusion.dart'; + +/// A class that holds the data of a layer from a sprite fusion map. +class SpriteFusionLayerData { + /// The name of the layer. + final String name; + + /// The tiles of the layer. + final List tiles; + + /// If the layer is a collider. + final bool collider; + + /// Creates a new instance of [SpriteFusionLayerData]. + SpriteFusionLayerData({ + required this.name, + required this.tiles, + required this.collider, + }); + + /// Creates a new instance of [SpriteFusionLayerData] from a map. + factory SpriteFusionLayerData.fromMap(Map map) { + return SpriteFusionLayerData( + name: map['name'] as String, + tiles: (map['tiles'] as List) + .map( + (tile) => + SpriteFusionTileData.fromMap(tile as Map), + ) + .toList(growable: false), + collider: map['collider'] as bool, + ); + } +} diff --git a/packages/flame_sprite_fusion/lib/src/sprite_fusion_tile_data.dart b/packages/flame_sprite_fusion/lib/src/sprite_fusion_tile_data.dart new file mode 100644 index 00000000000..e95064784bf --- /dev/null +++ b/packages/flame_sprite_fusion/lib/src/sprite_fusion_tile_data.dart @@ -0,0 +1,30 @@ +/// A class that holds the data of a tile from a sprite fusion map. +class SpriteFusionTileData { + /// The id of the tile. + /// + /// This is also the index position of the tile in the tileset, starting at 0, + /// from left to right, top to bottom. + final int id; + + /// The x position of the tile in tile units. + final int x; + + /// The y position of the tile in tile units. + final int y; + + /// Creates a new instance of [SpriteFusionTileData]. + SpriteFusionTileData({ + required this.id, + required this.x, + required this.y, + }); + + /// Creates a new instance of [SpriteFusionTileData] from a map. + factory SpriteFusionTileData.fromMap(Map map) { + return SpriteFusionTileData( + id: int.parse(map['id'].toString()), + x: int.parse(map['x'].toString()), + y: int.parse(map['y'].toString()), + ); + } +} diff --git a/packages/flame_sprite_fusion/lib/src/sprite_fusion_tilemap_component.dart b/packages/flame_sprite_fusion/lib/src/sprite_fusion_tilemap_component.dart new file mode 100644 index 00000000000..304f6f4762f --- /dev/null +++ b/packages/flame_sprite_fusion/lib/src/sprite_fusion_tilemap_component.dart @@ -0,0 +1,109 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:flame/cache.dart'; +import 'package:flame/components.dart'; +import 'package:flame/flame.dart'; +import 'package:flame/sprite.dart'; +import 'package:flame_sprite_fusion/flame_sprite_fusion.dart'; +import 'package:flutter/widgets.dart'; + +/// A component that renders a tilemap from a sprite fusion. +class SpriteFusionTilemapComponent extends PositionComponent { + /// The data of the tilemap. + final SpriteFusionTilemapData tilemapData; + + /// The sprite sheet of the tilemap. + final SpriteSheet spriteSheet; + + /// The sprite batch of the tilemap. + late final SpriteBatch _spriteBatch; + + /// Creates a new [SpriteFusionTilemapComponent] with the given [tilemapData] + /// and [spriteSheet]. + SpriteFusionTilemapComponent({ + required this.tilemapData, + required this.spriteSheet, + bool useAtlas = true, + super.position, + super.scale, + super.angle, + super.nativeAngle, + super.anchor, + super.children, + super.priority, + super.key, + }) : super( + size: Vector2( + tilemapData.mapWidth * tilemapData.tileSize, + tilemapData.mapHeight * tilemapData.tileSize, + ), + ) { + _spriteBatch = SpriteBatch(spriteSheet.image, useAtlas: useAtlas); + + for (final data in tilemapData.layers.reversed) { + for (final tileData in data.tiles) { + final sprite = spriteSheet.getSpriteById(tileData.id); + + _spriteBatch.add( + source: Rect.fromLTWH( + sprite.srcPosition.x, + sprite.srcPosition.y, + sprite.srcSize.x, + sprite.srcSize.y, + ), + offset: Vector2( + tileData.x * tilemapData.tileSize, + tileData.y * tilemapData.tileSize, + ), + ); + } + } + } + + @override + void render(Canvas canvas) { + _spriteBatch.render(canvas); + } + + /// Loads a [SpriteFusionTilemapComponent] from the given json file and + /// spritesheet file. + static Future load({ + required String mapJsonFile, + required String spriteSheetFile, + bool useAtlas = true, + String tilemapPrefix = 'assets/tiles/', + AssetBundle? assetBundle, + Images? images, + Vector2? position, + Vector2? scale, + double? angle, + double? nativeAngle, + Anchor? anchor, + Iterable? children, + int? priority, + ComponentKey? key, + }) async { + final content = await (assetBundle ?? Flame.bundle) + .loadString('$tilemapPrefix$mapJsonFile'); + + final json = jsonDecode(content) as Map; + + return SpriteFusionTilemapComponent( + tilemapData: SpriteFusionTilemapData.fromMap(json), + spriteSheet: SpriteSheet( + image: await (images ?? Flame.images).load(spriteSheetFile), + srcSize: Vector2.all(double.parse(json['tileSize'].toString())), + ), + useAtlas: useAtlas, + position: position, + scale: scale, + angle: angle, + nativeAngle: nativeAngle ?? 0, + anchor: anchor, + children: children, + priority: priority, + key: key, + ); + } +} diff --git a/packages/flame_sprite_fusion/lib/src/sprite_fusion_tilemap_data.dart b/packages/flame_sprite_fusion/lib/src/sprite_fusion_tilemap_data.dart new file mode 100644 index 00000000000..e757d2c7b28 --- /dev/null +++ b/packages/flame_sprite_fusion/lib/src/sprite_fusion_tilemap_data.dart @@ -0,0 +1,39 @@ +import 'package:flame_sprite_fusion/flame_sprite_fusion.dart'; + +/// A class that holds the data of the tilemap from a sprite fusion. +class SpriteFusionTilemapData { + /// The size of the tiles in the tilemap. + final double tileSize; + + /// The width of the tilemap in tile units. + final double mapWidth; + + /// The height of the tilemap in tile units. + final double mapHeight; + + /// The layers of the tilemap. + final List layers; + + /// Creates a new instance of [SpriteFusionTilemapData]. + SpriteFusionTilemapData({ + required this.tileSize, + required this.mapWidth, + required this.mapHeight, + required this.layers, + }); + + /// Creates a new instance of [SpriteFusionTilemapData] from a map. + factory SpriteFusionTilemapData.fromMap(Map map) { + return SpriteFusionTilemapData( + tileSize: double.parse(map['tileSize'].toString()), + mapWidth: double.parse(map['mapWidth'].toString()), + mapHeight: double.parse(map['mapHeight'].toString()), + layers: (map['layers'] as List) + .map( + (layer) => + SpriteFusionLayerData.fromMap(layer as Map), + ) + .toList(growable: false), + ); + } +} diff --git a/packages/flame_sprite_fusion/pubspec.yaml b/packages/flame_sprite_fusion/pubspec.yaml new file mode 100644 index 00000000000..343bbfaefcf --- /dev/null +++ b/packages/flame_sprite_fusion/pubspec.yaml @@ -0,0 +1,23 @@ +name: flame_sprite_fusion +description: "Sprite Fusion support for the Flame game engine. This package parses and renders tilemaps exported from Sprite Fusion tool." +version: 0.1.0 +homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_sprite_fusion +funding: + - https://opencollective.com/blue-fire + - https://github.com/sponsors/bluefireteam + - https://patreon.com/bluefireoss + +environment: + sdk: ">=3.0.0 <4.0.0" + flutter: ">=3.19.0" + +dependencies: + flame: ^1.16.0 + flutter: + sdk: flutter + +dev_dependencies: + flame_lint: ^1.1.2 + flame_test: ^1.16.0 + flutter_test: + sdk: flutter diff --git a/packages/flame_sprite_fusion/test/assets/map.json b/packages/flame_sprite_fusion/test/assets/map.json new file mode 100644 index 00000000000..cba078e149e --- /dev/null +++ b/packages/flame_sprite_fusion/test/assets/map.json @@ -0,0 +1,651 @@ +{ + "tileSize": 18, + "mapWidth": 20, + "mapHeight": 12, + "layers": [ + { + "name": "Spikes", + "tiles": [ + { + "id": "0", + "x": 0, + "y": 0 + }, + { + "id": "0", + "x": 17, + "y": 1 + } + ], + "collider": false + }, + { + "name": "Water", + "tiles": [ + { + "id": "1", + "x": 13, + "y": 8 + }, + { + "id": "2", + "x": 13, + "y": 9 + }, + { + "id": "3", + "x": 0, + "y": 11 + }, + { + "id": "3", + "x": 1, + "y": 11 + }, + { + "id": "3", + "x": 2, + "y": 11 + }, + { + "id": "3", + "x": 3, + "y": 11 + }, + { + "id": "3", + "x": 4, + "y": 11 + }, + { + "id": "3", + "x": 5, + "y": 11 + }, + { + "id": "3", + "x": 6, + "y": 11 + }, + { + "id": "3", + "x": 7, + "y": 11 + }, + { + "id": "3", + "x": 8, + "y": 11 + }, + { + "id": "3", + "x": 9, + "y": 11 + }, + { + "id": "3", + "x": 10, + "y": 11 + }, + { + "id": "3", + "x": 11, + "y": 11 + }, + { + "id": "3", + "x": 12, + "y": 11 + }, + { + "id": "3", + "x": 13, + "y": 11 + }, + { + "id": "3", + "x": 14, + "y": 11 + }, + { + "id": "3", + "x": 15, + "y": 11 + }, + { + "id": "3", + "x": 16, + "y": 11 + }, + { + "id": "3", + "x": 17, + "y": 11 + }, + { + "id": "3", + "x": 18, + "y": 11 + }, + { + "id": "3", + "x": 19, + "y": 11 + }, + { + "id": "4", + "x": 13, + "y": 10 + } + ], + "collider": false + }, + { + "name": "Grass", + "tiles": [ + { + "id": "5", + "x": 6, + "y": 7 + }, + { + "id": "6", + "x": 10, + "y": 7 + }, + { + "id": "7", + "x": 18, + "y": 5 + } + ], + "collider": false + }, + { + "name": "Platforms", + "tiles": [ + { + "id": "8", + "x": 16, + "y": 8 + }, + { + "id": "9", + "x": 19, + "y": 11 + }, + { + "id": "10", + "x": 19, + "y": 10 + }, + { + "id": "10", + "x": 19, + "y": 9 + }, + { + "id": "10", + "x": 19, + "y": 8 + }, + { + "id": "10", + "x": 19, + "y": 7 + }, + { + "id": "11", + "x": 19, + "y": 6 + }, + { + "id": "12", + "x": 16, + "y": 6 + }, + { + "id": "13", + "x": 17, + "y": 6 + }, + { + "id": "13", + "x": 18, + "y": 6 + }, + { + "id": "14", + "x": 16, + "y": 7 + }, + { + "id": "13", + "x": 15, + "y": 8 + }, + { + "id": "12", + "x": 14, + "y": 8 + }, + { + "id": "8", + "x": 17, + "y": 7 + }, + { + "id": "8", + "x": 18, + "y": 7 + }, + { + "id": "8", + "x": 18, + "y": 8 + }, + { + "id": "8", + "x": 18, + "y": 9 + }, + { + "id": "8", + "x": 18, + "y": 10 + }, + { + "id": "8", + "x": 17, + "y": 10 + }, + { + "id": "8", + "x": 16, + "y": 10 + }, + { + "id": "8", + "x": 15, + "y": 10 + }, + { + "id": "14", + "x": 14, + "y": 9 + }, + { + "id": "14", + "x": 14, + "y": 10 + }, + { + "id": "8", + "x": 15, + "y": 9 + }, + { + "id": "8", + "x": 16, + "y": 9 + }, + { + "id": "8", + "x": 17, + "y": 9 + }, + { + "id": "8", + "x": 17, + "y": 8 + }, + { + "id": "15", + "x": 18, + "y": 11 + }, + { + "id": "15", + "x": 17, + "y": 11 + }, + { + "id": "15", + "x": 16, + "y": 11 + }, + { + "id": "15", + "x": 15, + "y": 11 + }, + { + "id": "16", + "x": 14, + "y": 11 + }, + { + "id": "17", + "x": 11, + "y": 4 + }, + { + "id": "18", + "x": 12, + "y": 4 + }, + { + "id": "19", + "x": 13, + "y": 4 + }, + { + "id": "20", + "x": 6, + "y": 3 + }, + { + "id": "21", + "x": 7, + "y": 3 + }, + { + "id": "22", + "x": 8, + "y": 3 + }, + { + "id": "23", + "x": 10, + "y": 1 + }, + { + "id": "24", + "x": 1, + "y": 8 + }, + { + "id": "25", + "x": 1, + "y": 7 + }, + { + "id": "25", + "x": 1, + "y": 6 + }, + { + "id": "25", + "x": 1, + "y": 5 + }, + { + "id": "25", + "x": 1, + "y": 4 + }, + { + "id": "25", + "x": 1, + "y": 3 + }, + { + "id": "26", + "x": 1, + "y": 2 + }, + { + "id": "27", + "x": 1, + "y": 1 + }, + { + "id": "28", + "x": 2, + "y": 1 + }, + { + "id": "28", + "x": 3, + "y": 1 + }, + { + "id": "29", + "x": 4, + "y": 1 + }, + { + "id": "30", + "x": 0, + "y": 1 + }, + { + "id": "17", + "x": 15, + "y": 2 + }, + { + "id": "18", + "x": 16, + "y": 2 + }, + { + "id": "18", + "x": 17, + "y": 2 + }, + { + "id": "19", + "x": 18, + "y": 2 + }, + { + "id": "12", + "x": 0, + "y": 9 + }, + { + "id": "13", + "x": 1, + "y": 9 + }, + { + "id": "11", + "x": 2, + "y": 9 + }, + { + "id": "14", + "x": 0, + "y": 10 + }, + { + "id": "16", + "x": 0, + "y": 11 + }, + { + "id": "8", + "x": 1, + "y": 10 + }, + { + "id": "10", + "x": 2, + "y": 10 + }, + { + "id": "9", + "x": 2, + "y": 11 + }, + { + "id": "15", + "x": 1, + "y": 11 + }, + { + "id": "12", + "x": 5, + "y": 8 + }, + { + "id": "11", + "x": 12, + "y": 8 + }, + { + "id": "16", + "x": 5, + "y": 11 + }, + { + "id": "9", + "x": 12, + "y": 11 + }, + { + "id": "14", + "x": 5, + "y": 9 + }, + { + "id": "14", + "x": 5, + "y": 10 + }, + { + "id": "10", + "x": 12, + "y": 9 + }, + { + "id": "10", + "x": 12, + "y": 10 + }, + { + "id": "13", + "x": 6, + "y": 8 + }, + { + "id": "13", + "x": 7, + "y": 8 + }, + { + "id": "13", + "x": 8, + "y": 8 + }, + { + "id": "13", + "x": 9, + "y": 8 + }, + { + "id": "13", + "x": 10, + "y": 8 + }, + { + "id": "13", + "x": 11, + "y": 8 + }, + { + "id": "15", + "x": 6, + "y": 11 + }, + { + "id": "15", + "x": 7, + "y": 11 + }, + { + "id": "15", + "x": 8, + "y": 11 + }, + { + "id": "15", + "x": 9, + "y": 11 + }, + { + "id": "15", + "x": 10, + "y": 11 + }, + { + "id": "15", + "x": 11, + "y": 11 + }, + { + "id": "8", + "x": 6, + "y": 9 + }, + { + "id": "8", + "x": 7, + "y": 9 + }, + { + "id": "8", + "x": 8, + "y": 9 + }, + { + "id": "8", + "x": 9, + "y": 9 + }, + { + "id": "8", + "x": 10, + "y": 9 + }, + { + "id": "8", + "x": 11, + "y": 9 + }, + { + "id": "8", + "x": 11, + "y": 10 + }, + { + "id": "8", + "x": 10, + "y": 10 + }, + { + "id": "8", + "x": 9, + "y": 10 + }, + { + "id": "8", + "x": 8, + "y": 10 + }, + { + "id": "8", + "x": 7, + "y": 10 + }, + { + "id": "8", + "x": 6, + "y": 10 + } + ], + "collider": false + } + ] +} \ No newline at end of file diff --git a/packages/flame_sprite_fusion/test/assets/spritesheet.png b/packages/flame_sprite_fusion/test/assets/spritesheet.png new file mode 100644 index 0000000000000000000000000000000000000000..7746ef1abe5b99cc52ec38218cc17caa48ebeed9 GIT binary patch literal 2784 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 literal 0 HcmV?d00001 diff --git a/packages/flame_sprite_fusion/test/goldens/sprite_fusion_angle_test.png b/packages/flame_sprite_fusion/test/goldens/sprite_fusion_angle_test.png new file mode 100644 index 0000000000000000000000000000000000000000..003103f7cc83c469a7b6e88dcc18cd27d420c21b GIT binary patch literal 4833 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 a%;H}a_I|zcPy~Nd0cJ+GZ#EdXCH^-#TTQkA literal 0 HcmV?d00001 diff --git a/packages/flame_sprite_fusion/test/goldens/sprite_fusion_position_test.png b/packages/flame_sprite_fusion/test/goldens/sprite_fusion_position_test.png new file mode 100644 index 0000000000000000000000000000000000000000..7ab6431908c7c540d2d26b7d2aeff4469157615e GIT binary patch literal 2292 zcmeHJ`#;nBA0J^VLx+>c80F~lE#=a946`h>%w1)I`YKmpWLJ$#q+coe%wT{(|pM-}evi%j^AmydSU2^YwbZbG$rUAiH#T zfj}ULo2w%h1X2hG_9Ln)z})SZqzxe$!6fIS|#<{AemVGk%( z+B;!K_V~G;8>bgNcRgoS;`&M3{MT&KCDlLwYp;2!p;dbwMr@cImzVR$#nSYU$8dy9 zq#4{^k%T1vSsd#J%3gWg0R}w}SA=MuqAA$#w7~o)Lq+vqKd4$scYiTv$IYL@)4l$G z`M(GPgDFOVx{+zq0}ng*O^i_^kX{J5z>B@4pNbnuprtD6i-gGNl7_`+mf{3jkfOeT zPWdX`ediDkJWRrX+azPJmb<`d$L|&Y&idPJJfn4IeA#7gdhZ_>QL6EbJZ9i^;nS}3 z%k%}z#xd4zyu53phLhHsoHh#xlx&9jrX+v$%<&~sm$O&FLIQw}5%GR25fA-6i0|MR z)hQKFQ#7iNw?HnoE$s8pF@JNbv-DFyF2=>*IiMER{m5S2Sill&+WH5E z*9D&7C6^%;19PT9y*6h95j7p+;j}}Rnp2~RhcA|i+_mpi@dZf-=Ii~z3zIj8o;%rZ zm(Xi#fmvaPbOC$ni0SwBnJSk@RR-2rmZANNzCK;gj!xnJ~qH#_2I#HQ4i_G0Y1 z3AJMW@q>U)*=n3tP;~jyY7&f*?+d$_Dy>;Dw#MlQd+)z%a4?vX#p2lvGiD9?`wVT- z@VVm_He3l8q0N0EiJ9Wjw(Fvo7!8h;9@-19y7`H0vzPvpKt-)Pa)P-*ssk&jooI0# zNk4zX`0Z_ne>VY$-}?bn$YZ5eL*ku2{rd!!nWKha5}t|dyM)aO;4c016%E) z)mvi`71O2p;)l-A>~MF_?#$sc4(b`W{;&1h^gN@!XLUa8ftbj(g)sr=E?$M3j@ z>oM+1<)Mv~OxQ__y?f&~U)<}+YVrX$ugeS+gUv~}^b%+T3m0Q@8P!>LfntZCw^iKD zyZMGNH=7SAYBQgGOXfR-r2hzDX28=_!k4;aRvDOzHo4+SwNAEW5K||3?rn>7Uht}A z7PT%d46yn{=vu-P!W#g0h2#mw+~EbJ`!UZkLKSafbn338+}1y=zbT#MFFPCTQ-RNH zB|{f%IZe4nSr`OYnLQ&6qb+vG6Z(uO`II=53|yI&Dd+34WV1v9ZYmquOk7{3JZ!M! zRaB2;sJP~ls6;ov(I0`?}!vrvs% zD;U09nB40fdawwCIK!ako4g=Jhd~jnsnIFa6MoB}5$T~mzVUoeQGg=E_{4Qw@<0+F z$M4$cZg+^8h{)~wbY`Xe64LjS^%tUMV-Nvd5EJb)N?c*raE9GY`HXvsHNRLdrkK^D zO3ipqG`$!st!?+MNmRA64V&(lx9}}4cZdB>v(nLNEnk2E;>d$~x7kP3X}jjvyR-(+ zWO8YGO*nZ|M4!#3UezoS@FUyPr#hii_KM&!vH2G#xEOm%x~b7&{(ebCOkIo8fwGyK z5@vnD!G4V8NvR}Hi;aj10E>eyxPu0DyCoKtAH%l*)mv3Rbu8mFe11f^RpHmLCR`+W z)i!i*I88TA&XE@w@U%ZCagO#w;!MLM&pFU_pfx})q~Vb(19^R@wSZW!HTQ*DtKAK*4b;~3ZrIRB7?g=Y{1zAG&{%&Vwi1~~_NHYV zeXlw9_JiLQ>jlGp7^^^R8?rH^J@Gtod5Ul5cl(@BQcA^Lm}_b)L_2p5^^4pC{hJ%#f9Zp9KH_R;ZD_6#y_G>CfY5 z&(N>!cEQ~A8-t&fp)OF>E4WO5Ve-?3!q3u=u(J>10Dwy$s(%aq1h+nA9*3~K@?~@8 zLS8zd)M3(yUC?4X_Q8GRK-C0MD!Sxe7hF}hB1xZ_pkyy~7Q~c?Fx5X_S&AxVm{KZ4 zygc*1C;#+)nd{$0MKA>a=lo42ghEes``2g%NHuK=LYwy6P^Z3|fzXbgrl``UXra`p zhJ%G>zdp@YX%2f{AX04zF8}}^uH9mcv=T!C7FZ@$z&JIRK}VWX36L^~Is+6M^#i%X zuPAJO%ome1gIDI!p4%G0mmEvBMqF4I`OQ0KVE?0M+}wBpTPNO7xFYP<&^7>Q7a6RC zex)x_(P9Js@u^@A?+f~s+WPPAhN$T1UEdQDOi}nwuP z=zKq>|B2zegK0YM+Z-P)HetHsJ2GzWr-#S}MXc_n>hIN@4HD8Y(5M$(8S#6d2vtk=el*G4|KMdV zf^++j>jpNiV>r2mqsky&o}}9rp|PI~s){}^2>zXA*j}eBJ|BHROo5$pD0gBDIgaNw z#7rPV61_A~Xs3gu*g&kJ{G~-+xBC%j>%InLAUUz%_>n^7>-HG%XwDOSUC?A9)#;b# z8$Q@Z;q|1|dgc~HThPk9|cgmAk$>L56>(=Q%3jwK#!TtaAbw6A5*1g(X=3@$*DIrLB zV%tx3n1M3#=&r6wadj&xJ=%Ef$jf0LveY|{`aYQI+$<+5+KO3#&%XkK6``XQ2+SD5 znTI1)Py2XbJi?~WOK>rlne}RL11QY~lAt%AKAmIv%Plj9mjmKEv;LO9hR|FS?D*}d zfgtHF2ppG{{eBSg9oFZi$WQsFM{MOv(|WBQ$a(zr)IF1Kh)W#fS<+4f4dd3jdobi- zrmk6ydhOb^;S3R{%_!J5JcG*F9C34*qjL%uGTNv8ArM>Q%7hRr`Vk&@p6cjUBF(Wm z{Y=PYn8*1j;Txlv{8i0>w`n5VS$$DXVvmM&(iBsK()^TjNJV?1BEay$dS9#E(eDF4 zFHzANkBvLUPl(6l78QM5*=w7K-B?wLkmQ@3N|C+2IgaHpJ5;(0`VW+|tQu^ifHFNr zix2JxBsfJC3MGaW&ZgyF&N&t1)&W(U_h6fNrbXAi;Gh@S^4p_i49tm0EcfSRiChGx zFGxdaoA%Enmgov}s-I(c?=w@io?XW(0;TO` zCpLnay&3C@G5eFB#h1Ext9<{%-Z9CZRy#oQC}d{+k{}}PQLvw-cOi7=Rc_GQJN#Yw z2NnEAGwkWL99y-twA?N|fy^6D>&+ju0YnTAmuNxC&1C9wrlzK_M!kAw*c zyb^$=w6A+D;)&C?^W44*` z*+2Po!5<2zA-Ceb@@a$>KAWhDPSsoN(IvzXd(-81%`;?JTnCYbMD!DIqRqB-;K6XU7zUu$&&vL0Ujp=Zi=8|^r~ zbdUV#iO$P+2#o3(Eh^h%+}FRMi45tTTWh=+<0Z$b*pGP0gaUDcu2;vMJ?D^6 z^Z-_K`jE)ZeB0y@L8@rLQ^@2yR(a94lAkjKmhW1Np?6XT~D(eiB!!(fberOM_< zSQYVD64qUXHa%q+5_MP1$>DAu?Ztc{?x&TvdP&JCFjQfnaNPYxf>zJP{_Tgs<S;y*s(kVWX*d zkD2%>CRs8@%E*>(WzL(vR)U$M?V~C^>js~vW5GtFM)oY)Sq!MfeaK*21+g6VtkXqHQ9n78|s}Q zl3G5sJvwR;TlP1wm-8h3%EIU4Bky=jhqP`{xBNt=t5>x;^mc@lRs(ek1pB%KwXJ{I zd2^TO=;}R!!x@0WsEg>=SQ#L4FF*MfBd|ud0bp!tc^Y`>a)}wRn+)8Ta@B4Pq%=&E zbqsg_DQQV+87l9DfCU@>ORI6{&`CH1+FwKsJNRl7G61Amn0D8Rg_A!AB_E#~ zjJaxQvIJo?LRg!t>8BOtvjBEZ>S55TD=qLQ^Cb~>Z#Y9_)YhX!uh<*kCstKY&O}r- z|EW#skSO=5i@-!P{qGZ=0ePHTMYQDwgfU&jtGpmR5d^w`1t2_#QTN{OTE?%p__))N z0hme+BVq3>f?Y;J0=A4>;1u2U3u)@*RrdYnkUCUN~ zEdPjY0uG;DMPHa+F!<1_)M%k%{u>ir~hq1XJ{1RWaB;AXux_GDio(?x@NqzblNr_q!Y9kZd8I!O@OQ90o(|w-q3a zBJduJw<2>kR;I&jian<16Fqzw_`fh0nmUOMOt(tGZytXZr?MZEn5?-!`C7=kCYxl^eA68*_QIZ}!!q-|ZK1cy?H6E`0EGg{ zC3;)qI!%xa2>O=#`l{K)gi;6&QVA07gHC&WsQv0T@#lU&W9pM z>ET3A*~5^2WM9CmQz`i_H+Mc;IgLEl&1~DaW;WziQj#X+F8xXI&r=aiqR4YPLZVou z+XS~tLSghgGS^2hZ^xpuDcx7VOWGxu9m3ZVSJ|}Ojv*bP#aExrofH|4tmecP%KpyJ zu~ApmTOY5UdxMq9_B=FvO4wHm@`W&$%iJp#B1s_s#@v|<^RUNje)#Oj=aXSe>-e0L zs%D0!_mZTDJAOi12f`<)FFzm#WLPK>Hx+W!5BZcL?+@KMXJBoRk*i5>ICxIFIy_2m z!%{IDKutdSu~!>Z-}$Zn1+B9sJj7UE|J_XM^rz~x)ceBSPQQG=`uN$pZ1C978-}OQ z8>K+M^CJmKpXhxkua!qB4%PW3yC}X;;glp#d8_)9RH#@L0e6%k^9`jF&`#!u~ z|42r;dz7m~78@GFbqTdyduseLdHdLOQv;rmJ^`$xWOA_6?x%zi8(Kb}gH}PEv6O>M znQ6RHN*2W(#eKEynB>$aMjl&B~80kH6rUVIp>|Arnhk$QD}#x z{qO9!pF^)6Oi@DVV4+;#8{G1jm{R!xv=Uj3yCskk&MeziZU4h-7twCe$hI`iIGL1s5=&x2uq zUX$OQr*rD%J++F|U{iJ)KhHrb@@`f?bb;#eVFKNbWJVSPEl~^MaYLY_SNEB(Q}Yt( zTII=>={w7Lc8FJZN&?A+YUB@XTL!8xD*rG-mQuUxu!L?zlfnl79LjDGloY%XDaf19TN6JR2PK8#nC z7Pj8d?GMC#B;qf#qDx9Y$mjW<#=iV?_wwi+NECP%9R?qj@@u%|7O?xU_(4x_36<9S z_Bq!7Z4~$6aa{T%8ZcM$&?QxlCJ^E#vHu;Wa z=8ukb^Kmc|9fpvqaC9HmpsHQ$3FgyEs>jOk%gF5@o{GjmTfG~?!j18#464vh`-d#k zflpjHCz5LEK7S}%Mi1Cep#0*mU*DUaW3_dIyu^wFI9KhE>-c^tUMNqiMQr4cQeRnk+qnw_%#o0`1>=8 z@_?PC0U14di6nkEYghEX@U|ktMRh7Z{m@n+C+M~3Cw5)jcS53PjJyP_4HtV%#Fr*4 zEA^O}M4ztYky7fq4`~-6e$S|ztGI5);}r#xY+;X=zfG63Ov^b_C~@7p5JXA@AGdA( zXN>&}^*#nY@lg2;LeL9>@$Na`rQUQS?rANI{h%Q2Z&f5vsGG--vZVUz&6||{#Gzef zt;a$u$DivP(?6I*N0+f#Wq#0u=k{0aLv$k~P|oXdL+i?*TGd9m*KNV$7+m8R(_3Qd zYCjXO^OTqd=#-Y6Q(M@adxw=0A=XfGw)u(-2NLq*XqbkUFw;is z;`-=jYW#Tuf*|AmD%bBXAm&9IbEdcm%1$CyMvbzc>#K>BvA8OU>-)xCk#D@lavnv6 z70c}XU4N*RQ(BULEh%}Xi6%sNWz5ttbOJnYU-g`iS3FSY3)MU}VL4!a84Kk5WiVH9 z4j2x<>@MiTV?%)3Jx<+9D|ARwq$7DQ3M+F!M9;!4#WPvX7jZK1*rYJZlwC+a_#FDy z-FC4l)-j29g>qXCpL{}Y%~RcVAV?|V?)@f@E~AVbPZv}Y2ZByxaR+L>ZOfAM`Xd2{ zLvNhap;ZIjM4n5Jtjx#x|E_f%Qjy@X8BB1s=2e_Xl!5g1_KU?X@WpaV+Wv)}O~p9} z*XU?LPmRBv*iQJEIgTnUQMkD(c`h}!+)n5IEA!BzGTTgzMBj#UCY9#X-6o%mA`7(? zLK=KeoTm<}HGy^xtwq*sDK(LDg5O)?=;H`{4umbhOS$JF(BDd*-gNxlaQJsdJ!4%| zKodFSb={jQRf^n2ZVUs}vH3N{wQgr^%fDS0u+JdlTu+j1Q{v0@M;_|rA3{M# zgdcX3Pe~e!3dzBOe>R8f|2@{G?^1R0uDjQSj-U$ulJ)L^$;Ere>jf~)rAFTRhR}F$ zo5)3U+>mCk|7J97qC(q5kis4dZp)HO`pC=*#3j>r!~bXY#7!6ArRe_~P?i2+9O$(# VFqVB+N}sO*Py;jlD&2cg{{!z z6ulB*+7fDwohSyiB}FrKvD~;HX8wcw>7M6#&w0nF_fp_hV2fJ#Fe*ca!$odh^;M=5zPA zAXMz5%;@#ib!_3bo(#we2)lx36#xJU!sy4P{7{(P3Gj~nlO=}ai#({x@3fef4L&rTU|;rk2EBRm}@&+aSugNe9#ZkX05}cE})|wu6bCW&volv8}FQVg)vNQ)5?Il3{8*`WN)_d z@zF9_#*-&e>D+*grcSK`cXpwT`!?svZy(APlm4 zy3tAT{oQeOo9y7tzQ78s5-}!p%?dOlO0gKxy*|mA;|g9q>3~ni>GRA)L1ktfCVC!! zaXw>v%1Al6F!IqAZ2}T{{ln6N=MzQb>Qwy?$;wU!6B_XcGI3XJcUwDVR$Whp*%Y@= zYg2q<2lT$Dm(h-+OpZS5IncJ~?8VtVd0lsCLuAa@XjhutmVwE^{DjxOc+vPJiP~yC zHl7 zb+)9SNUAqr*ZpgM!{06 zZN6{g<#HOxd=!iNrH@PjT8XFxs8U*r+n%o<3k{^HYwTTp?1x{9WweQLCw?&)VOst5 zMDvbbs#>9B2TZpr5aCziSl`RVB(k8*DvH)sBxsBYw(0b+WIu@$O}|@pPy+mKQQ9 zr;}f5n+P2#P?eca<9Ua)6wC8(o*B5Z&GO;2ndI3`6}^L!G|BZ`1NhfW+|J4bh(nxu zOK57T>OxBzk~E+5xPUWl-t4jsRZ;O|E3SJDRx%zY?O}KdHPCSBK*t8)wam*Wdm`EWvu2* zjI^-dnN&4|uLB;KHU3$F2_uMPJ5m>CYJOCYkEX%ggKm@W5+?7XsZUQh5k%N>4VjUk zuj~L%>QoM7`gDLMN2M6N;r+!;QkI^krW1ng>8~&uR0Sh_(E&m-GcI4;GE)_?3khz1 za~sae7cqI>6gZZ~dTyy+OR!~~R6@bw}{O6**0+zg$qv6g@16pC4G56mwv z)m*yWs6ON3+y7S9a5V=vlakKRt(vk`b+(wv_Ufbe#$aCt5ynm4cxe|}&fhe^t80g6 zZQHYos+^|FU(iY!WlYR#fu=+4xzy@R4Q|25*9{M12$u909~Xk+?AVJoR{byuEu(u} znH^mUJc_2p5a7+vg?Rn070pxQ3-;NE+T*G5^(@HAI$N&@#06Rx{fS{HB2aMMAb5W% zY0c61wwz;N7JtA{hawWPGW)z|#BeJ8xM@p+r%x+lc;q*%_^JI!XBYeIPabnz#4_Z( z^hiT7XUv_u_%p$El^rW@7G~28U-pHr?fpX3{nF}HZkwpFJQT)o4H-?w&u!Ubg1Hrq zI2bt&e$ z+xae6t(rF?(zo3VvEf98`hW>l&Ukw451)(!x$l3E0fzvB3kB}>k=Y!3-BTcIAkZNP@XRCD!CKjQEi#T(*nh?c zuhThFgf}CIxI&b*@JWf+#H5~~zWAm>UQPPE;lbdyuQGEfoYSG}%QN0b4Ow4F0wb4R zxWW2re=Sja$K+vD4L%O^{C`JB@ArT8!zVLjFcSn3aUOaPd5+=!g}oo@C0U%i9^Ms_Oo z0Zh`s!5m#Rgpx>@EV#IG|psREGEcyS-68RZSqS9Zem$8|)pRg0{=NG1&tK zBa0lPfUY+_nYKQ}3+0Y@7u)*$r3KkwJBkQr?ElU{Rzf_BWFC_lUc7JF5-~GRbrQ(RsUo5Aq3!M_h`&R=jZoti|O+DiO E13=<++yDRo literal 0 HcmV?d00001 diff --git a/packages/flame_sprite_fusion/test/sprite_fusion_data_test.dart b/packages/flame_sprite_fusion/test/sprite_fusion_data_test.dart new file mode 100644 index 00000000000..b96a05ee369 --- /dev/null +++ b/packages/flame_sprite_fusion/test/sprite_fusion_data_test.dart @@ -0,0 +1,126 @@ +import 'package:flame_sprite_fusion/flame_sprite_fusion.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('SpriteFusionTileData', () { + test('creation test', () { + final tileData = SpriteFusionTileData(id: 50, x: 65, y: 89); + + expect(tileData.id, 50); + expect(tileData.x, 65); + expect(tileData.y, 89); + }); + + test('creation test with map', () { + final map = { + 'id': 50, + 'x': 65, + 'y': 89, + }; + final tileData = SpriteFusionTileData.fromMap(map); + + expect(tileData.id, map['id']); + expect(tileData.x, map['x']); + expect(tileData.y, map['y']); + }); + }); + + group('SpriteFusionLayerData', () { + test('creation test', () { + final tileData = SpriteFusionLayerData( + name: 'layer1', + tiles: [ + SpriteFusionTileData(id: 50, x: 65, y: 89), + SpriteFusionTileData(id: 51, x: 66, y: 90), + ], + collider: true, + ); + + expect(tileData.name, 'layer1'); + expect(tileData.tiles.length, 2); + expect(tileData.collider, true); + }); + + test('creation test with map', () { + final map = { + 'name': 'layer4', + 'tiles': [ + {'id': 50, 'x': 65, 'y': 89}, + {'id': 51, 'x': 66, 'y': 90}, + {'id': 40, 'x': 70, 'y': 95}, + ], + 'collider': false, + }; + final tileData = SpriteFusionLayerData.fromMap(map); + + expect(tileData.name, map['name']); + expect(tileData.tiles.length, 3); + expect(tileData.collider, map['collider']); + }); + }); + + group('SpriteFusionTilemapData', () { + test('creation test', () { + final tileData = SpriteFusionTilemapData( + mapWidth: 10, + mapHeight: 20, + tileSize: 32, + layers: [ + SpriteFusionLayerData( + name: 'layer1', + tiles: [ + SpriteFusionTileData(id: 50, x: 65, y: 89), + SpriteFusionTileData(id: 51, x: 66, y: 90), + ], + collider: true, + ), + SpriteFusionLayerData( + name: 'layer2', + tiles: [ + SpriteFusionTileData(id: 50, x: 65, y: 89), + SpriteFusionTileData(id: 51, x: 66, y: 90), + ], + collider: false, + ), + ], + ); + + expect(tileData.mapWidth, 10); + expect(tileData.mapHeight, 20); + expect(tileData.tileSize, 32); + expect(tileData.layers.length, 2); + }); + + test('creation test with map', () { + final map = { + 'mapWidth': 10, + 'mapHeight': 20, + 'tileSize': 32, + 'layers': [ + { + 'name': 'layer1', + 'tiles': [ + {'id': 50, 'x': 65, 'y': 89}, + {'id': 51, 'x': 66, 'y': 90}, + ], + 'collider': true, + }, + { + 'name': 'layer2', + 'tiles': [ + {'id': 50, 'x': 65, 'y': 89}, + {'id': 51, 'x': 66, 'y': 90}, + ], + 'collider': false, + }, + ], + }; + final tileData = SpriteFusionTilemapData.fromMap(map); + + expect(tileData.mapWidth, map['mapWidth']); + expect(tileData.mapHeight, map['mapHeight']); + expect(tileData.tileSize, map['tileSize']); + expect(tileData.layers.length, 2); + }); + }); +} diff --git a/packages/flame_sprite_fusion/test/sprite_fusion_tilemap_component_test.dart b/packages/flame_sprite_fusion/test/sprite_fusion_tilemap_component_test.dart new file mode 100644 index 00000000000..b8f6e54ba39 --- /dev/null +++ b/packages/flame_sprite_fusion/test/sprite_fusion_tilemap_component_test.dart @@ -0,0 +1,179 @@ +import 'dart:math'; + +import 'package:flame/cache.dart'; +import 'package:flame/components.dart'; +import 'package:flame/sprite.dart'; +import 'package:flame_sprite_fusion/flame_sprite_fusion.dart'; +import 'package:flame_test/flame_test.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'test_asset_bundle.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + group('SpriteFusionTilemapComponent', () { + late AssetBundle bundle; + late Images images; + + setUp(() { + bundle = TestAssetBundle( + imageNames: ['spritesheet.png'], + stringNames: ['map.json'], + ); + images = Images(bundle: bundle); + }); + + test('creation test', () async { + final tilemapData = SpriteFusionTilemapData( + mapWidth: 10, + mapHeight: 10, + tileSize: 16, + layers: [], + ); + + final spriteSheet = SpriteSheet( + image: await images.load('spritesheet.png'), + srcSize: Vector2.all(tilemapData.tileSize), + ); + + expect( + () => SpriteFusionTilemapComponent( + tilemapData: tilemapData, + spriteSheet: spriteSheet, + ), + returnsNormally, + ); + }); + + test('loads map from file', () { + expect( + SpriteFusionTilemapComponent.load( + mapJsonFile: 'map.json', + spriteSheetFile: 'spritesheet.png', + assetBundle: bundle, + images: images, + tilemapPrefix: '', + ), + completes, + ); + }); + + test('component size matches the map size', () async { + final tilemapData = SpriteFusionTilemapData( + mapWidth: 20, + mapHeight: 40, + tileSize: 16, + layers: [], + ); + + final spriteSheet = SpriteSheet( + image: await images.load('spritesheet.png'), + srcSize: Vector2.all(tilemapData.tileSize), + ); + + final component = SpriteFusionTilemapComponent( + tilemapData: tilemapData, + spriteSheet: spriteSheet, + ); + + expect( + component.size, + Vector2( + tilemapData.mapWidth * tilemapData.tileSize, + tilemapData.mapHeight * tilemapData.tileSize, + ), + ); + }); + + testGolden( + 'renders the map correctly', + (game) async { + final map = await SpriteFusionTilemapComponent.load( + mapJsonFile: 'map.json', + spriteSheetFile: 'spritesheet.png', + assetBundle: bundle, + images: images, + tilemapPrefix: '', + ); + await game.add(map); + await game.ready(); + }, + size: Vector2(360, 216), + goldenFile: 'goldens/sprite_fusion_render_test.png', + ); + + testGolden( + 'position is respected when rendering', + (game) async { + final map = await SpriteFusionTilemapComponent.load( + mapJsonFile: 'map.json', + spriteSheetFile: 'spritesheet.png', + assetBundle: bundle, + images: images, + tilemapPrefix: '', + position: Vector2(100, 100), + ); + await game.add(map); + await game.ready(); + }, + size: Vector2(360, 216), + goldenFile: 'goldens/sprite_fusion_position_test.png', + ); + + testGolden( + 'anchor is respected when rendering', + (game) async { + final map = await SpriteFusionTilemapComponent.load( + mapJsonFile: 'map.json', + spriteSheetFile: 'spritesheet.png', + assetBundle: bundle, + images: images, + tilemapPrefix: '', + anchor: Anchor.center, + ); + await game.add(map); + await game.ready(); + }, + size: Vector2(360, 216), + goldenFile: 'goldens/sprite_fusion_anchor_test.png', + ); + + testGolden( + 'scale is respected when rendering', + (game) async { + final map = await SpriteFusionTilemapComponent.load( + mapJsonFile: 'map.json', + spriteSheetFile: 'spritesheet.png', + assetBundle: bundle, + images: images, + tilemapPrefix: '', + scale: Vector2.all(0.5), + ); + await game.add(map); + await game.ready(); + }, + size: Vector2(360, 216), + goldenFile: 'goldens/sprite_fusion_scale_test.png', + ); + + testGolden( + 'angle is respected when rendering', + (game) async { + final map = await SpriteFusionTilemapComponent.load( + mapJsonFile: 'map.json', + spriteSheetFile: 'spritesheet.png', + assetBundle: bundle, + images: images, + tilemapPrefix: '', + angle: pi * 0.125, + ); + await game.add(map); + await game.ready(); + }, + size: Vector2(360, 216), + goldenFile: 'goldens/sprite_fusion_angle_test.png', + ); + }); +} diff --git a/packages/flame_sprite_fusion/test/test_asset_bundle.dart b/packages/flame_sprite_fusion/test/test_asset_bundle.dart new file mode 100644 index 00000000000..a8d4bc20c95 --- /dev/null +++ b/packages/flame_sprite_fusion/test/test_asset_bundle.dart @@ -0,0 +1,63 @@ +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:flutter/services.dart' show CachingAssetBundle; + +class TestAssetBundle extends CachingAssetBundle { + TestAssetBundle({ + required this.imageNames, + required this.stringNames, + }); + + final List imageNames; + final List stringNames; + + @override + Future load(String key) async { + late String imgName; + late String fileName; + if (key.contains('..')) { + final parts = key.split('/'); + + final index = parts.indexOf('..'); + + imgName = parts.sublist(index + 1).join('/'); + + fileName = key.replaceFirst('assets/images/', 'test/assets/'); + } else { + final pattern = RegExp(r'assets/images/(\.\./)*'); + final split = key.split('/'); + imgName = split.isNotEmpty ? key.replaceFirst(pattern, '') : key; + + final toLoadName = key.replaceFirst(pattern, ''); + fileName = 'test/assets/$toLoadName'; + } + + if (!imageNames.contains(imgName)) { + throw StateError( + 'No $fileName found in the TestAssetBundle. Did you forget to add it?', + ); + } + return File(fileName) + .readAsBytes() + .then((bytes) => ByteData.view(Uint8List.fromList(bytes).buffer)); + } + + @override + Future loadString(String key, {bool cache = true}) { + final pattern = RegExp(r'assets/tiles/(\.\./)*'); + final split = key.split('/'); + final mapName = split.isNotEmpty ? key.replaceFirst(pattern, '') : key; + + final toLoadName = key.replaceFirst(pattern, ''); + final fileName = 'test/assets/$toLoadName'; + + if (!stringNames.contains(mapName)) { + throw StateError( + 'No $fileName found in the TestAssetBundle. Did you forget to add it?', + ); + } + + return File(fileName).readAsString(); + } +} From 12841d6471c1413273cd5ed6ea8a05c69f6314db Mon Sep 17 00:00:00 2001 From: Eli B Date: Wed, 6 Mar 2024 08:40:54 -0500 Subject: [PATCH 15/79] docs: Update RawKeyEvent references to KeyEvent (#3052) (#3053) This PR fixes #3052 and updates deprecated type references in docs from `RawKeyEvent` to `KeyEvent`. Co-authored-by: Lukas Klingsbo --- doc/flame/inputs/keyboard_input.md | 8 ++++---- doc/tutorials/platformer/step_5.md | 4 ++-- examples/lib/stories/input/hardware_keyboard_example.dart | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/flame/inputs/keyboard_input.md b/doc/flame/inputs/keyboard_input.md index 512fd06f8ca..3aab488f652 100644 --- a/doc/flame/inputs/keyboard_input.md +++ b/doc/flame/inputs/keyboard_input.md @@ -26,7 +26,7 @@ To make a `Game` sub class sensitive to key stroke, mix it with `KeyboardEvents` After that, it will be possible to override an `onKeyEvent` method. This method receives two parameters, first the -[`RawKeyEvent`](https://api.flutter.dev/flutter/services/RawKeyEvent-class.html) +[`KeyEvent`](https://api.flutter.dev/flutter/services/KeyEvent-class.html) that triggers the callback in the first place. The second is a set of the currently pressed [`LogicalKeyboardKey`](https://api.flutter.dev/flutter/services/LogicalKeyboardKey-class.html). @@ -50,10 +50,10 @@ class MyGame extends FlameGame with KeyboardEvents { // ... @override KeyEventResult onKeyEvent( - RawKeyEvent event, + KeyEvent event, Set keysPressed, ) { - final isKeyDown = event is RawKeyDownEvent; + final isKeyDown = event is KeyDownEvent; final isSpace = keysPressed.contains(LogicalKeyboardKey.space); @@ -87,7 +87,7 @@ KeyboardHandlers must only be added to games that are mixed with `HasKeyboardHan After applying `KeyboardHandler`, it will be possible to override an `onKeyEvent` method. This method receives two parameters. First the -[`RawKeyEvent`](https://api.flutter.dev/flutter/services/RawKeyEvent-class.html) +[`KeyEvent`](https://api.flutter.dev/flutter/services/KeyEvent-class.html) that triggered the callback in the first place. The second is a set of the currently pressed [`LogicalKeyboardKey`](https://api.flutter.dev/flutter/services/LogicalKeyboardKey-class.html)s. diff --git a/doc/tutorials/platformer/step_5.md b/doc/tutorials/platformer/step_5.md index 90c6980ba41..0ed6381572b 100644 --- a/doc/tutorials/platformer/step_5.md +++ b/doc/tutorials/platformer/step_5.md @@ -27,7 +27,7 @@ Now we can add a new method: ```dart @override - bool onKeyEvent(RawKeyEvent event, Set keysPressed) { + bool onKeyEvent(KeyEvent event, Set keysPressed) { return true; } ``` @@ -50,7 +50,7 @@ Now in our `onKeyEvent` method, we can register the key pressed by adding: ```dart @override - bool onKeyEvent(RawKeyEvent event, Set keysPressed) { + bool onKeyEvent(KeyEvent event, Set keysPressed) { horizontalDirection = 0; horizontalDirection += (keysPressed.contains(LogicalKeyboardKey.keyA) || keysPressed.contains(LogicalKeyboardKey.arrowLeft)) diff --git a/examples/lib/stories/input/hardware_keyboard_example.dart b/examples/lib/stories/input/hardware_keyboard_example.dart index 86b52446742..d0ef86f0659 100644 --- a/examples/lib/stories/input/hardware_keyboard_example.dart +++ b/examples/lib/stories/input/hardware_keyboard_example.dart @@ -15,7 +15,7 @@ class HardwareKeyboardExample extends FlameGame { '''; /// The list of [KeyboardKey] components currently shown on the screen. This - /// list is re-generated on every RawKeyEvent. These components are also + /// list is re-generated on every KeyEvent. These components are also /// attached as children. List _keyComponents = []; @@ -221,9 +221,9 @@ class KeyboardKey extends PositionComponent { late final InlineTextElement textElement; late final RRect rect; - /// The RawKeyEvents may occur very fast, and out of sync with the game loop. + /// The KeyEvents may occur very fast, and out of sync with the game loop. /// On each such event we remove old KeyboardKey components, and add new ones. - /// However, since multiple RawKeyEvents may occur within a single game tick, + /// However, since multiple KeyEvents may occur within a single game tick, /// we end up adding/removing components many times within that tick, and for /// a brief moment there could be a situation that the old components still /// haven't been removed while the new ones were already added. In order to From 9282cc38f06cd6c87ed3a1880d28d5c9f290cc04 Mon Sep 17 00:00:00 2001 From: William Shakour Date: Wed, 6 Mar 2024 13:47:00 +0000 Subject: [PATCH 16/79] fix: Clamp opacity set by the `ColorEffect` to 1.0 (#3069) Clamp opacity set by the ColorEffect to 1.0; this was causing an issue when the tween returned values greater than 1. The test shows that when dt is greater than 0.5 and less than 0.75 for a period of 1 the tween returns approx 1.2 which causes Color to throw an exception. This has now been fixed. Since https://github.com/flutter/flutter/issues/89433 has also now been fixed, I have changed the min opacity to 0. --- .../flame/lib/src/effects/color_effect.dart | 5 +- .../flame/test/effects/color_effect_test.dart | 58 +++++++++++++++++-- 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/packages/flame/lib/src/effects/color_effect.dart b/packages/flame/lib/src/effects/color_effect.dart index 4fe5cffcd5e..3a1c291d3e2 100644 --- a/packages/flame/lib/src/effects/color_effect.dart +++ b/packages/flame/lib/src/effects/color_effect.dart @@ -43,10 +43,7 @@ class ColorEffect extends ComponentEffect { @override void apply(double progress) { final currentColor = color.withOpacity( - // Currently there is a bug when opacity is 0 in the color filter. - // "Expected a value of type 'SkDeletable', but got one of type 'Null'" - // https://github.com/flutter/flutter/issues/89433 - max(_tween.transform(progress), 1 / 255), + min(max(_tween.transform(progress), 0), 1), ); target.tint(currentColor, paintId: paintId); } diff --git a/packages/flame/test/effects/color_effect_test.dart b/packages/flame/test/effects/color_effect_test.dart index 3030adc46c4..39650ecb175 100644 --- a/packages/flame/test/effects/color_effect_test.dart +++ b/packages/flame/test/effects/color_effect_test.dart @@ -18,11 +18,7 @@ void main() { game.update(0); expect( component.paint.colorFilter.toString(), - // Once https://github.com/flutter/flutter/issues/89433 has been fixed - // the two equals lines should be swapped and the ColorEffect should go - // to opacity 0. - //equals('ColorFilter.mode(Color(0x00f44336), BlendMode.srcATop)'), - equals('ColorFilter.mode(Color(0x01f44336), BlendMode.srcATop)'), + equals('ColorFilter.mode(Color(0x00f44336), BlendMode.srcATop)'), ); game.update(0.5); @@ -62,6 +58,36 @@ void main() { }, ); + testWithFlameGame( + 'resets the color filter to the original state', + (game) async { + final component = _PaintComponent(); + await game.ensureAdd(component); + + final originalColorFilter = component.paint.colorFilter; + const color = Colors.red; + + final effect = ColorEffect( + color, + EffectController(duration: 1), + ); + await component.add(effect); + game.update(0.5); + + expect( + originalColorFilter, + isNot(equals(component.paint.colorFilter)), + ); + + effect.reset(); + + expect( + originalColorFilter, + equals(component.paint.colorFilter), + ); + }, + ); + testWithFlameGame( 'can be re-added in the component tree', (game) async { @@ -84,6 +110,28 @@ void main() { }, ); + testWithFlameGame( + 'will clamp controllers that over or under set the progress value', + (game) async { + final component = _PaintComponent(); + await game.ensureAdd(component); + + final effect = ColorEffect( + opacityFrom: 1, + opacityTo: 0, + Colors.black, + ZigzagEffectController( + period: 1, + ), + ); + await component.ensureAdd(effect); + expect( + () => game.update(0.56), + returnsNormally, + ); + }, + ); + test('Validates opacity values', () { expect( () => ColorEffect( From f49d24c02dd0d9b781926908bad1fb6dfcbda5f2 Mon Sep 17 00:00:00 2001 From: Yukiteru Attano <85680862+YukiAttano@users.noreply.github.com> Date: Fri, 8 Mar 2024 15:59:35 +0100 Subject: [PATCH 17/79] fix!: Removed unused parameters from SpriteWidget (#3074) The unused fields of "SpriteWidget", "srcPosition" and "srcSize" and their matching parameter in the default constructor has been removed. If SpriteWidget is used, remove the parameter srcPosition and srcSize as they have not been used in the default constructor. (This does not belong to SpriteWidget.asset()) --- packages/flame/lib/src/widgets/sprite_widget.dart | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/packages/flame/lib/src/widgets/sprite_widget.dart b/packages/flame/lib/src/widgets/sprite_widget.dart index 3fef4a669ce..08acc256c70 100644 --- a/packages/flame/lib/src/widgets/sprite_widget.dart +++ b/packages/flame/lib/src/widgets/sprite_widget.dart @@ -19,12 +19,6 @@ class SpriteWidget extends StatelessWidget { /// The angle to rotate this [Sprite], in rad. (default = 0) final double angle; - /// Holds the position of the sprite on the image - final Vector2? srcPosition; - - /// Holds the size of the sprite on the image - final Vector2? srcSize; - /// A builder function that is called if the loading fails final WidgetBuilder? errorBuilder; @@ -33,12 +27,13 @@ class SpriteWidget extends StatelessWidget { final FutureOr _spriteFuture; + /// renders the [sprite] as a Widget. + /// + /// To change the source size and position, see [Sprite.new] const SpriteWidget({ required Sprite sprite, this.anchor = Anchor.topLeft, this.angle = 0, - this.srcPosition, - this.srcSize, this.errorBuilder, this.loadingBuilder, super.key, @@ -55,8 +50,8 @@ class SpriteWidget extends StatelessWidget { Images? images, this.anchor = Anchor.topLeft, this.angle = 0, - this.srcPosition, - this.srcSize, + Vector2? srcPosition, + Vector2? srcSize, this.errorBuilder, this.loadingBuilder, super.key, From faf2df4b8c68015a1bfbdd96f93c950cb14963ef Mon Sep 17 00:00:00 2001 From: DevKage <33748002+ufrshubham@users.noreply.github.com> Date: Sun, 10 Mar 2024 21:59:15 +0530 Subject: [PATCH 18/79] feat: Add initial version of `behavior_tree` and `flame_behavior_tree` package (#3045) First pass on adding behavior tree for flame. This PR adds 2 packages: - behavior_tree: A pure dart implementation of behavior tree. - flame_behavior_tree: A bridge package that integrates behavior_tree with flame. Demo: https://github.com/flame-engine/flame/assets/33748002/1d2b00ab-1b6e-406e-9052-a24370c8f1ab --- packages/flame_behavior_tree/.metadata | 10 + packages/flame_behavior_tree/CHANGELOG.md | 0 packages/flame_behavior_tree/LICENSE | 21 ++ packages/flame_behavior_tree/README.md | 82 +++++ .../flame_behavior_tree/analysis_options.yaml | 1 + .../behavior_tree/CHANGELOG.md | 0 .../flame_behavior_tree/behavior_tree/LICENSE | 21 ++ .../behavior_tree/README.md | 72 ++++ .../behavior_tree/analysis_options.yaml | 1 + .../example/behavior_tree_example.dart | 39 +++ .../behavior_tree/lib/behavior_tree.dart | 12 + .../behavior_tree/lib/src/base_node.dart | 21 ++ .../lib/src/composites/selector.dart | 31 ++ .../lib/src/composites/sequence.dart | 31 ++ .../lib/src/decorators/inverter.dart | 39 +++ .../lib/src/decorators/limiter.dart | 48 +++ .../behavior_tree/lib/src/node.dart | 33 ++ .../lib/src/tasks/async_task.dart | 27 ++ .../lib/src/tasks/condition.dart | 18 + .../behavior_tree/lib/src/tasks/task.dart | 17 + .../behavior_tree/pubspec.yaml | 20 ++ .../behavior_tree/test/async_task_test.dart | 19 ++ .../behavior_tree/test/conditon_test.dart | 18 + .../behavior_tree/test/inverter_test.dart | 45 +++ .../behavior_tree/test/limiter_test.dart | 71 ++++ .../behavior_tree/test/selector_test.dart | 128 +++++++ .../behavior_tree/test/sequence_test.dart | 128 +++++++ .../behavior_tree/test/task_test.dart | 25 ++ .../flame_behavior_tree/example/.metadata | 42 +++ .../example/analysis_options.yaml | 1 + .../flame_behavior_tree/example/lib/main.dart | 323 ++++++++++++++++++ .../flame_behavior_tree/example/pubspec.yaml | 25 ++ .../lib/flame_behavior_tree.dart | 5 + .../lib/src/has_behavior_tree.dart | 57 ++++ packages/flame_behavior_tree/pubspec.yaml | 25 ++ .../test/has_behavior_tree_test.dart | 98 ++++++ 36 files changed, 1554 insertions(+) create mode 100644 packages/flame_behavior_tree/.metadata create mode 100644 packages/flame_behavior_tree/CHANGELOG.md create mode 100644 packages/flame_behavior_tree/LICENSE create mode 100644 packages/flame_behavior_tree/README.md create mode 100644 packages/flame_behavior_tree/analysis_options.yaml create mode 100644 packages/flame_behavior_tree/behavior_tree/CHANGELOG.md create mode 100644 packages/flame_behavior_tree/behavior_tree/LICENSE create mode 100644 packages/flame_behavior_tree/behavior_tree/README.md create mode 100644 packages/flame_behavior_tree/behavior_tree/analysis_options.yaml create mode 100644 packages/flame_behavior_tree/behavior_tree/example/behavior_tree_example.dart create mode 100644 packages/flame_behavior_tree/behavior_tree/lib/behavior_tree.dart create mode 100644 packages/flame_behavior_tree/behavior_tree/lib/src/base_node.dart create mode 100644 packages/flame_behavior_tree/behavior_tree/lib/src/composites/selector.dart create mode 100644 packages/flame_behavior_tree/behavior_tree/lib/src/composites/sequence.dart create mode 100644 packages/flame_behavior_tree/behavior_tree/lib/src/decorators/inverter.dart create mode 100644 packages/flame_behavior_tree/behavior_tree/lib/src/decorators/limiter.dart create mode 100644 packages/flame_behavior_tree/behavior_tree/lib/src/node.dart create mode 100644 packages/flame_behavior_tree/behavior_tree/lib/src/tasks/async_task.dart create mode 100644 packages/flame_behavior_tree/behavior_tree/lib/src/tasks/condition.dart create mode 100644 packages/flame_behavior_tree/behavior_tree/lib/src/tasks/task.dart create mode 100644 packages/flame_behavior_tree/behavior_tree/pubspec.yaml create mode 100644 packages/flame_behavior_tree/behavior_tree/test/async_task_test.dart create mode 100644 packages/flame_behavior_tree/behavior_tree/test/conditon_test.dart create mode 100644 packages/flame_behavior_tree/behavior_tree/test/inverter_test.dart create mode 100644 packages/flame_behavior_tree/behavior_tree/test/limiter_test.dart create mode 100644 packages/flame_behavior_tree/behavior_tree/test/selector_test.dart create mode 100644 packages/flame_behavior_tree/behavior_tree/test/sequence_test.dart create mode 100644 packages/flame_behavior_tree/behavior_tree/test/task_test.dart create mode 100644 packages/flame_behavior_tree/example/.metadata create mode 100644 packages/flame_behavior_tree/example/analysis_options.yaml create mode 100644 packages/flame_behavior_tree/example/lib/main.dart create mode 100644 packages/flame_behavior_tree/example/pubspec.yaml create mode 100644 packages/flame_behavior_tree/lib/flame_behavior_tree.dart create mode 100644 packages/flame_behavior_tree/lib/src/has_behavior_tree.dart create mode 100644 packages/flame_behavior_tree/pubspec.yaml create mode 100644 packages/flame_behavior_tree/test/has_behavior_tree_test.dart diff --git a/packages/flame_behavior_tree/.metadata b/packages/flame_behavior_tree/.metadata new file mode 100644 index 00000000000..48326e7c262 --- /dev/null +++ b/packages/flame_behavior_tree/.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: "bae5e49bc2a867403c43b2aae2de8f8c33b037e4" + channel: "stable" + +project_type: package diff --git a/packages/flame_behavior_tree/CHANGELOG.md b/packages/flame_behavior_tree/CHANGELOG.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/flame_behavior_tree/LICENSE b/packages/flame_behavior_tree/LICENSE new file mode 100644 index 00000000000..0cf87ff4640 --- /dev/null +++ b/packages/flame_behavior_tree/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Blue Fire + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/flame_behavior_tree/README.md b/packages/flame_behavior_tree/README.md new file mode 100644 index 00000000000..8740e79e0f9 --- /dev/null +++ b/packages/flame_behavior_tree/README.md @@ -0,0 +1,82 @@ + +

+ + flame + +

+ +

This is a bridge package that integrates the behavior_tree dart package with Flame engine. +

+ +

+ + + + +

+ +--- + + + +## Features + +This package provides a `HasBehaviorTree` mixin for Flame `Components`. It can be added to any +`Component` and it takes care of ticking the behavior tree along with the component's update. + + +## Getting started + +Add this package to your Flutter project using: + +```bash +flutter pub add flame_behavior_tree +``` + + +## Usage + +- Add the `HasBehaviorTree` mixin to the component that wants to follow a certain AI behavior. + + ```dart + class MyComponent extends Position with HasBehaviorTree { + + } + ``` + +- Set-up a behavior tree and set its root as the `treeRoot` of the `HasBehaviorTree`. + +```dart +class MyComponent extends PositionComponent with HasBehaviorTree { + Future onLoad() async { + treeRoot = Selector( + children: [ + Sequence(children: [task1, condition, task2]), + Sequence(...), + ] + ); + super.onLoad(); + } +} +``` + +- Increase the `tickInterval` to make the tree tick less frequently. + +```dart +class MyComponent extends PositionComponent with HasBehaviorTree { + Future onLoad() async { + treeRoot = Selector(...); + tickInterval = 4; + super.onLoad(); + } +} +``` + + +## Additional information + +When working with behavior trees, keep in mind that + +- nodes of a behavior tree do not necessarily update on every frame. +- avoid storing data in nodes as much as possible because it can go out of sync with rest of the +game as nodes are not ticked on every frame. diff --git a/packages/flame_behavior_tree/analysis_options.yaml b/packages/flame_behavior_tree/analysis_options.yaml new file mode 100644 index 00000000000..ba5631f3b8a --- /dev/null +++ b/packages/flame_behavior_tree/analysis_options.yaml @@ -0,0 +1 @@ +include: package:flame_lint/analysis_options.yaml \ No newline at end of file diff --git a/packages/flame_behavior_tree/behavior_tree/CHANGELOG.md b/packages/flame_behavior_tree/behavior_tree/CHANGELOG.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/flame_behavior_tree/behavior_tree/LICENSE b/packages/flame_behavior_tree/behavior_tree/LICENSE new file mode 100644 index 00000000000..0cf87ff4640 --- /dev/null +++ b/packages/flame_behavior_tree/behavior_tree/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Blue Fire + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/flame_behavior_tree/behavior_tree/README.md b/packages/flame_behavior_tree/behavior_tree/README.md new file mode 100644 index 00000000000..b29e372ac95 --- /dev/null +++ b/packages/flame_behavior_tree/behavior_tree/README.md @@ -0,0 +1,72 @@ + +

+ + flame + +

+ +

+This package provides a simple and easy to use behavior tree API in pure dart. +

+ +

+ + + + +

+ +--- + + + +Behavior tree is a very common way of implementing AI behavior in game and robotics. Using this, you +can break-down a complex behavior of an in game AI, into multiple smaller nodes. + + +## Features + +- Nodes + - Composite + - Sequence: Continues execution until one of the children fails. + - Selector: Continues execution until one of the children succeeds. + - Decorator + - Inverter: Flips the status of the child node. + - Limiter: Limits the number of ticks for child node. + - Task + - Task: Executes a given callback when ticked. + - AsyncTask: Executes an async callback when ticked. + - Condition: Checks a condition when ticked. + + +## Getting started + +Add this package to your dart project using, + +```bash +dart pub add behavior_tree +``` + + +## Usage + +- Create a behavior tree. + +```dart +final treeRoot = Sequence( + children: [ + Condition(() => isHungry), + Task(() => goToShop()), + Task(() => buyFood()), + Task(() => goToHome()), + Task(() => eatFood()), + ] +); +``` + +- Tick the root node to update the tree. + +```dart +final treeRoot = ...; +treeRoot.tick(); +``` diff --git a/packages/flame_behavior_tree/behavior_tree/analysis_options.yaml b/packages/flame_behavior_tree/behavior_tree/analysis_options.yaml new file mode 100644 index 00000000000..85732fa02fd --- /dev/null +++ b/packages/flame_behavior_tree/behavior_tree/analysis_options.yaml @@ -0,0 +1 @@ +include: package:flame_lint/analysis_options.yaml diff --git a/packages/flame_behavior_tree/behavior_tree/example/behavior_tree_example.dart b/packages/flame_behavior_tree/behavior_tree/example/behavior_tree_example.dart new file mode 100644 index 00000000000..b45d76675a8 --- /dev/null +++ b/packages/flame_behavior_tree/behavior_tree/example/behavior_tree_example.dart @@ -0,0 +1,39 @@ +import 'package:behavior_tree/behavior_tree.dart'; + +bool isHungry = true; + +void main() { + // Create a sequence of tasks + final treeRoot = Sequence( + children: [ + Condition(() => isHungry), + Task(goToShop), + Task(buyFood), + Task(goToHome), + Task(eatFood), + ], + ); + + // Tick the tree + treeRoot.tick(); +} + +NodeStatus goToShop() { + // Go to the shop + return NodeStatus.success; +} + +NodeStatus buyFood() { + // Buy food + return NodeStatus.success; +} + +NodeStatus goToHome() { + // Go home + return NodeStatus.success; +} + +NodeStatus eatFood() { + // Eat food + return NodeStatus.success; +} diff --git a/packages/flame_behavior_tree/behavior_tree/lib/behavior_tree.dart b/packages/flame_behavior_tree/behavior_tree/lib/behavior_tree.dart new file mode 100644 index 00000000000..c6e6ece5777 --- /dev/null +++ b/packages/flame_behavior_tree/behavior_tree/lib/behavior_tree.dart @@ -0,0 +1,12 @@ +/// Behavior tree implementation in dart +library behavior_tree; + +export 'src/base_node.dart'; +export 'src/composites/selector.dart'; +export 'src/composites/sequence.dart'; +export 'src/decorators/inverter.dart'; +export 'src/decorators/limiter.dart'; +export 'src/node.dart'; +export 'src/tasks/async_task.dart'; +export 'src/tasks/condition.dart'; +export 'src/tasks/task.dart'; diff --git a/packages/flame_behavior_tree/behavior_tree/lib/src/base_node.dart b/packages/flame_behavior_tree/behavior_tree/lib/src/base_node.dart new file mode 100644 index 00000000000..8c67e57ec6d --- /dev/null +++ b/packages/flame_behavior_tree/behavior_tree/lib/src/base_node.dart @@ -0,0 +1,21 @@ +import 'package:behavior_tree/behavior_tree.dart'; +import 'package:meta/meta.dart'; + +/// A base class for all the nodes. +abstract class BaseNode implements NodeInterface { + NodeStatus _status = NodeStatus.notStarted; + + @override + NodeStatus get status => _status; + + @override + set status(NodeStatus value) { + _status = value; + } + + @override + @mustCallSuper + void reset() { + _status = NodeStatus.notStarted; + } +} diff --git a/packages/flame_behavior_tree/behavior_tree/lib/src/composites/selector.dart b/packages/flame_behavior_tree/behavior_tree/lib/src/composites/selector.dart new file mode 100644 index 00000000000..a4a12cad8ec --- /dev/null +++ b/packages/flame_behavior_tree/behavior_tree/lib/src/composites/selector.dart @@ -0,0 +1,31 @@ +import 'package:behavior_tree/behavior_tree.dart'; + +/// A composite node that stops at its first non-failing child node. +class Selector extends BaseNode implements NodeInterface { + /// Creates a selector node for given [children] nodes. + Selector({List? children}) + : _children = children ?? []; + + final List _children; + + @override + void tick() { + for (final node in _children) { + node.tick(); + + if (node.status != NodeStatus.failure) { + status = node.status; + return; + } + } + status = NodeStatus.failure; + } + + @override + void reset() { + for (final node in _children) { + node.reset(); + } + super.reset(); + } +} diff --git a/packages/flame_behavior_tree/behavior_tree/lib/src/composites/sequence.dart b/packages/flame_behavior_tree/behavior_tree/lib/src/composites/sequence.dart new file mode 100644 index 00000000000..8e32b01b7cc --- /dev/null +++ b/packages/flame_behavior_tree/behavior_tree/lib/src/composites/sequence.dart @@ -0,0 +1,31 @@ +import 'package:behavior_tree/behavior_tree.dart'; + +/// A composite node that stops at its first successful child node. +class Sequence extends BaseNode implements NodeInterface { + /// Creates a sequence node for given [children] nodes. + Sequence({List? children}) + : _children = children ?? []; + + final List _children; + + @override + void tick() { + for (final node in _children) { + node.tick(); + + if (node.status != NodeStatus.success) { + status = node.status; + return; + } + } + status = NodeStatus.success; + } + + @override + void reset() { + for (final node in _children) { + node.reset(); + } + super.reset(); + } +} diff --git a/packages/flame_behavior_tree/behavior_tree/lib/src/decorators/inverter.dart b/packages/flame_behavior_tree/behavior_tree/lib/src/decorators/inverter.dart new file mode 100644 index 00000000000..776dbf887ed --- /dev/null +++ b/packages/flame_behavior_tree/behavior_tree/lib/src/decorators/inverter.dart @@ -0,0 +1,39 @@ +import 'package:behavior_tree/behavior_tree.dart'; + +/// A decorator node that inverts [child]'s status if it is not +/// [NodeStatus.running]. +class Inverter extends BaseNode implements NodeInterface { + /// Creates an inverter node for given [child] node. + Inverter(this.child) { + _invertStatus(); + } + + /// The child node whose status needs to be inverted. + final NodeInterface child; + + @override + void tick() { + child.tick(); + _invertStatus(); + } + + void _invertStatus() { + switch (child.status) { + case NodeStatus.notStarted: + status = NodeStatus.notStarted; + case NodeStatus.running: + status = NodeStatus.running; + case NodeStatus.success: + status = NodeStatus.failure; + case NodeStatus.failure: + status = NodeStatus.success; + } + } + + @override + void reset() { + super.reset(); + child.reset(); + _invertStatus(); + } +} diff --git a/packages/flame_behavior_tree/behavior_tree/lib/src/decorators/limiter.dart b/packages/flame_behavior_tree/behavior_tree/lib/src/decorators/limiter.dart new file mode 100644 index 00000000000..57086f60429 --- /dev/null +++ b/packages/flame_behavior_tree/behavior_tree/lib/src/decorators/limiter.dart @@ -0,0 +1,48 @@ +import 'package:behavior_tree/behavior_tree.dart'; + +/// A decorator node that limits the number of times [child] can be ticked. +class Limiter extends BaseNode implements NodeInterface { + /// Creates a limiter node for given [child] node and [limit]. + /// + /// Once this node has been ticked [limit] number of times, it stops ticking + /// the child node. After this, [status] will keep returning the status of + /// child the last time it was ticked. This behavior can be overridden by + /// providing an optional [statusAfterLimit]. + Limiter( + this.child, + this.limit, { + NodeStatus? statusAfterLimit, + }) : _statusAfterLimit = statusAfterLimit { + status = + (_tickCount < limit) ? child.status : _statusAfterLimit ?? child.status; + } + + var _tickCount = 0; + final NodeStatus? _statusAfterLimit; + + /// The child node whose ticks are to be limited. + final NodeInterface child; + + /// The max number of times [child] can be ticked. + final int limit; + + /// Returns the number of times [child] has been ticked. + int get tickCount => _tickCount; + + @override + void tick() { + if (_tickCount < limit) { + child.tick(); + ++_tickCount; + } + status = + (_tickCount < limit) ? child.status : _statusAfterLimit ?? child.status; + } + + @override + void reset() { + _tickCount = 0; + child.reset(); + super.reset(); + } +} diff --git a/packages/flame_behavior_tree/behavior_tree/lib/src/node.dart b/packages/flame_behavior_tree/behavior_tree/lib/src/node.dart new file mode 100644 index 00000000000..9bed85a11af --- /dev/null +++ b/packages/flame_behavior_tree/behavior_tree/lib/src/node.dart @@ -0,0 +1,33 @@ +import 'package:behavior_tree/behavior_tree.dart'; + +/// The valid values for status of a node. +enum NodeStatus { + /// Indicates that the node has not been ticked yet. + notStarted, + + /// Indicates that the node is running. + running, + + /// Indicates that the node has completed successfully. + success, + + /// Indicates that the node has failed. + failure, +} + +/// An interface which all the nodes implement. +/// +/// Some examples are [Selector], [Sequence], [Inverter] and [Limiter]. +abstract interface class NodeInterface { + /// Returns the current status of this node. + NodeStatus get status; + + /// Sets the status of this node. + set status(NodeStatus value); + + /// Updates the node and re-evaluates its status. + void tick(); + + /// Resets the node to its initial state. + void reset(); +} diff --git a/packages/flame_behavior_tree/behavior_tree/lib/src/tasks/async_task.dart b/packages/flame_behavior_tree/behavior_tree/lib/src/tasks/async_task.dart new file mode 100644 index 00000000000..aa06bf49469 --- /dev/null +++ b/packages/flame_behavior_tree/behavior_tree/lib/src/tasks/async_task.dart @@ -0,0 +1,27 @@ +import 'dart:async'; + +import 'package:behavior_tree/behavior_tree.dart'; + +typedef AsyncTaskCallback = Future Function(); + +/// This is a leaf node that will execute the given async task when ticked. +/// While the callback is executing, this node will report [status] as +/// [NodeStatus.running]. Once the callback finishes, the status will be updated +/// to the returned value of the callback. +class AsyncTask extends BaseNode implements NodeInterface { + /// Creates an async task node for given [callback]. + AsyncTask(AsyncTaskCallback callback) : _callback = callback; + + final AsyncTaskCallback _callback; + + @override + void tick() { + if (status != NodeStatus.running) { + status = NodeStatus.running; + + _callback().then((returnedStatus) { + status = returnedStatus; + }); + } + } +} diff --git a/packages/flame_behavior_tree/behavior_tree/lib/src/tasks/condition.dart b/packages/flame_behavior_tree/behavior_tree/lib/src/tasks/condition.dart new file mode 100644 index 00000000000..1e1c37135f1 --- /dev/null +++ b/packages/flame_behavior_tree/behavior_tree/lib/src/tasks/condition.dart @@ -0,0 +1,18 @@ +import 'package:behavior_tree/behavior_tree.dart'; + +typedef ConditionCallback = bool Function(); + +/// This is a leaf node that will updates its [status] based on +/// [conditionCallback]. +class Condition extends BaseNode { + /// Creates a condition node for given [conditionCallback]. + Condition(this.conditionCallback); + + /// The callback that will be executed when the condition is ticked. + final ConditionCallback conditionCallback; + + @override + void tick() { + status = conditionCallback() ? NodeStatus.success : NodeStatus.failure; + } +} diff --git a/packages/flame_behavior_tree/behavior_tree/lib/src/tasks/task.dart b/packages/flame_behavior_tree/behavior_tree/lib/src/tasks/task.dart new file mode 100644 index 00000000000..7ffc147ed23 --- /dev/null +++ b/packages/flame_behavior_tree/behavior_tree/lib/src/tasks/task.dart @@ -0,0 +1,17 @@ +import 'package:behavior_tree/behavior_tree.dart'; + +/// The type of callback used by the [Task] node. +typedef TaskCallback = NodeStatus Function(); + +/// This is a leaf node that will execute the given task when ticked. +class Task extends BaseNode implements NodeInterface { + /// Creates a task node for given [taskCallback]. + Task(this.taskCallback); + + /// The callback that will be executed when the task is ticked. + /// It should return the status of the task. + final TaskCallback taskCallback; + + @override + void tick() => status = taskCallback(); +} diff --git a/packages/flame_behavior_tree/behavior_tree/pubspec.yaml b/packages/flame_behavior_tree/behavior_tree/pubspec.yaml new file mode 100644 index 00000000000..840acab01b9 --- /dev/null +++ b/packages/flame_behavior_tree/behavior_tree/pubspec.yaml @@ -0,0 +1,20 @@ +name: behavior_tree +description: A behavior tree implementation written in dart. This package is designed to be used for implementing AI in games. +version: 0.1.0 +repository: https://github.com/flame-engine/flame/tree/main/packages/flame_behavior_tree/behavior_tree +funding: + - https://opencollective.com/blue-fire + - https://github.com/sponsors/bluefireteam + - https://patreon.com/bluefireoss + +environment: + sdk: ">=3.0.0 <4.0.0" + +dependencies: + meta: ^1.9.1 + +dev_dependencies: + flame_lint: ^1.1.2 + lints: ^3.0.0 + mocktail: ^1.0.1 + test: any diff --git a/packages/flame_behavior_tree/behavior_tree/test/async_task_test.dart b/packages/flame_behavior_tree/behavior_tree/test/async_task_test.dart new file mode 100644 index 00000000000..65e71f9f76e --- /dev/null +++ b/packages/flame_behavior_tree/behavior_tree/test/async_task_test.dart @@ -0,0 +1,19 @@ +import 'package:behavior_tree/behavior_tree.dart'; +import 'package:test/test.dart'; + +void main() { + group('AsyncTask', () { + test('sets status to running when ticked.', () { + final asyncTask = AsyncTask(() async => NodeStatus.success); + asyncTask.tick(); + expect(asyncTask.status, NodeStatus.running); + }); + + test('updates status to the returned value of the callback.', () async { + final asyncTask = AsyncTask(() async => NodeStatus.failure); + asyncTask.tick(); + await Future.delayed(Duration.zero); // Wait for the callback to complete + expect(asyncTask.status, equals(NodeStatus.failure)); + }); + }); +} diff --git a/packages/flame_behavior_tree/behavior_tree/test/conditon_test.dart b/packages/flame_behavior_tree/behavior_tree/test/conditon_test.dart new file mode 100644 index 00000000000..335f0e686eb --- /dev/null +++ b/packages/flame_behavior_tree/behavior_tree/test/conditon_test.dart @@ -0,0 +1,18 @@ +import 'package:behavior_tree/behavior_tree.dart'; +import 'package:test/test.dart'; + +void main() { + group('Condition', () { + test('status is success when condition returns true', () { + final condition = Condition(() => true); + condition.tick(); + expect(condition.status, NodeStatus.success); + }); + + test('status is failure when condition returns false', () { + final condition = Condition(() => false); + condition.tick(); + expect(condition.status, NodeStatus.failure); + }); + }); +} diff --git a/packages/flame_behavior_tree/behavior_tree/test/inverter_test.dart b/packages/flame_behavior_tree/behavior_tree/test/inverter_test.dart new file mode 100644 index 00000000000..e6a93c33d61 --- /dev/null +++ b/packages/flame_behavior_tree/behavior_tree/test/inverter_test.dart @@ -0,0 +1,45 @@ +import 'package:behavior_tree/behavior_tree.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:test/test.dart'; + +void main() { + group('Inverter', () { + final alwaysFailure = _MockNode(); + final alwaysSuccess = _MockNode(); + final alwaysRunning = _MockNode(); + + setUp(() { + reset(alwaysFailure); + reset(alwaysSuccess); + reset(alwaysRunning); + + when(() => alwaysFailure.status).thenReturn(NodeStatus.failure); + when(() => alwaysSuccess.status).thenReturn(NodeStatus.success); + when(() => alwaysRunning.status).thenReturn(NodeStatus.running); + }); + + test('can be instantiated.', () { + expect(() => Inverter(alwaysRunning), returnsNormally); + }); + + test('default status is inverted child status.', () { + final inverter = Inverter(alwaysSuccess); + expect(inverter.status, NodeStatus.failure); + }); + + test('inverts status of child.', () { + final inverter1 = Inverter(alwaysSuccess)..tick(); + expect(inverter1.status, NodeStatus.failure); + + final inverter2 = Inverter(alwaysFailure)..tick(); + expect(inverter2.status, NodeStatus.success); + }); + + test('keeping running if child is running.', () { + final inverter = Inverter(alwaysRunning)..tick(); + expect(inverter.status, NodeStatus.running); + }); + }); +} + +class _MockNode extends Mock implements NodeInterface {} diff --git a/packages/flame_behavior_tree/behavior_tree/test/limiter_test.dart b/packages/flame_behavior_tree/behavior_tree/test/limiter_test.dart new file mode 100644 index 00000000000..963442666c3 --- /dev/null +++ b/packages/flame_behavior_tree/behavior_tree/test/limiter_test.dart @@ -0,0 +1,71 @@ +import 'package:behavior_tree/behavior_tree.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:test/test.dart'; + +void main() { + group('Limiter', () { + final alwaysFailure = _MockNode(); + final alwaysSuccess = _MockNode(); + final alwaysRunning = _MockNode(); + + setUp(() { + reset(alwaysFailure); + reset(alwaysSuccess); + reset(alwaysRunning); + + when(() => alwaysFailure.status).thenReturn(NodeStatus.failure); + when(() => alwaysSuccess.status).thenReturn(NodeStatus.success); + when(() => alwaysRunning.status).thenReturn(NodeStatus.running); + }); + + test('can be instantiated.', () { + expect(() => Limiter(alwaysRunning, 5), returnsNormally); + }); + + test('default status same as status of child.', () { + final limiter = Limiter(alwaysSuccess, 5); + expect(limiter.status, alwaysSuccess.status); + }); + + test('limits tick count of child.', () { + const limit = 5; + final limiter = Limiter(alwaysRunning, limit); + + var count = 0; + while (count < 23) { + limiter.tick(); + ++count; + } + + expect(limiter.tickCount, limit); + expect(limiter.status, alwaysRunning.status); + }); + + test('overrides status after crossing limit.', () { + const limit = 5; + final failAfterLimit = Limiter( + alwaysSuccess, + limit, + statusAfterLimit: NodeStatus.failure, + ); + + final succeedAfterLimit = Limiter( + alwaysRunning, + limit, + statusAfterLimit: NodeStatus.success, + ); + + var count = 0; + while (count < 23) { + failAfterLimit.tick(); + succeedAfterLimit.tick(); + ++count; + } + + expect(failAfterLimit.status, NodeStatus.failure); + expect(succeedAfterLimit.status, NodeStatus.success); + }); + }); +} + +class _MockNode extends Mock implements NodeInterface {} diff --git a/packages/flame_behavior_tree/behavior_tree/test/selector_test.dart b/packages/flame_behavior_tree/behavior_tree/test/selector_test.dart new file mode 100644 index 00000000000..baef7ef3ef2 --- /dev/null +++ b/packages/flame_behavior_tree/behavior_tree/test/selector_test.dart @@ -0,0 +1,128 @@ +import 'package:behavior_tree/behavior_tree.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:test/test.dart'; + +void main() { + group('Selector', () { + const nTries = 20; + final alwaysFailure = _MockNode(); + final alwaysSuccess = _MockNode(); + final alwaysRunning = _MockNode(); + final successAfterTries = _StatusAfterNTries(nTries, NodeStatus.success); + final failureAfterTries = _StatusAfterNTries(nTries, NodeStatus.failure); + + setUp(() { + reset(alwaysFailure); + reset(alwaysSuccess); + reset(alwaysRunning); + + when(() => alwaysFailure.status).thenReturn(NodeStatus.failure); + when(() => alwaysSuccess.status).thenReturn(NodeStatus.success); + when(() => alwaysRunning.status).thenReturn(NodeStatus.running); + + successAfterTries.reset(); + failureAfterTries.reset(); + }); + + test('can be instantiated without the children.', () { + expect(Selector.new, returnsNormally); + }); + + test('can be instantiated with the children.', () { + expect( + () => Selector(children: [Selector(), Selector()]), + returnsNormally, + ); + }); + + test('default status is not started.', () { + final selector = Selector(); + expect(selector.status, NodeStatus.notStarted); + }); + + test('can be ticked without the children.', () { + final selector = Selector(); + expect(selector.tick, returnsNormally); + }); + + test('can be ticked with the children.', () { + final selector = Selector(children: [Selector(), Selector()]); + expect(selector.tick, returnsNormally); + }); + + test('succeeds if any one of the children succeeds.', () { + final selector = Selector(children: [alwaysFailure, alwaysSuccess]) + ..tick(); + expect(selector.status, NodeStatus.success); + }); + + test('fails if all of the children fail.', () { + final selector = Selector(children: [alwaysFailure, alwaysFailure]) + ..tick(); + expect(selector.status, NodeStatus.failure); + }); + + test('runs until all children fail.', () { + final selector = Selector( + children: [alwaysFailure, failureAfterTries], + ); + + var count = 0; + while (count <= nTries) { + selector.tick(); + + expect( + selector.status, + count == nTries ? NodeStatus.failure : NodeStatus.running, + ); + + ++count; + } + + verify(alwaysFailure.tick).called(count); + expect(failureAfterTries.tickCount, count); + }); + + test('runs until one of the children succeeds.', () { + final selector = Selector(children: [successAfterTries, alwaysFailure]); + + var count = 0; + while (count <= nTries) { + selector.tick(); + + expect( + selector.status, + count == nTries ? NodeStatus.success : NodeStatus.running, + ); + + ++count; + } + + verifyNever(alwaysFailure.tick); + expect(successAfterTries.tickCount, count); + }); + }); +} + +class _MockNode extends Mock implements NodeInterface {} + +class _StatusAfterNTries extends BaseNode implements NodeInterface { + _StatusAfterNTries(this.nTries, this.statusAfterTries); + + final int nTries; + final NodeStatus statusAfterTries; + + var _tickCount = 0; + int get tickCount => _tickCount; + + @override + void tick() { + status = _tickCount++ < nTries ? NodeStatus.running : statusAfterTries; + } + + @override + void reset() { + super.reset(); + _tickCount = 0; + } +} diff --git a/packages/flame_behavior_tree/behavior_tree/test/sequence_test.dart b/packages/flame_behavior_tree/behavior_tree/test/sequence_test.dart new file mode 100644 index 00000000000..9d492d4e460 --- /dev/null +++ b/packages/flame_behavior_tree/behavior_tree/test/sequence_test.dart @@ -0,0 +1,128 @@ +import 'package:behavior_tree/behavior_tree.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:test/test.dart'; + +void main() { + group('Sequence', () { + const nTries = 20; + final alwaysFailure = _MockNode(); + final alwaysSuccess = _MockNode(); + final alwaysRunning = _MockNode(); + final successAfterTries = _StatusAfterNTries(nTries, NodeStatus.success); + final failureAfterTries = _StatusAfterNTries(nTries, NodeStatus.failure); + + setUp(() { + reset(alwaysFailure); + reset(alwaysSuccess); + reset(alwaysRunning); + + when(() => alwaysFailure.status).thenReturn(NodeStatus.failure); + when(() => alwaysSuccess.status).thenReturn(NodeStatus.success); + when(() => alwaysRunning.status).thenReturn(NodeStatus.running); + + successAfterTries.reset(); + failureAfterTries.reset(); + }); + + test('can be instantiated without the children.', () { + expect(Sequence.new, returnsNormally); + }); + + test('can be instantiated with the children.', () { + expect( + () => Sequence(children: [Sequence(), Sequence()]), + returnsNormally, + ); + }); + + test('default status is not started.', () { + final sequence = Sequence(); + expect(sequence.status, NodeStatus.notStarted); + }); + + test('can be ticked without the children.', () { + final selector = Sequence(); + expect(selector.tick, returnsNormally); + }); + + test('can be ticked with the children.', () { + final selector = Sequence(children: [Sequence(), Sequence()]); + expect(selector.tick, returnsNormally); + }); + + test('succeeds if all of the children succeed.', () { + final sequence = Sequence(children: [alwaysSuccess, alwaysSuccess]) + ..tick(); + expect(sequence.status, NodeStatus.success); + }); + + test('fails if any of the children fails.', () { + final sequence = Sequence(children: [alwaysSuccess, alwaysFailure]) + ..tick(); + expect(sequence.status, NodeStatus.failure); + }); + + test('runs until first failure.', () { + final sequence = Sequence( + children: [alwaysSuccess, failureAfterTries], + ); + + var count = 0; + while (count <= nTries) { + sequence.tick(); + + expect( + sequence.status, + count == nTries ? NodeStatus.failure : NodeStatus.running, + ); + + ++count; + } + + verify(alwaysSuccess.tick).called(count); + expect(failureAfterTries.tickCount, count); + }); + + test('runs until all children succeed.', () { + final sequence = Sequence(children: [alwaysSuccess, successAfterTries]); + + var count = 0; + while (count <= nTries) { + sequence.tick(); + + expect( + sequence.status, + count == nTries ? NodeStatus.success : NodeStatus.running, + ); + + ++count; + } + + verify(alwaysSuccess.tick).called(count); + expect(successAfterTries.tickCount, count); + }); + }); +} + +class _MockNode extends Mock implements NodeInterface {} + +class _StatusAfterNTries extends BaseNode implements NodeInterface { + _StatusAfterNTries(this.nTries, this.statusAfterTries); + + final int nTries; + final NodeStatus statusAfterTries; + + var _tickCount = 0; + int get tickCount => _tickCount; + + @override + void tick() { + status = _tickCount++ < nTries ? NodeStatus.running : statusAfterTries; + } + + @override + void reset() { + super.reset(); + _tickCount = 0; + } +} diff --git a/packages/flame_behavior_tree/behavior_tree/test/task_test.dart b/packages/flame_behavior_tree/behavior_tree/test/task_test.dart new file mode 100644 index 00000000000..7b94edfd88c --- /dev/null +++ b/packages/flame_behavior_tree/behavior_tree/test/task_test.dart @@ -0,0 +1,25 @@ +import 'package:behavior_tree/behavior_tree.dart'; +import 'package:test/test.dart'; + +void main() { + group('Task', () { + test('returns the status returned by the task callback', () { + const expectedStatus = NodeStatus.success; + final task = Task(() => expectedStatus); + + task.tick(); + expect(task.status, equals(expectedStatus)); + }); + + test('executes the task callback when ticked', () { + var executed = false; + final task = Task(() { + executed = true; + return NodeStatus.success; + }); + + task.tick(); + expect(executed, isTrue); + }); + }); +} diff --git a/packages/flame_behavior_tree/example/.metadata b/packages/flame_behavior_tree/example/.metadata new file mode 100644 index 00000000000..251f0182bc1 --- /dev/null +++ b/packages/flame_behavior_tree/example/.metadata @@ -0,0 +1,42 @@ +# 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: "bae5e49bc2a867403c43b2aae2de8f8c33b037e4" + channel: "stable" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4 + base_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4 + - platform: android + create_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4 + base_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4 + - platform: linux + create_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4 + base_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4 + - platform: macos + create_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4 + base_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4 + - platform: web + create_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4 + base_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4 + - platform: windows + create_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4 + base_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/packages/flame_behavior_tree/example/analysis_options.yaml b/packages/flame_behavior_tree/example/analysis_options.yaml new file mode 100644 index 00000000000..85732fa02fd --- /dev/null +++ b/packages/flame_behavior_tree/example/analysis_options.yaml @@ -0,0 +1 @@ +include: package:flame_lint/analysis_options.yaml diff --git a/packages/flame_behavior_tree/example/lib/main.dart b/packages/flame_behavior_tree/example/lib/main.dart new file mode 100644 index 00000000000..dbf3f83c2f8 --- /dev/null +++ b/packages/flame_behavior_tree/example/lib/main.dart @@ -0,0 +1,323 @@ +import 'dart:async'; + +import 'dart:math'; + +import 'package:flame/components.dart'; +import 'package:flame/effects.dart'; +import 'package:flame/events.dart'; +import 'package:flame/game.dart'; +import 'package:flame/palette.dart'; +import 'package:flame_behavior_tree/flame_behavior_tree.dart'; +import 'package:flutter/material.dart'; + +typedef MyGame = FlameGame; +const gameWidth = 320.0; +const gameHeight = 180.0; + +void main() { + runApp(const MainApp()); +} + +class MainApp extends StatelessWidget { + const MainApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + body: GameWidget.controlled( + gameFactory: () => MyGame( + world: GameWorld(), + camera: CameraComponent.withFixedResolution( + width: gameWidth, + height: gameHeight, + ), + ), + ), + ), + ); + } +} + +class GameWorld extends World with HasGameReference { + @override + Future onLoad() async { + game.camera.moveTo(Vector2(gameWidth * 0.5, gameHeight * 0.5)); + + final house = RectangleComponent( + size: Vector2(100, 100), + position: Vector2(gameWidth * 0.5, 10), + paint: BasicPalette.cyan.paint() + ..strokeWidth = 5 + ..style = PaintingStyle.stroke, + anchor: Anchor.topCenter, + ); + + final door = Door( + size: Vector2(20, 4), + position: Vector2(40, house.size.y), + anchor: Anchor.centerLeft, + ); + + final agent = Agent( + door: door, + house: house, + position: Vector2(gameWidth * 0.76, gameHeight * 0.9), + ); + + await house.add(door); + await addAll([house, agent]); + } +} + +class Door extends RectangleComponent with TapCallbacks { + Door({super.position, super.size, super.anchor}) + : super(paint: BasicPalette.brown.paint()); + + bool isOpen = false; + bool _isInProgress = false; + bool _isKnocking = false; + + @override + void onTapDown(TapDownEvent event) { + if (!_isInProgress) { + _isInProgress = true; + add( + RotateEffect.to( + isOpen ? 0 : -pi * 0.5, + EffectController(duration: 0.5, curve: Curves.easeInOut), + onComplete: () { + isOpen = !isOpen; + _isInProgress = false; + }, + ), + ); + } + } + + void knock() { + if (!_isKnocking) { + _isKnocking = true; + add( + MoveEffect.by( + Vector2(0, -1), + EffectController( + alternate: true, + duration: 0.1, + repeatCount: 2, + ), + onComplete: () { + _isKnocking = false; + }, + ), + ); + } + } +} + +class Agent extends PositionComponent with HasBehaviorTree { + Agent({required this.door, required this.house, required Vector2 position}) + : _startPosition = position.clone(), + super(position: position); + + final Door door; + final PositionComponent house; + final Vector2 _startPosition; + + @override + Future onLoad() async { + await add(CircleComponent(radius: 3, anchor: Anchor.center)); + _setupBehaviorTree(); + super.onLoad(); + } + + void _setupBehaviorTree() { + var isInside = false; + var isAtTheDoor = false; + var isAtCenterOfHouse = false; + var isMoving = false; + var wantsToGoOutside = false; + + final walkTowardsDoorInside = Task(() { + if (!isAtTheDoor) { + isMoving = true; + + add( + MoveEffect.to( + door.absolutePosition + Vector2(door.size.x * 0.8, -15), + EffectController( + duration: 3, + curve: Curves.easeInOut, + ), + onComplete: () { + isMoving = false; + isAtTheDoor = true; + isAtCenterOfHouse = false; + }, + ), + ); + } + return isAtTheDoor ? NodeStatus.success : NodeStatus.running; + }); + + final stepOutTheDoor = Task(() { + if (isInside) { + isMoving = true; + add( + MoveEffect.to( + door.absolutePosition + Vector2(door.size.x * 0.5, 10), + EffectController( + duration: 2, + curve: Curves.easeInOut, + ), + onComplete: () { + isMoving = false; + isInside = false; + }, + ), + ); + } + return !isInside ? NodeStatus.success : NodeStatus.running; + }); + + final walkTowardsInitialPosition = Task( + () { + if (isAtTheDoor) { + isMoving = true; + isAtTheDoor = false; + + add( + MoveEffect.to( + _startPosition, + EffectController( + duration: 3, + curve: Curves.easeInOut, + ), + onComplete: () { + isMoving = false; + wantsToGoOutside = false; + }, + ), + ); + } + + return !wantsToGoOutside ? NodeStatus.success : NodeStatus.running; + }, + ); + + final walkTowardsDoorOutside = Task(() { + if (!isAtTheDoor) { + isMoving = true; + add( + MoveEffect.to( + door.absolutePosition + Vector2(door.size.x * 0.5, 10), + EffectController( + duration: 3, + curve: Curves.easeInOut, + ), + onComplete: () { + isMoving = false; + isAtTheDoor = true; + }, + ), + ); + } + return isAtTheDoor ? NodeStatus.success : NodeStatus.running; + }); + + final walkTowardsCenterOfTheHouse = Task(() { + if (!isAtCenterOfHouse) { + isMoving = true; + isInside = true; + + add( + MoveEffect.to( + house.absoluteCenter, + EffectController( + duration: 3, + curve: Curves.easeInOut, + ), + onComplete: () { + isMoving = false; + wantsToGoOutside = true; + isAtTheDoor = false; + isAtCenterOfHouse = true; + }, + ), + ); + } + return isInside ? NodeStatus.success : NodeStatus.running; + }); + + final checkIfDoorIsOpen = Condition(() => door.isOpen); + + final knockTheDoor = Task(() { + door.knock(); + return NodeStatus.success; + }); + + final goOutsideSequence = Sequence( + children: [ + Condition(() => wantsToGoOutside), + Selector( + children: [ + Sequence( + children: [ + Condition(() => isInside), + walkTowardsDoorInside, + Selector( + children: [ + Sequence( + children: [ + checkIfDoorIsOpen, + stepOutTheDoor, + ], + ), + knockTheDoor, + ], + ), + ], + ), + walkTowardsInitialPosition, + ], + ), + ], + ); + + final goInsideSequence = Sequence( + children: [ + Condition(() => !wantsToGoOutside), + Selector( + children: [ + Sequence( + children: [ + Condition(() => !isInside), + walkTowardsDoorOutside, + Selector( + children: [ + Sequence( + children: [ + checkIfDoorIsOpen, + walkTowardsCenterOfTheHouse, + ], + ), + knockTheDoor, + ], + ), + ], + ), + ], + ), + ], + ); + + treeRoot = Selector( + children: [ + Condition(() => isMoving), + goOutsideSequence, + goInsideSequence, + ], + ); + tickInterval = 2; + } +} diff --git a/packages/flame_behavior_tree/example/pubspec.yaml b/packages/flame_behavior_tree/example/pubspec.yaml new file mode 100644 index 00000000000..4155b245c6a --- /dev/null +++ b/packages/flame_behavior_tree/example/pubspec.yaml @@ -0,0 +1,25 @@ +name: flame_behavior_tree_example +description: "A simple demo to show usage of behavior trees in flame." +publish_to: 'none' +version: 0.1.0 +funding: + - https://opencollective.com/blue-fire + - https://github.com/sponsors/bluefireteam + - https://patreon.com/bluefireoss + +environment: + sdk: ">=3.0.0 <4.0.0" + +dependencies: + flame: ^1.16.0 + flame_behavior_tree: ^0.1.0 + flutter: + sdk: flutter + +dev_dependencies: + flame_lint: ^1.1.2 + flutter_test: + sdk: flutter + +flutter: + uses-material-design: true diff --git a/packages/flame_behavior_tree/lib/flame_behavior_tree.dart b/packages/flame_behavior_tree/lib/flame_behavior_tree.dart new file mode 100644 index 00000000000..e90ce54b309 --- /dev/null +++ b/packages/flame_behavior_tree/lib/flame_behavior_tree.dart @@ -0,0 +1,5 @@ +/// A bridge package that integrates behavior_tree package with flame. +library flame_behavior_tree; + +export 'package:behavior_tree/behavior_tree.dart'; +export 'src/has_behavior_tree.dart'; diff --git a/packages/flame_behavior_tree/lib/src/has_behavior_tree.dart b/packages/flame_behavior_tree/lib/src/has_behavior_tree.dart new file mode 100644 index 00000000000..e978745d2f6 --- /dev/null +++ b/packages/flame_behavior_tree/lib/src/has_behavior_tree.dart @@ -0,0 +1,57 @@ +import 'dart:async'; + +import 'package:behavior_tree/behavior_tree.dart'; +import 'package:flame/components.dart'; +import 'package:flutter/foundation.dart'; + +/// A mixin on [Component] to indicate that the component has a behavior tree. +/// +/// Reference to the behavior tree for this component can be set or accessed +/// via [treeRoot]. The update frequency of the tree can be reduced by +/// increasing [tickInterval]. By default, the tree will be updated on every +/// update of the component. +mixin HasBehaviorTree on Component { + T? _treeRoot; + Timer? _timer; + double _tickInterval = 0; + + /// The delay between any two ticks of the behavior tree. + double get tickInterval => _tickInterval; + set tickInterval(double interval) { + _tickInterval = interval; + + if (_tickInterval > 0) { + _timer ??= Timer(interval, repeat: true); + _timer?.limit = interval; + } else { + _timer?.onTick = null; + _timer = null; + _tickInterval = 0; + } + } + + /// The root node of the behavior tree. + T get treeRoot => _treeRoot!; + set treeRoot(T value) { + _treeRoot = value; + _timer?.onTick = _treeRoot!.tick; + } + + @override + @mustCallSuper + Future onLoad() async { + super.onLoad(); + _timer?.onTick = _treeRoot?.tick; + } + + @override + @mustCallSuper + void update(double dt) { + super.update(dt); + if (_tickInterval > 0) { + _timer?.update(dt); + } else { + _treeRoot?.tick(); + } + } +} diff --git a/packages/flame_behavior_tree/pubspec.yaml b/packages/flame_behavior_tree/pubspec.yaml new file mode 100644 index 00000000000..9975ab1d023 --- /dev/null +++ b/packages/flame_behavior_tree/pubspec.yaml @@ -0,0 +1,25 @@ +name: flame_behavior_tree +description: A bridge package that integrates behavior_tree package with flame. +version: 0.1.0 +homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_behavior_tree +funding: + - https://opencollective.com/blue-fire + - https://github.com/sponsors/bluefireteam + - https://patreon.com/bluefireoss + +environment: + sdk: ">=3.0.0 <4.0.0" + flutter: ">=3.19.0" + +dependencies: + behavior_tree: ^1.0.0 + flame: ^1.16.0 + flutter: + sdk: flutter + +dev_dependencies: + flame_lint: ^1.1.2 + flame_test: ^1.16.0 + flutter_test: + sdk: flutter + mocktail: ^1.0.1 diff --git a/packages/flame_behavior_tree/test/has_behavior_tree_test.dart b/packages/flame_behavior_tree/test/has_behavior_tree_test.dart new file mode 100644 index 00000000000..c7f0d36ecad --- /dev/null +++ b/packages/flame_behavior_tree/test/has_behavior_tree_test.dart @@ -0,0 +1,98 @@ +import 'package:flame/components.dart'; +import 'package:flame_behavior_tree/flame_behavior_tree.dart'; +import 'package:flame_test/flame_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; + +void main() { + group('HasBehaviorTree', () { + final alwaysFailure = _MockNode(); + final alwaysSuccess = _MockNode(); + final alwaysRunning = _MockNode(); + + setUp(() { + reset(alwaysFailure); + reset(alwaysSuccess); + reset(alwaysRunning); + + when(() => alwaysFailure.status).thenReturn(NodeStatus.failure); + when(() => alwaysSuccess.status).thenReturn(NodeStatus.success); + when(() => alwaysRunning.status).thenReturn(NodeStatus.running); + }); + + testWithFlameGame( + 'updates with null tree.', + (game) async { + final component = _BehaviorTreeComponent(); + expect(() => game.add(component), returnsNormally); + }, + ); + + test('tick interval can be changed', () { + final component = _BehaviorTreeComponent(); + expect(component.tickInterval, 0); + + component.tickInterval = 3; + expect(component.tickInterval, 3); + + component.tickInterval = -53; + expect(component.tickInterval, 0); + }); + + test('throws if treeNode is accessed before setting.', () { + final component = _BehaviorTreeComponent(); + expect(() => component.treeRoot, throwsA(isA())); + + component.treeRoot = _MockNode(); + expect(() => component.treeRoot, returnsNormally); + }); + + testWithFlameGame( + 'updates without errors with a valid tree.', + (game) async { + final component = _BehaviorTreeComponent() + ..treeRoot = + Sequence(children: [alwaysSuccess, alwaysFailure, alwaysRunning]); + + expect(() async => await game.add(component), returnsNormally); + + await game.ready(); + expect(() => game.update(10), returnsNormally); + + verify(alwaysSuccess.tick).called(1); + verify(alwaysFailure.tick).called(1); + verifyNever(alwaysRunning.tick); + }, + ); + + testWithFlameGame( + 'tree updates at a slower rate.', + (game) async { + final component = _BehaviorTreeComponent() + ..treeRoot = + Sequence(children: [alwaysSuccess, alwaysFailure, alwaysRunning]) + ..tickInterval = 1; + + await game.add(component); + await game.ready(); + + const dt = 1 / 60; + const gameTime = 3.0; + var elapsedTime = 0.0; + + while (elapsedTime < gameTime) { + game.update(dt); + elapsedTime += dt; + } + + verify(alwaysSuccess.tick).called(gameTime.toInt()); + verify(alwaysFailure.tick).called(gameTime.toInt()); + verifyNever(alwaysRunning.tick); + }, + ); + }); +} + +class _BehaviorTreeComponent extends Component with HasBehaviorTree {} + +class _MockNode extends Mock implements NodeInterface {} From 17da92b2d1c527162106778f459d72f19a5c5607 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Mon, 11 Mar 2024 22:34:48 +0100 Subject: [PATCH 19/79] fix: Implement necessary `ProviderSubscription` getters (#3075) This adds implementations of the necessary `ProviderSubscription` getters. --- packages/flame_riverpod/lib/src/widget.dart | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/flame_riverpod/lib/src/widget.dart b/packages/flame_riverpod/lib/src/widget.dart index c1303ca68f4..e9b6139954e 100644 --- a/packages/flame_riverpod/lib/src/widget.dart +++ b/packages/flame_riverpod/lib/src/widget.dart @@ -3,6 +3,8 @@ import 'package:flame/game.dart'; import 'package:flame_riverpod/flame_riverpod.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +// ignore: depend_on_referenced_packages, implementation_imports +import 'package:riverpod/src/framework.dart'; /// A [GameWidget] that provides access to [Component]s using /// [RiverpodComponentMixin] attached to [FlameGame]s using [RiverpodGameMixin] @@ -246,4 +248,10 @@ class _ListenManual implements ProviderSubscription { @override T read() => _subscription.read(); + + @override + bool get closed => _subscription.closed; + + @override + Node get source => _subscription.source; } From e3aaa7c21d89a6679c3ae70de6e676d1f11501fa Mon Sep 17 00:00:00 2001 From: markvideon Date: Fri, 15 Mar 2024 17:27:24 +1030 Subject: [PATCH 20/79] fix: Resolve breaking changes from Riverpod affecting flame_riverpod (#3080) Changes to how support for manual listeners is implemented in flutter_riverpod 2.5.1 (released 4 days ago) have affected flame_riverpod - specifically, the implementation of ProviderSubscription. This PR updates the implementation of manual listeners in flame_riverpod in the same manner that flutter_riverpod has. --- packages/flame_riverpod/example/pubspec.yaml | 2 +- packages/flame_riverpod/lib/src/widget.dart | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/flame_riverpod/example/pubspec.yaml b/packages/flame_riverpod/example/pubspec.yaml index eb97b7d5e2c..8a7d5d44444 100644 --- a/packages/flame_riverpod/example/pubspec.yaml +++ b/packages/flame_riverpod/example/pubspec.yaml @@ -9,7 +9,7 @@ dependencies: flame_riverpod: ^5.3.0 flutter: sdk: flutter - flutter_riverpod: ^2.1.3 + flutter_riverpod: ^2.5.1 dev_dependencies: flame_lint: ^0.2.0 diff --git a/packages/flame_riverpod/lib/src/widget.dart b/packages/flame_riverpod/lib/src/widget.dart index e9b6139954e..1a1aa691c47 100644 --- a/packages/flame_riverpod/lib/src/widget.dart +++ b/packages/flame_riverpod/lib/src/widget.dart @@ -219,8 +219,13 @@ class RiverpodAwareGameWidgetState extends GameWidgetState _assertNotDisposed(); final listeners = _manualListeners ??= []; + // Reading the container using "listen:false" to guarantee that this can + // be used inside initState. + final container = ProviderScope.containerOf(context, listen: false); + final sub = _ListenManual( - ProviderScope.containerOf(context, listen: false).listen( + container, + container.listen( provider, listener, onError: onError, @@ -234,16 +239,19 @@ class RiverpodAwareGameWidgetState extends GameWidgetState } } -class _ListenManual implements ProviderSubscription { - _ListenManual(this._subscription, this._element); +class _ListenManual extends ProviderSubscription { + _ListenManual(super.source, this._subscription, this._element); final ProviderSubscription _subscription; final RiverpodAwareGameWidgetState _element; @override void close() { - _subscription.close(); - _element._manualListeners?.remove(this); + if (!closed) { + _subscription.close(); + _element._manualListeners?.remove(this); + } + super.close(); } @override From 44b10fd60c61392d449a8d12020c45724ad19625 Mon Sep 17 00:00:00 2001 From: Tizian Seehaus <38123657+tibotix@users.noreply.github.com> Date: Fri, 15 Mar 2024 08:03:55 +0100 Subject: [PATCH 21/79] feat: Allow ComponentRef access in RiverpodGameMixin (#3010) This PR allows `ComponentRef` access through the `RiverpodGameMixin`. Closes #2971 --------- Co-authored-by: Lukas Klingsbo --- .../flame_riverpod/component.md | 2 + packages/flame_riverpod/lib/src/consumer.dart | 22 ++++++++ packages/flame_riverpod/test/widget_test.dart | 51 +++++++++++++++++++ 3 files changed, 75 insertions(+) diff --git a/doc/bridge_packages/flame_riverpod/component.md b/doc/bridge_packages/flame_riverpod/component.md index 6b18aeba9a2..b7195fa076d 100644 --- a/doc/bridge_packages/flame_riverpod/component.md +++ b/doc/bridge_packages/flame_riverpod/component.md @@ -44,3 +44,5 @@ class RiverpodAwareTextComponent extends PositionComponent `RiverpodGameMixin` provides listeners from all components to the build method of the `RiverpodAwareGameWidget`. +The `addToGameWidgetBuild` method is available in the `RiverpodGameMixin` as well, +enabling you to access `ComponentRef` methods directly in your Game class. diff --git a/packages/flame_riverpod/lib/src/consumer.dart b/packages/flame_riverpod/lib/src/consumer.dart index 5f3185008eb..d037211bbf0 100644 --- a/packages/flame_riverpod/lib/src/consumer.dart +++ b/packages/flame_riverpod/lib/src/consumer.dart @@ -139,8 +139,30 @@ mixin RiverpodGameMixin on FlameGame { /// Used to facilitate [Component] access to the [ProviderContainer]. GlobalKey? widgetKey; + final ComponentRef ref = ComponentRef(game: null); final List _onBuildCallbacks = []; + /// Adds a callback method to be invoked in the build method of + /// [RiverpodAwareGameWidgetState]. + void addToGameWidgetBuild(Function() cb) { + _onBuildCallbacks.add(cb); + } + + @override + void onMount() { + super.onMount(); + mounted.whenComplete(() { + widgetKey!.currentState!.forceBuild(); + }); + } + + @mustCallSuper + @override + FutureOr onLoad() { + ref.game = this; + return super.onLoad(); + } + /// Invoked in [RiverpodAwareGameWidgetState.build]. Each callback is /// expected to consist of calls to methods implemented in [WidgetRef]. /// E.g. [WidgetRef.watch], [WidgetRef.listen], etc. diff --git a/packages/flame_riverpod/test/widget_test.dart b/packages/flame_riverpod/test/widget_test.dart index 06f5569f21b..0f2aebd8bd2 100644 --- a/packages/flame_riverpod/test/widget_test.dart +++ b/packages/flame_riverpod/test/widget_test.dart @@ -11,6 +11,16 @@ final numberProvider = Provider.autoDispose((ref) { class MyGame extends FlameGame with RiverpodGameMixin {} +class MyGameWithRefAccess extends FlameGame with RiverpodGameMixin { + @override + void onMount() { + addToGameWidgetBuild(() { + ref.watch(numberProvider); + }); + super.onMount(); + } +} + class EmptyComponent extends Component with RiverpodComponentMixin { @override void onLoad() { @@ -136,4 +146,45 @@ void main() { // numberProvider as the watching component has been removed. expect(key.currentState?.exists(numberProvider), false); }); + + testWidgets( + 'Test registration and de-registration of Game Provider listeners', + (widgetTester) async { + final game = MyGameWithRefAccess(); + final key = GlobalKey(); + + await widgetTester.pumpWidget( + ProviderScope( + child: MaterialApp( + home: RiverpodAwareGameWidget( + game: game, + key: key, + ), + ), + ), + ); + await widgetTester.pump(Duration.zero); + + // Expect the game is ready to play + expect(game.isAttached, true); + expect(game.isMounted, true); + expect(game.isLoaded, true); + + // Pump to ensure the custom component's lifecycle events are handled + await widgetTester.pump(Duration.zero); + + // Expect that the GameWidget is initially listening to + // numberProvider + expect(key.currentState?.exists(numberProvider), true); + + // Replace the widget tree so that the GameWidget gets disposed + await widgetTester.pumpWidget(Container()); + await widgetTester.pumpAndSettle(); + + // Expect that the component has been removed from the game. + expect(game.isAttached, false); + + // Expect that the key no longer has access to a state. + expect(key.currentState, null); + }); } From b44011fd714ec5919de5407f53d0772f31ed1a13 Mon Sep 17 00:00:00 2001 From: markvideon Date: Fri, 15 Mar 2024 21:08:51 +1030 Subject: [PATCH 22/79] fix: Resolve logic error with assignment of ComponentRef's game property in flame_riverpod (#3082) Assignment of the game property on Components using RiverpodComponentMixin was being performed inside the onLoad method, meaning if components were unmounted and mounted once again, attempts to invoke callbacks to the GameWidget's build method would throw an exception. This functionality has been moved to the onMount method, where it always should have been. --- packages/flame_riverpod/lib/src/consumer.dart | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/flame_riverpod/lib/src/consumer.dart b/packages/flame_riverpod/lib/src/consumer.dart index d037211bbf0..82671084c5f 100644 --- a/packages/flame_riverpod/lib/src/consumer.dart +++ b/packages/flame_riverpod/lib/src/consumer.dart @@ -79,13 +79,6 @@ mixin RiverpodComponentMixin on Component { /// this component is removed. bool rebuildOnRemoveWhen(ComponentRef ref) => true; - @mustCallSuper - @override - FutureOr onLoad() { - ref.game = findGame()! as RiverpodGameMixin; - super.onLoad(); - } - /// Adds a callback method to be invoked in the build method of /// [RiverpodAwareGameWidgetState]. void addToGameWidgetBuild(Function() cb) { @@ -96,6 +89,7 @@ mixin RiverpodComponentMixin on Component { @override void onMount() { super.onMount(); + ref.game = findGame()! as RiverpodGameMixin; ref.game!._onBuildCallbacks.addAll(_onBuildCallbacks); if (rebuildOnMountWhen(ref) == true) { From af6ee6491706fc206863e2b3742212e93470692e Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Fri, 15 Mar 2024 12:02:39 +0100 Subject: [PATCH 23/79] chore: Publish flame_riverpod v5.4.0 (#3081) ``` Package Name Current Version Updated Version Update Reason flame_riverpod 5.3.0 5.4.0 updated with minor changes ``` --- CHANGELOG.md | 24 ++++++++++++++++++++ packages/flame_riverpod/CHANGELOG.md | 7 ++++++ packages/flame_riverpod/example/pubspec.yaml | 2 +- packages/flame_riverpod/pubspec.yaml | 16 +++++++++---- 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e0b8e728cc..0790be3c4e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2024-03-15 + +### Changes + +--- + +Packages with breaking changes: + + - There are no breaking changes in this release. + +Packages with other changes: + + - [`flame_riverpod` - `v5.4.0`](#flame_riverpod---v540) + +--- + +#### `flame_riverpod` - `v5.4.0` + + - **FIX**: Resolve logic error with assignment of ComponentRef's game property in flame_riverpod ([#3082](https://github.com/flame-engine/flame/issues/3082)). ([b44011fd](https://github.com/flame-engine/flame/commit/b44011fd714ec5919de5407f53d0772f31ed1a13)) + - **FIX**: Resolve breaking changes from Riverpod affecting flame_riverpod ([#3080](https://github.com/flame-engine/flame/issues/3080)). ([e3aaa7c2](https://github.com/flame-engine/flame/commit/e3aaa7c21d89a6679c3ae70de6e676d1f11501fa)) + - **FIX**: Implement necessary `ProviderSubscription` getters ([#3075](https://github.com/flame-engine/flame/issues/3075)). ([17da92b2](https://github.com/flame-engine/flame/commit/17da92b2d1c527162106778f459d72f19a5c5607)) + - **FEAT**: Allow ComponentRef access in RiverpodGameMixin ([#3010](https://github.com/flame-engine/flame/issues/3010)). ([44b10fd6](https://github.com/flame-engine/flame/commit/44b10fd60c61392d449a8d12020c45724ad19625)) + + ## 2024-02-17 ### Changes diff --git a/packages/flame_riverpod/CHANGELOG.md b/packages/flame_riverpod/CHANGELOG.md index acda8810a3b..ec1300be3d0 100644 --- a/packages/flame_riverpod/CHANGELOG.md +++ b/packages/flame_riverpod/CHANGELOG.md @@ -1,3 +1,10 @@ +## 5.4.0 + + - **FIX**: Resolve logic error with assignment of ComponentRef's game property in flame_riverpod ([#3082](https://github.com/flame-engine/flame/issues/3082)). ([b44011fd](https://github.com/flame-engine/flame/commit/b44011fd714ec5919de5407f53d0772f31ed1a13)) + - **FIX**: Resolve breaking changes from Riverpod affecting flame_riverpod ([#3080](https://github.com/flame-engine/flame/issues/3080)). ([e3aaa7c2](https://github.com/flame-engine/flame/commit/e3aaa7c21d89a6679c3ae70de6e676d1f11501fa)) + - **FIX**: Implement necessary `ProviderSubscription` getters ([#3075](https://github.com/flame-engine/flame/issues/3075)). ([17da92b2](https://github.com/flame-engine/flame/commit/17da92b2d1c527162106778f459d72f19a5c5607)) + - **FEAT**: Allow ComponentRef access in RiverpodGameMixin ([#3010](https://github.com/flame-engine/flame/issues/3010)). ([44b10fd6](https://github.com/flame-engine/flame/commit/44b10fd60c61392d449a8d12020c45724ad19625)) + ## 5.3.0 > Note: This release has breaking changes. diff --git a/packages/flame_riverpod/example/pubspec.yaml b/packages/flame_riverpod/example/pubspec.yaml index 8a7d5d44444..1eeef2ee4db 100644 --- a/packages/flame_riverpod/example/pubspec.yaml +++ b/packages/flame_riverpod/example/pubspec.yaml @@ -6,7 +6,7 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: flame: ^1.16.0 - flame_riverpod: ^5.3.0 + flame_riverpod: ^5.4.0 flutter: sdk: flutter flutter_riverpod: ^2.5.1 diff --git a/packages/flame_riverpod/pubspec.yaml b/packages/flame_riverpod/pubspec.yaml index 06fb6e26d21..cb6ff5a7b3d 100644 --- a/packages/flame_riverpod/pubspec.yaml +++ b/packages/flame_riverpod/pubspec.yaml @@ -1,17 +1,23 @@ name: flame_riverpod -description: Helpers for using Riverpod - a reactive caching and data-binding framework, - in conjunction with Flame. -version: 5.3.0 +description: Helpers for using Riverpod - a reactive caching and data-binding framework, in conjunction with Flame. +version: 5.4.0 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_riverpod +funding: + - https://opencollective.com/blue-fire + - https://github.com/sponsors/bluefireteam + - https://patreon.com/bluefireoss + environment: sdk: ">=3.0.0 <4.0.0" flutter: ">=3.19.0" + dependencies: flame: ^1.16.0 flutter: sdk: flutter - flutter_riverpod: ^2.1.3 + flutter_riverpod: ^2.5.1 + dev_dependencies: - flame_lint: ^0.2.0 + flame_lint: ^1.1.2 flutter_test: sdk: flutter From 76498eb95aa24ba0fa82b3f4538d465064dbc29f Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Fri, 15 Mar 2024 12:05:36 +0100 Subject: [PATCH 24/79] chore: Add riverpod as a direct dependency to flame_riverpod --- packages/flame_riverpod/pubspec.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/flame_riverpod/pubspec.yaml b/packages/flame_riverpod/pubspec.yaml index cb6ff5a7b3d..ea1598cefd9 100644 --- a/packages/flame_riverpod/pubspec.yaml +++ b/packages/flame_riverpod/pubspec.yaml @@ -16,6 +16,7 @@ dependencies: flutter: sdk: flutter flutter_riverpod: ^2.5.1 + riverpod: ^2.5.1 dev_dependencies: flame_lint: ^1.1.2 From bf3c282dd669e9a32a550b86770dba7fb8472afa Mon Sep 17 00:00:00 2001 From: Erick Date: Mon, 18 Mar 2024 10:41:46 -0300 Subject: [PATCH 25/79] feat: Add SpriteBatch.replace to allow the replacement of the batch information (#3079) This PR adds a new method to the `SpriteBatch` class which allow users to replace the information, based on an index of the batch. This is useful when you want to change some of the rendering calls without having to rebuild the whole batch. --------- Co-authored-by: Jochum van der Ploeg --- packages/flame/lib/src/sprite_batch.dart | 39 ++++++++++++++ packages/flame/test/sprite_batch_test.dart | 60 ++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 packages/flame/test/sprite_batch_test.dart diff --git a/packages/flame/lib/src/sprite_batch.dart b/packages/flame/lib/src/sprite_batch.dart index a0d876fbc28..8dfddf95ee9 100644 --- a/packages/flame/lib/src/sprite_batch.dart +++ b/packages/flame/lib/src/sprite_batch.dart @@ -243,6 +243,45 @@ class SpriteBatch { return picture.toImageSafe(image.width * 2, image.height); } + int get length => _sources.length; + + /// Replace provided values of a batch item at the [index], when a parameter + /// is not provided, the original value of the batch item will be used. + /// + /// Throws an [ArgumentError] if the [index] is out of bounds. + /// At least one of the parameters must be different from null. + void replace( + int index, { + Rect? source, + Color? color, + RSTransform? transform, + }) { + assert( + source != null || color != null || transform != null, + 'At least one of the parameters must be different from null.', + ); + + if (index < 0 || index >= length) { + throw ArgumentError('Index out of bounds: $index'); + } + + final currentBatchItem = _batchItems[index]; + final newBatchItem = BatchItem( + source: source ?? currentBatchItem.source, + transform: transform ?? currentBatchItem.transform, + color: color ?? currentBatchItem.paint.color, + flip: currentBatchItem.flip, + ); + + _batchItems[index] = newBatchItem; + + _sources[index] = newBatchItem.source; + _transforms[index] = newBatchItem.transform; + if (color != null) { + _colors[index] = color; + } + } + /// Add a new batch item using a RSTransform. /// /// The [source] parameter is the source location on the [atlas]. diff --git a/packages/flame/test/sprite_batch_test.dart b/packages/flame/test/sprite_batch_test.dart new file mode 100644 index 00000000000..8ccc4694607 --- /dev/null +++ b/packages/flame/test/sprite_batch_test.dart @@ -0,0 +1,60 @@ +import 'dart:ui'; + +import 'package:flame/sprite.dart'; +import 'package:flutter/material.dart' hide Image; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; + +class _MockImage extends Mock implements Image {} + +void main() { + group('SpriteBatch', () { + test('can add to the batch', () { + final image = _MockImage(); + final spriteBatch = SpriteBatch(image); + spriteBatch.add(source: Rect.zero); + + expect(spriteBatch.transforms, hasLength(1)); + }); + + test('can replace the color of a batch', () { + final image = _MockImage(); + final spriteBatch = SpriteBatch(image); + spriteBatch.add(source: Rect.zero, color: Colors.blue); + + spriteBatch.replace(0, color: Colors.red); + + expect(spriteBatch.colors, hasLength(1)); + expect(spriteBatch.colors.first, Colors.red); + }); + + test('can replace the source of a batch', () { + final image = _MockImage(); + final spriteBatch = SpriteBatch(image); + spriteBatch.add(source: Rect.zero); + + spriteBatch.replace(0, source: const Rect.fromLTWH(1, 1, 1, 1)); + + expect(spriteBatch.sources, hasLength(1)); + expect(spriteBatch.sources.first, const Rect.fromLTWH(1, 1, 1, 1)); + }); + + test('can replace the transform of a batch', () { + final image = _MockImage(); + final spriteBatch = SpriteBatch(image); + spriteBatch.add(source: Rect.zero); + + spriteBatch.replace(0, transform: RSTransform(1, 1, 1, 1)); + + expect(spriteBatch.transforms, hasLength(1)); + expect( + spriteBatch.transforms.first, + isA() + .having((t) => t.scos, 'scos', 1) + .having((t) => t.ssin, 'ssin', 1) + .having((t) => t.tx, 'tx', 1) + .having((t) => t.ty, 'ty', 1), + ); + }); + }); +} From e3e755c6dec35f36b4a42893afeea5f64ff025b7 Mon Sep 17 00:00:00 2001 From: Erick Date: Mon, 18 Mar 2024 15:06:28 -0300 Subject: [PATCH 26/79] feat: Update http dependency on flame_network_assets (#3084) Updates the http dependency on flame_network_assets --- packages/flame_network_assets/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/flame_network_assets/pubspec.yaml b/packages/flame_network_assets/pubspec.yaml index 4fc4d34192d..aba2aeee348 100644 --- a/packages/flame_network_assets/pubspec.yaml +++ b/packages/flame_network_assets/pubspec.yaml @@ -16,7 +16,7 @@ dependencies: flame: ^1.16.0 flutter: sdk: flutter - http: ^0.13.6 + http: ^1.2.1 path: ^1.8.3 path_provider: ^2.0.15 From 8f50c9279581999b4ff7f506682148425b248e28 Mon Sep 17 00:00:00 2001 From: Natalie Masse Hooper Date: Wed, 20 Mar 2024 08:27:01 +0000 Subject: [PATCH 27/79] fix: Updated oxygen dep to v0.3.1 and added removing components (#3087) Updated oxygen dep to v0.3.1 and added call to new method to remove components. --- packages/flame_oxygen/lib/src/flame_world.dart | 1 + packages/flame_oxygen/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/flame_oxygen/lib/src/flame_world.dart b/packages/flame_oxygen/lib/src/flame_world.dart index 190cecd04f4..c35d9f03eda 100644 --- a/packages/flame_oxygen/lib/src/flame_world.dart +++ b/packages/flame_oxygen/lib/src/flame_world.dart @@ -23,6 +23,7 @@ class FlameWorld extends World { system.update(delta); } entityManager.processRemovedEntities(); + entityManager.processRemovedComponents(); } @override diff --git a/packages/flame_oxygen/pubspec.yaml b/packages/flame_oxygen/pubspec.yaml index 2664ee352a2..436e2ebe31a 100644 --- a/packages/flame_oxygen/pubspec.yaml +++ b/packages/flame_oxygen/pubspec.yaml @@ -15,7 +15,7 @@ dependencies: flame: ^1.16.0 flutter: sdk: flutter - oxygen: ^0.2.0 + oxygen: ^0.3.1 dev_dependencies: dartdoc: ^6.3.0 From cc035fb4a3e123473d4e5e0db1fa0253e533bc61 Mon Sep 17 00:00:00 2001 From: Yukiteru Attano <85680862+YukiAttano@users.noreply.github.com> Date: Thu, 21 Mar 2024 11:52:12 +0100 Subject: [PATCH 28/79] refactor: Change the ClipComponent factory Constructor to redirect Constructor (#3089) The ClipComponent factory Constructor "circle", "rectangle" and "polygon" are now redirect Constructor while they persist their previous behaviour and syntax. This allows subclasses of ClipComponent to directly address them. ```dart /// Examples: SubClass.fancyShape() : super.polygon(); Smiley() : super.circle(); ``` --------- Co-authored-by: Lukas Klingsbo --- .../lib/src/components/clip_component.dart | 112 +++++++++--------- 1 file changed, 58 insertions(+), 54 deletions(-) diff --git a/packages/flame/lib/src/components/clip_component.dart b/packages/flame/lib/src/components/clip_component.dart index 0e7c8440c55..5b7199426e2 100644 --- a/packages/flame/lib/src/components/clip_component.dart +++ b/packages/flame/lib/src/components/clip_component.dart @@ -29,7 +29,7 @@ class ClipComponent extends PositionComponent implements SizeProvider { /// {@macro circle_clip_component} /// /// Clips the canvas in the form of a circle based on its size. - factory ClipComponent.circle({ + ClipComponent.circle({ Vector2? position, Vector2? size, Vector2? scale, @@ -38,24 +38,22 @@ class ClipComponent extends PositionComponent implements SizeProvider { Iterable? children, int? priority, ComponentKey? key, - }) { - return ClipComponent( - builder: (size) => Circle(size / 2, size.x / 2), - position: position, - size: size, - scale: scale, - angle: angle, - anchor: anchor, - children: children, - priority: priority, - key: key, - ); - } + }) : this( + builder: (size) => Circle(size / 2, size.x / 2), + position: position, + size: size, + scale: scale, + angle: angle, + anchor: anchor, + children: children, + priority: priority, + key: key, + ); /// {@macro rectangle_clip_component} /// /// Clips the canvas in the form of a rectangle based on its size. - factory ClipComponent.rectangle({ + ClipComponent.rectangle({ Vector2? position, Vector2? size, Vector2? scale, @@ -64,24 +62,22 @@ class ClipComponent extends PositionComponent implements SizeProvider { Iterable? children, int? priority, ComponentKey? key, - }) { - return ClipComponent( - builder: (size) => Rectangle.fromRect(size.toRect()), - position: position, - size: size, - scale: scale, - angle: angle, - anchor: anchor, - children: children, - priority: priority, - key: key, - ); - } + }) : this( + builder: (size) => Rectangle.fromRect(size.toRect()), + position: position, + size: size, + scale: scale, + angle: angle, + anchor: anchor, + children: children, + priority: priority, + key: key, + ); /// {@macro polygon_clip_component} /// /// Clips the canvas in the form of a polygon based on its size. - factory ClipComponent.polygon({ + ClipComponent.polygon({ required List points, Vector2? position, Vector2? size, @@ -91,31 +87,17 @@ class ClipComponent extends PositionComponent implements SizeProvider { Iterable? children, int? priority, ComponentKey? key, - }) { - assert( - points.length > 2, - 'PolygonClipComponent requires at least 3 points.', - ); - - return ClipComponent( - builder: (size) { - final translatedPoints = points - .map( - (p) => p.clone()..multiply(size), - ) - .toList(); - return Polygon(translatedPoints); - }, - position: position, - size: size, - scale: scale, - angle: angle, - anchor: anchor, - children: children, - priority: priority, - key: key, - ); - } + }) : this( + builder: _polygonShapeBuilder(points), + position: position, + size: size, + scale: scale, + angle: angle, + anchor: anchor, + children: children, + priority: priority, + key: key, + ); late Path _path; late Shape _shape; @@ -144,4 +126,26 @@ class ClipComponent extends PositionComponent implements SizeProvider { bool containsLocalPoint(Vector2 point) { return _shape.containsPoint(point); } + + /// Returns the [ShapeBuilder] function that builds a polygon + /// + /// this allows us to use an assertion during Constructor initialization + /// rather than at the execution of the builder function. + static ShapeBuilder _polygonShapeBuilder(List points) { + assert( + points.length >= 3, + 'PolygonClipComponent requires at least 3 points.', + ); + + return (Vector2 size) => _polygonBuilder(points, size); + } + + static Shape _polygonBuilder(List points, Vector2 size) { + final translatedPoints = points + .map( + (p) => p.clone()..multiply(size), + ) + .toList(); + return Polygon(translatedPoints); + } } From 0028b5cb15f7b115de197aa5fb4adc62776d2040 Mon Sep 17 00:00:00 2001 From: Lim Chee Keen <62128387+xjyribro@users.noreply.github.com> Date: Sat, 23 Mar 2024 20:21:09 +0800 Subject: [PATCH 29/79] docs: Jenny example (#3086) Replace this text. --------- Co-authored-by: xjyribro Co-authored-by: Lukas Klingsbo --- examples/assets/images/dialogue_box.png | Bin 0 -> 1458 bytes examples/assets/images/green_button_sqr.png | Bin 0 -> 675 bytes examples/assets/images/red_button_sqr.png | Bin 0 -> 670 bytes examples/assets/yarn/advanced.yarn | 21 +++++ examples/assets/yarn/simple.yarn | 6 ++ examples/lib/main.dart | 2 + .../flame_jenny/commons/commons.dart | 8 ++ .../flame_jenny/components/button_row.dart | 71 +++++++++++++++ .../flame_jenny/components/dialogue_box.dart | 43 +++++++++ .../components/dialogue_button.dart | 36 ++++++++ .../dialogue_controller_component.dart | 85 ++++++++++++++++++ .../components/dialogue_text_box.dart | 17 ++++ .../flame_jenny/components/menu_button.dart | 35 ++++++++ .../bridge_libraries/flame_jenny/jenny.dart | 29 ++++++ .../flame_jenny/jenny_advanced_example.dart | 76 ++++++++++++++++ .../flame_jenny/jenny_simple_example.dart | 36 ++++++++ examples/pubspec.yaml | 2 + 17 files changed, 467 insertions(+) create mode 100644 examples/assets/images/dialogue_box.png create mode 100644 examples/assets/images/green_button_sqr.png create mode 100644 examples/assets/images/red_button_sqr.png create mode 100644 examples/assets/yarn/advanced.yarn create mode 100644 examples/assets/yarn/simple.yarn create mode 100644 examples/lib/stories/bridge_libraries/flame_jenny/commons/commons.dart create mode 100644 examples/lib/stories/bridge_libraries/flame_jenny/components/button_row.dart create mode 100644 examples/lib/stories/bridge_libraries/flame_jenny/components/dialogue_box.dart create mode 100644 examples/lib/stories/bridge_libraries/flame_jenny/components/dialogue_button.dart create mode 100644 examples/lib/stories/bridge_libraries/flame_jenny/components/dialogue_controller_component.dart create mode 100644 examples/lib/stories/bridge_libraries/flame_jenny/components/dialogue_text_box.dart create mode 100644 examples/lib/stories/bridge_libraries/flame_jenny/components/menu_button.dart create mode 100644 examples/lib/stories/bridge_libraries/flame_jenny/jenny.dart create mode 100644 examples/lib/stories/bridge_libraries/flame_jenny/jenny_advanced_example.dart create mode 100644 examples/lib/stories/bridge_libraries/flame_jenny/jenny_simple_example.dart diff --git a/examples/assets/images/dialogue_box.png b/examples/assets/images/dialogue_box.png new file mode 100644 index 0000000000000000000000000000000000000000..d9bdbbc66c77d488e6f785092fd7cf6b9707e5ed GIT binary patch literal 1458 zcmeAS@N?(olHy`uVBq!ia0y~yV0r*#H*l~4Nw2MUsu&m;8#0}p13aCb6$*;-(=u~X z85lGs)=u=*a0!%Xo4>QeWm2SvSb5`AO~uHp4w0pXr|uuxTmJ9Lo$OuZDak8yrnb)S z-QU`48qFQObjtimTU$jpPF(l?&dgb!$5vjhtUCXFU+r`21+r^IzxHrv?d)B#=2U6@x??VvHY+UQ=8v>A*WaUJvtinK z&3mGJ(UQuFHEMU>dNm*7_cG`Hv&uqt!!o18c{XM`GGf;*r{+xCIJGeMVco;NmbV`J z%%UH(JSsg}R(4hE+se2b6H3ySP1V~y*YMcP6fW7xq0>%IQde58+~w}`Zn5Z}+{SvZ zm}NVrZ9HOlh|A3Ff&1Ts?{8ME+;`6@$XO(7UhV(A!dcrNR-gX9zpv*1Z;4g&9$eD= z8P1pZ!THPDN!JP)e5DKOLNA?>-EpJk+VMFLr5Zz2qrI0tcpI`WlP@Z7LES=w?T>8L zzY9!{^o==u&#q*tYW2oLyI-Gr{w?3Pu+IKNTT$`F=`x(aC}B(Tc6VXWV^Cty7hlzS z7AV45;1OBOz@VoL!i*J5?aP3I>?NMQuIw+E*f?0NSF;yu0fi(>Tq8=H^K)}k^GX<; zi&7IyQd1PlGfOfQ+&z5*!W;R-85o%RJY5_^DsH{KyD|4wfJno`#~R8T83Y4YX$YsV zNLi^ZSe)46)38EmO$FooC*hW#m}h4nZ~5M`f4!OBy4msW$JLmC7J-4=$#sR3w_ksL zDv*i6fc5v`!VqWsIOQGUpJ%EwG8_mANp9Lx-eA7?x5m=udTbm%+By&o$cN|>9t8V`lrruoDceV zSM*+!Gy{XL+#qb!WVPe5GX1wW`3|U!rT684jeL<#<1<$(~2Int|cL z^Sgf@%mC75=a_81eo|#%n6ND-chk|DvTy3sPIB(}D$Ky}LjUUdumGT%HWmv8hCizr zw*Tj4U@+$?U|?`)U}k7wU}s|n6kqHCC zhtn`qXZSVP1Jg(!Fw6Y%{Q5bv;WjYcG<+<(T{=}f^$q{=H%XvC-@iP(A=;Udq2YB& z@pIPv_2;i9*>yk7`doYV`t$a!A`A>3N6N4N@^m@!*gs$E7$bwg-NWXtdjA&8YjQsl zKlwv&5-?g1%HEeZdO533oq12+hmH=bBf*Bi2oJvWrz#Wn z(3n^|(bnUzgUr$R;H65U?A%=zDJ%TMj_AvHi*_e0+#(uPYOwPQ_bd|?O})OR?1KmU zkFIL&-n@=)U6aBO#z$`+EP0`%`cGeTOUK6tJLKQLvwe4u(P{Cakj>dl0j8%tjwUCW zZP#Lpdw5)d<&49W87tK_8`U9`*->Z2O z-c9~e70oTr`1kgKqovW4zc-wgO?crso#*7lKPIhCj1~5a^G`7{Z+Cb<>vnXu{BnMW zwp~&C82R`bH!7vBuimqJ`R48Q=ePX&&A6_&XupnA+hkz0uqAoBy8vk*`02d69!PN( zctjR6Fz6|RFk{71`!b*)dx@v7EBgy(ab`x1Nv@31Kq1Kz*N775{M_8syb=cIqSVBa z)D(sC%#sWRcTeAd@J2pyprUF|7srr{dv9-TKZDyQnUz%FK_d7EeJJ3W% z1_cHN7KR1}1_1^JCI$xv1`Z^_E1_lPCfiSI*e_V6w?>k4^I?riH-MTLJYD@<);T3K F0RZWt3m*Ug literal 0 HcmV?d00001 diff --git a/examples/assets/images/red_button_sqr.png b/examples/assets/images/red_button_sqr.png new file mode 100644 index 0000000000000000000000000000000000000000..041864dd3a924ec232cdd9180890b928826273d0 GIT binary patch literal 670 zcmeAS@N?(olHy`uVBq!ia0vp^2|%pC!3HGX9;gjrU|?*?baoE#baqxKD9TUE%t>Wn z(3n^|(bnUzgUr$R;H65U?A%=zDJ%TMj_AvHi*_e0+#(uPYOwPQ_bd|?O})OR?1KmU zkFIL&-n@=)U6aBO#z$`+EP0`%`cGeTOUK6tJLKQLvwe4u(P{Cakj>dl0j8%tjwUCW zZP#Lpdw5)d<&49W87tK_8`U9`*->Z2O z-c9~e70oTr`1kgKqovW4zc-wgO?crso#*7lKPIhCj1~5a^G`7{Z+Cb<>vnXu{BnMW zwp~&C82R`bH!7vBuimqJ`R48Q=ePX&&A6_&XupnA+hkz0uqAoBy8vk*`02d69!PN( zctjR6Fz6|RFk{71`!b*)dx@v7EBgy(ab`w|EprUN1BE0@Tq8=H^K)}k^GX<;i&7Iy zQd1PlGfOfQ+&z5*!W;R-fr`pJT^vI)?!CRWk+(rXz#-6}?*L!Ua|XT#40*@--Yi(F zcq!B4#BbRPce(E#y|CqJ4eQ@)kzO_P#FZs)->SY5Y&4hOI;(c?cV;$rpka&*3JeS^ z3=Iqn0t^gH3=Rwo97uv^Ld(s!Y(K4GpRg)#LJj94*1MOU0yQysy85}Sb4q9e0FJr} A=>Px# literal 0 HcmV?d00001 diff --git a/examples/assets/yarn/advanced.yarn b/examples/assets/yarn/advanced.yarn new file mode 100644 index 00000000000..7012d80082a --- /dev/null +++ b/examples/assets/yarn/advanced.yarn @@ -0,0 +1,21 @@ +<> +<> +title: gamble +--- +Jenny: Hello {$playerName}. This is a game of chance. +Jenny: You can win or lose up to 10 coins. Do you want to play? +-> No + Jenny: No bids made. +-> Yes + <> // returns a random value from -10 to 10 + <> + Jenny: Too bad, you did not win anything. + <> + Jenny: Bad luck. You lost {$winnings} coins. + Jenny: Play again to change your fortunes. + <> + Jenny: Congratulations! You won {$winnings} coins. + Jenny: Play again to win even more. + <> + <> +=== \ No newline at end of file diff --git a/examples/assets/yarn/simple.yarn b/examples/assets/yarn/simple.yarn new file mode 100644 index 00000000000..f312b236261 --- /dev/null +++ b/examples/assets/yarn/simple.yarn @@ -0,0 +1,6 @@ +<> +title: hello_world +--- +Jenny: Hello world. My name is Jenny. +Jenny: Thanks for using Flame! +=== \ No newline at end of file diff --git a/examples/lib/main.dart b/examples/lib/main.dart index f4fb18a896c..b7ac835fb15 100644 --- a/examples/lib/main.dart +++ b/examples/lib/main.dart @@ -16,6 +16,7 @@ import 'package:examples/stories/bridge_libraries/flame_forge2d/joints/revolute_ import 'package:examples/stories/bridge_libraries/flame_forge2d/joints/rope_joint.dart'; import 'package:examples/stories/bridge_libraries/flame_forge2d/joints/weld_joint.dart'; import 'package:examples/stories/bridge_libraries/flame_isolate/isolate.dart'; +import 'package:examples/stories/bridge_libraries/flame_jenny/jenny.dart'; import 'package:examples/stories/bridge_libraries/flame_lottie/lottie.dart'; import 'package:examples/stories/bridge_libraries/flame_spine/flame_spine.dart'; import 'package:examples/stories/camera_and_viewport/camera_and_viewport.dart'; @@ -98,6 +99,7 @@ void runAsDashbook() { // Bridge package examples addForge2DStories(dashbook); addFlameIsolateExample(dashbook); + addFlameJennyExample(dashbook); addFlameLottieExample(dashbook); addFlameSpineExamples(dashbook); diff --git a/examples/lib/stories/bridge_libraries/flame_jenny/commons/commons.dart b/examples/lib/stories/bridge_libraries/flame_jenny/commons/commons.dart new file mode 100644 index 00000000000..79f92abd102 --- /dev/null +++ b/examples/lib/stories/bridge_libraries/flame_jenny/commons/commons.dart @@ -0,0 +1,8 @@ +String baseLink(String path) { + const basePath = + 'https://github.com/flame-engine/flame/blob/main/packages/flame_jenny/'; + + return '$basePath$path'; +} + +const double fontSize = 24; diff --git a/examples/lib/stories/bridge_libraries/flame_jenny/components/button_row.dart b/examples/lib/stories/bridge_libraries/flame_jenny/components/button_row.dart new file mode 100644 index 00000000000..52524946d88 --- /dev/null +++ b/examples/lib/stories/bridge_libraries/flame_jenny/components/button_row.dart @@ -0,0 +1,71 @@ +import 'package:examples/stories/bridge_libraries/flame_jenny/components/dialogue_button.dart'; +import 'package:flame/components.dart'; +import 'package:jenny/jenny.dart'; + +class ButtonRow extends PositionComponent { + ButtonRow({required super.size}) : super(position: Vector2(0, 96)); + + void removeButtons() { + final buttonList = children.query(); + if (buttonList.isNotEmpty) { + for (final dialogueButton in buttonList) { + if (dialogueButton.parent != null) { + dialogueButton.removeFromParent(); + } + } + } + } + + void showNextButton(Function() onNextButtonPressed) { + removeButtons(); + final nextButton = DialogueButton( + assetPath: 'green_button_sqr.png', + text: 'Next', + position: Vector2(size.x / 2, 0), + onPressed: () { + onNextButtonPressed(); + removeButtons(); + }, + ); + add(nextButton); + } + + void showOptionButtons({ + required Function(int optionNumber) onChoice, + required DialogueOption option1, + required DialogueOption option2, + }) { + removeButtons(); + final optionButtons = [ + DialogueButton( + assetPath: 'green_button_sqr.png', + text: option1.text, + position: Vector2(size.x / 4, 0), + onPressed: () { + onChoice(0); + removeButtons(); + }, + ), + DialogueButton( + assetPath: 'red_button_sqr.png', + text: option2.text, + position: Vector2(size.x * 3 / 4, 0), + onPressed: () { + onChoice(1); + removeButtons(); + }, + ), + ]; + addAll(optionButtons); + } + + void showCloseButton(Function() onClose) { + final closeButton = DialogueButton( + assetPath: 'green_button_sqr.png', + text: 'Close', + onPressed: () => onClose(), + position: Vector2(size.x / 2, 0), + ); + add(closeButton); + } +} diff --git a/examples/lib/stories/bridge_libraries/flame_jenny/components/dialogue_box.dart b/examples/lib/stories/bridge_libraries/flame_jenny/components/dialogue_box.dart new file mode 100644 index 00000000000..4820ce8d05a --- /dev/null +++ b/examples/lib/stories/bridge_libraries/flame_jenny/components/dialogue_box.dart @@ -0,0 +1,43 @@ +import 'package:examples/stories/bridge_libraries/flame_jenny/components/button_row.dart'; +import 'package:examples/stories/bridge_libraries/flame_jenny/components/dialogue_text_box.dart'; +import 'package:flame/components.dart'; +import 'package:jenny/jenny.dart'; + +class DialogueBoxComponent extends SpriteComponent with HasGameReference { + DialogueTextBox textBox = DialogueTextBox(text: ''); + final Vector2 spriteSize = Vector2(736, 128); + late final ButtonRow buttonRow = ButtonRow(size: spriteSize); + + @override + Future onLoad() async { + position = Vector2(game.size.x / 2, 96); + anchor = Anchor.center; + sprite = await Sprite.load( + 'dialogue_box.png', + srcSize: spriteSize, + ); + await addAll([buttonRow, textBox]); + return super.onLoad(); + } + + void changeText(String newText, Function() goNextLine) { + textBox.text = newText; + buttonRow.showNextButton(goNextLine); + } + + void showOptions({ + required Function(int optionNumber) onChoice, + required DialogueOption option1, + required DialogueOption option2, + }) { + buttonRow.showOptionButtons( + onChoice: onChoice, + option1: option1, + option2: option2, + ); + } + + void showCloseButton(Function() onClose) { + buttonRow.showCloseButton(onClose); + } +} diff --git a/examples/lib/stories/bridge_libraries/flame_jenny/components/dialogue_button.dart b/examples/lib/stories/bridge_libraries/flame_jenny/components/dialogue_button.dart new file mode 100644 index 00000000000..f685782ce4c --- /dev/null +++ b/examples/lib/stories/bridge_libraries/flame_jenny/components/dialogue_button.dart @@ -0,0 +1,36 @@ +import 'package:examples/stories/bridge_libraries/flame_jenny/commons/commons.dart'; +import 'package:flame/components.dart'; +import 'package:flame/input.dart'; +import 'package:flutter/material.dart'; + +class DialogueButton extends SpriteButtonComponent { + DialogueButton({ + required super.position, + required this.assetPath, + required this.text, + required super.onPressed, + super.anchor = Anchor.center, + }); + + final String text; + final String assetPath; + + @override + Future onLoad() async { + button = await Sprite.load(assetPath); + add( + TextComponent( + text: text, + position: Vector2(48, 16), + anchor: Anchor.center, + size: Vector2(88, 28), + textRenderer: TextPaint( + style: const TextStyle( + fontSize: fontSize, + color: Colors.white70, + ), + ), + ), + ); + } +} diff --git a/examples/lib/stories/bridge_libraries/flame_jenny/components/dialogue_controller_component.dart b/examples/lib/stories/bridge_libraries/flame_jenny/components/dialogue_controller_component.dart new file mode 100644 index 00000000000..79580df5a43 --- /dev/null +++ b/examples/lib/stories/bridge_libraries/flame_jenny/components/dialogue_controller_component.dart @@ -0,0 +1,85 @@ +import 'dart:async'; +import 'package:examples/stories/bridge_libraries/flame_jenny/components/dialogue_box.dart'; +import 'package:flame/components.dart' hide Timer; +import 'package:jenny/jenny.dart'; + +class DialogueControllerComponent extends Component + with DialogueView, HasGameReference { + Completer _forwardCompleter = Completer(); + Completer _choiceCompleter = Completer(); + Completer _closeCompleter = Completer(); + late final DialogueBoxComponent _dialogueBoxComponent = + DialogueBoxComponent(); + + @override + Future onNodeStart(Node node) async { + _closeCompleter = Completer(); + _addDialogueBox(); + } + + void _addDialogueBox() { + game.camera.viewport.add(_dialogueBoxComponent); + } + + @override + Future onNodeFinish(Node node) async { + _dialogueBoxComponent.showCloseButton(_onClose); + return _closeCompleter.future; + } + + void _onClose() { + if (!_closeCompleter.isCompleted) { + _closeCompleter.complete(); + } + final list = game.camera.viewport.children.query(); + if (list.isNotEmpty) { + game.camera.viewport.removeAll(list); + } + } + + Future _advance() async { + return _forwardCompleter.future; + } + + @override + FutureOr onLineStart(DialogueLine line) async { + _forwardCompleter = Completer(); + _changeTextAndShowNextButton(line); + await _advance(); + return super.onLineStart(line); + } + + void _changeTextAndShowNextButton(DialogueLine line) { + final characterName = line.character?.name ?? ''; + final dialogueLineText = '$characterName: ${line.text}'; + _dialogueBoxComponent.changeText(dialogueLineText, _goNextLine); + } + + void _goNextLine() { + if (!_forwardCompleter.isCompleted) { + _forwardCompleter.complete(); + } + } + + @override + FutureOr onChoiceStart(DialogueChoice choice) async { + _forwardCompleter = Completer(); + _choiceCompleter = Completer(); + _dialogueBoxComponent.showOptions( + onChoice: _onChoice, + option1: choice.options[0], + option2: choice.options[1], + ); + await _advance(); + return _choiceCompleter.future; + } + + void _onChoice(int optionNumber) { + if (!_forwardCompleter.isCompleted) { + _forwardCompleter.complete(); + } + if (!_choiceCompleter.isCompleted) { + _choiceCompleter.complete(optionNumber); + } + } +} diff --git a/examples/lib/stories/bridge_libraries/flame_jenny/components/dialogue_text_box.dart b/examples/lib/stories/bridge_libraries/flame_jenny/components/dialogue_text_box.dart new file mode 100644 index 00000000000..fe38ebfcc6d --- /dev/null +++ b/examples/lib/stories/bridge_libraries/flame_jenny/components/dialogue_text_box.dart @@ -0,0 +1,17 @@ +import 'package:examples/stories/bridge_libraries/flame_jenny/commons/commons.dart'; +import 'package:flame/components.dart'; +import 'package:flutter/material.dart'; + +class DialogueTextBox extends TextBoxComponent { + DialogueTextBox({required super.text}) + : super( + position: Vector2(16, 16), + size: Vector2(704, 96), + textRenderer: TextPaint( + style: const TextStyle( + fontSize: fontSize, + color: Colors.black, + ), + ), + ); +} diff --git a/examples/lib/stories/bridge_libraries/flame_jenny/components/menu_button.dart b/examples/lib/stories/bridge_libraries/flame_jenny/components/menu_button.dart new file mode 100644 index 00000000000..de161965264 --- /dev/null +++ b/examples/lib/stories/bridge_libraries/flame_jenny/components/menu_button.dart @@ -0,0 +1,35 @@ +import 'package:flame/components.dart'; +import 'package:flame/input.dart'; +import 'package:flame/palette.dart'; +import 'package:flame/text.dart'; +import 'package:flutter/material.dart'; + +class MenuButton extends ButtonComponent { + MenuButton({ + required super.position, + required super.onPressed, + required this.text, + }) : super(size: Vector2(128, 42)); + + late String text; + + final Paint white = BasicPalette.white.paint(); + final TextPaint topTextPaint = TextPaint( + style: TextStyle(color: BasicPalette.black.color), + ); + + @override + Future onLoad() async { + button = RectangleComponent(paint: white, size: size); + anchor = Anchor.center; + add( + TextComponent( + text: text, + textRenderer: topTextPaint, + position: size / 2, + anchor: Anchor.center, + priority: 1, + ), + ); + } +} diff --git a/examples/lib/stories/bridge_libraries/flame_jenny/jenny.dart b/examples/lib/stories/bridge_libraries/flame_jenny/jenny.dart new file mode 100644 index 00000000000..e9d512e7652 --- /dev/null +++ b/examples/lib/stories/bridge_libraries/flame_jenny/jenny.dart @@ -0,0 +1,29 @@ +import 'package:dashbook/dashbook.dart'; +import 'package:examples/stories/bridge_libraries/flame_jenny/commons/commons.dart'; +import 'package:examples/stories/bridge_libraries/flame_jenny/jenny_advanced_example.dart'; +import 'package:examples/stories/bridge_libraries/flame_jenny/jenny_simple_example.dart'; +import 'package:flame/game.dart'; + +void addFlameJennyExample(Dashbook dashbook) { + dashbook.storiesOf('FlameJenny') + ..add( + 'Simple Jenny example', + (_) => GameWidget( + game: JennySimpleExample(), + ), + codeLink: baseLink( + 'bridge_libraries/flame_jenny/jenny_simple_example.dart', + ), + info: JennySimpleExample.description, + ) + ..add( + 'Advanced Jenny example', + (_) => GameWidget( + game: JennyAdvancedExample(), + ), + codeLink: baseLink( + 'bridge_libraries/flame_jenny/jenny_advanced_example.dart', + ), + info: JennyAdvancedExample.description, + ); +} diff --git a/examples/lib/stories/bridge_libraries/flame_jenny/jenny_advanced_example.dart b/examples/lib/stories/bridge_libraries/flame_jenny/jenny_advanced_example.dart new file mode 100644 index 00000000000..c7686aa2fab --- /dev/null +++ b/examples/lib/stories/bridge_libraries/flame_jenny/jenny_advanced_example.dart @@ -0,0 +1,76 @@ +import 'dart:ui'; + +import 'package:examples/stories/bridge_libraries/flame_jenny/components/dialogue_controller_component.dart'; +import 'package:examples/stories/bridge_libraries/flame_jenny/components/menu_button.dart'; +import 'package:flame/components.dart'; +import 'package:flame/game.dart'; +import 'package:flame/palette.dart'; +import 'package:flame/text.dart'; +import 'package:flutter/services.dart'; +import 'package:jenny/jenny.dart'; + +class JennyAdvancedExample extends FlameGame { + static const String description = ''' + This is an advanced example of how to use the Jenny Package. + It includes implementing dialogue choices, setting custom variables, + using commands and implementing User-Defined Commands, . + '''; + + int coins = 0; + + final Paint white = BasicPalette.white.paint(); + final TextPaint mainTextPaint = TextPaint( + style: TextStyle(color: BasicPalette.white.color), + ); + final TextPaint buttonTextPaint = TextPaint( + style: TextStyle(color: BasicPalette.black.color), + ); + final startButtonSize = Vector2(128, 56); + + late final TextComponent header = TextComponent( + text: 'Select player name.', + position: Vector2(size.x / 2, 56), + size: startButtonSize, + anchor: Anchor.center, + textRenderer: mainTextPaint, + ); + + Future startDialogue(String playerName) async { + final dialogueControllerComponent = DialogueControllerComponent(); + add(dialogueControllerComponent); + + final yarnProject = YarnProject(); + + yarnProject + ..commands.addCommand1('updateCoins', updateCoins) + ..variables.setVariable(r'$playerName', playerName) + ..parse(await rootBundle.loadString('assets/yarn/advanced.yarn')); + final dialogueRunner = DialogueRunner( + yarnProject: yarnProject, + dialogueViews: [dialogueControllerComponent], + ); + dialogueRunner.startDialogue('gamble'); + } + + void updateCoins(int amountChange) { + coins += amountChange; + header.text = 'Select player name. Current coins: $coins'; + } + + @override + Future onLoad() async { + addAll([ + header, + MenuButton( + position: Vector2(size.x / 4, 128), + onPressed: () => startDialogue('Jessie'), + text: 'Jessie', + ), + MenuButton( + position: Vector2(size.x * 3 / 4, 128), + onPressed: () => startDialogue('James'), + text: 'James', + ), + ]); + } +} diff --git a/examples/lib/stories/bridge_libraries/flame_jenny/jenny_simple_example.dart b/examples/lib/stories/bridge_libraries/flame_jenny/jenny_simple_example.dart new file mode 100644 index 00000000000..7aacc08316b --- /dev/null +++ b/examples/lib/stories/bridge_libraries/flame_jenny/jenny_simple_example.dart @@ -0,0 +1,36 @@ +import 'package:examples/stories/bridge_libraries/flame_jenny/components/dialogue_controller_component.dart'; +import 'package:examples/stories/bridge_libraries/flame_jenny/components/menu_button.dart'; +import 'package:flame/game.dart'; +import 'package:flutter/services.dart'; +import 'package:jenny/jenny.dart'; + +class JennySimpleExample extends FlameGame { + static const String description = ''' + This is a simple example of how to use the Jenny Package. + It includes instantiating YarnProject and parsing a .yarn script. + '''; + + Future startDialogue() async { + final dialogueControllerComponent = DialogueControllerComponent(); + add(dialogueControllerComponent); + + final yarnProject = YarnProject(); + yarnProject.parse(await rootBundle.loadString('assets/yarn/simple.yarn')); + final dialogueRunner = DialogueRunner( + yarnProject: yarnProject, + dialogueViews: [dialogueControllerComponent], + ); + dialogueRunner.startDialogue('hello_world'); + } + + @override + Future onLoad() async { + addAll([ + MenuButton( + position: Vector2(size.x / 2, 96), + onPressed: startDialogue, + text: 'Start conversation', + ), + ]); + } +} diff --git a/examples/pubspec.yaml b/examples/pubspec.yaml index abd00ba1663..0036431dc63 100644 --- a/examples/pubspec.yaml +++ b/examples/pubspec.yaml @@ -23,6 +23,7 @@ dependencies: flutter: sdk: flutter google_fonts: ^4.0.4 + jenny: ^1.3.0 meta: ^1.9.1 padracing: ^1.0.0 provider: ^6.0.5 @@ -49,3 +50,4 @@ flutter: - assets/tiles/ - assets/audio/music/ - assets/audio/sfx/ + - assets/yarn/ From 3c35d59b4a4ec064106d24a17e748005a20d9fde Mon Sep 17 00:00:00 2001 From: DevKage <33748002+ufrshubham@users.noreply.github.com> Date: Sat, 23 Mar 2024 21:31:46 +0530 Subject: [PATCH 30/79] fix: Null gravity override by Forge2dGame (#3092) `Forge2dGame` overrides the world's gravity even when a gravity vector is not provided to it. This causes the world to use the default gravity. --- packages/flame_forge2d/lib/forge2d_game.dart | 2 +- packages/flame_forge2d/test/forge2d_game_test.dart | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/flame_forge2d/lib/forge2d_game.dart b/packages/flame_forge2d/lib/forge2d_game.dart index 522ba4d7e57..70071c06c50 100644 --- a/packages/flame_forge2d/lib/forge2d_game.dart +++ b/packages/flame_forge2d/lib/forge2d_game.dart @@ -12,7 +12,7 @@ class Forge2DGame extends FlameGame { ContactListener? contactListener, double zoom = 10, }) : super( - world: ((world?..gravity = gravity) ?? + world: ((world?..gravity = gravity ?? world.gravity) ?? Forge2DWorld( gravity: gravity, contactListener: contactListener, diff --git a/packages/flame_forge2d/test/forge2d_game_test.dart b/packages/flame_forge2d/test/forge2d_game_test.dart index d140b2f697c..74a3e99576c 100644 --- a/packages/flame_forge2d/test/forge2d_game_test.dart +++ b/packages/flame_forge2d/test/forge2d_game_test.dart @@ -78,6 +78,12 @@ void main() { game.camera.viewfinder.zoom, ); }); + + test("Game does not override World's gravity with null", () { + final game = Forge2DGame(world: Forge2DWorld(gravity: Vector2(10, 0))); + expect(game.world.gravity.x, 10); + expect(game.world.gravity.y, 0); + }); }, ); } From 6daf7a3d353d7c1e7e3a8ab08f825a9d6d2fa498 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Mon, 25 Mar 2024 10:43:49 +0100 Subject: [PATCH 31/79] docs: Fix broken link to flame_jenny example code (#3093) The links for the flame_jenny examples were pointing on the wrong URL. --- .../stories/bridge_libraries/flame_jenny/commons/commons.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/lib/stories/bridge_libraries/flame_jenny/commons/commons.dart b/examples/lib/stories/bridge_libraries/flame_jenny/commons/commons.dart index 79f92abd102..ae2f08cf3e8 100644 --- a/examples/lib/stories/bridge_libraries/flame_jenny/commons/commons.dart +++ b/examples/lib/stories/bridge_libraries/flame_jenny/commons/commons.dart @@ -1,6 +1,6 @@ String baseLink(String path) { const basePath = - 'https://github.com/flame-engine/flame/blob/main/packages/flame_jenny/'; + 'https://github.com/flame-engine/flame/blob/main/examples/lib/stories/bridge_libraries/flame_jenny/'; return '$basePath$path'; } From b1f01986b440ac18bb35b0d76963b2c66f49ea33 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Mon, 25 Mar 2024 11:39:03 +0100 Subject: [PATCH 32/79] feat: Add PositionComponent.toString (#3095) Adds a `toString` override for `PositionComponent` so that one can see all its properties easily. --- .../flame/lib/src/components/position_component.dart | 12 ++++++++++++ packages/flame/lib/src/extensions/vector2.dart | 8 ++++++++ packages/flame/test/extensions/vector2_test.dart | 9 +++++++++ 3 files changed, 29 insertions(+) diff --git a/packages/flame/lib/src/components/position_component.dart b/packages/flame/lib/src/components/position_component.dart index 8a8498b53dd..39d49e97cde 100644 --- a/packages/flame/lib/src/components/position_component.dart +++ b/packages/flame/lib/src/components/position_component.dart @@ -503,4 +503,16 @@ class PositionComponent extends Component size.setValues(rect.width, rect.height); topLeftPosition = rect.topLeft.toVector2(); } + + @override + String toString() { + // ignore_for_file: no_runtimeType_toString + return ''' +$runtimeType( + position: ${position.toStringWithMaxPrecision(4)}, + size: ${size.toStringWithMaxPrecision(4)}, + angle: $angle, + scale: $scale, +)'''; + } } diff --git a/packages/flame/lib/src/extensions/vector2.dart b/packages/flame/lib/src/extensions/vector2.dart index a7265e18c90..5fbec23e2f2 100644 --- a/packages/flame/lib/src/extensions/vector2.dart +++ b/packages/flame/lib/src/extensions/vector2.dart @@ -192,6 +192,14 @@ extension Vector2Extension on Vector2 { /// Modulo/Remainder Vector2 operator %(Vector2 mod) => Vector2(x % mod.x, y % mod.y); + /// Stringifies the Vector2 with a maximum precision of [maxPrecision]. + String toStringWithMaxPrecision(int maxPrecision) { + final precision = pow(10, maxPrecision); + final truncatedX = (x * precision).truncate() / precision; + final truncatedY = (y * precision).truncate() / precision; + return 'Vector2($truncatedX, $truncatedY)'; + } + /// Create a Vector2 with ints as input static Vector2 fromInts(int x, int y) => Vector2(x.toDouble(), y.toDouble()); diff --git a/packages/flame/test/extensions/vector2_test.dart b/packages/flame/test/extensions/vector2_test.dart index 5cba3ea1bce..69f337744c2 100644 --- a/packages/flame/test/extensions/vector2_test.dart +++ b/packages/flame/test/extensions/vector2_test.dart @@ -488,6 +488,15 @@ void main() { expectDouble(p2.length, math.sqrt(2)); expect(p2.x, p2.y); }); + + test('toStringWithMaxPrecision', () { + final p1 = Vector2(1.123456789, 2.123456789); + expect(p1.toStringWithMaxPrecision(2), 'Vector2(1.12, 2.12)'); + final p2 = Vector2(1, 2.123456789); + expect(p2.toStringWithMaxPrecision(3), 'Vector2(1.0, 2.123)'); + final p3 = Vector2(-1, -2.123456789); + expect(p3.toStringWithMaxPrecision(3), 'Vector2(-1.0, -2.123)'); + }); }); testRandom('Creating a Vector2 fromRadians points to the correct direction', From bf5d68e9b5147dd5e7c10d72bf9c2f705733d688 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Mon, 25 Mar 2024 21:36:17 +0100 Subject: [PATCH 33/79] feat: Component tree for the devtools extension tab (#3094) This PR creates a devtools extension tab for Flame where you can: * Turn on `debugMode` for a chosen component or the whole tree * See the component tree * Play, pause and step the game loop. [Screencast from 2024-03-24 22-09-55.webm](https://github.com/flame-engine/flame/assets/744771/82217afb-e096-4375-a892-b59e1be6d7ec) --- doc/flame/other/debug.md | 8 + melos.yaml | 11 + packages/flame/.pubignore | 1 + packages/flame/lib/devtools.dart | 2 + .../connectors/component_tree_connector.dart | 63 ++++++ .../connectors/debug_mode_connector.dart | 63 +++--- .../lib/src/devtools/dev_tools_service.dart | 2 + packages/flame_devtools/README.md | 27 +++ packages/flame_devtools/lib/main.dart | 7 +- packages/flame_devtools/lib/repository.dart | 23 +- .../lib/widgets/component_tree.dart | 205 ++++++++++++++++++ .../lib/widgets/debug_mode_button.dart | 17 +- .../lib/widgets/game_loop_controls.dart | 18 +- packages/flame_devtools/pubspec.yaml | 8 +- 14 files changed, 407 insertions(+), 48 deletions(-) create mode 100644 packages/flame/.pubignore create mode 100644 packages/flame/lib/devtools.dart create mode 100644 packages/flame/lib/src/devtools/connectors/component_tree_connector.dart create mode 100644 packages/flame_devtools/lib/widgets/component_tree.dart diff --git a/doc/flame/other/debug.md b/doc/flame/other/debug.md index f75607fa3a3..fbd02f3a8ae 100644 --- a/doc/flame/other/debug.md +++ b/doc/flame/other/debug.md @@ -13,6 +13,14 @@ To see a working example of the debugging features of the `FlameGame`, check thi [example](https://github.com/flame-engine/flame/blob/main/examples/lib/stories/components/debug_example.dart). +## Devtools extension + +If you open the [Flutter DevTools](https://docs.flutter.dev/tools/devtools/overview), you will see a +new tab called "Flame". This tab will show you information about the current game, for example a +visualization of the component tree, the ability to play, pause and step the game, information +about the selected component, and more. + + ## FPS The FPS reported from Flame might be a bit lower than what is reported from for example the Flutter diff --git a/melos.yaml b/melos.yaml index 2e29ea1b08d..a16a30fa2ec 100644 --- a/melos.yaml +++ b/melos.yaml @@ -13,6 +13,7 @@ command: branch: main # Generates a link to a prefilled GitHub release creation page. releaseUrl: true + bootstrap: environment: sdk: ">=3.0.0 <4.0.0" @@ -24,6 +25,10 @@ command: dartdoc: ^6.3.0 mocktail: ^1.0.1 test: any + + publish: + hooks: + pre: melos devtools-build scripts: lint:all: @@ -118,3 +123,9 @@ scripts: packageFilters: scope: flame_devtools description: Builds the devtools and copies the build directory to the Flame package. + + devtools-simulator: + run: melos exec -- flutter run -d chrome --dart-define=use_simulated_environment=true + packageFilters: + scope: flame_devtools + description: Runs the devtools in the simulated mode. diff --git a/packages/flame/.pubignore b/packages/flame/.pubignore new file mode 100644 index 00000000000..f192e449890 --- /dev/null +++ b/packages/flame/.pubignore @@ -0,0 +1 @@ +!extension/**/* diff --git a/packages/flame/lib/devtools.dart b/packages/flame/lib/devtools.dart new file mode 100644 index 00000000000..87093bab12b --- /dev/null +++ b/packages/flame/lib/devtools.dart @@ -0,0 +1,2 @@ +export 'src/devtools/connectors/component_tree_connector.dart' + show ComponentTreeNode; diff --git a/packages/flame/lib/src/devtools/connectors/component_tree_connector.dart b/packages/flame/lib/src/devtools/connectors/component_tree_connector.dart new file mode 100644 index 00000000000..0e1ea1abb6a --- /dev/null +++ b/packages/flame/lib/src/devtools/connectors/component_tree_connector.dart @@ -0,0 +1,63 @@ +import 'dart:convert'; +import 'dart:developer'; + +import 'package:flame/components.dart'; +import 'package:flame/src/devtools/dev_tools_connector.dart'; + +/// The [ComponentTreeConnector] is responsible for reporting the component +/// tree of the game to the devtools extension. +class ComponentTreeConnector extends DevToolsConnector { + @override + void init() { + // Get the component tree of the game. + registerExtension( + 'ext.flame_devtools.getComponentTree', + (method, parameters) async { + final componentTree = ComponentTreeNode.fromComponent(game); + + return ServiceExtensionResponse.result( + json.encode({ + 'component_tree': componentTree.toJson(), + }), + ); + }, + ); + } +} + +/// This should only be used internally by the devtools extension. +class ComponentTreeNode { + final int id; + final String name; + final String toStringText; + final List children; + + ComponentTreeNode(this.id, this.name, this.toStringText, this.children); + + ComponentTreeNode.fromComponent(Component component) + : this( + component.hashCode, + component.runtimeType.toString(), + component.toString(), + component.children.map(ComponentTreeNode.fromComponent).toList(), + ); + + ComponentTreeNode.fromJson(Map json) + : this( + json['id'] as int, + json['name'] as String, + json['toString'] as String, + (json['children'] as List) + .map((e) => ComponentTreeNode.fromJson(e as Map)) + .toList(), + ); + + Map toJson() { + return { + 'id': id, + 'name': name, + 'toString': toStringText, + 'children': children.map((e) => e.toJson()).toList(), + }; + } +} diff --git a/packages/flame/lib/src/devtools/connectors/debug_mode_connector.dart b/packages/flame/lib/src/devtools/connectors/debug_mode_connector.dart index 8a2a3ca12e6..f75097a5166 100644 --- a/packages/flame/lib/src/devtools/connectors/debug_mode_connector.dart +++ b/packages/flame/lib/src/devtools/connectors/debug_mode_connector.dart @@ -2,37 +2,40 @@ import 'dart:convert'; import 'dart:developer'; import 'package:flame/components.dart'; -import 'package:flame/game.dart'; import 'package:flame/src/devtools/dev_tools_connector.dart'; -import 'package:flutter/foundation.dart'; /// The [DebugModeConnector] is responsible for reporting and setting the /// `debugMode` of the game from the devtools extension. class DebugModeConnector extends DevToolsConnector { - var _debugModeNotifier = ValueNotifier(false); - @override void init() { - // Get the current `debugMode`. + // Get the `debugMode` for a component in the tree. + // If no id is provided, the `debugMode` for the entire game will be + // returned. registerExtension( 'ext.flame_devtools.getDebugMode', (method, parameters) async { + final id = int.tryParse(parameters['id'] ?? '') ?? game.hashCode; return ServiceExtensionResponse.result( json.encode({ - 'debug_mode': _debugModeNotifier.value, + 'id': id, + 'debug_mode': _getDebugMode(id), }), ); }, ); - // Set the `debugMode` for all components in the tree. + // Set the `debugMode` for a component in the tree. + // If no id is provided, the `debugMode` will be set for the entire game. registerExtension( 'ext.flame_devtools.setDebugMode', (method, parameters) async { + final id = int.tryParse(parameters['id'] ?? ''); final debugMode = bool.parse(parameters['debug_mode'] ?? 'false'); - _debugModeNotifier.value = debugMode; + _setDebugMode(debugMode, id: id); return ServiceExtensionResponse.result( json.encode({ + 'id': id, 'debug_mode': debugMode, }), ); @@ -40,24 +43,34 @@ class DebugModeConnector extends DevToolsConnector { ); } - @override - void initGame(FlameGame game) { - super.initGame(game); - _debugModeNotifier = ValueNotifier(game.debugMode); - _debugModeNotifier.addListener(() { - final newDebugMode = _debugModeNotifier.value; - game.propagateToChildren( - (c) { - c.debugMode = newDebugMode; - return true; - }, - includeSelf: true, - ); - }); + bool _getDebugMode(int id) { + var debugMode = false; + game.propagateToChildren( + (c) { + if (c.hashCode == id) { + debugMode = c.debugMode; + return false; + } + return true; + }, + includeSelf: true, + ); + return debugMode; } - @override - void disposeGame() { - _debugModeNotifier.dispose(); + void _setDebugMode(bool debugMode, {int? id}) { + game.propagateToChildren( + (c) { + if (id == null) { + c.debugMode = debugMode; + return true; + } else if (c.hashCode == id) { + c.debugMode = debugMode; + return false; + } + return true; + }, + includeSelf: true, + ); } } diff --git a/packages/flame/lib/src/devtools/dev_tools_service.dart b/packages/flame/lib/src/devtools/dev_tools_service.dart index d56bd4a56fc..fe11e207401 100644 --- a/packages/flame/lib/src/devtools/dev_tools_service.dart +++ b/packages/flame/lib/src/devtools/dev_tools_service.dart @@ -1,5 +1,6 @@ import 'package:flame/game.dart'; import 'package:flame/src/devtools/connectors/component_count_connector.dart'; +import 'package:flame/src/devtools/connectors/component_tree_connector.dart'; import 'package:flame/src/devtools/connectors/debug_mode_connector.dart'; import 'package:flame/src/devtools/connectors/game_loop_connector.dart'; import 'package:flame/src/devtools/dev_tools_connector.dart'; @@ -32,6 +33,7 @@ class DevToolsService { final connectors = [ DebugModeConnector(), ComponentCountConnector(), + ComponentTreeConnector(), GameLoopConnector(), ]; diff --git a/packages/flame_devtools/README.md b/packages/flame_devtools/README.md index 012490dcaea..65d286374ba 100644 --- a/packages/flame_devtools/README.md +++ b/packages/flame_devtools/README.md @@ -1,3 +1,24 @@ + +

+ + flame + +

+ +

+A Flutter-based game engine. +

+ +

+ + + + +

+ +--- + + # flame_devtools A DevTools extension for Flame games. To use it you just have to run your @@ -18,3 +39,9 @@ To develop things from the Flame side, create a new `DevToolsConnector` which registers the new extension end points so that you can communicate with Flame from the devtools extension. Don't forget to add the new connector to the list of connectors in the `DevToolsService` class. + +If you want to run with the devtools extension with the simulated mode for +faster development, you can use `melos devtools-simulate` to start the +simulated environment and run the devtools extension in the browser. +Remember that you have to manually enter the Dart VM Service Connection URI +in the simulated devtools environment. diff --git a/packages/flame_devtools/lib/main.dart b/packages/flame_devtools/lib/main.dart index 91a7878898d..d0c7d58d619 100644 --- a/packages/flame_devtools/lib/main.dart +++ b/packages/flame_devtools/lib/main.dart @@ -1,5 +1,5 @@ import 'package:devtools_extensions/devtools_extensions.dart'; -import 'package:flame_devtools/widgets/component_counter.dart'; +import 'package:flame_devtools/widgets/component_tree.dart'; import 'package:flame_devtools/widgets/debug_mode_button.dart'; import 'package:flame_devtools/widgets/game_loop_controls.dart'; import 'package:flutter/material.dart'; @@ -16,15 +16,14 @@ class FlameDevTools extends StatelessWidget { return DevToolsExtension( child: Column( children: [ - const GameLoopControls(), Row( mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.end, children: [ - const ComponentCounter(), + const GameLoopControls(), const DebugModeButton(), ].withSpacing(), ), + const Expanded(child: ComponentTree()), ].withSpacing(), ), ); diff --git a/packages/flame_devtools/lib/repository.dart b/packages/flame_devtools/lib/repository.dart index 2f657f9d5ab..c9fc22b54c8 100644 --- a/packages/flame_devtools/lib/repository.dart +++ b/packages/flame_devtools/lib/repository.dart @@ -1,4 +1,5 @@ import 'package:devtools_extensions/devtools_extensions.dart'; +import 'package:flame/devtools.dart'; sealed class Repository { Repository._(); @@ -11,19 +12,33 @@ sealed class Repository { return componentCountResponse.json!['component_count'] as int; } - static Future swapDebugMode() async { - final nextDebugMode = !(await getDebugMode()); + static Future getComponentTree() async { + final componentTreeResponse = + await serviceManager.callServiceExtensionOnMainIsolate( + 'ext.flame_devtools.getComponentTree', + ); + return ComponentTreeNode.fromJson( + componentTreeResponse.json!['component_tree'] as Map, + ); + } + + static Future swapDebugMode({int? id}) async { + final nextDebugMode = !(await getDebugMode(id: id)); await serviceManager.callServiceExtensionOnMainIsolate( 'ext.flame_devtools.setDebugMode', - args: {'debug_mode': nextDebugMode}, + args: { + 'debug_mode': nextDebugMode, + 'id': id, + }, ); return nextDebugMode; } - static Future getDebugMode() async { + static Future getDebugMode({int? id}) async { final debugModeResponse = await serviceManager.callServiceExtensionOnMainIsolate( 'ext.flame_devtools.getDebugMode', + args: {'id': id}, ); return debugModeResponse.json!['debug_mode'] as bool; } diff --git a/packages/flame_devtools/lib/widgets/component_tree.dart b/packages/flame_devtools/lib/widgets/component_tree.dart new file mode 100644 index 00000000000..0bbf3fc733a --- /dev/null +++ b/packages/flame_devtools/lib/widgets/component_tree.dart @@ -0,0 +1,205 @@ +import 'package:animated_tree_view/animated_tree_view.dart'; +import 'package:devtools_app_shared/ui.dart'; +import 'package:flame/devtools.dart'; +import 'package:flame_devtools/repository.dart'; +import 'package:flame_devtools/widgets/debug_mode_button.dart'; +import 'package:flutter/material.dart'; + +class ComponentTree extends StatefulWidget { + const ComponentTree({super.key}); + + @override + State createState() => _ComponentTreeState(); +} + +class _ComponentTreeState extends State { + Future? _componentTree; + final TreeNode _tree = TreeNode.root(); + TreeNode? _selectedTreeNode; + int _componentCount = 0; + + @override + void initState() { + _refreshComponentTree(); + super.initState(); + } + + void _refreshComponentTree() { + _tree.clear(); + _componentCount = 0; + _componentTree = Repository.getComponentTree(); + _componentTree?.then((value) => setState(() => _buildTree(value, _tree))); + } + + void _buildTree(ComponentTreeNode node, TreeNode parent) { + _componentCount++; + final current = TreeNode( + key: node.id.toString(), + parent: parent, + data: node, + ); + parent.add(current); + for (final child in node.children) { + _buildTree(child, current); + } + } + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return FutureBuilder( + future: _componentTree, + builder: (context, value) { + return Split( + axis: MediaQuery.of(context).size.width > 1000 + ? Axis.horizontal + : Axis.vertical, + initialFractions: const [0.5, 0.5], + minSizes: const [300, 350], + children: [ + RoundedOutlinedBorder( + child: Column( + children: [ + AreaPaneHeader( + title: Row( + children: [ + Text( + 'Component Tree ($_componentCount components)', + style: theme.textTheme.titleSmall, + ), + IconButton( + icon: const Icon(Icons.refresh), + iconSize: 18, + alignment: Alignment.center, + onPressed: () => setState(_refreshComponentTree), + ), + ], + ), + ), + if (value.hasData) + Expanded( + child: SingleChildScrollView( + child: TreeView.simple( + showRootNode: false, + shrinkWrap: true, + indentation: const Indentation( + color: Colors.blue, + style: IndentStyle.roundJoint, + ), + onTreeReady: (controller) => + controller.expandAllChildren(controller.tree), + padding: const EdgeInsets.only(left: 20), + expansionIndicatorBuilder: (context, node) => + node.isLeaf + ? NoExpansionIndicator(tree: node) + : ChevronIndicator.rightDown( + tree: node, + alignment: Alignment.centerLeft, + ), + builder: (context, node) { + return Padding( + padding: node.isLeaf + ? EdgeInsets.zero + : const EdgeInsets.only(left: 20), + child: ListTile( + key: Key( + node.data?.id.toString() ?? node.key, + ), + selected: node == _selectedTreeNode, + selectedColor: theme.colorScheme.primary, + title: Text(node.data!.name), + subtitle: Text(node.data!.id.toString()), + onTap: () { + return setState( + () => _selectedTreeNode = node, + ); + }, + ), + ); + }, + tree: _tree, + ), + ), + ) + else + const CircularProgressIndicator(strokeWidth: 20), + ], + ), + ), + ComponentView(_selectedTreeNode?.data), + ], + ); + }, + ); + } +} + +class ComponentView extends StatelessWidget { + const ComponentView(this.componentNode, {super.key}); + + final ComponentTreeNode? componentNode; + + @override + Widget build(BuildContext context) { + final node = componentNode; + final theme = Theme.of(context); + final textStyle = theme.textTheme.bodyLarge; + + return RoundedOutlinedBorder( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AreaPaneHeader( + title: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Selected Component', + style: theme.textTheme.titleSmall, + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.all(20), + child: node == null + ? Text( + 'Select a component in the tree', + style: textStyle, + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text('Id: ${node.id}', style: textStyle), + DebugModeButton(id: node.id), + ].withSpacing(), + ), + Text('Type: ${node.name}', style: textStyle), + Text( + 'Children: ${node.children.length}', + style: textStyle, + ), + Text( + 'toString:\n${node.toStringText}', + style: textStyle, + ), + ].withSpacing(), + ), + ), + ], + ), + ); + } +} + +extension on List { + List withSpacing() { + return expand((item) sync* { + yield const SizedBox(width: 10, height: 10); + yield item; + }).skip(1).toList(); + } +} diff --git a/packages/flame_devtools/lib/widgets/debug_mode_button.dart b/packages/flame_devtools/lib/widgets/debug_mode_button.dart index d79f9424156..93e2742a72c 100644 --- a/packages/flame_devtools/lib/widgets/debug_mode_button.dart +++ b/packages/flame_devtools/lib/widgets/debug_mode_button.dart @@ -2,7 +2,12 @@ import 'package:flame_devtools/repository.dart'; import 'package:flutter/material.dart'; class DebugModeButton extends StatefulWidget { - const DebugModeButton({super.key}); + const DebugModeButton({super.key, this.id}); + + final int? id; + + @override + Key? get key => super.key ?? ValueKey(id); @override State createState() => _DebugModeButtonState(); @@ -13,7 +18,7 @@ class _DebugModeButtonState extends State { @override void initState() { - _debugMode = Repository.getDebugMode(); + _debugMode = Repository.getDebugMode(id: widget.id); super.initState(); } @@ -31,7 +36,13 @@ class _DebugModeButtonState extends State { return ElevatedButton( onPressed: value.data == null ? null - : () => setState(() => _debugMode = Repository.swapDebugMode()), + : () { + setState( + () { + _debugMode = Repository.swapDebugMode(id: widget.id); + }, + ); + }, child: Text('$buttonPrefix Debug Mode'), ); }, diff --git a/packages/flame_devtools/lib/widgets/game_loop_controls.dart b/packages/flame_devtools/lib/widgets/game_loop_controls.dart index 5ecff67c555..565b5c2a27d 100644 --- a/packages/flame_devtools/lib/widgets/game_loop_controls.dart +++ b/packages/flame_devtools/lib/widgets/game_loop_controls.dart @@ -45,29 +45,25 @@ class _GameLoopControlsState extends State { IconButton( onPressed: (isPaused == null || !isPaused) ? null - : () => setState( - () => Repository.step(stepTime: -stepTime), - ), + : () => Repository.step(stepTime: -stepTime), icon: const Icon(Icons.skip_previous), ), IconButton( onPressed: (isPaused == null || isPaused) ? null - : () => setState(() => _paused = Repository.setPaused(true)), + : () => _setPaused(true), icon: const Icon(Icons.pause), ), IconButton( onPressed: (isPaused == null || !isPaused) ? null - : () => setState(() => _paused = Repository.setPaused(false)), + : () => _setPaused(false), icon: const Icon(Icons.play_arrow), ), IconButton( onPressed: (isPaused == null || !isPaused) ? null - : () => setState( - () => Repository.step(stepTime: stepTime), - ), + : () => Repository.step(stepTime: stepTime), icon: const Icon(Icons.skip_next), ), ], @@ -76,6 +72,12 @@ class _GameLoopControlsState extends State { ); } + void _setPaused(bool paused) { + setState(() { + _paused = Repository.setPaused(paused); + }); + } + @override void dispose() { _stepTimeController.dispose(); diff --git a/packages/flame_devtools/pubspec.yaml b/packages/flame_devtools/pubspec.yaml index 8dae46f7a4d..26b5d7c74ad 100644 --- a/packages/flame_devtools/pubspec.yaml +++ b/packages/flame_devtools/pubspec.yaml @@ -7,15 +7,15 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - devtools_app_shared: ^0.0.9 - devtools_extensions: ^0.0.13 + animated_tree_view: ^2.2.0 + devtools_app_shared: ^0.0.10 + devtools_extensions: ^0.0.14 + flame: ^1.16.0 flutter: sdk: flutter dev_dependencies: flame_lint: ^1.1.2 - flutter_test: - sdk: flutter flutter: uses-material-design: true From ed690b3048924749f829c7c44156e258bf4ab3e7 Mon Sep 17 00:00:00 2001 From: Yayo Arellano Date: Tue, 26 Mar 2024 20:10:16 +0800 Subject: [PATCH 34/79] feat: Support for new atlas format and rotated sprites (#3097) Added support to load new atlas format and support for rotated sprites --------- Co-authored-by: Lukas Klingsbo --- packages/flame_texturepacker/README.md | 28 ++-- .../lib/src/model/region.dart | 14 +- .../lib/src/texture_packer_atlas.dart | 2 +- .../lib/src/texture_packer_sprite.dart | 78 ++++++++++- .../test/assets/atlasMap.atlas | 35 +++++ .../test/assets/atlasMap.png | Bin 0 -> 187617 bytes .../multiplePages/MultiplePageAtlasMap.atlas | 102 ++++++++++++++ .../multiplePages/MultiplePageAtlasMap.png | Bin 0 -> 63797 bytes .../multiplePages/MultiplePageAtlasMap2.png | Bin 0 -> 62085 bytes .../multiplePages/MultiplePageAtlasMap3.png | Bin 0 -> 61942 bytes .../singlePage/SinglePageAtlasMap.atlas | 90 ++++++++++++ .../legacy/singlePage/SinglePageAtlasMap.png | Bin 0 -> 187617 bytes .../multiplePages/MultiplePageAtlasMap.atlas | 49 +++++++ .../multiplePages/MultiplePageAtlasMap.png | Bin 0 -> 63797 bytes .../multiplePages/MultiplePageAtlasMap2.png | Bin 0 -> 62085 bytes .../multiplePages/MultiplePageAtlasMap3.png | Bin 0 -> 61942 bytes .../singlePage/SinglePageAtlasMap.atlas | 35 +++++ .../singlePage/SinglePageAtlasMap.png | Bin 0 -> 187617 bytes .../test/legacy_format_test.dart | 129 +++++++++++++++++ .../test/new_format_test.dart | 130 ++++++++++++++++++ 20 files changed, 672 insertions(+), 20 deletions(-) create mode 100644 packages/flame_texturepacker/test/assets/atlasMap.atlas create mode 100644 packages/flame_texturepacker/test/assets/atlasMap.png create mode 100644 packages/flame_texturepacker/test/assets/legacy/multiplePages/MultiplePageAtlasMap.atlas create mode 100644 packages/flame_texturepacker/test/assets/legacy/multiplePages/MultiplePageAtlasMap.png create mode 100644 packages/flame_texturepacker/test/assets/legacy/multiplePages/MultiplePageAtlasMap2.png create mode 100644 packages/flame_texturepacker/test/assets/legacy/multiplePages/MultiplePageAtlasMap3.png create mode 100644 packages/flame_texturepacker/test/assets/legacy/singlePage/SinglePageAtlasMap.atlas create mode 100644 packages/flame_texturepacker/test/assets/legacy/singlePage/SinglePageAtlasMap.png create mode 100644 packages/flame_texturepacker/test/assets/newFormat/multiplePages/MultiplePageAtlasMap.atlas create mode 100644 packages/flame_texturepacker/test/assets/newFormat/multiplePages/MultiplePageAtlasMap.png create mode 100644 packages/flame_texturepacker/test/assets/newFormat/multiplePages/MultiplePageAtlasMap2.png create mode 100644 packages/flame_texturepacker/test/assets/newFormat/multiplePages/MultiplePageAtlasMap3.png create mode 100644 packages/flame_texturepacker/test/assets/newFormat/singlePage/SinglePageAtlasMap.atlas create mode 100644 packages/flame_texturepacker/test/assets/newFormat/singlePage/SinglePageAtlasMap.png create mode 100644 packages/flame_texturepacker/test/legacy_format_test.dart create mode 100644 packages/flame_texturepacker/test/new_format_test.dart diff --git a/packages/flame_texturepacker/README.md b/packages/flame_texturepacker/README.md index db55247e136..dcc0744f534 100644 --- a/packages/flame_texturepacker/README.md +++ b/packages/flame_texturepacker/README.md @@ -6,8 +6,8 @@

-A flame plugin to import sprite sheets generated by [Gdx Texture Packer][2] and -[Code and Web Texture Packer][1] +A flame plugin to import sprite sheets generated by Gdx Texture Packer and +Code & Web Texture Packer

@@ -21,12 +21,11 @@ A flame plugin to import sprite sheets generated by [Gdx Texture Packer][2] and + # flame_texturepacker TexturePacker is a tool to create efficient sprite sheets. This plugin allows you to import sprite -sheets generated by TexturePacker into your Flame game. - -Note: Rotated sprites are not currently supported. +sheets generated by [Gdx Texture Packer][2] and [Code and Web Texture Packer][1] into your Flame game. ## Install from Pub @@ -46,8 +45,8 @@ Drop generated atlas file and sprite sheet images into the `assets/` and link th ```yaml assets: - - assets/atlas_map.atlas - - assets/sprite_sheet1.png + - assets/atlas_map.atlas + - assets/sprite_sheet1.png ``` Import the plugin like this: @@ -90,6 +89,20 @@ final fallSprite = atlas.findSpriteByName('robot_fall')!; final idleSprite = atlas.findSpriteByName('robot_idle')!; ``` + +## Supported Features + +| Feature | Supported | +|--------------------|-----------| +| Allow Rotation | YES | +| Multiple Pages | YES | +| Use indices | YES | +| Strip whitespace X | NO | +| Strip whitespace Y | NO | + + +## Example + Full working example can be found in [example folder][3]. Note: Sprites used in this example can be found OpenGameArt [here][4]. @@ -106,4 +119,3 @@ Thanks to [Gnarhard][6] for the feature to build the atlas file from a device's [4]: https://opengameart.org/content/toon-characters-1 'Robot sprite' [5]: https://github.com/Brixto [6]: https://github.com/gnarhard - diff --git a/packages/flame_texturepacker/lib/src/model/region.dart b/packages/flame_texturepacker/lib/src/model/region.dart index 1b54e2bad9d..a0a3b6fa764 100644 --- a/packages/flame_texturepacker/lib/src/model/region.dart +++ b/packages/flame_texturepacker/lib/src/model/region.dart @@ -8,11 +8,11 @@ class Region { late double top; late double width; late double height; - late double offsetX; - late double offsetY; - late double originalWidth; - late double originalHeight; - late int degrees; - late bool rotate; - late int index; + double offsetX = 0; + double offsetY = 0; + double originalWidth = 0; + double originalHeight = 0; + int degrees = 0; + bool rotate = false; + int index = -1; } diff --git a/packages/flame_texturepacker/lib/src/texture_packer_atlas.dart b/packages/flame_texturepacker/lib/src/texture_packer_atlas.dart index 6704a070f2d..690430fcc65 100644 --- a/packages/flame_texturepacker/lib/src/texture_packer_atlas.dart +++ b/packages/flame_texturepacker/lib/src/texture_packer_atlas.dart @@ -131,7 +131,7 @@ Future<_TextureAtlasData> _parse( page = Page(); page.textureFile = line; final parentPath = (path.split('/')..removeLast()).join('/'); - final texturePath = '$parentPath/$line'; + final texturePath = parentPath.isEmpty ? line : '$parentPath/$line'; if (fromStorage) { try { diff --git a/packages/flame_texturepacker/lib/src/texture_packer_sprite.dart b/packages/flame_texturepacker/lib/src/texture_packer_sprite.dart index a8586924d07..7882dbeb3b8 100644 --- a/packages/flame_texturepacker/lib/src/texture_packer_sprite.dart +++ b/packages/flame_texturepacker/lib/src/texture_packer_sprite.dart @@ -1,4 +1,9 @@ +import 'dart:math' as math; +import 'dart:ui'; + import 'package:flame/components.dart'; +import 'package:flame/game.dart'; +import 'package:flame/rendering.dart'; import 'package:flame_texturepacker/src/model/region.dart'; /// {@template _texture_packer_sprite} @@ -11,8 +16,8 @@ class TexturePackerSprite extends Sprite { index = region.index, offsetX = region.offsetX, offsetY = region.offsetY, - packedWidth = region.width, - packedHeight = region.height, + packedWidth = region.rotate ? region.height : region.width, + packedHeight = region.rotate ? region.width : region.height, originalWidth = region.originalWidth, originalHeight = region.originalHeight, rotate = region.rotate, @@ -20,8 +25,16 @@ class TexturePackerSprite extends Sprite { super( region.page.texture, srcPosition: Vector2(region.left, region.top), - srcSize: Vector2(region.width, region.height), - ); + srcSize: Vector2( + region.rotate ? region.height : region.width, + region.rotate ? region.width : region.height, + ), + ) { + _decorator = Transform2DDecorator(_transform); + if (region.rotate) { + _transform.angle = math.pi / 2; + } + } /// The number at the end of the original image file name, or -1 if none. /// @@ -68,4 +81,61 @@ class TexturePackerSprite extends Sprite { /// The [degrees] field (angle) represented as radians. double get angle => radians(degrees.toDouble()); + + late final Decorator _decorator; + final Transform2D _transform = Transform2D(); + + // Used to avoid the creation of new Vector2 objects in render. + static final _tmpRenderPosition = Vector2.zero(); + static final _tmpRenderSize = Vector2.zero(); + + @override + void render( + Canvas canvas, { + Vector2? position, + Vector2? size, + Anchor anchor = Anchor.topLeft, + Paint? overridePaint, + }) { + if (!rotate) { + return super.render( + canvas, + position: position, + size: size, + anchor: anchor, + overridePaint: overridePaint, + ); + } + if (position != null) { + _tmpRenderPosition.setFrom(position); + } else { + _tmpRenderPosition.setZero(); + } + + // If the sprite is rotated on the sprite sheet un-rotate it + // and adjust the size + final auxAnchor = rotate ? Anchor.bottomLeft : anchor; + + final tempSize = size ?? srcSize; + final tempWidth = rotate ? tempSize.y : tempSize.x; + final tempHeight = rotate ? tempSize.x : tempSize.y; + + _tmpRenderSize.setValues(tempWidth, tempHeight); + + _tmpRenderPosition.setValues( + _tmpRenderPosition.x - (auxAnchor.x * _tmpRenderSize.x), + _tmpRenderPosition.y - (auxAnchor.y * _tmpRenderSize.y), + ); + + _decorator.applyChain( + (applyCanvas) => super.render( + applyCanvas, + position: _tmpRenderPosition, + size: _tmpRenderSize, + anchor: anchor, + overridePaint: overridePaint, + ), + canvas, + ); + } } diff --git a/packages/flame_texturepacker/test/assets/atlasMap.atlas b/packages/flame_texturepacker/test/assets/atlasMap.atlas new file mode 100644 index 00000000000..ada13e1e40d --- /dev/null +++ b/packages/flame_texturepacker/test/assets/atlasMap.atlas @@ -0,0 +1,35 @@ +atlasMap.png + size: 778, 776 + repeat: none +robot_duck + bounds: 390, 518, 192, 256 +robot_fall + bounds: 390, 260, 192, 256 +robot_idle + bounds: 584, 518, 192, 256 +robot_jump + bounds: 196, 518, 192, 256 +robot_walk + index: 0 + bounds: 2, 518, 192, 256 +robot_walk + index: 5 + bounds: 2, 260, 192, 256 +robot_walk + index: 2 + bounds: 2, 2, 192, 256 +robot_walk + index: 7 + bounds: 196, 260, 192, 256 +robot_walk + index: 4 + bounds: 196, 2, 192, 256 +robot_walk + index: 1 + bounds: 390, 2, 192, 256 +robot_walk + index: 6 + bounds: 584, 260, 192, 256 +robot_walk + index: 3 + bounds: 584, 2, 192, 256 diff --git a/packages/flame_texturepacker/test/assets/atlasMap.png b/packages/flame_texturepacker/test/assets/atlasMap.png new file mode 100644 index 0000000000000000000000000000000000000000..a8d6394805b6fe1b55d9103b37f12804f7dfb620 GIT binary patch literal 187617 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 IM6N<$g0CvhcK`qY literal 0 HcmV?d00001 diff --git a/packages/flame_texturepacker/test/assets/legacy/multiplePages/MultiplePageAtlasMap3.png b/packages/flame_texturepacker/test/assets/legacy/multiplePages/MultiplePageAtlasMap3.png new file mode 100644 index 0000000000000000000000000000000000000000..4b91169a6b2219cd747a20f57e5f97135c2cbfcd GIT binary patch literal 61942 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 IM6N<$g0CvhcK`qY literal 0 HcmV?d00001 diff --git a/packages/flame_texturepacker/test/assets/newFormat/multiplePages/MultiplePageAtlasMap3.png b/packages/flame_texturepacker/test/assets/newFormat/multiplePages/MultiplePageAtlasMap3.png new file mode 100644 index 0000000000000000000000000000000000000000..4b91169a6b2219cd747a20f57e5f97135c2cbfcd GIT binary patch literal 61942 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 Date: Tue, 26 Mar 2024 22:59:29 +0100 Subject: [PATCH 35/79] fix: CircleHitbox should properly detect when ray is outside (#3100) Previously some rays that originated outside of the `CircleHitbox` were counted as inside, this solves that and adds an example of how to use the `isInsideHitbox` functionality (thanks to @wurzelsand). Closes #3063 --- .../collision_detection.dart | 7 + .../rays_in_shape_example.dart | 158 ++++++++++++++++++ .../collisions/hitboxes/circle_hitbox.dart | 3 +- .../collisions/collision_detection_test.dart | 19 +++ 4 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 examples/lib/stories/collision_detection/rays_in_shape_example.dart diff --git a/examples/lib/stories/collision_detection/collision_detection.dart b/examples/lib/stories/collision_detection/collision_detection.dart index cd327f87ce5..108f5ecc76f 100644 --- a/examples/lib/stories/collision_detection/collision_detection.dart +++ b/examples/lib/stories/collision_detection/collision_detection.dart @@ -9,6 +9,7 @@ import 'package:examples/stories/collision_detection/quadtree_example.dart'; import 'package:examples/stories/collision_detection/raycast_example.dart'; import 'package:examples/stories/collision_detection/raycast_light_example.dart'; import 'package:examples/stories/collision_detection/raycast_max_distance_example.dart'; +import 'package:examples/stories/collision_detection/rays_in_shape_example.dart'; import 'package:examples/stories/collision_detection/raytrace_example.dart'; import 'package:flame/game.dart'; import 'package:flutter/widgets.dart'; @@ -76,5 +77,11 @@ void addCollisionDetectionStories(Dashbook dashbook) { codeLink: baseLink('collision_detection/raycast_max_distance_example.dart'), info: RaycastMaxDistanceExample.description, + ) + ..add( + 'Ray inside/outside shapes', + (_) => GameWidget(game: RaysInShapeExample()), + codeLink: baseLink('collision_detection/rays_in_shape_example.dart'), + info: RaysInShapeExample.description, ); } diff --git a/examples/lib/stories/collision_detection/rays_in_shape_example.dart b/examples/lib/stories/collision_detection/rays_in_shape_example.dart new file mode 100644 index 00000000000..28f6171f7fb --- /dev/null +++ b/examples/lib/stories/collision_detection/rays_in_shape_example.dart @@ -0,0 +1,158 @@ +import 'dart:async'; +import 'dart:math'; + +import 'package:flame/collisions.dart'; +import 'package:flame/components.dart'; +import 'package:flame/events.dart'; +import 'package:flame/extensions.dart'; +import 'package:flame/game.dart'; +import 'package:flame/geometry.dart'; +import 'package:flutter/material.dart'; + +const playArea = Rect.fromLTRB(-100, -100, 100, 100); + +class RaysInShapeExample extends FlameGame { + static const description = ''' +In this example we showcase the raytrace functionality where you can see whether +the rays are inside the shapes or not. Click to change the shape that the rays +are casted against. The rays originates from small circles, and if the circle is +inside the shape it will be red, otherwise green. And if the ray doesn't hit any +shape it will be gray. +'''; + + RaysInShapeExample() + : super( + world: RaysInShapeWorld(), + camera: CameraComponent.withFixedResolution( + width: playArea.width, + height: playArea.height, + ), + ); +} + +final whiteStroke = Paint() + ..color = const Color(0xffffffff) + ..style = PaintingStyle.stroke; + +final lightStroke = Paint() + ..color = const Color(0x50ffffff) + ..style = PaintingStyle.stroke; + +final greenStroke = Paint() + ..color = const Color(0xff00ff00) + ..style = PaintingStyle.stroke; + +final redStroke = Paint() + ..color = const Color(0xffff0000) + ..style = PaintingStyle.stroke; + +class RaysInShapeWorld extends World + with + HasGameReference, + HasCollisionDetection, + TapCallbacks { + final _rng = Random(); + List _rays = []; + + List randomRays(int count) => List.generate( + count, + (index) => Ray2( + origin: (Vector2.random(_rng)) * playArea.size.width - + playArea.size.toVector2() / 2, + direction: (Vector2.random(_rng) - Vector2(0.5, 0.5)).normalized(), + ), + ); + + int _componentIndex = 0; + + final _components = [ + CircleComponent( + radius: 60, + anchor: Anchor.center, + position: Vector2.zero(), + paint: whiteStroke, + children: [CircleHitbox()], + ), + RectangleComponent( + size: Vector2(100, 100), + anchor: Anchor.center, + position: Vector2.zero(), + paint: whiteStroke, + children: [RectangleHitbox()], + ), + PositionComponent( + position: Vector2.zero(), + children: [ + PolygonHitbox.relative( + [ + Vector2(-0.7, -1), + Vector2(1, -0.4), + Vector2(0.3, 1), + Vector2(-1, 0.6), + ], + parentSize: Vector2(100, 100), + anchor: Anchor.center, + position: Vector2.zero(), + ) + ..paint = whiteStroke + ..renderShape = true, + ], + ), + ]; + + @override + FutureOr onLoad() { + super.onLoad(); + add(_components[_componentIndex]); + _rays = randomRays(200); + } + + @override + void onTapUp(TapUpEvent event) { + super.onTapUp(event); + remove(_components[_componentIndex]); + _componentIndex = (_componentIndex + 1) % _components.length; + add(_components[_componentIndex]); + _recording.clear(); + _rays = randomRays(200); + } + + final Map?> _recording = {}; + + @override + void update(double dt) { + super.update(dt); + + for (final ray in _rays) { + final result = collisionDetection.raycast(ray); + _recording.addAll({ray: result}); + } + } + + @override + void render(Canvas canvas) { + super.render(canvas); + for (final ray in _recording.keys) { + final result = _recording[ray]; + if (result == null) { + canvas.drawLine( + ray.origin.toOffset(), + (ray.origin + ray.direction.scaled(10)).toOffset(), + lightStroke, + ); + canvas.drawCircle(ray.origin.toOffset(), 1, lightStroke); + } else { + canvas.drawLine( + ray.origin.toOffset(), + result.intersectionPoint!.toOffset(), + lightStroke, + ); + canvas.drawCircle( + ray.origin.toOffset(), + 1, + result.isInsideHitbox ? redStroke : greenStroke, + ); + } + } + } +} diff --git a/packages/flame/lib/src/collisions/hitboxes/circle_hitbox.dart b/packages/flame/lib/src/collisions/hitboxes/circle_hitbox.dart index 9f0ec435c66..aa6b92dca4f 100644 --- a/packages/flame/lib/src/collisions/hitboxes/circle_hitbox.dart +++ b/packages/flame/lib/src/collisions/hitboxes/circle_hitbox.dart @@ -73,7 +73,8 @@ class CircleHitbox extends CircleComponent with ShapeHitbox { ..y *= (ray.direction.y.sign * _temporaryLineSegment.to.y.sign); } - if (_temporaryLineSegment.to.length2 < radius * radius) { + if (ray.origin.distanceToSquared(_temporaryAbsoluteCenter) < + radius * radius) { _temporaryLineSegment.to.scaleTo(2 * radius); isInsideHitbox = true; } diff --git a/packages/flame/test/collisions/collision_detection_test.dart b/packages/flame/test/collisions/collision_detection_test.dart index a8733780b13..bc15d8d2dc6 100644 --- a/packages/flame/test/collisions/collision_detection_test.dart +++ b/packages/flame/test/collisions/collision_detection_test.dart @@ -1459,6 +1459,25 @@ void main() { closeToVector(Vector2(0, 1)), ); }, + 'ray from slightly outside of the CircleHitbox should not be counted ' + 'as inside': (collisionSystem) async { + final game = collisionSystem as FlameGame; + final world = game.world; + final positionComponent = PositionComponent( + position: Vector2.zero(), + anchor: Anchor.center, + size: Vector2.all(120), + )..add(CircleHitbox()); + await world.ensureAdd(positionComponent); + await game.ready(); + final ray = Ray2( + origin: Vector2(-38.06044293218409, -48.5986651724067), + direction: Vector2(0.927474693393028, -0.3738859359691247), + ); + final result = collisionSystem.collisionDetection.raycast(ray); + expect(result?.hitbox?.parent, positionComponent); + expect(result?.isInsideHitbox, isFalse); + }, }); }); From b946ba70cbfb5793a8d4d7c61d6ba029fbc303ab Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Tue, 26 Mar 2024 23:21:26 +0100 Subject: [PATCH 36/79] feat: Add `copyWith` method on the `TextBoxConfig` (#3099) Simplifies the creation of the `TextBoxConfig` in the `ScrollTextBoxComponent` by adding a `copyWith` method to it and making it `const`. --- .../lib/stories/rendering/text_example.dart | 13 +++++++----- .../components/scroll_text_box_component.dart | 16 ++------------- .../src/components/text_box_component.dart | 20 +++++++++++++++++-- .../components/text_box_component_test.dart | 8 ++++---- .../test/text/sprite_font_renderer_test.dart | 4 ++-- 5 files changed, 34 insertions(+), 27 deletions(-) diff --git a/examples/lib/stories/rendering/text_example.dart b/examples/lib/stories/rendering/text_example.dart index 197187764c4..14f5dad3c07 100644 --- a/examples/lib/stories/rendering/text_example.dart +++ b/examples/lib/stories/rendering/text_example.dart @@ -77,9 +77,9 @@ class TextExample extends FlameGame { size: Vector2(200, 150), position: Vector2(size.x / 2, size.y / 2 + 100), anchor: Anchor.topCenter, - boxConfig: TextBoxConfig( + boxConfig: const TextBoxConfig( timePerChar: 0.005, - margins: const EdgeInsets.fromLTRB(10, 10, 10, 10), + margins: EdgeInsets.fromLTRB(10, 10, 10, 10), ), ), ], @@ -138,6 +138,9 @@ class MyTextBox extends TextBoxComponent { Future onLoad() { paint = Paint(); bgRect = Rect.fromLTWH(0, 0, width, height); + size.addListener(() { + bgRect = Rect.fromLTWH(0, 0, width, height); + }); paint.color = Colors.white10; return super.onLoad(); @@ -152,7 +155,7 @@ class MyTextBox extends TextBoxComponent { class MyScrollTextBox extends ScrollTextBoxComponent { late Paint paint; - late Rect bgRect; + late Rect backgroundRect; MyScrollTextBox( String text, { @@ -165,7 +168,7 @@ class MyScrollTextBox extends ScrollTextBoxComponent { @override FutureOr onLoad() { paint = Paint(); - bgRect = Rect.fromLTWH(0, 0, width, height); + backgroundRect = Rect.fromLTWH(0, 0, width, height); paint.color = Colors.white10; return super.onLoad(); @@ -173,7 +176,7 @@ class MyScrollTextBox extends ScrollTextBoxComponent { @override void render(Canvas canvas) { - canvas.drawRect(bgRect, paint); + canvas.drawRect(backgroundRect, paint); super.render(canvas); } } diff --git a/packages/flame/lib/src/components/scroll_text_box_component.dart b/packages/flame/lib/src/components/scroll_text_box_component.dart index ea7599e88f2..45e74777b54 100644 --- a/packages/flame/lib/src/components/scroll_text_box_component.dart +++ b/packages/flame/lib/src/components/scroll_text_box_component.dart @@ -48,19 +48,7 @@ class ScrollTextBoxComponent extends PositionComponent { final marginBottom = boxConfig?.margins.bottom ?? 0; final innerMargins = EdgeInsets.fromLTRB(0, marginTop, 0, marginBottom); - boxConfig ??= TextBoxConfig(); - boxConfig = TextBoxConfig( - timePerChar: boxConfig.timePerChar, - dismissDelay: boxConfig.dismissDelay, - growingBox: boxConfig.growingBox, - maxWidth: size.x, - margins: EdgeInsets.fromLTRB( - boxConfig.margins.left, - 0, - boxConfig.margins.right, - 0, - ), - ); + boxConfig = (boxConfig ?? const TextBoxConfig()).copyWith(maxWidth: size.x); _scrollTextBoxComponent = _ScrollTextBoxComponent( text: text, @@ -119,7 +107,7 @@ class _ScrollTextBoxComponent extends TextBoxComponent }) : super( text: text ?? '', textRenderer: textRenderer ?? TextPaint(), - boxConfig: boxConfig ?? TextBoxConfig(), + boxConfig: boxConfig ?? const TextBoxConfig(), ); @override diff --git a/packages/flame/lib/src/components/text_box_component.dart b/packages/flame/lib/src/components/text_box_component.dart index f578014b58d..d753b9c0266 100644 --- a/packages/flame/lib/src/components/text_box_component.dart +++ b/packages/flame/lib/src/components/text_box_component.dart @@ -37,13 +37,29 @@ class TextBoxConfig { /// beginning (both width and height). final bool growingBox; - TextBoxConfig({ + const TextBoxConfig({ this.maxWidth = 200.0, this.margins = const EdgeInsets.all(8.0), this.timePerChar = 0.0, this.dismissDelay, this.growingBox = false, }); + + TextBoxConfig copyWith({ + double? maxWidth, + EdgeInsets? margins, + double? timePerChar, + double? dismissDelay, + bool? growingBox, + }) { + return TextBoxConfig( + maxWidth: maxWidth ?? this.maxWidth, + margins: margins ?? this.margins, + timePerChar: timePerChar ?? this.timePerChar, + dismissDelay: dismissDelay ?? this.dismissDelay, + growingBox: growingBox ?? this.growingBox, + ); + } } class TextBoxComponent extends TextComponent { @@ -81,7 +97,7 @@ class TextBoxComponent extends TextComponent { super.children, super.priority, super.key, - }) : _boxConfig = boxConfig ?? TextBoxConfig(), + }) : _boxConfig = boxConfig ?? const TextBoxConfig(), _fixedSize = size != null, align = align ?? Anchor.topLeft, pixelRatio = pixelRatio ?? diff --git a/packages/flame/test/components/text_box_component_test.dart b/packages/flame/test/components/text_box_component_test.dart index d84b6cb2097..518f560bb52 100644 --- a/packages/flame/test/components/text_box_component_test.dart +++ b/packages/flame/test/components/text_box_component_test.dart @@ -11,7 +11,7 @@ void main() { test('size is properly computed', () { final c = TextBoxComponent( text: 'The quick brown fox jumps over the lazy dog.', - boxConfig: TextBoxConfig( + boxConfig: const TextBoxConfig( maxWidth: 100.0, ), ); @@ -23,7 +23,7 @@ void main() { test('size is properly computed with new line character', () { final c = TextBoxComponent( text: 'The quick brown fox \n jumps over the lazy dog.', - boxConfig: TextBoxConfig( + boxConfig: const TextBoxConfig( maxWidth: 100.0, ), ); @@ -35,7 +35,7 @@ void main() { test('lines are properly computed with new line character', () { final c = TextBoxComponent( text: 'The quick brown fox \n jumps over the lazy dog.', - boxConfig: TextBoxConfig( + boxConfig: const TextBoxConfig( maxWidth: 400.0, ), ); @@ -51,7 +51,7 @@ void main() { (game) async { final component = TextBoxComponent( text: 'foo bar', - boxConfig: TextBoxConfig( + boxConfig: const TextBoxConfig( dismissDelay: 10.0, timePerChar: 1.0, ), diff --git a/packages/flame/test/text/sprite_font_renderer_test.dart b/packages/flame/test/text/sprite_font_renderer_test.dart index 08b89312529..262e73f41ad 100644 --- a/packages/flame/test/text/sprite_font_renderer_test.dart +++ b/packages/flame/test/text/sprite_font_renderer_test.dart @@ -37,12 +37,12 @@ void main() { TextBoxComponent( text: textSample, textRenderer: await createRenderer(letterSpacing: 1), - boxConfig: TextBoxConfig(maxWidth: 800), + boxConfig: const TextBoxConfig(maxWidth: 800), ), TextBoxComponent( text: textSample, textRenderer: await createRenderer(scale: 2), - boxConfig: TextBoxConfig(maxWidth: 800), + boxConfig: const TextBoxConfig(maxWidth: 800), position: Vector2(0, 100), ), TextComponent( From 6c8190b7215671e7d6e1e271b6aac2a9723ec20d Mon Sep 17 00:00:00 2001 From: Yayo Arellano Date: Wed, 27 Mar 2024 15:46:50 +0800 Subject: [PATCH 37/79] refactor: Deprecate `fromAtlas` in favour of `atlasFromAssets` and `atlasFromStorage` (#3098) Originally, the function was named `fromAtlas` because there was another function named `fromJson` that loaded `.json` files. but since that one is gone, and now every function is loading a `.atlas` it make sense to have `fromAssets` and `fromStorage` --------- Co-authored-by: Lukas Klingsbo --- packages/flame_texturepacker/README.md | 4 ++-- packages/flame_texturepacker/example/lib/main.dart | 2 +- .../flame_texturepacker/lib/flame_texturepacker.dart | 11 +++++++++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/flame_texturepacker/README.md b/packages/flame_texturepacker/README.md index dcc0744f534..292d10fd0b9 100644 --- a/packages/flame_texturepacker/README.md +++ b/packages/flame_texturepacker/README.md @@ -56,7 +56,7 @@ Import the plugin like this: Load the TextureAtlas passing the path of the sprite sheet atlas file: ```Dart -final atlas = await fromAtlas('atlas_map.atlas'); +final atlas = await atlasFromAssets('atlas_map.atlas'); ``` @@ -66,7 +66,7 @@ If you are using file storage, grab your atlas file like this: ```Dart final documentsPath = (await getApplicationDocumentsDirectory()).path; -final atlas = await fromAtlas('$documentsPath/atlas_map.atlas', fromStorage: true); +final atlas = await atlasFromStorage('$documentsPath/atlas_map.atlas'); ``` Get a list of sprites ordered by their index, you can use the list to generate an animation: diff --git a/packages/flame_texturepacker/example/lib/main.dart b/packages/flame_texturepacker/example/lib/main.dart index 3fac2802ff0..24dce3f9c69 100644 --- a/packages/flame_texturepacker/example/lib/main.dart +++ b/packages/flame_texturepacker/example/lib/main.dart @@ -18,7 +18,7 @@ class MyGame extends FlameGame { super.onLoad(); // Load the atlasMap. - final atlas = await fromAtlas('atlas_map.atlas'); + final atlas = await atlasFromAssets('atlas_map.atlas'); // Get a list of sprites ordered by their index final walkingSprites = atlas.findSpritesByName('robot_walk'); diff --git a/packages/flame_texturepacker/lib/flame_texturepacker.dart b/packages/flame_texturepacker/lib/flame_texturepacker.dart index ad214bd1040..1b5c0eb7227 100644 --- a/packages/flame_texturepacker/lib/flame_texturepacker.dart +++ b/packages/flame_texturepacker/lib/flame_texturepacker.dart @@ -9,9 +9,20 @@ export 'package:flame_texturepacker/src/texture_packer_sprite.dart'; extension TexturepackerLoader on Game { /// Loads the specified pack file. /// Uses the parent directory of the pack file to find the page images. + @Deprecated('Use [atlasFromAssets] or [atlasFromStorage] instead') Future fromAtlas( String assetsPath, { bool fromStorage = false, }) async => TexturePackerAtlas.load(assetsPath, fromStorage: fromStorage); + + /// Loads the specified pack file from assets + /// Uses the parent directory of the pack file to find the page images. + Future atlasFromAssets(String assetsPath) async => + TexturePackerAtlas.load(assetsPath); + + /// Loads the specified pack file from storage + /// Uses the parent directory of the pack file to find the page images. + Future atlasFromStorage(String storagePath) async => + TexturePackerAtlas.load(storagePath, fromStorage: true); } From 233cc94c557e0af2fcf7599943ddf75180abf801 Mon Sep 17 00:00:00 2001 From: KurtLa Date: Thu, 28 Mar 2024 17:19:10 +0100 Subject: [PATCH 38/79] feat: Add onFinished callback to ScrollTextBoxComponent (#3105) Implemented a callback function to notify when all text is displayed. Removed unnecessary code. --- doc/flame/rendering/text_rendering.md | 9 +- .../components/scroll_text_box_component.dart | 48 ++++++--- .../src/components/text_box_component.dart | 31 +++++- .../scroll_text_box_component_test.dart | 99 +++++++++++++++++++ .../components/text_box_component_test.dart | 44 +++++++++ 5 files changed, 211 insertions(+), 20 deletions(-) create mode 100644 packages/flame/test/components/scroll_text_box_component_test.dart diff --git a/doc/flame/rendering/text_rendering.md b/doc/flame/rendering/text_rendering.md index 86d544793fa..a42b52ba0c1 100644 --- a/doc/flame/rendering/text_rendering.md +++ b/doc/flame/rendering/text_rendering.md @@ -10,11 +10,10 @@ components: - `TextComponent` for rendering a single line of text - `TextBoxComponent` for bounding multi-line text within a sized box, including the possibility of a -typing effect -- `ScrollTextBoxComponent` enhances the functionality of `TextBoxComponent` by adding scrolling -capability when the text exceeds the boundaries of the enclosing box. - -Use the `onFinished` callback to get notified when the text is completely printed. +typing effect. You can use the `newLineNotifier` to be notified when a new line is added. Use the +`onComplete` callback to execute a function when the text is completely printed. +- `ScrollTextBoxComponent` enhances the functionality of `TextBoxComponent` by adding vertical +scrolling capability when the text exceeds the boundaries of the enclosing box. All components are showcased in diff --git a/packages/flame/lib/src/components/scroll_text_box_component.dart b/packages/flame/lib/src/components/scroll_text_box_component.dart index 45e74777b54..c8e26efdaee 100644 --- a/packages/flame/lib/src/components/scroll_text_box_component.dart +++ b/packages/flame/lib/src/components/scroll_text_box_component.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:flame/components.dart'; import 'package:flame/events.dart'; import 'package:flame/text.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/painting.dart'; /// [ScrollTextBoxComponent] configures the layout and interactivity of a @@ -15,6 +16,7 @@ import 'package:flutter/painting.dart'; /// capabilities. class ScrollTextBoxComponent extends PositionComponent { late final _ScrollTextBoxComponent _scrollTextBoxComponent; + late final ValueNotifier newLineNotifier; /// Constructor for [ScrollTextBoxComponent]. /// - [size]: Specifies the size of the text box. @@ -22,6 +24,7 @@ class ScrollTextBoxComponent extends PositionComponent { /// - [text]: The text content to be displayed. /// - [textRenderer]: Handles the rendering of the text. /// - [boxConfig]: Configuration for the text box appearance. + /// - [onComplete]: Callback will be executed after all text is displayed. /// - Other parameters include alignment, pixel ratio, and positioning /// settings. /// An assertion ensures that the [size] has positive dimensions. @@ -39,6 +42,7 @@ class ScrollTextBoxComponent extends PositionComponent { super.priority, super.key, List? children, + void Function()? onComplete, }) : assert( size.x > 0 && size.y > 0, 'size must have positive dimensions: $size', @@ -48,15 +52,29 @@ class ScrollTextBoxComponent extends PositionComponent { final marginBottom = boxConfig?.margins.bottom ?? 0; final innerMargins = EdgeInsets.fromLTRB(0, marginTop, 0, marginBottom); - boxConfig = (boxConfig ?? const TextBoxConfig()).copyWith(maxWidth: size.x); - + boxConfig ??= const TextBoxConfig(); + boxConfig = TextBoxConfig( + timePerChar: boxConfig.timePerChar, + dismissDelay: boxConfig.dismissDelay, + growingBox: boxConfig.growingBox, + maxWidth: size.x, + margins: EdgeInsets.fromLTRB( + boxConfig.margins.left, + 0, + boxConfig.margins.right, + 0, + ), + ); _scrollTextBoxComponent = _ScrollTextBoxComponent( text: text, textRenderer: textRenderer, boxConfig: boxConfig, align: align, pixelRatio: pixelRatio, + onComplete: onComplete, ); + newLineNotifier = _scrollTextBoxComponent.newLineNotifier; + _scrollTextBoxComponent.setOwnerComponent = this; // Integrates the [ClipComponent] for managing // the text box's scrollable area. @@ -89,12 +107,13 @@ class ScrollTextBoxComponent extends PositionComponent { class _ScrollTextBoxComponent extends TextBoxComponent with DragCallbacks { double scrollBoundsY = 0.0; - int _linesScrolled = 0; late final ClipComponent clipComponent; late ScrollTextBoxComponent _owner; + bool _isOnCompleteExecuted = false; + _ScrollTextBoxComponent({ String? text, T? textRenderer, @@ -104,6 +123,7 @@ class _ScrollTextBoxComponent extends TextBoxComponent super.position, super.scale, double super.angle = 0.0, + super.onComplete, }) : super( text: text ?? '', textRenderer: textRenderer ?? TextPaint(), @@ -113,25 +133,29 @@ class _ScrollTextBoxComponent extends TextBoxComponent @override Future onLoad() { clipComponent = parent! as ClipComponent; + newLinePositionNotifier.addListener(() { + if (newLinePositionNotifier.value > clipComponent.size.y) { + position.y = -newLinePositionNotifier.value + clipComponent.size.y; + } + }); return super.onLoad(); } @override - Future redraw() async { - if ((currentLine + 1 - _linesScrolled) * lineHeight > - clipComponent.size.y) { - _linesScrolled++; - position.y -= lineHeight; - scrollBoundsY = -position.y; + void update(double dt) { + if (!_isOnCompleteExecuted && finished) { + _isOnCompleteExecuted = true; + scrollBoundsY = clipComponent.size.y - size.y; } - await super.redraw(); + + super.update(dt); } @override void onDragUpdate(DragUpdateEvent event) { - if (finished && _linesScrolled > 0) { + if (finished && scrollBoundsY < 0) { position.y += event.localDelta.y; - position.y = position.y.clamp(-scrollBoundsY, 0); + position.y = position.y.clamp(scrollBoundsY, 0); } } diff --git a/packages/flame/lib/src/components/text_box_component.dart b/packages/flame/lib/src/components/text_box_component.dart index d753b9c0266..7aece0d0e4d 100644 --- a/packages/flame/lib/src/components/text_box_component.dart +++ b/packages/flame/lib/src/components/text_box_component.dart @@ -80,6 +80,20 @@ class TextBoxComponent extends TextComponent { @visibleForTesting Image? cache; + /// Notifies when a new line is rendered. + final ValueNotifier newLineNotifier = ValueNotifier(0); + + // Notifies when a new line is rendered with the position of the new line. + @internal + final ValueNotifier newLinePositionNotifier = + ValueNotifier(0); + + double _currentLinePosition = 0.0; + bool _isOnCompleteExecuted = false; + + /// Callback function to be executed after all text is displayed. + void Function()? onComplete; + TextBoxConfig get boxConfig => _boxConfig; double get lineHeight => _lineHeight; @@ -96,6 +110,7 @@ class TextBoxComponent extends TextComponent { super.anchor, super.children, super.priority, + this.onComplete, super.key, }) : _boxConfig = boxConfig ?? const TextBoxConfig(), _fixedSize = size != null, @@ -300,7 +315,11 @@ class TextBoxComponent extends TextComponent { i * _lineHeight, ); textElement.render(canvas, position); - + if (position.y > _currentLinePosition) { + _currentLinePosition = position.y; + newLineNotifier.value = newLineNotifier.value + 1; + newLinePositionNotifier.value = _currentLinePosition + _lineHeight; + } charCount += lines[i].length; } } @@ -334,8 +353,14 @@ class TextBoxComponent extends TextComponent { } _previousChar = currentChar; - if (_boxConfig.dismissDelay != null && finished) { - removeFromParent(); + if (finished) { + if (!_isOnCompleteExecuted) { + _isOnCompleteExecuted = true; + onComplete?.call(); + } + if (_boxConfig.dismissDelay != null) { + removeFromParent(); + } } } diff --git a/packages/flame/test/components/scroll_text_box_component_test.dart b/packages/flame/test/components/scroll_text_box_component_test.dart new file mode 100644 index 00000000000..ef83aec181a --- /dev/null +++ b/packages/flame/test/components/scroll_text_box_component_test.dart @@ -0,0 +1,99 @@ +import 'package:flame/components.dart'; +import 'package:flame_test/flame_test.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; + +void main() { + group('ScrollTextBoxComponent', () { + testWithFlameGame( + 'onComplete is called when no scrolling is required', + (game) async { + final onComplete = MockOnCompleteCallback(); + + when(onComplete).thenReturn(null); + + final component = ScrollTextBoxComponent( + size: Vector2(200, 100), + text: 'Short text', + onComplete: onComplete, + ); + await game.ensureAdd(component); + + game.update(0.1); + + verify(onComplete).called(1); + }, + ); + + testWithFlameGame( + 'onComplete is called when scrolling is required', + (game) async { + final onComplete = MockOnCompleteCallback(); + + when(onComplete).thenReturn(null); + + final component = ScrollTextBoxComponent( + size: Vector2(200, 100), + text: '''Long text that will definitely require scrolling to be +fully visible in the given size of the ScrollTextBoxComponent.''', + onComplete: onComplete, + ); + await game.ensureAdd(component); + + game.update(0.1); + + verify(onComplete).called(1); + }, + ); + + testWithFlameGame( + 'Text position moves to <0 when scrolled', + (game) async { + final scrollComponent = ScrollTextBoxComponent( + size: Vector2(50, 50), + text: '''This is a test text that is long enough to require scrolling +to see the entire content. It should test whether the scrolling +functionality properly adjusts the text position.''', + onComplete: () {}, + ); + + expect(scrollComponent.children.length, greaterThan(0)); + expect(scrollComponent.children.first, isA()); + final clipCmp = scrollComponent.children.first as ClipComponent; + + expect(clipCmp.children.length, greaterThan(0)); + expect(clipCmp.children.first, isA()); + final innerScrollComponent = + clipCmp.children.first as PositionComponent; + + expect(innerScrollComponent.position.y, equals(0)); + await game.ensureAdd(scrollComponent); + + expect(innerScrollComponent.position.y, lessThan(0)); + }, + ); + + testWithFlameGame('Text notifies if a new line is added', (game) async { + var newLineCount = 0; + final scrollComponent = ScrollTextBoxComponent( + size: Vector2(50, 50), + text: '''This +test +has +five +lines.''', + ); + expect(scrollComponent.newLineNotifier.value, equals(0)); + + scrollComponent.newLineNotifier.addListener(() { + newLineCount++; + }); + await game.ensureAdd(scrollComponent); + expect(newLineCount, equals(5)); + }); + }); +} + +class MockOnCompleteCallback extends Mock { + void call(); +} diff --git a/packages/flame/test/components/text_box_component_test.dart b/packages/flame/test/components/text_box_component_test.dart index 518f560bb52..db323d953fe 100644 --- a/packages/flame/test/components/text_box_component_test.dart +++ b/packages/flame/test/components/text_box_component_test.dart @@ -5,6 +5,9 @@ import 'package:flame/components.dart'; import 'package:flame/palette.dart'; import 'package:flame_test/flame_test.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; + +import 'scroll_text_box_component_test.dart'; void main() { group('TextBoxComponent', () { @@ -121,6 +124,47 @@ void main() { }, ); + testWithFlameGame( + 'onComplete is called when no scrolling is required', + (game) async { + final onComplete = MockOnCompleteCallback(); + + when(onComplete).thenReturn(null); + + final component = ScrollTextBoxComponent( + size: Vector2(200, 100), + text: 'Short text', + onComplete: onComplete, + ); + await game.ensureAdd(component); + + game.update(0.1); + + verify(onComplete).called(1); + }, + ); + + testWithFlameGame( + 'TextBoxComponent notifies if a new line is added and requires space', + (game) async { + var lineSize = 0.0; + final textBoxComponent = TextBoxComponent( + size: Vector2(50, 50), + text: '''This +test +has +five +lines.''', + ); + expect(textBoxComponent.newLinePositionNotifier.value, equals(0)); + + textBoxComponent.newLinePositionNotifier.addListener(() { + lineSize += textBoxComponent.newLinePositionNotifier.value; + }); + await game.ensureAdd(textBoxComponent); + expect(lineSize, greaterThan(0)); + }); + testGolden( 'Alignment options', (game) async { From cb1e37014bac7bb68b647234b718a37e26ad7559 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Fri, 29 Mar 2024 11:26:55 +0100 Subject: [PATCH 39/79] fix: Call `render` properly from nested `FlameGame`s (#3106) Old typo where `renderTree` should call `render` and not itself when the parent isn't null, since otherwise it will cause an infinite recursion. --- packages/flame/lib/src/game/flame_game.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/flame/lib/src/game/flame_game.dart b/packages/flame/lib/src/game/flame_game.dart index 5fa988ba697..59cde184c2c 100644 --- a/packages/flame/lib/src/game/flame_game.dart +++ b/packages/flame/lib/src/game/flame_game.dart @@ -138,7 +138,7 @@ class FlameGame extends ComponentTreeRoot @override void renderTree(Canvas canvas) { if (parent != null) { - renderTree(canvas); + render(canvas); } for (final component in children) { component.renderTree(canvas); From 5d74e62fb2047ea6fbd6876bb403e5df33b26d2f Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Fri, 29 Mar 2024 12:00:09 +0100 Subject: [PATCH 40/79] chore: Bump to use Melos ^5.2.0 (#3107) --- melos.yaml | 42 ++++++++++++++++-------------------------- pubspec.yaml | 2 +- 2 files changed, 17 insertions(+), 27 deletions(-) diff --git a/melos.yaml b/melos.yaml index a16a30fa2ec..62f439a9bd2 100644 --- a/melos.yaml +++ b/melos.yaml @@ -13,7 +13,7 @@ command: branch: main # Generates a link to a prefilled GitHub release creation page. releaseUrl: true - + bootstrap: environment: sdk: ">=3.0.0 <4.0.0" @@ -25,26 +25,18 @@ command: dartdoc: ^6.3.0 mocktail: ^1.0.1 test: any - + publish: hooks: pre: melos devtools-build scripts: lint:all: - run: melos run analyze && melos run format + steps: + - analyze + - format description: Run all static analysis checks. - analyze: - run: | - melos exec -c 1 -- \ - flutter analyze --fatal-infos - description: Run `flutter analyze` for all packages. - - format: - run: melos exec dart format . --fix - description: Run `dart format` for all packages. - format-check: run: melos exec dart format . --set-exit-if-changed description: Run `dart format` checks for all packages. @@ -62,16 +54,14 @@ scripts: description: Run dartdoc checks for all packages. doc-setup: - run: > - echo Checking python version: && - python3 --version && - (python3 -c "import sys; sys.exit(0 if sys.version_info >= (3,8) else 2)" || - (echo Error: Python 3.8+ is required && exit 1)) && - echo Installing required python modules: && - python3 -m pip install -r "$MELOS_ROOT_PATH/doc/_sphinx/requirements.txt" && - echo Installing dartdoc_json: && - dart pub global activate dartdoc_json && - echo Done. + steps: + - "echo Checking python version:" + - 'python3 --version && (python3 -c "import sys; sys.exit(0 if sys.version_info >= (3,8) else 2)" || (echo Error: Python 3.8+ is required && exit 1))' + - "echo Installing required python modules:" + - 'python3 -m pip install -r "$MELOS_ROOT_PATH/doc/_sphinx/requirements.txt"' + - "echo Installing dartdoc_json:" + - "dart pub global activate dartdoc_json" + - "echo Done." description: Prepares the environment for documentation development. doc-build: @@ -105,9 +95,9 @@ scripts: description: Run all Flutter tests in this project. coverage: - run: | - melos exec -- flutter test --coverage && - melos exec -- genhtml coverage/lcov.info --output-directory=coverage/ + steps: + - melos exec -- flutter test --coverage + - melos exec -- genhtml coverage/lcov.info --output-directory=coverage/ packageFilters: dirExists: test description: Generate coverage for the selected package. diff --git a/pubspec.yaml b/pubspec.yaml index 1d4f21d9507..cffa5012575 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,4 +4,4 @@ environment: sdk: ">=3.0.0 <4.0.0" dev_dependencies: - melos: ^3.2.0 + melos: ^5.2.0 From 639dac0732b9ba0a5349f14286cb90292b7c6d45 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Fri, 29 Mar 2024 16:26:20 +0100 Subject: [PATCH 41/79] chore(release): Publish Flame v1.17.0 (#3108) ``` Package Name Current Version Updated Version Update Reason flame 1.16.0 1.17.0 manual versioning flame_forge2d 0.17.0 0.17.1 manual versioning flame_oxygen 0.2.0 0.2.1 manual versioning behavior_tree 0.1.0 0.1.1 updated with minor changes flame_behavior_tree 0.1.0 0.1.1 updated with minor changes flame_network_assets 0.3.0 0.3.1 updated with minor changes flame_sprite_fusion 0.1.0 0.1.1 updated with minor changes flame_texturepacker 3.1.0 3.2.0 updated with minor changes flame_tiled 1.19.0 1.20.0 updated with minor changes flame_test 1.16.0 1.16.1 dependency was updated flame_isolate 0.6.0 0.6.0+1 dependency was updated flame_fire_atlas 1.5.0 1.5.1 dependency was updated flame_audio 2.10.0 2.10.1 dependency was updated flame_spine 0.2.0 0.2.0+1 dependency was updated flame_bloc 1.11.0 1.11.1 dependency was updated flame_lottie 0.4.0 0.4.0+1 dependency was updated flame_markdown 0.2.0 0.2.0+1 dependency was updated flame_rive 1.10.0 1.10.1 dependency was updated flame_noise 0.3.0 0.3.0+1 dependency was updated flame_riverpod 5.4.0 5.4.1 dependency was updated flame_svg 1.10.0 1.10.1 dependency was updated ``` --- CHANGELOG.md | 106 ++++++++++++++++++ doc/flame/examples/pubspec.yaml | 4 +- doc/tutorials/klondike/app/pubspec.yaml | 2 +- doc/tutorials/platformer/app/pubspec.yaml | 2 +- doc/tutorials/space_shooter/app/pubspec.yaml | 2 +- examples/games/padracing/pubspec.yaml | 4 +- examples/games/rogue_shooter/pubspec.yaml | 2 +- examples/games/trex/pubspec.yaml | 2 +- examples/pubspec.yaml | 18 +-- packages/flame/CHANGELOG.md | 21 ++++ packages/flame/example/pubspec.yaml | 2 +- packages/flame/pubspec.yaml | 4 +- packages/flame_audio/CHANGELOG.md | 4 + packages/flame_audio/example/pubspec.yaml | 4 +- packages/flame_audio/pubspec.yaml | 4 +- packages/flame_behavior_tree/CHANGELOG.md | 4 + .../behavior_tree/CHANGELOG.md | 4 + .../behavior_tree/pubspec.yaml | 2 +- .../flame_behavior_tree/example/pubspec.yaml | 4 +- packages/flame_behavior_tree/pubspec.yaml | 8 +- packages/flame_bloc/CHANGELOG.md | 4 + packages/flame_bloc/example/pubspec.yaml | 4 +- packages/flame_bloc/pubspec.yaml | 6 +- packages/flame_devtools/pubspec.yaml | 2 +- packages/flame_fire_atlas/CHANGELOG.md | 4 + .../flame_fire_atlas/example/pubspec.yaml | 4 +- packages/flame_fire_atlas/pubspec.yaml | 4 +- packages/flame_forge2d/CHANGELOG.md | 4 + packages/flame_forge2d/example/pubspec.yaml | 4 +- packages/flame_forge2d/pubspec.yaml | 6 +- packages/flame_isolate/CHANGELOG.md | 4 + packages/flame_isolate/example/pubspec.yaml | 4 +- packages/flame_isolate/pubspec.yaml | 6 +- packages/flame_jenny/pubspec.yaml | 2 +- packages/flame_lottie/CHANGELOG.md | 4 + packages/flame_lottie/example/pubspec.yaml | 4 +- packages/flame_lottie/pubspec.yaml | 6 +- packages/flame_markdown/CHANGELOG.md | 4 + packages/flame_markdown/example/pubspec.yaml | 4 +- packages/flame_markdown/pubspec.yaml | 4 +- packages/flame_network_assets/CHANGELOG.md | 4 + .../flame_network_assets/example/pubspec.yaml | 4 +- packages/flame_network_assets/pubspec.yaml | 4 +- packages/flame_noise/CHANGELOG.md | 4 + packages/flame_noise/pubspec.yaml | 6 +- packages/flame_oxygen/CHANGELOG.md | 4 + packages/flame_oxygen/example/pubspec.yaml | 4 +- packages/flame_oxygen/pubspec.yaml | 4 +- packages/flame_rive/CHANGELOG.md | 4 + packages/flame_rive/example/pubspec.yaml | 4 +- packages/flame_rive/pubspec.yaml | 6 +- packages/flame_riverpod/CHANGELOG.md | 4 + packages/flame_riverpod/example/pubspec.yaml | 4 +- packages/flame_riverpod/pubspec.yaml | 4 +- packages/flame_spine/CHANGELOG.md | 4 + packages/flame_spine/example/pubspec.yaml | 4 +- packages/flame_spine/pubspec.yaml | 4 +- packages/flame_sprite_fusion/CHANGELOG.md | 4 + .../flame_sprite_fusion/example/pubspec.yaml | 4 +- packages/flame_sprite_fusion/pubspec.yaml | 6 +- packages/flame_studio/pubspec.yaml | 2 +- packages/flame_svg/CHANGELOG.md | 4 + packages/flame_svg/example/pubspec.yaml | 4 +- packages/flame_svg/pubspec.yaml | 4 +- packages/flame_test/CHANGELOG.md | 4 + packages/flame_test/example/pubspec.yaml | 4 +- packages/flame_test/pubspec.yaml | 4 +- packages/flame_texturepacker/CHANGELOG.md | 6 + .../flame_texturepacker/example/pubspec.yaml | 4 +- packages/flame_texturepacker/pubspec.yaml | 4 +- packages/flame_tiled/CHANGELOG.md | 4 + packages/flame_tiled/example/pubspec.yaml | 4 +- packages/flame_tiled/pubspec.yaml | 4 +- 73 files changed, 317 insertions(+), 108 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0790be3c4e9..b0535327102 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,112 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2024-03-29 + +### Changes + +--- + +Packages with breaking changes: + + - [`flame` - `v1.17.0`](#flame---v1170) + +Packages with other changes: + + - [`flame_forge2d` - `v0.17.1`](#flame_forge2d---v0171) + - [`flame_oxygen` - `v0.2.1`](#flame_oxygen---v021) + - [`behavior_tree` - `v0.1.1`](#behavior_tree---v011) + - [`flame_behavior_tree` - `v0.1.1`](#flame_behavior_tree---v011) + - [`flame_network_assets` - `v0.3.1`](#flame_network_assets---v031) + - [`flame_sprite_fusion` - `v0.1.1`](#flame_sprite_fusion---v011) + - [`flame_texturepacker` - `v3.2.0`](#flame_texturepacker---v320) + - [`flame_tiled` - `v1.20.0`](#flame_tiled---v1200) + - [`flame_test` - `v1.16.1`](#flame_test---v1161) + - [`flame_isolate` - `v0.6.0+1`](#flame_isolate---v0601) + - [`flame_fire_atlas` - `v1.5.1`](#flame_fire_atlas---v151) + - [`flame_audio` - `v2.10.1`](#flame_audio---v2101) + - [`flame_spine` - `v0.2.0+1`](#flame_spine---v0201) + - [`flame_bloc` - `v1.11.1`](#flame_bloc---v1111) + - [`flame_lottie` - `v0.4.0+1`](#flame_lottie---v0401) + - [`flame_markdown` - `v0.2.0+1`](#flame_markdown---v0201) + - [`flame_rive` - `v1.10.1`](#flame_rive---v1101) + - [`flame_noise` - `v0.3.0+1`](#flame_noise---v0301) + - [`flame_riverpod` - `v5.4.1`](#flame_riverpod---v541) + - [`flame_svg` - `v1.10.1`](#flame_svg---v1101) + +Packages with dependency updates only: + +> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project. + + - `flame_test` - `v1.16.1` + - `flame_isolate` - `v0.6.0+1` + - `flame_fire_atlas` - `v1.5.1` + - `flame_audio` - `v2.10.1` + - `flame_spine` - `v0.2.0+1` + - `flame_bloc` - `v1.11.1` + - `flame_lottie` - `v0.4.0+1` + - `flame_markdown` - `v0.2.0+1` + - `flame_rive` - `v1.10.1` + - `flame_noise` - `v0.3.0+1` + - `flame_riverpod` - `v5.4.1` + - `flame_svg` - `v1.10.1` + +--- + +#### `flame` - `v1.17.0` + + - **REFACTOR**: Change the ClipComponent factory Constructor to redirect Constructor ([#3089](https://github.com/flame-engine/flame/issues/3089)). ([cc035fb4](https://github.com/flame-engine/flame/commit/cc035fb4a3e123473d4e5e0db1fa0253e533bc61)) + - **FIX**: Call `render` properly from nested `FlameGame`s ([#3106](https://github.com/flame-engine/flame/issues/3106)). ([cb1e3701](https://github.com/flame-engine/flame/commit/cb1e37014bac7bb68b647234b718a37e26ad7559)) + - **FIX**: CircleHitbox should properly detect when ray is outside ([#3100](https://github.com/flame-engine/flame/issues/3100)). ([8cd9e123](https://github.com/flame-engine/flame/commit/8cd9e12319c0715def655fcf42f3976fa5f45e11)) + - **FIX**: Clamp opacity set by the `ColorEffect` to 1.0 ([#3069](https://github.com/flame-engine/flame/issues/3069)). ([9282cc38](https://github.com/flame-engine/flame/commit/9282cc38f06cd6c87ed3a1880d28d5c9f290cc04)) + - **FIX**: FutureOr return type of ComponentViewportMargin.onLoad ([#3059](https://github.com/flame-engine/flame/issues/3059)). ([72678c67](https://github.com/flame-engine/flame/commit/72678c676020480beae1d944ee687fd73eac9cf7)) + - **FIX**: Size for `SpriteComponent.fromImage` should be nullable ([#3054](https://github.com/flame-engine/flame/issues/3054)). ([2ed71a3c](https://github.com/flame-engine/flame/commit/2ed71a3c89b3c2182828f2812d8515811483f4d5)) + - **FIX**: Check for removing state while adding a child ([#3050](https://github.com/flame-engine/flame/issues/3050)). ([3a24a51d](https://github.com/flame-engine/flame/commit/3a24a51d108b1138ac3dd735956f4276f16b2974)) + - **FEAT**: Add onFinished callback to ScrollTextBoxComponent ([#3105](https://github.com/flame-engine/flame/issues/3105)). ([233cc94c](https://github.com/flame-engine/flame/commit/233cc94c557e0af2fcf7599943ddf75180abf801)) + - **FEAT**: Add `copyWith` method on the `TextBoxConfig` ([#3099](https://github.com/flame-engine/flame/issues/3099)). ([b946ba70](https://github.com/flame-engine/flame/commit/b946ba70cbfb5793a8d4d7c61d6ba029fbc303ab)) + - **FEAT**: Component tree for the devtools extension tab ([#3094](https://github.com/flame-engine/flame/issues/3094)). ([bf5d68e9](https://github.com/flame-engine/flame/commit/bf5d68e9b5147dd5e7c10d72bf9c2f705733d688)) + - **FEAT**: Add PositionComponent.toString ([#3095](https://github.com/flame-engine/flame/issues/3095)). ([b1f01986](https://github.com/flame-engine/flame/commit/b1f01986b440ac18bb35b0d76963b2c66f49ea33)) + - **FEAT**: Add SpriteBatch.replace to allow the replacement of the batch information ([#3079](https://github.com/flame-engine/flame/issues/3079)). ([bf3c282d](https://github.com/flame-engine/flame/commit/bf3c282dd669e9a32a550b86770dba7fb8472afa)) + - **FEAT**: Initial functionality of flame_devtools ([#3061](https://github.com/flame-engine/flame/issues/3061)). ([c92910c6](https://github.com/flame-engine/flame/commit/c92910c688f5dc4463e129132759102e7ebf2e36)) + - **FEAT**: Add `HasPerformanceTracker` mixin on `Game` ([#3043](https://github.com/flame-engine/flame/issues/3043)). ([6270353a](https://github.com/flame-engine/flame/commit/6270353af9a6ec58ee9275ddfa6a8b26276a2c20)) + - **BREAKING** **REFACTOR**: Use HasTimeScale for Route ([#3064](https://github.com/flame-engine/flame/issues/3064)). ([30fde805](https://github.com/flame-engine/flame/commit/30fde805b4650cc802f9908f9a1149dae19669d4)) + - **BREAKING** **FIX**: Removed unused parameters from SpriteWidget ([#3074](https://github.com/flame-engine/flame/issues/3074)). ([f49d24c0](https://github.com/flame-engine/flame/commit/f49d24c02dd0d9b781926908bad1fb6dfcbda5f2)) + +#### `flame_forge2d` - `v0.17.1` + + - **FIX**: Null gravity override by Forge2dGame ([#3092](https://github.com/flame-engine/flame/issues/3092)). ([3c35d59b](https://github.com/flame-engine/flame/commit/3c35d59b4a4ec064106d24a17e748005a20d9fde)) + +#### `flame_oxygen` - `v0.2.1` + + - **FIX**: Updated oxygen dep to v0.3.1 and added removing components ([#3087](https://github.com/flame-engine/flame/issues/3087)). ([8f50c927](https://github.com/flame-engine/flame/commit/8f50c9279581999b4ff7f506682148425b248e28)) + +#### `behavior_tree` - `v0.1.1` + + - **FEAT**: Add initial version of `behavior_tree` and `flame_behavior_tree` package ([#3045](https://github.com/flame-engine/flame/issues/3045)). ([faf2df4b](https://github.com/flame-engine/flame/commit/faf2df4b8c68015a1bfbdd96f93c950cb14963ef)) + +#### `flame_behavior_tree` - `v0.1.1` + + - **FEAT**: Add initial version of `behavior_tree` and `flame_behavior_tree` package ([#3045](https://github.com/flame-engine/flame/issues/3045)). ([faf2df4b](https://github.com/flame-engine/flame/commit/faf2df4b8c68015a1bfbdd96f93c950cb14963ef)) + +#### `flame_network_assets` - `v0.3.1` + + - **FEAT**: Update http dependency on flame_network_assets ([#3084](https://github.com/flame-engine/flame/issues/3084)). ([e3e755c6](https://github.com/flame-engine/flame/commit/e3e755c6dec35f36b4a42893afeea5f64ff025b7)) + +#### `flame_sprite_fusion` - `v0.1.1` + + - **FEAT**: Add initial version of `flame_sprite_fusion` package ([#3062](https://github.com/flame-engine/flame/issues/3062)). ([1c51334e](https://github.com/flame-engine/flame/commit/1c51334e865ae7000f93832574e24707e8c9dfa0)) + +#### `flame_texturepacker` - `v3.2.0` + + - **REFACTOR**: Deprecate `fromAtlas` in favour of `atlasFromAssets` and `atlasFromStorage` ([#3098](https://github.com/flame-engine/flame/issues/3098)). ([6c8190b7](https://github.com/flame-engine/flame/commit/6c8190b7215671e7d6e1e271b6aac2a9723ec20d)) + - **FEAT**: Support for new atlas format and rotated sprites ([#3097](https://github.com/flame-engine/flame/issues/3097)). ([ed690b30](https://github.com/flame-engine/flame/commit/ed690b3048924749f829c7c44156e258bf4ab3e7)) + - **FEAT**(flame_texturepacker): Expose TexturePackerAtlas ([#3047](https://github.com/flame-engine/flame/issues/3047)). ([892052b9](https://github.com/flame-engine/flame/commit/892052b99a21a8e371c4163e1e1918fd187c6e11)) + +#### `flame_tiled` - `v1.20.0` + + - **FEAT**: Export `TileAtlas` from `flame_tiled` package ([#3049](https://github.com/flame-engine/flame/issues/3049)). ([41e9e4e3](https://github.com/flame-engine/flame/commit/41e9e4e38c643b07a3a7269b1cd8d3fa60cbeebb)) + + ## 2024-03-15 ### Changes diff --git a/doc/flame/examples/pubspec.yaml b/doc/flame/examples/pubspec.yaml index 2e87303d7a8..999a0883af2 100644 --- a/doc/flame/examples/pubspec.yaml +++ b/doc/flame/examples/pubspec.yaml @@ -8,8 +8,8 @@ environment: flutter: ">=3.19.0" dependencies: - flame: ^1.16.0 - flame_rive: ^1.10.0 + flame: ^1.17.0 + flame_rive: ^1.10.1 flutter: sdk: flutter diff --git a/doc/tutorials/klondike/app/pubspec.yaml b/doc/tutorials/klondike/app/pubspec.yaml index 988f00767bd..8d29e4ba7a0 100644 --- a/doc/tutorials/klondike/app/pubspec.yaml +++ b/doc/tutorials/klondike/app/pubspec.yaml @@ -7,7 +7,7 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter diff --git a/doc/tutorials/platformer/app/pubspec.yaml b/doc/tutorials/platformer/app/pubspec.yaml index 8040a36814a..cf088d10988 100644 --- a/doc/tutorials/platformer/app/pubspec.yaml +++ b/doc/tutorials/platformer/app/pubspec.yaml @@ -8,7 +8,7 @@ environment: flutter: ">=3.19.0" dependencies: - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter diff --git a/doc/tutorials/space_shooter/app/pubspec.yaml b/doc/tutorials/space_shooter/app/pubspec.yaml index 7b678045a16..3ad62453616 100644 --- a/doc/tutorials/space_shooter/app/pubspec.yaml +++ b/doc/tutorials/space_shooter/app/pubspec.yaml @@ -9,7 +9,7 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter diff --git a/examples/games/padracing/pubspec.yaml b/examples/games/padracing/pubspec.yaml index 71a926e882d..79f41163d12 100644 --- a/examples/games/padracing/pubspec.yaml +++ b/examples/games/padracing/pubspec.yaml @@ -8,8 +8,8 @@ environment: dependencies: collection: ^1.17.1 - flame: ^1.16.0 - flame_forge2d: ^0.17.0 + flame: ^1.17.0 + flame_forge2d: ^0.17.1 flutter: sdk: flutter google_fonts: ^4.0.4 diff --git a/examples/games/rogue_shooter/pubspec.yaml b/examples/games/rogue_shooter/pubspec.yaml index d8224be125a..820ebbeb163 100644 --- a/examples/games/rogue_shooter/pubspec.yaml +++ b/examples/games/rogue_shooter/pubspec.yaml @@ -10,7 +10,7 @@ environment: flutter: ">=3.19.0" dependencies: - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter diff --git a/examples/games/trex/pubspec.yaml b/examples/games/trex/pubspec.yaml index ce17c4e5fd1..9e701b55ac8 100644 --- a/examples/games/trex/pubspec.yaml +++ b/examples/games/trex/pubspec.yaml @@ -11,7 +11,7 @@ environment: dependencies: collection: ^1.16.0 - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter diff --git a/examples/pubspec.yaml b/examples/pubspec.yaml index 0036431dc63..d64290dcc24 100644 --- a/examples/pubspec.yaml +++ b/examples/pubspec.yaml @@ -11,15 +11,15 @@ environment: dependencies: dashbook: ^0.1.12 - flame: ^1.16.0 - flame_audio: ^2.10.0 - flame_forge2d: ^0.17.0 - flame_isolate: ^0.6.0 - flame_lottie: ^0.4.0 - flame_noise: ^0.3.0 - flame_spine: ^0.2.0 - flame_svg: ^1.10.0 - flame_tiled: ^1.19.0 + flame: ^1.17.0 + flame_audio: ^2.10.1 + flame_forge2d: ^0.17.1 + flame_isolate: ^0.6.0+1 + flame_lottie: ^0.4.0+1 + flame_noise: ^0.3.0+1 + flame_spine: ^0.2.0+1 + flame_svg: ^1.10.1 + flame_tiled: ^1.20.0 flutter: sdk: flutter google_fonts: ^4.0.4 diff --git a/packages/flame/CHANGELOG.md b/packages/flame/CHANGELOG.md index 33a2472df8e..db20dbfea5a 100644 --- a/packages/flame/CHANGELOG.md +++ b/packages/flame/CHANGELOG.md @@ -1,3 +1,24 @@ +## 1.17.0 + +> Note: This release has breaking changes. + + - **REFACTOR**: Change the ClipComponent factory Constructor to redirect Constructor ([#3089](https://github.com/flame-engine/flame/issues/3089)). ([cc035fb4](https://github.com/flame-engine/flame/commit/cc035fb4a3e123473d4e5e0db1fa0253e533bc61)) + - **FIX**: Call `render` properly from nested `FlameGame`s ([#3106](https://github.com/flame-engine/flame/issues/3106)). ([cb1e3701](https://github.com/flame-engine/flame/commit/cb1e37014bac7bb68b647234b718a37e26ad7559)) + - **FIX**: CircleHitbox should properly detect when ray is outside ([#3100](https://github.com/flame-engine/flame/issues/3100)). ([8cd9e123](https://github.com/flame-engine/flame/commit/8cd9e12319c0715def655fcf42f3976fa5f45e11)) + - **FIX**: Clamp opacity set by the `ColorEffect` to 1.0 ([#3069](https://github.com/flame-engine/flame/issues/3069)). ([9282cc38](https://github.com/flame-engine/flame/commit/9282cc38f06cd6c87ed3a1880d28d5c9f290cc04)) + - **FIX**: FutureOr return type of ComponentViewportMargin.onLoad ([#3059](https://github.com/flame-engine/flame/issues/3059)). ([72678c67](https://github.com/flame-engine/flame/commit/72678c676020480beae1d944ee687fd73eac9cf7)) + - **FIX**: Size for `SpriteComponent.fromImage` should be nullable ([#3054](https://github.com/flame-engine/flame/issues/3054)). ([2ed71a3c](https://github.com/flame-engine/flame/commit/2ed71a3c89b3c2182828f2812d8515811483f4d5)) + - **FIX**: Check for removing state while adding a child ([#3050](https://github.com/flame-engine/flame/issues/3050)). ([3a24a51d](https://github.com/flame-engine/flame/commit/3a24a51d108b1138ac3dd735956f4276f16b2974)) + - **FEAT**: Add onFinished callback to ScrollTextBoxComponent ([#3105](https://github.com/flame-engine/flame/issues/3105)). ([233cc94c](https://github.com/flame-engine/flame/commit/233cc94c557e0af2fcf7599943ddf75180abf801)) + - **FEAT**: Add `copyWith` method on the `TextBoxConfig` ([#3099](https://github.com/flame-engine/flame/issues/3099)). ([b946ba70](https://github.com/flame-engine/flame/commit/b946ba70cbfb5793a8d4d7c61d6ba029fbc303ab)) + - **FEAT**: Component tree for the devtools extension tab ([#3094](https://github.com/flame-engine/flame/issues/3094)). ([bf5d68e9](https://github.com/flame-engine/flame/commit/bf5d68e9b5147dd5e7c10d72bf9c2f705733d688)) + - **FEAT**: Add PositionComponent.toString ([#3095](https://github.com/flame-engine/flame/issues/3095)). ([b1f01986](https://github.com/flame-engine/flame/commit/b1f01986b440ac18bb35b0d76963b2c66f49ea33)) + - **FEAT**: Add SpriteBatch.replace to allow the replacement of the batch information ([#3079](https://github.com/flame-engine/flame/issues/3079)). ([bf3c282d](https://github.com/flame-engine/flame/commit/bf3c282dd669e9a32a550b86770dba7fb8472afa)) + - **FEAT**: Initial functionality of flame_devtools ([#3061](https://github.com/flame-engine/flame/issues/3061)). ([c92910c6](https://github.com/flame-engine/flame/commit/c92910c688f5dc4463e129132759102e7ebf2e36)) + - **FEAT**: Add `HasPerformanceTracker` mixin on `Game` ([#3043](https://github.com/flame-engine/flame/issues/3043)). ([6270353a](https://github.com/flame-engine/flame/commit/6270353af9a6ec58ee9275ddfa6a8b26276a2c20)) + - **BREAKING** **REFACTOR**: Use HasTimeScale for Route ([#3064](https://github.com/flame-engine/flame/issues/3064)). ([30fde805](https://github.com/flame-engine/flame/commit/30fde805b4650cc802f9908f9a1149dae19669d4)) + - **BREAKING** **FIX**: Removed unused parameters from SpriteWidget ([#3074](https://github.com/flame-engine/flame/issues/3074)). ([f49d24c0](https://github.com/flame-engine/flame/commit/f49d24c02dd0d9b781926908bad1fb6dfcbda5f2)) + ## 1.16.0 > Note: This release has breaking changes. diff --git a/packages/flame/example/pubspec.yaml b/packages/flame/example/pubspec.yaml index 0381ea19e72..f12f3f3a9bb 100644 --- a/packages/flame/example/pubspec.yaml +++ b/packages/flame/example/pubspec.yaml @@ -8,7 +8,7 @@ environment: flutter: ">=3.19.0" dependencies: - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter diff --git a/packages/flame/pubspec.yaml b/packages/flame/pubspec.yaml index 8b2c3a56ade..ea7a6fad117 100644 --- a/packages/flame/pubspec.yaml +++ b/packages/flame/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: 1.16.0 +version: 1.17.0 homepage: https://github.com/flame-engine/flame funding: - https://opencollective.com/blue-fire @@ -23,7 +23,7 @@ dev_dependencies: canvas_test: ^0.2.0 dartdoc: ^6.3.0 flame_lint: ^1.1.2 - flame_test: ^1.16.0 + flame_test: ^1.16.1 flutter_test: sdk: flutter mocktail: ^1.0.1 diff --git a/packages/flame_audio/CHANGELOG.md b/packages/flame_audio/CHANGELOG.md index ec48b276d0d..0b3c00c7e32 100644 --- a/packages/flame_audio/CHANGELOG.md +++ b/packages/flame_audio/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.10.1 + + - Update a dependency to the latest release. + ## 2.10.0 > Note: This release has breaking changes. diff --git a/packages/flame_audio/example/pubspec.yaml b/packages/flame_audio/example/pubspec.yaml index 8bdfdc7e54e..14812b927e6 100644 --- a/packages/flame_audio/example/pubspec.yaml +++ b/packages/flame_audio/example/pubspec.yaml @@ -9,8 +9,8 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.16.0 - flame_audio: ^2.10.0 + flame: ^1.17.0 + flame_audio: ^2.10.1 flutter: sdk: flutter diff --git a/packages/flame_audio/pubspec.yaml b/packages/flame_audio/pubspec.yaml index 0c9deb191a1..b3575cd2a30 100644 --- a/packages/flame_audio/pubspec.yaml +++ b/packages/flame_audio/pubspec.yaml @@ -1,7 +1,7 @@ name: flame_audio description: | Audio support for the Flame game engine, basically a thin wrapper around the audioplayers package. -version: 2.10.0 +version: 2.10.1 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_audio funding: - https://opencollective.com/blue-fire @@ -14,7 +14,7 @@ environment: dependencies: audioplayers: ^5.0.0 - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter synchronized: ^3.1.0 diff --git a/packages/flame_behavior_tree/CHANGELOG.md b/packages/flame_behavior_tree/CHANGELOG.md index e69de29bb2d..7550ca67b73 100644 --- a/packages/flame_behavior_tree/CHANGELOG.md +++ b/packages/flame_behavior_tree/CHANGELOG.md @@ -0,0 +1,4 @@ +## 0.1.1 + + - **FEAT**: Add initial version of `behavior_tree` and `flame_behavior_tree` package ([#3045](https://github.com/flame-engine/flame/issues/3045)). ([faf2df4b](https://github.com/flame-engine/flame/commit/faf2df4b8c68015a1bfbdd96f93c950cb14963ef)) + diff --git a/packages/flame_behavior_tree/behavior_tree/CHANGELOG.md b/packages/flame_behavior_tree/behavior_tree/CHANGELOG.md index e69de29bb2d..7550ca67b73 100644 --- a/packages/flame_behavior_tree/behavior_tree/CHANGELOG.md +++ b/packages/flame_behavior_tree/behavior_tree/CHANGELOG.md @@ -0,0 +1,4 @@ +## 0.1.1 + + - **FEAT**: Add initial version of `behavior_tree` and `flame_behavior_tree` package ([#3045](https://github.com/flame-engine/flame/issues/3045)). ([faf2df4b](https://github.com/flame-engine/flame/commit/faf2df4b8c68015a1bfbdd96f93c950cb14963ef)) + diff --git a/packages/flame_behavior_tree/behavior_tree/pubspec.yaml b/packages/flame_behavior_tree/behavior_tree/pubspec.yaml index 840acab01b9..05c2b0b552b 100644 --- a/packages/flame_behavior_tree/behavior_tree/pubspec.yaml +++ b/packages/flame_behavior_tree/behavior_tree/pubspec.yaml @@ -1,6 +1,6 @@ name: behavior_tree description: A behavior tree implementation written in dart. This package is designed to be used for implementing AI in games. -version: 0.1.0 +version: 0.1.1 repository: https://github.com/flame-engine/flame/tree/main/packages/flame_behavior_tree/behavior_tree funding: - https://opencollective.com/blue-fire diff --git a/packages/flame_behavior_tree/example/pubspec.yaml b/packages/flame_behavior_tree/example/pubspec.yaml index 4155b245c6a..6c7919ced9c 100644 --- a/packages/flame_behavior_tree/example/pubspec.yaml +++ b/packages/flame_behavior_tree/example/pubspec.yaml @@ -11,8 +11,8 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.16.0 - flame_behavior_tree: ^0.1.0 + flame: ^1.17.0 + flame_behavior_tree: ^0.1.1 flutter: sdk: flutter diff --git a/packages/flame_behavior_tree/pubspec.yaml b/packages/flame_behavior_tree/pubspec.yaml index 9975ab1d023..4cc63f4275f 100644 --- a/packages/flame_behavior_tree/pubspec.yaml +++ b/packages/flame_behavior_tree/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_behavior_tree description: A bridge package that integrates behavior_tree package with flame. -version: 0.1.0 +version: 0.1.1 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_behavior_tree funding: - https://opencollective.com/blue-fire @@ -12,14 +12,14 @@ environment: flutter: ">=3.19.0" dependencies: - behavior_tree: ^1.0.0 - flame: ^1.16.0 + behavior_tree: ^0.1.1 + flame: ^1.17.0 flutter: sdk: flutter dev_dependencies: flame_lint: ^1.1.2 - flame_test: ^1.16.0 + flame_test: ^1.16.1 flutter_test: sdk: flutter mocktail: ^1.0.1 diff --git a/packages/flame_bloc/CHANGELOG.md b/packages/flame_bloc/CHANGELOG.md index 8088f6e2735..f1dc2e41789 100644 --- a/packages/flame_bloc/CHANGELOG.md +++ b/packages/flame_bloc/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.11.1 + + - Update a dependency to the latest release. + ## 1.11.0 > Note: This release has breaking changes. diff --git a/packages/flame_bloc/example/pubspec.yaml b/packages/flame_bloc/example/pubspec.yaml index 3085ad3b533..5a05669c370 100644 --- a/packages/flame_bloc/example/pubspec.yaml +++ b/packages/flame_bloc/example/pubspec.yaml @@ -11,8 +11,8 @@ environment: dependencies: equatable: ^2.0.5 - flame: ^1.16.0 - flame_bloc: ^1.11.0 + flame: ^1.17.0 + flame_bloc: ^1.11.1 flutter: sdk: flutter flutter_bloc: ^8.1.2 diff --git a/packages/flame_bloc/pubspec.yaml b/packages/flame_bloc/pubspec.yaml index 9af93423d8f..23c42c8293e 100644 --- a/packages/flame_bloc/pubspec.yaml +++ b/packages/flame_bloc/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_bloc description: Integration for the Bloc state management library to Flame games. -version: 1.11.0 +version: 1.11.1 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_bloc funding: - https://opencollective.com/blue-fire @@ -13,7 +13,7 @@ environment: dependencies: bloc: ^8.1.1 - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter flutter_bloc: ^8.1.2 @@ -22,7 +22,7 @@ dependencies: dev_dependencies: dartdoc: ^6.3.0 flame_lint: ^1.1.2 - flame_test: ^1.16.0 + flame_test: ^1.16.1 flutter_lints: ^2.0.1 flutter_test: sdk: flutter diff --git a/packages/flame_devtools/pubspec.yaml b/packages/flame_devtools/pubspec.yaml index 26b5d7c74ad..1e1eb1e5ac2 100644 --- a/packages/flame_devtools/pubspec.yaml +++ b/packages/flame_devtools/pubspec.yaml @@ -10,7 +10,7 @@ dependencies: animated_tree_view: ^2.2.0 devtools_app_shared: ^0.0.10 devtools_extensions: ^0.0.14 - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter diff --git a/packages/flame_fire_atlas/CHANGELOG.md b/packages/flame_fire_atlas/CHANGELOG.md index ce92374c389..4df75eabae5 100644 --- a/packages/flame_fire_atlas/CHANGELOG.md +++ b/packages/flame_fire_atlas/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.5.1 + + - Update a dependency to the latest release. + ## 1.5.0 > Note: This release has breaking changes. diff --git a/packages/flame_fire_atlas/example/pubspec.yaml b/packages/flame_fire_atlas/example/pubspec.yaml index 60b1dc1b23a..b328919063c 100644 --- a/packages/flame_fire_atlas/example/pubspec.yaml +++ b/packages/flame_fire_atlas/example/pubspec.yaml @@ -9,8 +9,8 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.16.0 - flame_fire_atlas: ^1.5.0 + flame: ^1.17.0 + flame_fire_atlas: ^1.5.1 flutter: sdk: flutter diff --git a/packages/flame_fire_atlas/pubspec.yaml b/packages/flame_fire_atlas/pubspec.yaml index 531de83ea10..706024cefc0 100644 --- a/packages/flame_fire_atlas/pubspec.yaml +++ b/packages/flame_fire_atlas/pubspec.yaml @@ -1,7 +1,7 @@ name: flame_fire_atlas description: Easy to use texture atlases for the flame engine created with the fire atlas editor -version: 1.5.0 +version: 1.5.1 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_fire_atlas funding: - https://opencollective.com/blue-fire @@ -14,7 +14,7 @@ environment: dependencies: archive: ^3.3.9 - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter diff --git a/packages/flame_forge2d/CHANGELOG.md b/packages/flame_forge2d/CHANGELOG.md index 21d0415fb2e..e39ec195267 100644 --- a/packages/flame_forge2d/CHANGELOG.md +++ b/packages/flame_forge2d/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.17.1 + + - **FIX**: Null gravity override by Forge2dGame ([#3092](https://github.com/flame-engine/flame/issues/3092)). ([3c35d59b](https://github.com/flame-engine/flame/commit/3c35d59b4a4ec064106d24a17e748005a20d9fde)) + ## 0.17.0 > Note: This release has breaking changes. diff --git a/packages/flame_forge2d/example/pubspec.yaml b/packages/flame_forge2d/example/pubspec.yaml index e76a0eb0628..e05a763a334 100644 --- a/packages/flame_forge2d/example/pubspec.yaml +++ b/packages/flame_forge2d/example/pubspec.yaml @@ -11,8 +11,8 @@ environment: dependencies: dashbook: ^0.1.12 - flame: ^1.16.0 - flame_forge2d: ^0.17.0 + flame: ^1.17.0 + flame_forge2d: ^0.17.1 flutter: sdk: flutter diff --git a/packages/flame_forge2d/pubspec.yaml b/packages/flame_forge2d/pubspec.yaml index 9980a3c5ddc..e2df5ca2c41 100644 --- a/packages/flame_forge2d/pubspec.yaml +++ b/packages/flame_forge2d/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_forge2d description: Forge2D (Box2D) support for the Flame game engine. This uses the forge2d package and provides wrappers and components to be used inside Flame. -version: 0.17.0 +version: 0.17.1 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_forge2d funding: - https://opencollective.com/blue-fire @@ -12,7 +12,7 @@ environment: flutter: ">=3.19.0" dependencies: - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter forge2d: ">=0.12.2 <0.13.0" @@ -20,7 +20,7 @@ dependencies: dev_dependencies: dartdoc: ^6.3.0 flame_lint: ^1.1.2 - flame_test: ^1.16.0 + flame_test: ^1.16.1 flutter_test: sdk: flutter mocktail: ^1.0.1 diff --git a/packages/flame_isolate/CHANGELOG.md b/packages/flame_isolate/CHANGELOG.md index 262c1317599..53f4008ff3d 100644 --- a/packages/flame_isolate/CHANGELOG.md +++ b/packages/flame_isolate/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.6.0+1 + + - Update a dependency to the latest release. + ## 0.6.0 > Note: This release has breaking changes. diff --git a/packages/flame_isolate/example/pubspec.yaml b/packages/flame_isolate/example/pubspec.yaml index 9ef5d97785d..12089ef563f 100755 --- a/packages/flame_isolate/example/pubspec.yaml +++ b/packages/flame_isolate/example/pubspec.yaml @@ -11,8 +11,8 @@ environment: dependencies: collection: ^1.18.0 - flame: ^1.16.0 - flame_isolate: ^0.6.0 + flame: ^1.17.0 + flame_isolate: ^0.6.0+1 flutter: sdk: flutter quiver: ^3.2.1 diff --git a/packages/flame_isolate/pubspec.yaml b/packages/flame_isolate/pubspec.yaml index cd531579cbc..5df38dd32ee 100644 --- a/packages/flame_isolate/pubspec.yaml +++ b/packages/flame_isolate/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_isolate description: Flame wrapper for integral_isolates making multi-threading easy in Flame -version: 0.6.0 +version: 0.6.0+1 repository: https://github.com/flame-engine/flame/blob/main/packages/flame_isolate environment: @@ -8,14 +8,14 @@ environment: flutter: ">=3.19.0" dependencies: - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter integral_isolates: ^0.5.1 dev_dependencies: flame_lint: ^1.1.2 - flame_test: ^1.16.0 + flame_test: ^1.16.1 flutter_test: sdk: flutter test: any diff --git a/packages/flame_jenny/pubspec.yaml b/packages/flame_jenny/pubspec.yaml index 0ba9fd71b4b..32b40b4c535 100644 --- a/packages/flame_jenny/pubspec.yaml +++ b/packages/flame_jenny/pubspec.yaml @@ -14,7 +14,7 @@ environment: dependencies: collection: ^1.17.1 - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter jenny: ^1.3.0 diff --git a/packages/flame_lottie/CHANGELOG.md b/packages/flame_lottie/CHANGELOG.md index 6ef21948a7a..c352de7c22d 100644 --- a/packages/flame_lottie/CHANGELOG.md +++ b/packages/flame_lottie/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.0+1 + + - Update a dependency to the latest release. + ## 0.4.0 > Note: This release has breaking changes. diff --git a/packages/flame_lottie/example/pubspec.yaml b/packages/flame_lottie/example/pubspec.yaml index 6d47fe315d4..c06e2f93d2f 100644 --- a/packages/flame_lottie/example/pubspec.yaml +++ b/packages/flame_lottie/example/pubspec.yaml @@ -8,8 +8,8 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.16.0 - flame_lottie: ^0.4.0 + flame: ^1.17.0 + flame_lottie: ^0.4.0+1 flutter: sdk: flutter lottie: diff --git a/packages/flame_lottie/pubspec.yaml b/packages/flame_lottie/pubspec.yaml index 932941ebdfd..c21a661b35f 100644 --- a/packages/flame_lottie/pubspec.yaml +++ b/packages/flame_lottie/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_lottie description: Flame wrapper for Lottie by AirBnB. This package implements a bridge between Lottie and Flame, allowing to load and display Lottie animations. -version: 0.4.0 +version: 0.4.0+1 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_lottie funding: - https://opencollective.com/blue-fire @@ -12,14 +12,14 @@ environment: flutter: ">=3.19.0" dependencies: - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter lottie: ^2.3.2 dev_dependencies: flame_lint: ^1.1.2 - flame_test: ^1.16.0 + flame_test: ^1.16.1 flutter_test: sdk: flutter lint: ^2.1.2 diff --git a/packages/flame_markdown/CHANGELOG.md b/packages/flame_markdown/CHANGELOG.md index 70f81bc17a2..2f6ad08dc9f 100644 --- a/packages/flame_markdown/CHANGELOG.md +++ b/packages/flame_markdown/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.0+1 + + - Update a dependency to the latest release. + ## 0.2.0 > Note: This release has breaking changes. diff --git a/packages/flame_markdown/example/pubspec.yaml b/packages/flame_markdown/example/pubspec.yaml index 69b7f04d1a4..0f70d8e750b 100644 --- a/packages/flame_markdown/example/pubspec.yaml +++ b/packages/flame_markdown/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.16.0 - flame_markdown: ^0.2.0 + flame: ^1.17.0 + flame_markdown: ^0.2.0+1 flutter: sdk: flutter diff --git a/packages/flame_markdown/pubspec.yaml b/packages/flame_markdown/pubspec.yaml index 244e0222c78..b8d47354009 100644 --- a/packages/flame_markdown/pubspec.yaml +++ b/packages/flame_markdown/pubspec.yaml @@ -1,7 +1,7 @@ name: flame_markdown description: | Markdown support for the Flame game engine, bridging the markdown package into Flame's text rendering pipeline. -version: 0.2.0 +version: 0.2.0+1 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_markdown funding: - https://opencollective.com/blue-fire @@ -13,7 +13,7 @@ environment: flutter: ">=3.19.0" dependencies: - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter markdown: ^7.1.1 diff --git a/packages/flame_network_assets/CHANGELOG.md b/packages/flame_network_assets/CHANGELOG.md index a4896e9a5d6..d0a297e8e14 100644 --- a/packages/flame_network_assets/CHANGELOG.md +++ b/packages/flame_network_assets/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.1 + + - **FEAT**: Update http dependency on flame_network_assets ([#3084](https://github.com/flame-engine/flame/issues/3084)). ([e3e755c6](https://github.com/flame-engine/flame/commit/e3e755c6dec35f36b4a42893afeea5f64ff025b7)) + ## 0.3.0 > Note: This release has breaking changes. diff --git a/packages/flame_network_assets/example/pubspec.yaml b/packages/flame_network_assets/example/pubspec.yaml index c15202c0765..d4c265e07d3 100644 --- a/packages/flame_network_assets/example/pubspec.yaml +++ b/packages/flame_network_assets/example/pubspec.yaml @@ -8,8 +8,8 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.16.0 - flame_network_assets: ^0.3.0 + flame: ^1.17.0 + flame_network_assets: ^0.3.1 flutter: sdk: flutter diff --git a/packages/flame_network_assets/pubspec.yaml b/packages/flame_network_assets/pubspec.yaml index aba2aeee348..bf4d4d8e0a3 100644 --- a/packages/flame_network_assets/pubspec.yaml +++ b/packages/flame_network_assets/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_network_assets description: Network assets support for Flame. -version: 0.3.0 +version: 0.3.1 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_network_assets funding: - https://opencollective.com/blue-fire @@ -13,7 +13,7 @@ environment: dependencies: dev: ^1.0.0 - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter http: ^1.2.1 diff --git a/packages/flame_noise/CHANGELOG.md b/packages/flame_noise/CHANGELOG.md index 52e6eba141b..1a5c428d226 100644 --- a/packages/flame_noise/CHANGELOG.md +++ b/packages/flame_noise/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.0+1 + + - Update a dependency to the latest release. + ## 0.3.0 > Note: This release has breaking changes. diff --git a/packages/flame_noise/pubspec.yaml b/packages/flame_noise/pubspec.yaml index d2d798bca68..1b70dbde530 100644 --- a/packages/flame_noise/pubspec.yaml +++ b/packages/flame_noise/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_noise description: Integrate the fast_noise package into Flame -version: 0.3.0 +version: 0.3.0+1 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_noise funding: - https://opencollective.com/blue-fire @@ -13,12 +13,12 @@ environment: dependencies: fast_noise: ^2.0.0 - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter dev_dependencies: dartdoc: ^6.3.0 flame_lint: ^1.1.2 - flame_test: ^1.16.0 + flame_test: ^1.16.1 test: any \ No newline at end of file diff --git a/packages/flame_oxygen/CHANGELOG.md b/packages/flame_oxygen/CHANGELOG.md index c153f8c528b..2c46d1a87b9 100644 --- a/packages/flame_oxygen/CHANGELOG.md +++ b/packages/flame_oxygen/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.1 + + - **FIX**: Updated oxygen dep to v0.3.1 and added removing components ([#3087](https://github.com/flame-engine/flame/issues/3087)). ([8f50c927](https://github.com/flame-engine/flame/commit/8f50c9279581999b4ff7f506682148425b248e28)) + ## 0.2.0 > Note: This release has breaking changes. diff --git a/packages/flame_oxygen/example/pubspec.yaml b/packages/flame_oxygen/example/pubspec.yaml index 28dfd91e20e..92645edece2 100644 --- a/packages/flame_oxygen/example/pubspec.yaml +++ b/packages/flame_oxygen/example/pubspec.yaml @@ -9,8 +9,8 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.16.0 - flame_oxygen: ^0.2.0 + flame: ^1.17.0 + flame_oxygen: ^0.2.1 flutter: sdk: flutter diff --git a/packages/flame_oxygen/pubspec.yaml b/packages/flame_oxygen/pubspec.yaml index 436e2ebe31a..62e8f88e117 100644 --- a/packages/flame_oxygen/pubspec.yaml +++ b/packages/flame_oxygen/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_oxygen description: Integrate the Oxygen ECS with the Flame Engine. -version: 0.2.0 +version: 0.2.1 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_oxygen funding: - https://opencollective.com/blue-fire @@ -12,7 +12,7 @@ environment: flutter: ">=3.19.0" dependencies: - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter oxygen: ^0.3.1 diff --git a/packages/flame_rive/CHANGELOG.md b/packages/flame_rive/CHANGELOG.md index 94b965c7d07..8cb4f4f004f 100644 --- a/packages/flame_rive/CHANGELOG.md +++ b/packages/flame_rive/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.10.1 + + - Update a dependency to the latest release. + ## 1.10.0 > Note: This release has breaking changes. diff --git a/packages/flame_rive/example/pubspec.yaml b/packages/flame_rive/example/pubspec.yaml index b5be3cc310f..581d3eabb32 100644 --- a/packages/flame_rive/example/pubspec.yaml +++ b/packages/flame_rive/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.16.0 - flame_rive: ^1.10.0 + flame: ^1.17.0 + flame_rive: ^1.10.1 flutter: sdk: flutter rive: ^0.12.3 diff --git a/packages/flame_rive/pubspec.yaml b/packages/flame_rive/pubspec.yaml index e8ec5ccae95..6cee0150d70 100644 --- a/packages/flame_rive/pubspec.yaml +++ b/packages/flame_rive/pubspec.yaml @@ -1,7 +1,7 @@ name: flame_rive description: Rive support for the Flame game engine. This uses the rive package and provides wrappers and components to be used inside Flame. homepage: https://github.com/flame-engine/flame -version: 1.10.0 +version: 1.10.1 funding: - https://opencollective.com/blue-fire - https://github.com/sponsors/bluefireteam @@ -12,7 +12,7 @@ environment: flutter: ">=3.19.0" dependencies: - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter rive: ^0.12.3 @@ -20,6 +20,6 @@ dependencies: dev_dependencies: dartdoc: ^6.3.0 flame_lint: ^1.1.2 - flame_test: ^1.16.0 + flame_test: ^1.16.1 flutter_test: sdk: flutter diff --git a/packages/flame_riverpod/CHANGELOG.md b/packages/flame_riverpod/CHANGELOG.md index ec1300be3d0..90251e9116c 100644 --- a/packages/flame_riverpod/CHANGELOG.md +++ b/packages/flame_riverpod/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.4.1 + + - Update a dependency to the latest release. + ## 5.4.0 - **FIX**: Resolve logic error with assignment of ComponentRef's game property in flame_riverpod ([#3082](https://github.com/flame-engine/flame/issues/3082)). ([b44011fd](https://github.com/flame-engine/flame/commit/b44011fd714ec5919de5407f53d0772f31ed1a13)) diff --git a/packages/flame_riverpod/example/pubspec.yaml b/packages/flame_riverpod/example/pubspec.yaml index 1eeef2ee4db..52d49b14d10 100644 --- a/packages/flame_riverpod/example/pubspec.yaml +++ b/packages/flame_riverpod/example/pubspec.yaml @@ -5,8 +5,8 @@ version: 1.0.0+1 environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.16.0 - flame_riverpod: ^5.4.0 + flame: ^1.17.0 + flame_riverpod: ^5.4.1 flutter: sdk: flutter flutter_riverpod: ^2.5.1 diff --git a/packages/flame_riverpod/pubspec.yaml b/packages/flame_riverpod/pubspec.yaml index ea1598cefd9..2b0571ce8d4 100644 --- a/packages/flame_riverpod/pubspec.yaml +++ b/packages/flame_riverpod/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_riverpod description: Helpers for using Riverpod - a reactive caching and data-binding framework, in conjunction with Flame. -version: 5.4.0 +version: 5.4.1 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_riverpod funding: - https://opencollective.com/blue-fire @@ -12,7 +12,7 @@ environment: flutter: ">=3.19.0" dependencies: - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter flutter_riverpod: ^2.5.1 diff --git a/packages/flame_spine/CHANGELOG.md b/packages/flame_spine/CHANGELOG.md index 9cf9f2cd0d7..fd2ad0fb7e4 100644 --- a/packages/flame_spine/CHANGELOG.md +++ b/packages/flame_spine/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.0+1 + + - Update a dependency to the latest release. + ## 0.2.0 > Note: This release has breaking changes. diff --git a/packages/flame_spine/example/pubspec.yaml b/packages/flame_spine/example/pubspec.yaml index e0f75aa6e6d..aa6905ab0ef 100644 --- a/packages/flame_spine/example/pubspec.yaml +++ b/packages/flame_spine/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.16.0 - flame_spine: ^0.2.0 + flame: ^1.17.0 + flame_spine: ^0.2.0+1 flutter: sdk: flutter diff --git a/packages/flame_spine/pubspec.yaml b/packages/flame_spine/pubspec.yaml index a8e4ee33e19..eed8d287e8c 100644 --- a/packages/flame_spine/pubspec.yaml +++ b/packages/flame_spine/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_spine description: Spine support for the Flame game engine. This uses the spine_flutter package and provides wrappers and components to be used inside Flame. -version: 0.2.0 +version: 0.2.0+1 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_sprine funding: - https://opencollective.com/blue-fire @@ -13,7 +13,7 @@ environment: dependencies: collection: ^1.17.1 - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter spine_flutter: ^4.2.18 diff --git a/packages/flame_sprite_fusion/CHANGELOG.md b/packages/flame_sprite_fusion/CHANGELOG.md index e69de29bb2d..1142373de2d 100644 --- a/packages/flame_sprite_fusion/CHANGELOG.md +++ b/packages/flame_sprite_fusion/CHANGELOG.md @@ -0,0 +1,4 @@ +## 0.1.1 + + - **FEAT**: Add initial version of `flame_sprite_fusion` package ([#3062](https://github.com/flame-engine/flame/issues/3062)). ([1c51334e](https://github.com/flame-engine/flame/commit/1c51334e865ae7000f93832574e24707e8c9dfa0)) + diff --git a/packages/flame_sprite_fusion/example/pubspec.yaml b/packages/flame_sprite_fusion/example/pubspec.yaml index 064206fadba..2c83b2bdad2 100644 --- a/packages/flame_sprite_fusion/example/pubspec.yaml +++ b/packages/flame_sprite_fusion/example/pubspec.yaml @@ -9,8 +9,8 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.16.0 - flame_sprite_fusion: ^0.1.0 + flame: ^1.17.0 + flame_sprite_fusion: ^0.1.1 flutter: sdk: flutter diff --git a/packages/flame_sprite_fusion/pubspec.yaml b/packages/flame_sprite_fusion/pubspec.yaml index 343bbfaefcf..d4d7bd68d6e 100644 --- a/packages/flame_sprite_fusion/pubspec.yaml +++ b/packages/flame_sprite_fusion/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_sprite_fusion description: "Sprite Fusion support for the Flame game engine. This package parses and renders tilemaps exported from Sprite Fusion tool." -version: 0.1.0 +version: 0.1.1 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_sprite_fusion funding: - https://opencollective.com/blue-fire @@ -12,12 +12,12 @@ environment: flutter: ">=3.19.0" dependencies: - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter dev_dependencies: flame_lint: ^1.1.2 - flame_test: ^1.16.0 + flame_test: ^1.16.1 flutter_test: sdk: flutter diff --git a/packages/flame_studio/pubspec.yaml b/packages/flame_studio/pubspec.yaml index 72875002ab8..60457ecfbaa 100644 --- a/packages/flame_studio/pubspec.yaml +++ b/packages/flame_studio/pubspec.yaml @@ -14,7 +14,7 @@ environment: dependencies: collection: ^1.17.1 - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter flutter_riverpod: ^2.3.6 diff --git a/packages/flame_svg/CHANGELOG.md b/packages/flame_svg/CHANGELOG.md index d2b4029f414..c1221a7fa03 100644 --- a/packages/flame_svg/CHANGELOG.md +++ b/packages/flame_svg/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.10.1 + + - Update a dependency to the latest release. + ## 1.10.0 > Note: This release has breaking changes. diff --git a/packages/flame_svg/example/pubspec.yaml b/packages/flame_svg/example/pubspec.yaml index d25a2647efd..bf8762b004e 100644 --- a/packages/flame_svg/example/pubspec.yaml +++ b/packages/flame_svg/example/pubspec.yaml @@ -9,8 +9,8 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.16.0 - flame_svg: ^1.10.0 + flame: ^1.17.0 + flame_svg: ^1.10.1 flutter: sdk: flutter diff --git a/packages/flame_svg/pubspec.yaml b/packages/flame_svg/pubspec.yaml index cefc820a026..6e210c0bb0b 100644 --- a/packages/flame_svg/pubspec.yaml +++ b/packages/flame_svg/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_svg description: Package to add SVG rendering support for the Flame game engine -version: 1.10.0 +version: 1.10.1 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_svg funding: - https://opencollective.com/blue-fire @@ -12,7 +12,7 @@ environment: flutter: ">=3.19.0" dependencies: - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter flutter_svg: ^2.0.5 diff --git a/packages/flame_test/CHANGELOG.md b/packages/flame_test/CHANGELOG.md index 29c2c0466e8..ab8305e53c1 100644 --- a/packages/flame_test/CHANGELOG.md +++ b/packages/flame_test/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.16.1 + + - Update a dependency to the latest release. + ## 1.16.0 > Note: This release has breaking changes. diff --git a/packages/flame_test/example/pubspec.yaml b/packages/flame_test/example/pubspec.yaml index 8a7be8f7653..f229cf9f715 100644 --- a/packages/flame_test/example/pubspec.yaml +++ b/packages/flame_test/example/pubspec.yaml @@ -8,13 +8,13 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter dev_dependencies: flame_lint: ^1.1.2 - flame_test: ^1.16.0 + flame_test: ^1.16.1 flutter_test: sdk: flutter test: any diff --git a/packages/flame_test/pubspec.yaml b/packages/flame_test/pubspec.yaml index 8decb077df1..c2a5d7337d7 100644 --- a/packages/flame_test/pubspec.yaml +++ b/packages/flame_test/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_test description: A package with classes to help testing applications using Flame -version: 1.16.0 +version: 1.16.1 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_test funding: - https://opencollective.com/blue-fire @@ -12,7 +12,7 @@ environment: flutter: ">=3.19.0" dependencies: - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter flutter_test: diff --git a/packages/flame_texturepacker/CHANGELOG.md b/packages/flame_texturepacker/CHANGELOG.md index 4c282a3f5d7..5e8e5800c11 100644 --- a/packages/flame_texturepacker/CHANGELOG.md +++ b/packages/flame_texturepacker/CHANGELOG.md @@ -1,3 +1,9 @@ +## 3.2.0 + + - **REFACTOR**: Deprecate `fromAtlas` in favour of `atlasFromAssets` and `atlasFromStorage` ([#3098](https://github.com/flame-engine/flame/issues/3098)). ([6c8190b7](https://github.com/flame-engine/flame/commit/6c8190b7215671e7d6e1e271b6aac2a9723ec20d)) + - **FEAT**: Support for new atlas format and rotated sprites ([#3097](https://github.com/flame-engine/flame/issues/3097)). ([ed690b30](https://github.com/flame-engine/flame/commit/ed690b3048924749f829c7c44156e258bf4ab3e7)) + - **FEAT**(flame_texturepacker): Expose TexturePackerAtlas ([#3047](https://github.com/flame-engine/flame/issues/3047)). ([892052b9](https://github.com/flame-engine/flame/commit/892052b99a21a8e371c4163e1e1918fd187c6e11)) + ## 3.1.0 > Note: This release has breaking changes. diff --git a/packages/flame_texturepacker/example/pubspec.yaml b/packages/flame_texturepacker/example/pubspec.yaml index 34bddea64e7..30753c9d0c3 100644 --- a/packages/flame_texturepacker/example/pubspec.yaml +++ b/packages/flame_texturepacker/example/pubspec.yaml @@ -8,8 +8,8 @@ environment: flutter: ">=3.19.0" dependencies: - flame: ^1.16.0 - flame_texturepacker: ^3.1.0 + flame: ^1.17.0 + flame_texturepacker: ^3.2.0 flutter: sdk: flutter diff --git a/packages/flame_texturepacker/pubspec.yaml b/packages/flame_texturepacker/pubspec.yaml index d41ec7267a2..19be867b8f8 100644 --- a/packages/flame_texturepacker/pubspec.yaml +++ b/packages/flame_texturepacker/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_texturepacker description: A simple plugin for the Flame Engine to import spritesheets generated by the TexturePacker tool. -version: 3.1.0 +version: 3.2.0 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_texturepacker funding: - https://opencollective.com/blue-fire @@ -13,7 +13,7 @@ environment: dependencies: collection: ^1.17.1 - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter diff --git a/packages/flame_tiled/CHANGELOG.md b/packages/flame_tiled/CHANGELOG.md index 6699c920c4a..7d9bc3db7d1 100644 --- a/packages/flame_tiled/CHANGELOG.md +++ b/packages/flame_tiled/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.20.0 + + - **FEAT**: Export `TileAtlas` from `flame_tiled` package ([#3049](https://github.com/flame-engine/flame/issues/3049)). ([41e9e4e3](https://github.com/flame-engine/flame/commit/41e9e4e38c643b07a3a7269b1cd8d3fa60cbeebb)) + ## 1.19.0 > Note: This release has breaking changes. diff --git a/packages/flame_tiled/example/pubspec.yaml b/packages/flame_tiled/example/pubspec.yaml index a71b1ff4c9d..5a02a6c64b2 100644 --- a/packages/flame_tiled/example/pubspec.yaml +++ b/packages/flame_tiled/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: sdk: ">=3.0.0 <4.0.0" dependencies: - flame: ^1.16.0 - flame_tiled: ^1.19.0 + flame: ^1.17.0 + flame_tiled: ^1.20.0 flutter: sdk: flutter diff --git a/packages/flame_tiled/pubspec.yaml b/packages/flame_tiled/pubspec.yaml index 2d790dd575d..392102f1ff2 100644 --- a/packages/flame_tiled/pubspec.yaml +++ b/packages/flame_tiled/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_tiled description: Tiled support for the Flame game engine. This uses the tiled package and provides wrappers and components to be used inside Flame. -version: 1.19.0 +version: 1.20.0 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_tiled funding: - https://opencollective.com/blue-fire @@ -13,7 +13,7 @@ environment: dependencies: collection: ^1.17.1 - flame: ^1.16.0 + flame: ^1.17.0 flutter: sdk: flutter meta: ^1.9.1 From a717bcb475a5604c5d8c66a3a5ac53f0dc173109 Mon Sep 17 00:00:00 2001 From: Sai Rajendra Immadi Date: Sat, 30 Mar 2024 00:53:05 +0530 Subject: [PATCH 42/79] docs: Upgrade dashbook version (#3109) This PR upgrades the `dashbook` to the latest version in the examples. After upgrading, the links related to this are also being updated in the docs. It also removes `dashbook` from dependencies of examples in `forge2d` as it no longer uses it. --- doc/flame/collision_detection.md | 8 ++++---- doc/flame/components.md | 2 +- doc/flame/inputs/other_inputs.md | 2 +- examples/pubspec.yaml | 2 +- packages/flame_forge2d/example/pubspec.yaml | 1 - 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/doc/flame/collision_detection.md b/doc/flame/collision_detection.md index 04574f72848..e22874fee3d 100644 --- a/doc/flame/collision_detection.md +++ b/doc/flame/collision_detection.md @@ -630,7 +630,7 @@ need some of the following things (since it is simpler to not involve Forge2D): ## Examples -- [https://examples.flame-engine.org/#/Collision%20Detection_Collidable%20AnimationComponent] -- [https://examples.flame-engine.org/#/Collision%20Detection_Circles] -- [https://examples.flame-engine.org/#/Collision%20Detection_Multiple%20shapes] -- [https://github.com/flame-engine/flame/tree/main/examples/lib/stories/collision_detection] +- [Collidable AnimationComponent](https://examples.flame-engine.org/#/Collision_Detection_Collidable_AnimationComponent) +- [Circles](https://examples.flame-engine.org/#/Collision_Detection_Circles) +- [Multiple shapes](https://examples.flame-engine.org/#/Collision_Detection_Multiple_shapes) +- [More Examples](https://github.com/flame-engine/flame/tree/main/examples/lib/stories/collision_detection) diff --git a/doc/flame/components.md b/doc/flame/components.md index 5e71512fec9..2285e269938 100644 --- a/doc/flame/components.md +++ b/doc/flame/components.md @@ -1254,7 +1254,7 @@ This is an example of how a quarter-length map looks like: Flame's Example app contains a more in-depth example, featuring how to parse coordinates to make a selector. The code can be found [here](https://github.com/flame-engine/flame/blob/main/examples/lib/stories/rendering/isometric_tile_map_example.dart), -and a live version can be seen [here](https://examples.flame-engine.org/#/Rendering_Isometric%20Tile%20Map). +and a live version can be seen [here](https://examples.flame-engine.org/#/Rendering_Isometric_Tile_Map). ## NineTileBoxComponent diff --git a/doc/flame/inputs/other_inputs.md b/doc/flame/inputs/other_inputs.md index 88f46b0b6c8..10636cf6331 100644 --- a/doc/flame/inputs/other_inputs.md +++ b/doc/flame/inputs/other_inputs.md @@ -96,7 +96,7 @@ And it can be seen running [here](https://examples.flame-engine.org/#/Input_Joys There is also a more advanced example [here](https://github.com/flame-engine/flame/blob/main/examples/lib/stories/input/joystick_advanced_example.dart) -which is running [here](https://examples.flame-engine.org/#/Input_Joystick%20Advanced). +which is running [here](https://examples.flame-engine.org/#/Input_Joystick_Advanced). ## HudButtonComponent diff --git a/examples/pubspec.yaml b/examples/pubspec.yaml index d64290dcc24..c01c71e1345 100644 --- a/examples/pubspec.yaml +++ b/examples/pubspec.yaml @@ -10,7 +10,7 @@ environment: flutter: ">=3.19.0" dependencies: - dashbook: ^0.1.12 + dashbook: ^0.1.14 flame: ^1.17.0 flame_audio: ^2.10.1 flame_forge2d: ^0.17.1 diff --git a/packages/flame_forge2d/example/pubspec.yaml b/packages/flame_forge2d/example/pubspec.yaml index e05a763a334..90b28f9d50f 100644 --- a/packages/flame_forge2d/example/pubspec.yaml +++ b/packages/flame_forge2d/example/pubspec.yaml @@ -10,7 +10,6 @@ environment: flutter: ">=3.19.0" dependencies: - dashbook: ^0.1.12 flame: ^1.17.0 flame_forge2d: ^0.17.1 flutter: From a95d7df606bd2119423cc8a7ae51cacfb7b4dbed Mon Sep 17 00:00:00 2001 From: Lucas Lima Date: Mon, 1 Apr 2024 11:14:52 -0300 Subject: [PATCH 43/79] feat: Add custom long tap delay (#3110) Currently `longTapDelay` is hardcoded to 300ms. This is good for most of the games. But same games required custom long press values. This PR allows it. --------- Co-authored-by: Lukas Klingsbo --- doc/flame/inputs/tap_events.md | 4 +++ .../multi_tap_dispatcher.dart | 3 ++- .../game_mixins/multi_touch_tap_detector.dart | 3 ++- packages/flame/lib/src/events/tap_config.dart | 27 +++++++++++++++++++ .../flame/test/events/tap_config_test.dart | 20 ++++++++++++++ 5 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 packages/flame/lib/src/events/tap_config.dart create mode 100644 packages/flame/test/events/tap_config_test.dart diff --git a/doc/flame/inputs/tap_events.md b/doc/flame/inputs/tap_events.md index 2718d15cc51..c863e93d14b 100644 --- a/doc/flame/inputs/tap_events.md +++ b/doc/flame/inputs/tap_events.md @@ -62,6 +62,10 @@ in `MultiTapDispatcher`), "long tap" will be triggered. This event invokes the `void onLongTapDown(TapDownEvent)` handler on those components that previously received the `onTapDown` event. +By default, the `.longTapDelay` is set to 300 milliseconds, what may be different of the system default. +You can change this value by setting the `TapConfig.longTapDelay` value. +It may also be useful for specific accessibility needs. + ### onTapUp diff --git a/packages/flame/lib/src/events/flame_game_mixins/multi_tap_dispatcher.dart b/packages/flame/lib/src/events/flame_game_mixins/multi_tap_dispatcher.dart index 20c7480e6c8..fda4c01026a 100644 --- a/packages/flame/lib/src/events/flame_game_mixins/multi_tap_dispatcher.dart +++ b/packages/flame/lib/src/events/flame_game_mixins/multi_tap_dispatcher.dart @@ -5,6 +5,7 @@ import 'package:flame/src/events/messages/tap_cancel_event.dart'; import 'package:flame/src/events/messages/tap_down_event.dart'; import 'package:flame/src/events/messages/tap_up_event.dart'; import 'package:flame/src/events/tagged_component.dart'; +import 'package:flame/src/events/tap_config.dart'; import 'package:flame/src/game/flame_game.dart'; import 'package:flame/src/game/game_render_box.dart'; import 'package:flutter/gestures.dart'; @@ -120,7 +121,7 @@ class MultiTapDispatcher extends Component implements MultiTapListener { /// The delay (in seconds) after which a tap is considered a long tap. @override - double get longTapDelay => 0.300; + double get longTapDelay => TapConfig.longTapDelay; @override void handleTap(int pointerId) {} diff --git a/packages/flame/lib/src/events/game_mixins/multi_touch_tap_detector.dart b/packages/flame/lib/src/events/game_mixins/multi_touch_tap_detector.dart index ca510d81629..bd5b41b0897 100644 --- a/packages/flame/lib/src/events/game_mixins/multi_touch_tap_detector.dart +++ b/packages/flame/lib/src/events/game_mixins/multi_touch_tap_detector.dart @@ -1,4 +1,5 @@ import 'package:flame/events.dart'; +import 'package:flame/src/events/tap_config.dart'; import 'package:flame/src/game/game.dart'; import 'package:flutter/gestures.dart'; @@ -22,7 +23,7 @@ mixin MultiTouchTapDetector on Game implements MultiTapListener { //#region MultiTapListener API @override - double get longTapDelay => 0.300; + double get longTapDelay => TapConfig.longTapDelay; @override void handleTap(int pointerId) => onTap(pointerId); diff --git a/packages/flame/lib/src/events/tap_config.dart b/packages/flame/lib/src/events/tap_config.dart new file mode 100644 index 00000000000..9d1c6c45aff --- /dev/null +++ b/packages/flame/lib/src/events/tap_config.dart @@ -0,0 +1,27 @@ +import 'dart:math'; + +/// [TapConfig] is used to expose specific configurations +/// related to the tap dispatcher. +final class TapConfig { + TapConfig._(); + + static double _longTapDelay = _defaultLongTapDelay; + + /// The delay (in seconds) after which a tap is considered a long tap. + static double get longTapDelay => _longTapDelay; + + /// Set the delay (in seconds) after which a tap is considered a long tap. + /// Same games may want to change the long tap delay to better + /// fit their needs or accessibility requirements. + static set longTapDelay(double value) { + _longTapDelay = max(_minLongTapDelay, value); + } + + /// Min delay to long tap delay is defined below. + /// Values too low don't make sense because they + /// would be basically a regular tap. + static const double _minLongTapDelay = 0.150; + + /// Default long tap delay is 0.3 seconds. + static const double _defaultLongTapDelay = 0.3; +} diff --git a/packages/flame/test/events/tap_config_test.dart b/packages/flame/test/events/tap_config_test.dart new file mode 100644 index 00000000000..c8ee59ec64a --- /dev/null +++ b/packages/flame/test/events/tap_config_test.dart @@ -0,0 +1,20 @@ +import 'package:flame/src/events/tap_config.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('TapConfig', () { + test('default longTapDelay is 0.3', () { + expect(TapConfig.longTapDelay, 0.3); + }); + + test('longTapDelay can be set new values', () { + TapConfig.longTapDelay = 0.5; + expect(TapConfig.longTapDelay, 0.5); + }); + + test('longTapDelay cannot be set to a value lower than 0.150', () { + TapConfig.longTapDelay = 0.1; + expect(TapConfig.longTapDelay, 0.150); + }); + }); +} From 418cc578053d969a4a5c3789b1713b9e1a4b3bdd Mon Sep 17 00:00:00 2001 From: Anton Borries Date: Tue, 2 Apr 2024 10:12:32 +0200 Subject: [PATCH 44/79] feat!: Use `Flame.images` in flame_texturepacker (#3103) Using `Flame.images` instead of a custom `ImageCache` in `TexturePackerAtlas` allowing users to override the `ImageCache`'s prefix to support loading Atlas Animations from different packages. Due to this change the `prefix` of the used `ImageCache` changed from `assets/` to `assets/images/` Migration instructions Either move all sprites and textures from `assets/` to `assets/images/` or provide a custom cache using `images: Images(prefix: 'assets/')`or use `Flame.images.prefix = 'assets/'` to point to the same Location as before. Be aware that the latter approach might interfere with loading other Image Assets --- packages/flame_texturepacker/README.md | 6 ++--- .../assets/{ => images}/atlas_map.atlas | 0 .../assets/{ => images}/sprite_sheet1.png | Bin .../assets/{ => images}/sprite_sheet2.png | Bin .../assets/{ => images}/sprite_sheet3.png | Bin .../flame_texturepacker/example/pubspec.yaml | 2 +- .../lib/flame_texturepacker.dart | 22 +++++++++++++---- .../lib/src/texture_packer_atlas.dart | 23 +++++++++--------- 8 files changed, 33 insertions(+), 20 deletions(-) rename packages/flame_texturepacker/example/assets/{ => images}/atlas_map.atlas (100%) rename packages/flame_texturepacker/example/assets/{ => images}/sprite_sheet1.png (100%) rename packages/flame_texturepacker/example/assets/{ => images}/sprite_sheet2.png (100%) rename packages/flame_texturepacker/example/assets/{ => images}/sprite_sheet3.png (100%) diff --git a/packages/flame_texturepacker/README.md b/packages/flame_texturepacker/README.md index 292d10fd0b9..23d8a12b9d2 100644 --- a/packages/flame_texturepacker/README.md +++ b/packages/flame_texturepacker/README.md @@ -40,13 +40,13 @@ flutter pub add flame_texturepacker ### Asset Storage -Drop generated atlas file and sprite sheet images into the `assets/` and link the files in your +Drop generated atlas file and sprite sheet images into the `assets/images/` and link the files in your `pubspec.yaml` file: ```yaml assets: - - assets/atlas_map.atlas - - assets/sprite_sheet1.png + - assets/images/atlas_map.atlas + - assets/images/sprite_sheet1.png ``` Import the plugin like this: diff --git a/packages/flame_texturepacker/example/assets/atlas_map.atlas b/packages/flame_texturepacker/example/assets/images/atlas_map.atlas similarity index 100% rename from packages/flame_texturepacker/example/assets/atlas_map.atlas rename to packages/flame_texturepacker/example/assets/images/atlas_map.atlas diff --git a/packages/flame_texturepacker/example/assets/sprite_sheet1.png b/packages/flame_texturepacker/example/assets/images/sprite_sheet1.png similarity index 100% rename from packages/flame_texturepacker/example/assets/sprite_sheet1.png rename to packages/flame_texturepacker/example/assets/images/sprite_sheet1.png diff --git a/packages/flame_texturepacker/example/assets/sprite_sheet2.png b/packages/flame_texturepacker/example/assets/images/sprite_sheet2.png similarity index 100% rename from packages/flame_texturepacker/example/assets/sprite_sheet2.png rename to packages/flame_texturepacker/example/assets/images/sprite_sheet2.png diff --git a/packages/flame_texturepacker/example/assets/sprite_sheet3.png b/packages/flame_texturepacker/example/assets/images/sprite_sheet3.png similarity index 100% rename from packages/flame_texturepacker/example/assets/sprite_sheet3.png rename to packages/flame_texturepacker/example/assets/images/sprite_sheet3.png diff --git a/packages/flame_texturepacker/example/pubspec.yaml b/packages/flame_texturepacker/example/pubspec.yaml index 30753c9d0c3..3a7c8bf2940 100644 --- a/packages/flame_texturepacker/example/pubspec.yaml +++ b/packages/flame_texturepacker/example/pubspec.yaml @@ -18,4 +18,4 @@ dev_dependencies: flutter: assets: - - assets/ \ No newline at end of file + - assets/images/ \ No newline at end of file diff --git a/packages/flame_texturepacker/lib/flame_texturepacker.dart b/packages/flame_texturepacker/lib/flame_texturepacker.dart index 1b5c0eb7227..b5d65798cda 100644 --- a/packages/flame_texturepacker/lib/flame_texturepacker.dart +++ b/packages/flame_texturepacker/lib/flame_texturepacker.dart @@ -1,5 +1,6 @@ library flame_texturepacker; +import 'package:flame/cache.dart'; import 'package:flame/game.dart'; import 'package:flame_texturepacker/src/texture_packer_atlas.dart'; @@ -13,16 +14,27 @@ extension TexturepackerLoader on Game { Future fromAtlas( String assetsPath, { bool fromStorage = false, + Images? images, }) async => - TexturePackerAtlas.load(assetsPath, fromStorage: fromStorage); + TexturePackerAtlas.load( + assetsPath, + fromStorage: fromStorage, + images: images, + ); /// Loads the specified pack file from assets /// Uses the parent directory of the pack file to find the page images. - Future atlasFromAssets(String assetsPath) async => - TexturePackerAtlas.load(assetsPath); + Future atlasFromAssets( + String assetsPath, { + Images? images, + }) async => + TexturePackerAtlas.load(assetsPath, images: images); /// Loads the specified pack file from storage /// Uses the parent directory of the pack file to find the page images. - Future atlasFromStorage(String storagePath) async => - TexturePackerAtlas.load(storagePath, fromStorage: true); + Future atlasFromStorage( + String storagePath, { + Images? images, + }) async => + TexturePackerAtlas.load(storagePath, fromStorage: true, images: images); } diff --git a/packages/flame_texturepacker/lib/src/texture_packer_atlas.dart b/packages/flame_texturepacker/lib/src/texture_packer_atlas.dart index 690430fcc65..309779837dc 100644 --- a/packages/flame_texturepacker/lib/src/texture_packer_atlas.dart +++ b/packages/flame_texturepacker/lib/src/texture_packer_atlas.dart @@ -11,8 +11,6 @@ import 'package:flame_texturepacker/src/model/region.dart'; import 'package:flame_texturepacker/src/texture_packer_sprite.dart'; import 'package:flutter/painting.dart'; -final _images = Images(prefix: 'assets/'); - class TexturePackerAtlas { /// The sprites contained in this atlas. final List sprites; @@ -26,13 +24,14 @@ class TexturePackerAtlas { static Future load( String path, { bool fromStorage = false, + Images? images, }) async { final _TextureAtlasData atlasData; if (fromStorage) { - atlasData = await _fromStorage(path); + atlasData = await _fromStorage(path, images: images); } else { - atlasData = await _fromAssets(path); + atlasData = await _fromAssets(path, images: images); } return TexturePackerAtlas( @@ -67,9 +66,9 @@ class TexturePackerAtlas { /// Loads images from the assets folder. /// Uses the [path] to find the image directory. -Future<_TextureAtlasData> _fromAssets(String path) async { +Future<_TextureAtlasData> _fromAssets(String path, {Images? images}) async { try { - return await _parse(path, fromStorage: false); + return await _parse(path, fromStorage: false, images: images); } on Exception catch (e) { throw Exception('Error loading $path from assets: $e'); } @@ -77,9 +76,9 @@ Future<_TextureAtlasData> _fromAssets(String path) async { /// Loads images from the device's storage. /// Uses the [path] to find the image directory. -Future<_TextureAtlasData> _fromStorage(String path) async { +Future<_TextureAtlasData> _fromStorage(String path, {Images? images}) async { try { - return await _parse(path, fromStorage: true); + return await _parse(path, fromStorage: true, images: images); } on Exception catch (e) { throw Exception('Error loading $path from storage: $e'); } @@ -93,6 +92,7 @@ Future<_TextureAtlasData> _fromStorage(String path) async { Future<_TextureAtlasData> _parse( String path, { required bool fromStorage, + Images? images, }) async { final pages = []; final regions = []; @@ -133,18 +133,19 @@ Future<_TextureAtlasData> _parse( final parentPath = (path.split('/')..removeLast()).join('/'); final texturePath = parentPath.isEmpty ? line : '$parentPath/$line'; + images ??= Flame.images; if (fromStorage) { try { final textureFile = File(texturePath); final bytes = await textureFile.readAsBytes(); final decodedBytes = await decodeImageFromList(bytes); - Flame.images.add(texturePath, decodedBytes); - page.texture = Flame.images.fromCache(texturePath); + images.add(texturePath, decodedBytes); + page.texture = images.fromCache(texturePath); } on Exception catch (e) { throw Exception('Could not add storage file to Flame cache. $e'); } } else { - page.texture = await _images.load(texturePath); + page.texture = await images.load(texturePath); } while (true) { From e34774743038bc75fec14afc3c753fa997e71577 Mon Sep 17 00:00:00 2001 From: Fabian Gebert Date: Wed, 3 Apr 2024 17:09:58 +0200 Subject: [PATCH 45/79] fix: Respect tile offset when drawing tiles (#3112) Fixes #2915 --- .../tile_layers/hexagonal_tile_layer.dart | 3 + .../tile_layers/isometric_tile_layer.dart | 3 + .../tile_layers/orthogonal_tile_layer.dart | 3 + .../tile_layers/staggered_tile_layer.dart | 3 + .../assets/test_tile_offset_hexagonal.tmx | 16 +++ .../assets/test_tile_offset_isometric.tmx | 16 +++ .../assets/test_tile_offset_orthogonal.tmx | 16 +++ .../assets/test_tile_offset_staggered.tmx | 16 +++ .../goldens/test_tile_offset_hexagonal.png | Bin 0 -> 205 bytes .../goldens/test_tile_offset_isometric.png | Bin 0 -> 168 bytes .../goldens/test_tile_offset_orthogonal.png | Bin 0 -> 169 bytes .../goldens/test_tile_offset_staggered.png | Bin 0 -> 166 bytes packages/flame_tiled/test/tiled_test.dart | 93 ++++++++++++++++++ 13 files changed, 169 insertions(+) create mode 100644 packages/flame_tiled/test/assets/test_tile_offset_hexagonal.tmx create mode 100644 packages/flame_tiled/test/assets/test_tile_offset_isometric.tmx create mode 100644 packages/flame_tiled/test/assets/test_tile_offset_orthogonal.tmx create mode 100644 packages/flame_tiled/test/assets/test_tile_offset_staggered.tmx create mode 100644 packages/flame_tiled/test/goldens/test_tile_offset_hexagonal.png create mode 100644 packages/flame_tiled/test/goldens/test_tile_offset_isometric.png create mode 100644 packages/flame_tiled/test/goldens/test_tile_offset_orthogonal.png create mode 100644 packages/flame_tiled/test/goldens/test_tile_offset_staggered.png diff --git a/packages/flame_tiled/lib/src/renderable_layers/tile_layers/hexagonal_tile_layer.dart b/packages/flame_tiled/lib/src/renderable_layers/tile_layers/hexagonal_tile_layer.dart index b07eba7fcd4..e3f4de0b809 100644 --- a/packages/flame_tiled/lib/src/renderable_layers/tile_layers/hexagonal_tile_layer.dart +++ b/packages/flame_tiled/lib/src/renderable_layers/tile_layers/hexagonal_tile_layer.dart @@ -119,6 +119,9 @@ class HexagonalTileLayer extends FlameTileLayer { offsetY = ty * size.y + staggerY + halfDestinationTile.y; } + offsetX += tileset.tileOffset?.x ?? 0; + offsetY += tileset.tileOffset?.y ?? 0; + final scos = flips.cos * scale; final ssin = flips.sin * scale; diff --git a/packages/flame_tiled/lib/src/renderable_layers/tile_layers/isometric_tile_layer.dart b/packages/flame_tiled/lib/src/renderable_layers/tile_layers/isometric_tile_layer.dart index cc520dbcdc7..f2e1d210911 100644 --- a/packages/flame_tiled/lib/src/renderable_layers/tile_layers/isometric_tile_layer.dart +++ b/packages/flame_tiled/lib/src/renderable_layers/tile_layers/isometric_tile_layer.dart @@ -72,6 +72,9 @@ class IsometricTileLayer extends FlameTileLayer { offsetX = halfDestinationTile.x * (tx - ty) + isometricXShift; offsetY = halfDestinationTile.y * (tx + ty) + isometricYShift; + offsetX += tileset.tileOffset?.x ?? 0; + offsetY += tileset.tileOffset?.y ?? 0; + final scos = flips.cos * scale; final ssin = flips.sin * scale; diff --git a/packages/flame_tiled/lib/src/renderable_layers/tile_layers/orthogonal_tile_layer.dart b/packages/flame_tiled/lib/src/renderable_layers/tile_layers/orthogonal_tile_layer.dart index 585312e178a..6c7d7ca3dd0 100644 --- a/packages/flame_tiled/lib/src/renderable_layers/tile_layers/orthogonal_tile_layer.dart +++ b/packages/flame_tiled/lib/src/renderable_layers/tile_layers/orthogonal_tile_layer.dart @@ -70,6 +70,9 @@ class OrthogonalTileLayer extends FlameTileLayer { offsetX = (tx + .5) * size.x; offsetY = (ty + .5) * size.y; + offsetX += tileset.tileOffset?.x ?? 0; + offsetY += tileset.tileOffset?.y ?? 0; + final scos = flips.cos * scale; final ssin = flips.sin * scale; diff --git a/packages/flame_tiled/lib/src/renderable_layers/tile_layers/staggered_tile_layer.dart b/packages/flame_tiled/lib/src/renderable_layers/tile_layers/staggered_tile_layer.dart index 883ce7bea49..017061a6e6b 100644 --- a/packages/flame_tiled/lib/src/renderable_layers/tile_layers/staggered_tile_layer.dart +++ b/packages/flame_tiled/lib/src/renderable_layers/tile_layers/staggered_tile_layer.dart @@ -119,6 +119,9 @@ class StaggeredTileLayer extends FlameTileLayer { offsetY = ty * size.y + staggerY + halfDestinationTile.y; } + offsetX += tileset.tileOffset?.x ?? 0; + offsetY += tileset.tileOffset?.y ?? 0; + final scos = flips.cos * scale; final ssin = flips.sin * scale; diff --git a/packages/flame_tiled/test/assets/test_tile_offset_hexagonal.tmx b/packages/flame_tiled/test/assets/test_tile_offset_hexagonal.tmx new file mode 100644 index 00000000000..e066c2f3e68 --- /dev/null +++ b/packages/flame_tiled/test/assets/test_tile_offset_hexagonal.tmx @@ -0,0 +1,16 @@ + + + + + + + + + + + +5,1, +1,1 + + + diff --git a/packages/flame_tiled/test/assets/test_tile_offset_isometric.tmx b/packages/flame_tiled/test/assets/test_tile_offset_isometric.tmx new file mode 100644 index 00000000000..de019c1302c --- /dev/null +++ b/packages/flame_tiled/test/assets/test_tile_offset_isometric.tmx @@ -0,0 +1,16 @@ + + + + + + + + + + + +5,1, +1,1 + + + diff --git a/packages/flame_tiled/test/assets/test_tile_offset_orthogonal.tmx b/packages/flame_tiled/test/assets/test_tile_offset_orthogonal.tmx new file mode 100644 index 00000000000..f6bec2cd1d8 --- /dev/null +++ b/packages/flame_tiled/test/assets/test_tile_offset_orthogonal.tmx @@ -0,0 +1,16 @@ + + + + + + + + + + + +5,1, +1,1 + + + diff --git a/packages/flame_tiled/test/assets/test_tile_offset_staggered.tmx b/packages/flame_tiled/test/assets/test_tile_offset_staggered.tmx new file mode 100644 index 00000000000..4079cb5f77f --- /dev/null +++ b/packages/flame_tiled/test/assets/test_tile_offset_staggered.tmx @@ -0,0 +1,16 @@ + + + + + + + + + + + +5,1, +1,1 + + + diff --git a/packages/flame_tiled/test/goldens/test_tile_offset_hexagonal.png b/packages/flame_tiled/test/goldens/test_tile_offset_hexagonal.png new file mode 100644 index 0000000000000000000000000000000000000000..6467faf2073a58730dfbd7da3adb37da684a176b GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^8bB<=!3HFSMgLv{Qk(@Ik;M!Q+`=Ht$S`Y;1W>Tv z)5S3)qV?@`N3I3~0p{|f|Lb?&3pPBV@J_LKjhK^!Qd#I)rX8nq<16ZF_Hce?=k)M& z@L~$`v#r>jo!gc-bD^=Z#r}gVOLF+Erg>bhT3~Uq=gVVhABR)V61qk5j_*sWY3B6U yXuZNu>tFQgcm4SWjGE?rtAt-{mo(l7)E46=Ea)t7i0=f@DGZ*jelF{r5}E+!*+km_ literal 0 HcmV?d00001 diff --git a/packages/flame_tiled/test/goldens/test_tile_offset_isometric.png b/packages/flame_tiled/test/goldens/test_tile_offset_isometric.png new file mode 100644 index 0000000000000000000000000000000000000000..b1173bf696f83cd95d3a767413f33b8bd2b59b96 GIT binary patch literal 168 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?3oVGw3ym^DWNC>Z7G z;usRq`u3V3-vI*-mVZVO z;usRq`u3V57lR^?^Tm`Gf7icxlb$$%Yw?HJsH5(R5#CZ+Yf5fDJaDwjhqaIJV)Mq_`Uv3&V=FPrPtoi>BtLPF9kH85+)f=3J{VHB${QJqR1>`SMNM-)+&uwJqo_ri=2ZN`p KpUXO@geCws5;l7P literal 0 HcmV?d00001 diff --git a/packages/flame_tiled/test/tiled_test.dart b/packages/flame_tiled/test/tiled_test.dart index 28d8feb2d7c..b356b6eb359 100644 --- a/packages/flame_tiled/test/tiled_test.dart +++ b/packages/flame_tiled/test/tiled_test.dart @@ -605,6 +605,99 @@ void main() { }); }); + group('tile offset', () { + late TiledComponent component; + + Future setupMap( + String tmxFile, + String imageFile, + Vector2 destTileSize, + ) async { + final bundle = TestAssetBundle( + imageNames: [ + imageFile, + ], + stringNames: [tmxFile], + ); + return component = await TiledComponent.load( + tmxFile, + destTileSize, + bundle: bundle, + images: Images(bundle: bundle), + ); + } + + test('tile offset hexagonal', () async { + await setupMap( + // flame tiled currently does not support hexagon side length property, + // to use export from Tiled, tweak that value + 'test_tile_offset_hexagonal.tmx', + '4_color_sprite.png', + Vector2(16, 16), + ); + + expect(component.size, Vector2(40, 28)); + + final pngData = await renderMapToPng(component); + + expect( + pngData, + matchesGoldenFile('goldens/test_tile_offset_hexagonal.png'), + ); + }); + + test('tile offset isometric', () async { + await setupMap( + 'test_tile_offset_isometric.tmx', + '4_color_sprite.png', + Vector2(16, 16), + ); + + expect(component.size, Vector2(32, 32)); + + final pngData = await renderMapToPng(component); + + expect( + pngData, + matchesGoldenFile('goldens/test_tile_offset_isometric.png'), + ); + }); + + test('tile offset orthogonal', () async { + await setupMap( + 'test_tile_offset_orthogonal.tmx', + '4_color_sprite.png', + Vector2(16, 16), + ); + + expect(component.size, Vector2(32, 32)); + + final pngData = await renderMapToPng(component); + + expect( + pngData, + matchesGoldenFile('goldens/test_tile_offset_orthogonal.png'), + ); + }); + + test('tile offset staggered', () async { + await setupMap( + 'test_tile_offset_staggered.tmx', + '4_color_sprite.png', + Vector2(16, 16), + ); + + expect(component.size, Vector2(40, 24)); + + final pngData = await renderMapToPng(component); + + expect( + pngData, + matchesGoldenFile('goldens/test_tile_offset_staggered.png'), + ); + }); + }); + group('isometric staggered', () { late TiledComponent component; From 9d97b12348161b4b150ee4166ba552f28d5f9d8b Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Thu, 4 Apr 2024 21:58:03 +0200 Subject: [PATCH 46/79] fix: Use camera argument name in Forge2DGame (#3115) Since the old camera now is completely removed, to be consistent with `FlameGame` the `Forge2DGame` should also name it's camera argument `camera`. Fixes #3114 --- packages/flame_forge2d/lib/forge2d_game.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/flame_forge2d/lib/forge2d_game.dart b/packages/flame_forge2d/lib/forge2d_game.dart index 70071c06c50..307cf0088bb 100644 --- a/packages/flame_forge2d/lib/forge2d_game.dart +++ b/packages/flame_forge2d/lib/forge2d_game.dart @@ -7,6 +7,8 @@ import 'package:forge2d/forge2d.dart'; class Forge2DGame extends FlameGame { Forge2DGame({ Forge2DWorld? world, + CameraComponent? camera, + @Deprecated('Use the `camera` argument instead') CameraComponent? cameraComponent, Vector2? gravity, ContactListener? contactListener, @@ -17,7 +19,7 @@ class Forge2DGame extends FlameGame { gravity: gravity, contactListener: contactListener, )) as T, - camera: (cameraComponent ?? CameraComponent()) + camera: (camera ?? cameraComponent ?? CameraComponent()) ..viewfinder.zoom = zoom, ); From fd113b707b2344c1d03b9e41e71e16330197823d Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Fri, 5 Apr 2024 14:25:26 +0200 Subject: [PATCH 47/79] chore: Bump forge2d to 0.13.0 (#3116) --- packages/flame_forge2d/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/flame_forge2d/pubspec.yaml b/packages/flame_forge2d/pubspec.yaml index e2df5ca2c41..247f2d4d292 100644 --- a/packages/flame_forge2d/pubspec.yaml +++ b/packages/flame_forge2d/pubspec.yaml @@ -15,7 +15,7 @@ dependencies: flame: ^1.17.0 flutter: sdk: flutter - forge2d: ">=0.12.2 <0.13.0" + forge2d: ^0.13.0 dev_dependencies: dartdoc: ^6.3.0 From cca12b88c9740e300a4e8ee17f4a80bfd160515b Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Fri, 5 Apr 2024 15:00:59 +0200 Subject: [PATCH 48/79] chore(release): Publish packages (#3117) ``` Package Name Current Version Updated Version Update Reason flame_forge2d 0.17.1 0.18.0 manual versioning flame_texturepacker 3.2.0 4.0.0 updated with major changes flame_tiled 1.20.0 1.20.1 updated with patch changes ``` --- CHANGELOG.md | 31 +++++++++++++++++++ examples/games/padracing/pubspec.yaml | 2 +- examples/pubspec.yaml | 4 +-- packages/flame_forge2d/CHANGELOG.md | 5 +++ packages/flame_forge2d/example/pubspec.yaml | 2 +- packages/flame_forge2d/pubspec.yaml | 2 +- packages/flame_texturepacker/CHANGELOG.md | 6 ++++ .../flame_texturepacker/example/pubspec.yaml | 2 +- packages/flame_texturepacker/pubspec.yaml | 2 +- packages/flame_tiled/CHANGELOG.md | 4 +++ packages/flame_tiled/example/pubspec.yaml | 2 +- packages/flame_tiled/pubspec.yaml | 2 +- 12 files changed, 55 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0535327102..b87a64ea367 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,37 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2024-04-05 + +### Changes + +--- + +Packages with breaking changes: + + - [`flame_texturepacker` - `v4.0.0`](#flame_texturepacker---v400) + +Packages with other changes: + + - [`flame_forge2d` - `v0.18.0`](#flame_forge2d---v0180) + - [`flame_tiled` - `v1.20.1`](#flame_tiled---v1201) + +--- + +#### `flame_texturepacker` - `v4.0.0` + + - **BREAKING** **FEAT**: Use `Flame.images` in flame_texturepacker ([#3103](https://github.com/flame-engine/flame/issues/3103)). ([418cc578](https://github.com/flame-engine/flame/commit/418cc578053d969a4a5c3789b1713b9e1a4b3bdd)) + +#### `flame_forge2d` - `v0.18.0` + + - **FIX**: Use camera argument name in Forge2DGame ([#3115](https://github.com/flame-engine/flame/issues/3115)). ([9d97b123](https://github.com/flame-engine/flame/commit/9d97b12348161b4b150ee4166ba552f28d5f9d8b)) + - **DOCS**: Upgrade dashbook version ([#3109](https://github.com/flame-engine/flame/issues/3109)). ([a717bcb4](https://github.com/flame-engine/flame/commit/a717bcb475a5604c5d8c66a3a5ac53f0dc173109)) + +#### `flame_tiled` - `v1.20.1` + + - **FIX**: Respect tile offset when drawing tiles ([#3112](https://github.com/flame-engine/flame/issues/3112)). ([e3477474](https://github.com/flame-engine/flame/commit/e34774743038bc75fec14afc3c753fa997e71577)) + + ## 2024-03-29 ### Changes diff --git a/examples/games/padracing/pubspec.yaml b/examples/games/padracing/pubspec.yaml index 79f41163d12..c07fc7d1415 100644 --- a/examples/games/padracing/pubspec.yaml +++ b/examples/games/padracing/pubspec.yaml @@ -9,7 +9,7 @@ environment: dependencies: collection: ^1.17.1 flame: ^1.17.0 - flame_forge2d: ^0.17.1 + flame_forge2d: ^0.18.0 flutter: sdk: flutter google_fonts: ^4.0.4 diff --git a/examples/pubspec.yaml b/examples/pubspec.yaml index c01c71e1345..6867ffa7359 100644 --- a/examples/pubspec.yaml +++ b/examples/pubspec.yaml @@ -13,13 +13,13 @@ dependencies: dashbook: ^0.1.14 flame: ^1.17.0 flame_audio: ^2.10.1 - flame_forge2d: ^0.17.1 + flame_forge2d: ^0.18.0 flame_isolate: ^0.6.0+1 flame_lottie: ^0.4.0+1 flame_noise: ^0.3.0+1 flame_spine: ^0.2.0+1 flame_svg: ^1.10.1 - flame_tiled: ^1.20.0 + flame_tiled: ^1.20.1 flutter: sdk: flutter google_fonts: ^4.0.4 diff --git a/packages/flame_forge2d/CHANGELOG.md b/packages/flame_forge2d/CHANGELOG.md index e39ec195267..030fc6a5856 100644 --- a/packages/flame_forge2d/CHANGELOG.md +++ b/packages/flame_forge2d/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.18.0 + + - **FIX**: Use camera argument name in Forge2DGame ([#3115](https://github.com/flame-engine/flame/issues/3115)). ([9d97b123](https://github.com/flame-engine/flame/commit/9d97b12348161b4b150ee4166ba552f28d5f9d8b)) + - **DOCS**: Upgrade dashbook version ([#3109](https://github.com/flame-engine/flame/issues/3109)). ([a717bcb4](https://github.com/flame-engine/flame/commit/a717bcb475a5604c5d8c66a3a5ac53f0dc173109)) + ## 0.17.1 - **FIX**: Null gravity override by Forge2dGame ([#3092](https://github.com/flame-engine/flame/issues/3092)). ([3c35d59b](https://github.com/flame-engine/flame/commit/3c35d59b4a4ec064106d24a17e748005a20d9fde)) diff --git a/packages/flame_forge2d/example/pubspec.yaml b/packages/flame_forge2d/example/pubspec.yaml index 90b28f9d50f..17af10bd577 100644 --- a/packages/flame_forge2d/example/pubspec.yaml +++ b/packages/flame_forge2d/example/pubspec.yaml @@ -11,7 +11,7 @@ environment: dependencies: flame: ^1.17.0 - flame_forge2d: ^0.17.1 + flame_forge2d: ^0.18.0 flutter: sdk: flutter diff --git a/packages/flame_forge2d/pubspec.yaml b/packages/flame_forge2d/pubspec.yaml index 247f2d4d292..c59b30403eb 100644 --- a/packages/flame_forge2d/pubspec.yaml +++ b/packages/flame_forge2d/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_forge2d description: Forge2D (Box2D) support for the Flame game engine. This uses the forge2d package and provides wrappers and components to be used inside Flame. -version: 0.17.1 +version: 0.18.0 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_forge2d funding: - https://opencollective.com/blue-fire diff --git a/packages/flame_texturepacker/CHANGELOG.md b/packages/flame_texturepacker/CHANGELOG.md index 5e8e5800c11..85174156223 100644 --- a/packages/flame_texturepacker/CHANGELOG.md +++ b/packages/flame_texturepacker/CHANGELOG.md @@ -1,3 +1,9 @@ +## 4.0.0 + +> Note: This release has breaking changes. + + - **BREAKING** **FEAT**: Use `Flame.images` in flame_texturepacker ([#3103](https://github.com/flame-engine/flame/issues/3103)). ([418cc578](https://github.com/flame-engine/flame/commit/418cc578053d969a4a5c3789b1713b9e1a4b3bdd)) + ## 3.2.0 - **REFACTOR**: Deprecate `fromAtlas` in favour of `atlasFromAssets` and `atlasFromStorage` ([#3098](https://github.com/flame-engine/flame/issues/3098)). ([6c8190b7](https://github.com/flame-engine/flame/commit/6c8190b7215671e7d6e1e271b6aac2a9723ec20d)) diff --git a/packages/flame_texturepacker/example/pubspec.yaml b/packages/flame_texturepacker/example/pubspec.yaml index 3a7c8bf2940..95e6b82893c 100644 --- a/packages/flame_texturepacker/example/pubspec.yaml +++ b/packages/flame_texturepacker/example/pubspec.yaml @@ -9,7 +9,7 @@ environment: dependencies: flame: ^1.17.0 - flame_texturepacker: ^3.2.0 + flame_texturepacker: ^4.0.0 flutter: sdk: flutter diff --git a/packages/flame_texturepacker/pubspec.yaml b/packages/flame_texturepacker/pubspec.yaml index 19be867b8f8..75b1dfbe9d0 100644 --- a/packages/flame_texturepacker/pubspec.yaml +++ b/packages/flame_texturepacker/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_texturepacker description: A simple plugin for the Flame Engine to import spritesheets generated by the TexturePacker tool. -version: 3.2.0 +version: 4.0.0 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_texturepacker funding: - https://opencollective.com/blue-fire diff --git a/packages/flame_tiled/CHANGELOG.md b/packages/flame_tiled/CHANGELOG.md index 7d9bc3db7d1..957c33921ce 100644 --- a/packages/flame_tiled/CHANGELOG.md +++ b/packages/flame_tiled/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.20.1 + + - **FIX**: Respect tile offset when drawing tiles ([#3112](https://github.com/flame-engine/flame/issues/3112)). ([e3477474](https://github.com/flame-engine/flame/commit/e34774743038bc75fec14afc3c753fa997e71577)) + ## 1.20.0 - **FEAT**: Export `TileAtlas` from `flame_tiled` package ([#3049](https://github.com/flame-engine/flame/issues/3049)). ([41e9e4e3](https://github.com/flame-engine/flame/commit/41e9e4e38c643b07a3a7269b1cd8d3fa60cbeebb)) diff --git a/packages/flame_tiled/example/pubspec.yaml b/packages/flame_tiled/example/pubspec.yaml index 5a02a6c64b2..50e95faed43 100644 --- a/packages/flame_tiled/example/pubspec.yaml +++ b/packages/flame_tiled/example/pubspec.yaml @@ -8,7 +8,7 @@ environment: dependencies: flame: ^1.17.0 - flame_tiled: ^1.20.0 + flame_tiled: ^1.20.1 flutter: sdk: flutter diff --git a/packages/flame_tiled/pubspec.yaml b/packages/flame_tiled/pubspec.yaml index 392102f1ff2..b4aaa16b8f4 100644 --- a/packages/flame_tiled/pubspec.yaml +++ b/packages/flame_tiled/pubspec.yaml @@ -1,6 +1,6 @@ name: flame_tiled description: Tiled support for the Flame game engine. This uses the tiled package and provides wrappers and components to be used inside Flame. -version: 1.20.0 +version: 1.20.1 homepage: https://github.com/flame-engine/flame/tree/main/packages/flame_tiled funding: - https://opencollective.com/blue-fire From 67e24a2ae7ffc771bd2f3b85323b6e0dce3f44bd Mon Sep 17 00:00:00 2001 From: guqicun <166205493+guqicun@users.noreply.github.com> Date: Sat, 6 Apr 2024 22:35:29 +0800 Subject: [PATCH 49/79] chore: Remove repetitive words (#3118) Replace this text. Signed-off-by: guqicun --- doc/bridge_packages/flame_forge2d/joints.md | 2 +- doc/development/documentation.md | 2 +- doc/flame/rendering/text_rendering.md | 2 +- .../bridge_libraries/flame_isolate/simple_isolate_example.dart | 2 +- packages/flame/lib/src/camera/camera_component.dart | 2 +- .../lib/src/components/sprite_animation_group_component.dart | 2 +- packages/flame/lib/src/components/sprite_group_component.dart | 2 +- packages/flame/lib/src/extensions/image.dart | 2 +- packages/flame/lib/src/parallax.dart | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/bridge_packages/flame_forge2d/joints.md b/doc/bridge_packages/flame_forge2d/joints.md index 71bf4a892cf..a2a94b90f22 100644 --- a/doc/bridge_packages/flame_forge2d/joints.md +++ b/doc/bridge_packages/flame_forge2d/joints.md @@ -482,7 +482,7 @@ joint.getCurrentLengthB() ```{warning} `PulleyJoint` can get a bit troublesome by itself. They often work better when -combined with prismatic joints. You should also cover the the anchor points +combined with prismatic joints. You should also cover the anchor points with static shapes to prevent one side from going to zero length. ``` diff --git a/doc/development/documentation.md b/doc/development/documentation.md index 08efe28ed2e..16880800ed1 100644 --- a/doc/development/documentation.md +++ b/doc/development/documentation.md @@ -194,7 +194,7 @@ rebuild the documents that have changed since the previous run, so usually, a re second or two. If you want to automatically recompile the docs every time there is a change to one of the files -you can use the the built-in Melos target below, which will also serve and open your default +you can use the built-in Melos target below, which will also serve and open your default browser with the docs. ```shell diff --git a/doc/flame/rendering/text_rendering.md b/doc/flame/rendering/text_rendering.md index a42b52ba0c1..ebfd81b1fc6 100644 --- a/doc/flame/rendering/text_rendering.md +++ b/doc/flame/rendering/text_rendering.md @@ -81,7 +81,7 @@ You can decide if the box should grow as the text is written or if it should be `growingBox` variable in the `TextBoxConfig`. A static box could either have a fixed size (setting the `size` property of the `TextBoxComponent`), or to automatically shrink to fit the text content. -In addition, the `align` property allows you to control the the horizontal and vertical alignment of +In addition, the `align` property allows you to control the horizontal and vertical alignment of the text content. For example, setting `align` to `Anchor.center` will center the text within its bounding box both vertically and horizontally. diff --git a/examples/lib/stories/bridge_libraries/flame_isolate/simple_isolate_example.dart b/examples/lib/stories/bridge_libraries/flame_isolate/simple_isolate_example.dart index c034f0922fa..44fab01a772 100644 --- a/examples/lib/stories/bridge_libraries/flame_isolate/simple_isolate_example.dart +++ b/examples/lib/stories/bridge_libraries/flame_isolate/simple_isolate_example.dart @@ -13,7 +13,7 @@ class SimpleIsolateExample extends FlameGame { This example showcases a simple FlameIsolate example, making it easy to continually run heavy load without stutter. - Tap the brown square to swap between running heavy load in in an isolate or + Tap the brown square to swap between running heavy load in an isolate or synchronous. The selected backpressure strategy used for this example is diff --git a/packages/flame/lib/src/camera/camera_component.dart b/packages/flame/lib/src/camera/camera_component.dart index a75dbaf9d23..6bc63472e29 100644 --- a/packages/flame/lib/src/camera/camera_component.dart +++ b/packages/flame/lib/src/camera/camera_component.dart @@ -393,7 +393,7 @@ class CameraComponent extends Component { /// the world to which the given [component] belongs (if any). This means, in /// such cases, any component overlapping the [visibleWorldRect] will be /// reported as visible, even if it is not part of the [world] this camera is - /// currently looking at. This can be changed by passing the the component's + /// currently looking at. This can be changed by passing the component's /// world as [componentWorld]. bool canSee(PositionComponent component, {World? componentWorld}) { if (!(world?.isMounted ?? false) || diff --git a/packages/flame/lib/src/components/sprite_animation_group_component.dart b/packages/flame/lib/src/components/sprite_animation_group_component.dart index 78a44fab840..74dd3dd0812 100644 --- a/packages/flame/lib/src/components/sprite_animation_group_component.dart +++ b/packages/flame/lib/src/components/sprite_animation_group_component.dart @@ -134,7 +134,7 @@ class SpriteAnimationGroupComponent extends PositionComponent /// Returns the current group state. T? get current => _current; - /// The the group state to given state. + /// The group state to given state. /// /// Will update [size] if [autoResize] is true. set current(T? value) { diff --git a/packages/flame/lib/src/components/sprite_group_component.dart b/packages/flame/lib/src/components/sprite_group_component.dart index 7d27da784c9..9e9a268fb5e 100644 --- a/packages/flame/lib/src/components/sprite_group_component.dart +++ b/packages/flame/lib/src/components/sprite_group_component.dart @@ -64,7 +64,7 @@ class SpriteGroupComponent extends PositionComponent /// Returns the current group state. T? get current => _current; - /// The the group state to given state. + /// The group state to given state. /// /// Will update [size] if [autoResize] is true. set current(T? value) { diff --git a/packages/flame/lib/src/extensions/image.dart b/packages/flame/lib/src/extensions/image.dart index 907025c8728..3c3055f342c 100644 --- a/packages/flame/lib/src/extensions/image.dart +++ b/packages/flame/lib/src/extensions/image.dart @@ -96,7 +96,7 @@ extension ImageExtension on Image { /// Resizes this image to the given [newSize]. /// /// Keep in mind that is considered an expensive operation and should be - /// avoided in the the game loop methods. Prefer using it + /// avoided in the game loop methods. Prefer using it /// in the loading phase of the game or components. Future resize(Vector2 newSize) async { final recorder = PictureRecorder(); diff --git a/packages/flame/lib/src/parallax.dart b/packages/flame/lib/src/parallax.dart index a1583d7ae62..d1928cb52c2 100644 --- a/packages/flame/lib/src/parallax.dart +++ b/packages/flame/lib/src/parallax.dart @@ -189,7 +189,7 @@ class ParallaxAnimation extends ParallaxRenderer { /// /// _IMPORTANT_: This method pre render all the frames of the animation into /// image instances so it can be used inside the parallax. Just keep that in - /// mind when using animations in in parallax, the over use of it, or the use + /// mind when using animations in parallax, the over use of it, or the use /// of big animations (be it in number of frames or the size of the images) /// can lead to high use of memory. static Future load( From 843984dee5f5f6afd351ef29ad2adb39650f30bb Mon Sep 17 00:00:00 2001 From: Lim Chee Keen <62128387+xjyribro@users.noreply.github.com> Date: Tue, 9 Apr 2024 20:03:34 +0800 Subject: [PATCH 50/79] docs: Update flame_audio readme (#3119) Closes: #2511 --------- Co-authored-by: xjyribro Co-authored-by: Lukas Klingsbo --- packages/flame_audio/README.md | 106 ++++++++++++++++++++++++++++++++- 1 file changed, 105 insertions(+), 1 deletion(-) diff --git a/packages/flame_audio/README.md b/packages/flame_audio/README.md index 3bf640b34f3..541514832b0 100644 --- a/packages/flame_audio/README.md +++ b/packages/flame_audio/README.md @@ -27,4 +27,108 @@ This package makes it easy to add audio capabilities to your games, integrating code. Add this as a dependency to your Flame game if you want to play background music, -ambient sounds, sound effects, etc. +ambient sounds, sound effects, etc. For the full documentation, visit [flame_audio](https://docs.flame-engine.org/latest/bridge_packages/flame_audio/flame_audio.html). + + +## How to use + +Add sound files to `assets/audio`. Remember to run `pub get` after updating pubspec.yaml with: + +```dart +assets: + - assets/audio +``` + + +### General sounds + +Use these built-in methods to play sounds in your Flame game: + +```dart +import 'package:flame_audio/flame_audio.dart'; + +// For shorter reused audio clips, like sound effects +FlameAudio.play('explosion.mp3'); + +// For looping an audio file +FlameAudio.loop('music.mp3'); + +// For playing a longer audio file +FlameAudio.playLongAudio('music.mp3'); + +// For looping a longer audio file +FlameAudio.loopLongAudio('music.mp3'); +``` + + +### Background music + +Start by initializing FlameAudio bgm. + +```dart +FlameAudio.bgm.initialize(); +``` + +Remember to call dispose to remove the observer. + +```dart +FlameAudio.bgm.dispose(); +``` + +To play a looping background music + +```dart +import 'package:flame_audio/flame_audio.dart'; + +// play with optional volume param +FlameAudio.bgm.play('music/world-map.mp3', volume: .25); +``` + +To stop background music + +```dart +FlameAudio.bgm.stop(); +``` + +To pause and resume background music + +```dart +FlameAudio.bgm.pause(); +FlameAudio.bgm.resume(); +``` + + +### Caching + +You can pre-load your sounds into the audioCache. +This prevents a delay for the first time an audio file is called. +The files are cached automatically after the first time. + +```dart +// cache single track +await FlameAudio.audioCache.load('explosion.mp3'); + +// cache multiple tracks +await FlameAudio.audioCache.loadAll(['explosion.mp3', 'music.mp3']); +``` + +To clear the cache + +```dart +// clear specific track +FlameAudio.audioCache.clear('explosion.mp3'); + +// clear whole cache +FlameAudio.audioCache.clearCache(); +``` + + +### Audio pool + +Use AudioPools if you have extremely quick firing, repetitive or simultaneous sounds. +To create an AudioPool: + +```dart +AudioPool audioPool = await FlameAudio.createPool('explosion.mp3', maxPlayers: 2); +audioPool.start(); +``` From a4a6a6a724b214537acafb87846d63a8028dec13 Mon Sep 17 00:00:00 2001 From: shreya <70858293+alt-shreya@users.noreply.github.com> Date: Tue, 9 Apr 2024 21:11:58 +0530 Subject: [PATCH 51/79] docs(ui): Improved accessibility (#3072) * Improved color contrast ratio. * Added discernible links and alt text for screen readers. * Fixed broken links and redirected deprecated repos. --- doc/README.md | 2 +- doc/_sphinx/theme/flames.css | 39 ++++++++++++++++++--------- doc/_sphinx/theme/layout.html | 4 +-- doc/flame/inputs/other_inputs.md | 30 ++++++++++++--------- doc/flame/other/debug.md | 3 +-- doc/flame/overlays.md | 3 +-- doc/flame/rendering/images.md | 23 ++++++++-------- doc/flame/rendering/layers.md | 13 +++++---- doc/flame/rendering/palette.md | 12 ++++----- doc/flame/rendering/particles.md | 15 +++++------ doc/flame/rendering/text_rendering.md | 18 ++++++------- 11 files changed, 86 insertions(+), 76 deletions(-) diff --git a/doc/README.md b/doc/README.md index 9ca29c8c20f..cae361a4ff2 100644 --- a/doc/README.md +++ b/doc/README.md @@ -63,7 +63,7 @@ Flame doesn't bundle any network feature, which may be needed to write online mu If you are building a multiplayer game, here are some recommendations of packages/services: -- [Nakama](https://github.com/obrunsmann/flutter_nakama/): Nakama is an open-source server designed +- [Nakama](https://github.com/obrunsmann/flutter_nakama/): An open-source server designed to power modern games and apps. - [Firebase](https://firebase.google.com/): Provides dozens of services that can be used to write simpler multiplayer experiences. diff --git a/doc/_sphinx/theme/flames.css b/doc/_sphinx/theme/flames.css index b4e7b073dd0..b82c1b89654 100644 --- a/doc/_sphinx/theme/flames.css +++ b/doc/_sphinx/theme/flames.css @@ -20,8 +20,8 @@ } body { - background-color: #484848; - color: #b8b8b8; + background-color: #383838; + color: #cccccc; font-family: var(--font-sans); font-size: 15px; line-height: 1.5; @@ -32,7 +32,7 @@ body { } a { - color: #ffbb3e; + color: #ff9500; text-decoration: none; } @@ -40,6 +40,10 @@ a:hover { color: #ddbb99; } +a:visited { + color: #ffbc70; +} + a:hover code { color: white; } @@ -69,7 +73,7 @@ code { code.xref { background: none; - color: #f75151; + color: #ff9500; padding: 0; } @@ -84,6 +88,7 @@ strong { color: white; } + div.expander { flex: 1; } @@ -140,7 +145,7 @@ div.top-bar .btn { background-color: transparent; border: none; border-radius: 0.25rem; - color: #ffd78d; + color: #ff9500; cursor: pointer; display: inline-flex; font-size: 1rem; @@ -195,7 +200,7 @@ div.top-bar #menu-button { } #versions-menu > .btn > .version-id { - color: #ffe95c; + color: #ff9500; font-weight: bold; padding: 0 0 0 6px; } @@ -347,7 +352,7 @@ div.nav-left li { div.nav-left li > a, div.nav-left li > div.submenu > a.reference { border-radius: 5px 0 0 5px; - color: #9d9175; + color: #ff9500; display: block; font-size: 13px; margin-left: -5px; @@ -420,7 +425,7 @@ div.nav-right > #toc-local { flex-direction: column; margin: 0 0 0 6px; max-width: var(--right-menu-width); - padding: 0 0 0 10px; + padding: 0 0 0 1rem; } div.nav-right > #toc-local > div.header { @@ -431,7 +436,7 @@ div.nav-right > #toc-local > div.header { div.nav-right > #toc-local > a.list-group-item { border: none; border-left: 4px solid transparent; - color: #9d9175; + color: #ff9500; display: block; font-size: 13px; line-height: 1.2; @@ -514,7 +519,7 @@ div.warning .version { div.document { background-color: #282828; - color: #b0b0b0; + color: #D6D6D6; border-radius: 2pt; box-shadow: 2px 2px 3px 0 #000; padding: var(--document-padding); @@ -526,12 +531,18 @@ div.document::after { /* clearfix */ clear: both; } + div.copyright { + color: #cccccc; font-size: 12px; margin-top: 3px; opacity: 0.5; } +.copyright a { + color: #ff9500; + text-decoration: underline; +} div.document h1 { border-bottom: 1px solid #555; color: #ccc; @@ -626,7 +637,7 @@ div.document :is(h1, h2, h3, h4) > code { } .prev-next-area > a > .prev-next-info > p.prev-next-subtitle { - color: #888; + color: #ffffe8; } .prev-next-area > a:hover > .prev-next-info > p.prev-next-title { @@ -690,7 +701,9 @@ div.highlight-text pre:before { content: "text"; color: #666; } - +span.keyword { + color: #ffffcA; +} /*----------------------------------------------------------------------------* * Search elements @@ -867,7 +880,7 @@ table.docutils td { } table.docutils th { - color: #9d9175; + color: #ff9500; } /* This ensures that when navigating to a link within a page, the link diff --git a/doc/_sphinx/theme/layout.html b/doc/_sphinx/theme/layout.html index 3a33826beb1..b029f1f1da7 100644 --- a/doc/_sphinx/theme/layout.html +++ b/doc/_sphinx/theme/layout.html @@ -83,8 +83,8 @@ }); - - + + Flame logo: a fiery symbol along with the FLAME wordmark.

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