From 23f13c395a0a641d6f413beea42123655f0247dd Mon Sep 17 00:00:00 2001 From: Renan Date: Thu, 6 Aug 2020 01:21:20 +0100 Subject: [PATCH] Improvement(#419): Rename animation to sprite animation (#429) * rename animation stuff * rename sprite animation component * pr stuff --- CHANGELOG.md | 1 + doc/animation_widget_article/article.md | 14 ++--- doc/examples/.gitignore | 1 + doc/examples/animation_widget/README.md | 2 +- doc/examples/animation_widget/lib/main.dart | 6 +-- doc/examples/animation_widget/pubspec.yaml | 2 +- doc/examples/animations/lib/main.dart | 19 ++++--- doc/examples/aseprite/lib/main.dart | 8 +-- doc/examples/particles/lib/main.dart | 12 ++--- doc/examples/render_flip/lib/main.dart | 10 ++-- doc/examples/spritesheet/lib/main.dart | 6 +-- doc/examples/tiled/lib/main.dart | 8 +-- doc/examples/widgets/lib/main.dart | 2 +- doc/images.md | 5 +- ...t.dart => sprite_animation_component.dart} | 14 ++--- lib/particles/animation_particle.dart | 8 +-- lib/{animation.dart => sprite_animation.dart} | 52 +++++++++---------- lib/spritesheet.dart | 8 +-- lib/util.dart | 45 ---------------- lib/widgets/animation_widget.dart | 20 ++++--- lib/widgets/sprite_widget.dart | 15 ++++-- 21 files changed, 115 insertions(+), 143 deletions(-) rename lib/components/{animation_component.dart => sprite_animation_component.dart} (82%) rename lib/{animation.dart => sprite_animation.dart} (83%) diff --git a/CHANGELOG.md b/CHANGELOG.md index dae5b71c1..1a29bbe51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ## [next] - Preventing some crashed that could happen on web when some methods were called + - Rename Animation to SpriteAnimation ## 0.24.0 - Outsourcing SVG support to an external package diff --git a/doc/animation_widget_article/article.md b/doc/animation_widget_article/article.md index a0a7d0899..37d2f6542 100644 --- a/doc/animation_widget_article/article.md +++ b/doc/animation_widget_article/article.md @@ -1,16 +1,16 @@ # Sprite Sheet Animations in Flutter -### UPDATE 05/27/2020 +### UPDATE 09/04/2020 -As for Flame 0.22.0 there is a new way to use Animations and Sprites inside your widget tree. +As for Flame 1.0, the `animationAsWidget` has been removed in favor of a direct usage of `SpriteAnimationWidget`. -Flame now includes a widget catalog and inside it you will find `AnimationWidget` and `SpriteWidget`. +Flame now includes a widget catalog and inside it you will find `SpriteAnimationWidget` and `SpriteWidget`. Check the example mentioned on this article to see the updated version. ## Introduction -Flutter provides lots of cool and slick animations out of the box, most related to movement and tweens (continuous changes in size, position, color, et cetera). However, one particular thing that it's really hard to do using only the native APIs is a simple sprite sheet animation. Or any sprite sheet handling, for that matter. +Flutter provides lots of cool and slick animations out of the box, most related to movement and tweens (continuous changes in size, position, color, etc). However, one particular thing that it's really hard to do using only the native APIs is a simple sprite sheet animation. Or any sprite sheet handling, for that matter. A sprite sheet is a single image that has multiple images (sprites) inside, each one being accessed via it's defining rectangle (x, y, width, and height). Maybe every sprite inside has the same size, like a tileset; for example: @@ -118,10 +118,10 @@ Let's you have your `build` method in one of your pages; pretty normal Flutter s } ``` -Note that it could be any component, however complex, inside your widgets tree. Note also that I have omitted the "magic" of the equation here. How is it that we create a component for an animation? Very basically (more details in the flame tutorial), Flame provides components, one of which is the `AnimationComponent` that receives an `Animation` object describing the animation and does exactly what we want. All components live inside a `Game` instance, that can add custom logic relating to the game loop. For our case, we just want to create a simple, empty game and add a single `AnimationComponent` with a simple `Animation` inside. So Flame provides a helper to do that, the `Flame.util.animationAsWidget` method. It takes the size of the object as a Flame's `Position` instance (a generic class to represent a pair of doubles), and also takes in an `Animation` instance representing our frame list. To use that, let's import both `Flame` and the `Animation` class. However, since Flutter adds it's own animation classes, let's use an alias in order to not mess up the names. Therefore, add these imports to the top of the file: +Note that it could be any component, however complex, inside your widgets tree. Note also that I have omitted the "magic" of the equation here. How is it that we create a component for an animation? Very basically (more details in the flame tutorial), Flame provides components, one of which is the `SpriteAnimationComponent` that receives a `SpriteAnimation` object describing the animation and does exactly what we want. All components live inside a `Game` instance, that can add custom logic relating to the game loop. For our case, we just want to create a simple, empty game and add a single `AnimationComponent` with a simple `Animation` inside. So Flame provides a helper to do that, the `Flame.util.animationAsWidget` method. It takes the size of the object as a Flame's `Position` instance (a generic class to represent a pair of doubles), and also takes in an `Animation` instance representing our frame list. To use that, let's import both `Flame` and the `Animation` class. However, since Flutter adds it's own animation classes, let's use an alias in order to not mess up the names. Therefore, add these imports to the top of the file: ```dart -import 'package:flame/animation.dart' as animation; // imports the Animation class under animation.Animation +import 'package:flame/sprite_animation.dart'; // imports the SpriteAnimation class import 'package:flame/flame.dart'; // imports the Flame helper class import 'package:flame/position.dart'; // imports the Position class ``` @@ -129,7 +129,7 @@ import 'package:flame/position.dart'; // imports the Position class How we do the magic then? Just add the following to your widget tree: ```dart - Flame.util.animationAsWidget(Position(WIDTH, HEIGHT), animation.Animation.sequenced('minotaur.png', AMOUNT, textureWidth: FRAME_WIDTH)) + Flame.util.animationAsWidget(Position(WIDTH, HEIGHT), SpriteAnimation.sequenced('minotaur.png', AMOUNT, textureWidth: FRAME_WIDTH)) ``` The first parameter's `WIDTH` and `HEIGHT` are the actual size of the widget on the screen. This does not need to match the sprite size, as Flame will scale it for you. You might, however, wanna keep the aspect, so things don't get distorted. In your case, the minotaur asset is a row of 96x96 pixels, so squares, therefore we can scale keeping `WIDTH/HEIGHT = 1`. We will choose the size as 256 px. The `sequenced` constructor is a helper that easily creates the animation assuming equal-sized frames in a row, in order. You can configure the start x, start y, texture width and height, but those will default gracefully to (0,0) and the actual width and height of the file. You can create your animation passing in the frame list, each frame with a different step time and sprite (source rectangle). diff --git a/doc/examples/.gitignore b/doc/examples/.gitignore index 65edf49aa..63233d01b 100644 --- a/doc/examples/.gitignore +++ b/doc/examples/.gitignore @@ -2,5 +2,6 @@ web/ ios/ android/ test/ +macos/ generated_plugin_registrant.dart diff --git a/doc/examples/animation_widget/README.md b/doc/examples/animation_widget/README.md index 4b0e7c95a..689cfb41e 100644 --- a/doc/examples/animation_widget/README.md +++ b/doc/examples/animation_widget/README.md @@ -1,6 +1,6 @@ # animation_widget -A sample Flame project to showcase the animationAsWidget method to render easy sprite sheet animations on regular (non-game) Flutter apps. +A sample Flame project to showcase the SpriteAnimationWidget to render easy sprite sheet animations on regular (non-game) Flutter apps. ## Credits diff --git a/doc/examples/animation_widget/lib/main.dart b/doc/examples/animation_widget/lib/main.dart index fc856c3d0..5daa91634 100644 --- a/doc/examples/animation_widget/lib/main.dart +++ b/doc/examples/animation_widget/lib/main.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:flame/flame.dart'; -import 'package:flame/animation.dart' as animation; +import 'package:flame/sprite_animation.dart'; import 'package:flame/sprite.dart'; import 'package:flame/spritesheet.dart'; import 'package:flame/position.dart'; @@ -10,7 +10,7 @@ import 'package:flame/widgets/sprite_widget.dart'; import 'package:flutter/material.dart'; Sprite _sprite; -animation.Animation _animation; +SpriteAnimation _animation; void main() async { WidgetsFlutterBinding.ensureInitialized(); @@ -91,7 +91,7 @@ class _MyHomePageState extends State { Container( width: 200, height: 200, - child: AnimationWidget(animation: _animation), + child: SpriteAnimationWidget(animation: _animation), ), const Text('Neat, hum?'), const Text( diff --git a/doc/examples/animation_widget/pubspec.yaml b/doc/examples/animation_widget/pubspec.yaml index cc60be880..2c51ff39d 100644 --- a/doc/examples/animation_widget/pubspec.yaml +++ b/doc/examples/animation_widget/pubspec.yaml @@ -1,5 +1,5 @@ name: animation_widget -description: A sample Flame project to showcase the animationAsWidget method. +description: A sample Flame project to showcase the SpriteAnimationWidget widget. version: 0.1.0 diff --git a/doc/examples/animations/lib/main.dart b/doc/examples/animations/lib/main.dart index 26d953ebf..8f86e2e54 100644 --- a/doc/examples/animations/lib/main.dart +++ b/doc/examples/animations/lib/main.dart @@ -2,8 +2,8 @@ import 'package:flame/gestures.dart'; import 'package:flutter/gestures.dart'; import 'package:flame/flame.dart'; import 'package:flame/game.dart'; -import 'package:flame/animation.dart' as flame_animation; -import 'package:flame/components/animation_component.dart'; +import 'package:flame/sprite_animation.dart'; +import 'package:flame/components/sprite_animation_component.dart'; import 'package:flutter/material.dart'; void main() async { @@ -16,7 +16,7 @@ void main() async { } class MyGame extends BaseGame with TapDetector { - final animation = flame_animation.Animation.sequenced( + final animation = SpriteAnimation.sequenced( 'chopper.png', 4, textureWidth: 48, @@ -28,7 +28,8 @@ class MyGame extends BaseGame with TapDetector { void addAnimation(double x, double y) { const textureWidth = 291.0; const textureHeight = 178.0; - final animationComponent = AnimationComponent.sequenced( + + final animationComponent = SpriteAnimationComponent.sequenced( 291, 178, 'creature.png', @@ -40,6 +41,7 @@ class MyGame extends BaseGame with TapDetector { loop: false, destroyOnFinish: true, ); + animationComponent.x = x - textureWidth / 2; animationComponent.y = y - textureHeight / 2; @@ -55,12 +57,15 @@ class MyGame extends BaseGame with TapDetector { size = screenSize; const s = 100.0; - final animationComponent = AnimationComponent(s, s, animation); + final animationComponent = SpriteAnimationComponent(s, s, animation); animationComponent.x = size.width / 2 - s; animationComponent.y = s; - final reversedAnimationComponent = - AnimationComponent(s, s, animation.reversed()); + final reversedAnimationComponent = SpriteAnimationComponent( + s, + s, + animation.reversed(), + ); reversedAnimationComponent.x = size.width / 2; reversedAnimationComponent.y = s; diff --git a/doc/examples/aseprite/lib/main.dart b/doc/examples/aseprite/lib/main.dart index 27e2350b2..bf17d2bdf 100644 --- a/doc/examples/aseprite/lib/main.dart +++ b/doc/examples/aseprite/lib/main.dart @@ -1,7 +1,7 @@ import 'package:flame/flame.dart'; import 'package:flame/game.dart'; -import 'package:flame/animation.dart' as flame_animation; -import 'package:flame/components/animation_component.dart'; +import 'package:flame/sprite_animation.dart'; +import 'package:flame/components/sprite_animation_component.dart'; import 'package:flutter/material.dart'; void main() async { @@ -17,11 +17,11 @@ class MyGame extends BaseGame { } void _start() async { - final animation = await flame_animation.Animation.fromAsepriteData( + final animation = await SpriteAnimation.fromAsepriteData( 'chopper.png', 'chopper.json', ); - final animationComponent = AnimationComponent(200, 200, animation); + final animationComponent = SpriteAnimationComponent(200, 200, animation); animationComponent.x = (size.width / 2) - 100; animationComponent.y = (size.height / 2) - 100; diff --git a/doc/examples/particles/lib/main.dart b/doc/examples/particles/lib/main.dart index 4f5608ab7..805e83e70 100644 --- a/doc/examples/particles/lib/main.dart +++ b/doc/examples/particles/lib/main.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'dart:math'; import 'dart:ui'; -import 'package:flame/animation.dart'; +import 'package:flame/sprite_animation.dart'; import 'package:flame/components/component.dart'; import 'package:flame/flare_animation.dart'; import 'package:flame/particles/circle_particle.dart'; @@ -392,10 +392,10 @@ class MyGame extends BaseGame { ); } - /// An [AnimationParticle] takes a Flame [Animation] + /// An [SpriteAnimationParticle] takes a Flame [SpriteAnimation] /// and plays it during the particle lifespan. Particle animationParticle() { - return AnimationParticle( + return SpriteAnimationParticle( animation: getBoomAnimation(), size: Position(128, 128), ); @@ -550,8 +550,8 @@ class MyGame extends BaseGame { return list[rnd.nextInt(list.length)]; } - /// Sample "explosion" animation for [AnimationParticle] example - Animation getBoomAnimation() { + /// Sample "explosion" animation for [SpriteAnimationParticle] example + SpriteAnimation getBoomAnimation() { const columns = 8; const rows = 8; const frames = columns * rows; @@ -569,7 +569,7 @@ class MyGame extends BaseGame { (i) => spritesheet.getSprite(i ~/ rows, i % columns), ); - return Animation.spriteList(sprites); + return SpriteAnimation.spriteList(sprites); } } diff --git a/doc/examples/render_flip/lib/main.dart b/doc/examples/render_flip/lib/main.dart index abf7fdfae..1943b91ee 100644 --- a/doc/examples/render_flip/lib/main.dart +++ b/doc/examples/render_flip/lib/main.dart @@ -1,5 +1,5 @@ -import 'package:flame/animation.dart' as flame_animation; -import 'package:flame/components/animation_component.dart'; +import 'package:flame/sprite_animation.dart'; +import 'package:flame/components/sprite_animation_component.dart'; import 'package:flame/flame.dart'; import 'package:flame/game.dart'; import 'package:flutter/material.dart'; @@ -12,7 +12,7 @@ void main() async { } class MyGame extends BaseGame { - final animation = flame_animation.Animation.sequenced( + final animation = SpriteAnimation.sequenced( 'chopper.png', 4, textureWidth: 48, @@ -20,8 +20,8 @@ class MyGame extends BaseGame { stepTime: 0.15, ); - AnimationComponent buildAnimation() { - final ac = AnimationComponent(100, 100, animation); + SpriteAnimationComponent buildAnimation() { + final ac = SpriteAnimationComponent(100, 100, animation); ac.x = size.width / 2 - ac.width / 2; return ac; } diff --git a/doc/examples/spritesheet/lib/main.dart b/doc/examples/spritesheet/lib/main.dart index 5845239d2..743d62a50 100644 --- a/doc/examples/spritesheet/lib/main.dart +++ b/doc/examples/spritesheet/lib/main.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flame/components/animation_component.dart'; +import 'package:flame/components/sprite_animation_component.dart'; import 'package:flame/components/sprite_component.dart'; import 'package:flame/flame.dart'; import 'package:flame/game.dart'; @@ -56,11 +56,11 @@ class MyGame extends BaseGame { spriteSheet.createAnimation(0, stepTime: 0.1, to: 7); final ghostAnimation = spriteSheet.createAnimation(1, stepTime: 0.1, to: 7); - final vampireComponent = AnimationComponent(80, 90, vampireAnimation) + final vampireComponent = SpriteAnimationComponent(80, 90, vampireAnimation) ..x = 150 ..y = 100; - final ghostComponent = AnimationComponent(80, 90, ghostAnimation) + final ghostComponent = SpriteAnimationComponent(80, 90, ghostAnimation) ..x = 150 ..y = 220; diff --git a/doc/examples/tiled/lib/main.dart b/doc/examples/tiled/lib/main.dart index be2540b9f..c7f1d3833 100644 --- a/doc/examples/tiled/lib/main.dart +++ b/doc/examples/tiled/lib/main.dart @@ -1,5 +1,5 @@ -import 'package:flame/animation.dart'; -import 'package:flame/components/animation_component.dart'; +import 'package:flame/sprite_animation.dart'; +import 'package:flame/components/sprite_animation_component.dart'; import 'package:flame/components/tiled_component.dart'; import 'package:flame/flame.dart'; import 'package:flame/game.dart'; @@ -27,10 +27,10 @@ class TiledGame extends BaseGame { return; } objGroup.tmxObjects.forEach((TmxObject obj) { - final comp = AnimationComponent( + final comp = SpriteAnimationComponent( 20.0, 20.0, - Animation.sequenced( + SpriteAnimation.sequenced( 'coins.png', 8, textureWidth: 20, diff --git a/doc/examples/widgets/lib/main.dart b/doc/examples/widgets/lib/main.dart index 2cad698f5..f03362a16 100644 --- a/doc/examples/widgets/lib/main.dart +++ b/doc/examples/widgets/lib/main.dart @@ -129,7 +129,7 @@ void main() async { (ctx) => Container( width: ctx.numberProperty('container width', 400), height: ctx.numberProperty('container height', 200), - child: AnimationWidget( + child: SpriteAnimationWidget( animation: _animation, playing: ctx.boolProperty('playing', true), anchor: parseAnchor( diff --git a/doc/images.md b/doc/images.md index 85bd8dc51..2190ea944 100644 --- a/doc/images.md +++ b/doc/images.md @@ -48,7 +48,7 @@ The render method will do nothing while the sprite has not been loaded, so you d All render methods from the Sprite class can receive a `Paint` instance as the optional named parameter `overridePaint` that parameter will override the current `Sprite` paint instance for that render call. -Sprites can also be used as widgets, to do so just use `Flame.util.spriteAsWidget` +Sprites can also be used as widgets, to do so just use `SpriteWidget` class. A complete example using sprite as widgets can be found [here](/doc/examples/animation_widget). @@ -178,9 +178,6 @@ Animations, after created, have an update and render method; the latter renders Animations are normally used inside `AnimationComponent`s, but custom components with several Animations can be created as well. - -Animations can also be used as widgets, to do so, just use `Flame.util.animationAsWidget` - A complete example of using animations as widgets can be found [here](/doc/examples/animation_widget). ## FlareAnimation diff --git a/lib/components/animation_component.dart b/lib/components/sprite_animation_component.dart similarity index 82% rename from lib/components/animation_component.dart rename to lib/components/sprite_animation_component.dart index 8366cfd49..0d8e04265 100644 --- a/lib/components/animation_component.dart +++ b/lib/components/sprite_animation_component.dart @@ -1,14 +1,14 @@ import 'dart:ui'; -import '../animation.dart'; +import '../sprite_animation.dart'; import 'position_component.dart'; -class AnimationComponent extends PositionComponent { - Animation animation; +class SpriteAnimationComponent extends PositionComponent { + SpriteAnimation animation; Paint overridePaint; bool destroyOnFinish = false; - AnimationComponent( + SpriteAnimationComponent( double width, double height, this.animation, { @@ -18,9 +18,9 @@ class AnimationComponent extends PositionComponent { this.height = height; } - AnimationComponent.empty(); + SpriteAnimationComponent.empty(); - AnimationComponent.sequenced( + SpriteAnimationComponent.sequenced( double width, double height, String imagePath, @@ -36,7 +36,7 @@ class AnimationComponent extends PositionComponent { }) { this.width = width; this.height = height; - animation = Animation.sequenced( + animation = SpriteAnimation.sequenced( imagePath, amount, amountPerRow: amountPerRow, diff --git a/lib/particles/animation_particle.dart b/lib/particles/animation_particle.dart index 81a350dd5..d323af604 100644 --- a/lib/particles/animation_particle.dart +++ b/lib/particles/animation_particle.dart @@ -2,17 +2,17 @@ import 'dart:ui'; import 'package:flutter/foundation.dart'; -import '../animation.dart'; +import '../sprite_animation.dart'; import '../particle.dart'; import '../position.dart'; -class AnimationParticle extends Particle { - final Animation animation; +class SpriteAnimationParticle extends Particle { + final SpriteAnimation animation; final Position size; final Paint overridePaint; final bool alignAnimationTime; - AnimationParticle({ + SpriteAnimationParticle({ @required this.animation, this.size, this.overridePaint, diff --git a/lib/animation.dart b/lib/sprite_animation.dart similarity index 83% rename from lib/animation.dart rename to lib/sprite_animation.dart index 463e1e113..1fbc7ce34 100644 --- a/lib/animation.dart +++ b/lib/sprite_animation.dart @@ -3,8 +3,8 @@ import 'dart:convert'; import 'flame.dart'; import 'sprite.dart'; -/// Represents a single animation frame. -class Frame { +/// Represents a single sprite animation frame. +class SpriteAnimationFrame { /// The [Sprite] to be displayed. Sprite sprite; @@ -12,15 +12,15 @@ class Frame { double stepTime; /// Create based on the parameters. - Frame(this.sprite, this.stepTime); + SpriteAnimationFrame(this.sprite, this.stepTime); } -typedef OnCompleteAnimation = void Function(); +typedef OnCompleteSpriteAnimation = void Function(); -/// Represents an animation, that is, a list of sprites that change with time. -class Animation { +/// Represents a sprite animation, that is, a list of sprites that change with time. +class SpriteAnimation { /// The frames that compose this animation. - List frames = []; + List frames = []; /// Index of the current frame that should be displayed. int currentIndex = 0; @@ -37,23 +37,23 @@ class Animation { bool loop = true; /// Registered method to be triggered when the animation complete. - OnCompleteAnimation onCompleteAnimation; + OnCompleteSpriteAnimation onComplete; /// Creates an animation given a list of frames. - Animation(this.frames, {this.loop = true}); + SpriteAnimation(this.frames, {this.loop = true}); /// Creates an empty animation - Animation.empty(); + SpriteAnimation.empty(); /// Creates an animation based on the parameters. /// /// All frames have the same [stepTime]. - Animation.spriteList(List sprites, + SpriteAnimation.spriteList(List sprites, {double stepTime, this.loop = true}) { if (sprites.isEmpty) { throw Exception('You must have at least one frame!'); } - frames = sprites.map((s) => Frame(s, stepTime)).toList(); + frames = sprites.map((s) => SpriteAnimationFrame(s, stepTime)).toList(); } /// Automatically creates a sequenced animation, that is, an animation based on a sprite sheet. @@ -71,7 +71,7 @@ class Animation { /// For example, if you have a sprite sheet where each row is an animation, and each frame is 32x32 /// Animation.sequenced('sheet.png', 8, textureY: 32.0 * i, textureWidth: 32.0, textureHeight: 32.0); /// This will create the i-th animation on the 'sheet.png', given it has 8 frames. - Animation.sequenced( + SpriteAnimation.sequenced( String imagePath, int amount, { int amountPerRow, @@ -83,7 +83,7 @@ class Animation { this.loop = true, }) : assert(amountPerRow == null || amount >= amountPerRow) { amountPerRow ??= amount; - frames = List(amount); + frames = List(amount); for (var i = 0; i < amount; i++) { final Sprite sprite = Sprite( imagePath, @@ -92,12 +92,12 @@ class Animation { width: textureWidth, height: textureHeight, ); - frames[i] = Frame(sprite, stepTime); + frames[i] = SpriteAnimationFrame(sprite, stepTime); } } - /// Works just like [Animation.sequenced], but it takes a list of variable [stepTimes], associating each one with one frame in the sequence. - Animation.variableSequenced( + /// Works just like [SpriteAnimation.sequenced], but it takes a list of variable [stepTimes], associating each one with one frame in the sequence. + SpriteAnimation.variableSequenced( String imagePath, int amount, List stepTimes, { @@ -109,7 +109,7 @@ class Animation { this.loop = true, }) : assert(amountPerRow == null || amount >= amountPerRow) { amountPerRow ??= amount; - frames = List(amount); + frames = List(amount); for (var i = 0; i < amount; i++) { final Sprite sprite = Sprite( imagePath, @@ -118,7 +118,7 @@ class Animation { width: textureWidth, height: textureHeight, ); - frames[i] = Frame(sprite, stepTimes[i]); + frames[i] = SpriteAnimationFrame(sprite, stepTimes[i]); } } @@ -127,7 +127,7 @@ class Animation { /// /// [imagePath]: Source of the sprite sheet animation /// [dataPath]: Animation's exported data in json format - static Future fromAsepriteData( + static Future fromAsepriteData( String imagePath, String dataPath) async { final String content = await Flame.assets.readFile(dataPath); final Map json = jsonDecode(content); @@ -151,14 +151,14 @@ class Animation { height: height.toDouble(), ); - return Frame(sprite, stepTime); + return SpriteAnimationFrame(sprite, stepTime); }); - return Animation(frames.toList(), loop: true); + return SpriteAnimation(frames.toList(), loop: true); } /// The current frame that should be displayed. - Frame get currentFrame => frames[currentIndex]; + SpriteAnimationFrame get currentFrame => frames[currentIndex]; /// Returns whether the animation is on the last frame. bool get isLastFrame => currentIndex == frames.length - 1; @@ -209,7 +209,7 @@ class Animation { return; } if (!loop && isLastFrame) { - onCompleteAnimation?.call(); + onComplete?.call(); return; } while (clock > currentFrame.stepTime) { @@ -226,8 +226,8 @@ class Animation { } /// Returns a new Animation based on this animation, but with its frames in reversed order - Animation reversed() { - return Animation(frames.reversed.toList(), loop: loop); + SpriteAnimation reversed() { + return SpriteAnimation(frames.reversed.toList(), loop: loop); } /// Whether all sprites composing this animation are loaded. diff --git a/lib/spritesheet.dart b/lib/spritesheet.dart index 996c05a37..c3b550db7 100644 --- a/lib/spritesheet.dart +++ b/lib/spritesheet.dart @@ -1,6 +1,6 @@ import 'package:meta/meta.dart'; import 'sprite.dart'; -import 'animation.dart'; +import 'sprite_animation.dart'; import 'dart:ui'; @@ -85,10 +85,10 @@ class SpriteSheet { return s; } - /// Creates an animation from this SpriteSheet + /// Creates a sprite animation from this SpriteSheet /// /// An [from] and a [to] parameter can be specified to create an animation from a subset of the columns on the row - Animation createAnimation(int row, + SpriteAnimation createAnimation(int row, {double stepTime, bool loop = true, int from = 0, int to}) { final spriteRow = _sprites[row]; @@ -98,7 +98,7 @@ class SpriteSheet { final spriteList = spriteRow.sublist(from, to); - return Animation.spriteList( + return SpriteAnimation.spriteList( spriteList, stepTime: stepTime, loop: loop, diff --git a/lib/util.dart b/lib/util.dart index 523986d47..01b74d2af 100644 --- a/lib/util.dart +++ b/lib/util.dart @@ -4,13 +4,7 @@ import 'dart:ui'; import 'package:flutter/gestures.dart'; import 'package:flutter/services.dart'; import 'package:flutter/foundation.dart'; -import 'package:flutter/widgets.dart' as widgets; -import 'animation.dart'; -import 'game/base_game.dart'; -import 'game/embedded_game_widget.dart'; -import 'sprite.dart'; -import 'components/animation_component.dart'; import 'position.dart'; /// Some utilities that did not fit anywhere else. @@ -159,43 +153,4 @@ class Util { fn(c); c.translate(-p.x, -p.y); } - - /// Returns a regular Flutter widget representing this animation, rendered with the specified size. - /// - /// This actually creates an [EmbeddedGameWidget] with a [SimpleGame] whose only content is an [AnimationComponent] created from the provided [animation]. - /// You can use this implementation as base to easily create your own widgets based on more complex games. - /// This is intended to be used by non-game apps that want to add a sprite sheet animation. - /// - @Deprecated('Use SpriteAnimation instead') - widgets.Widget animationAsWidget(Position size, Animation animation) { - return EmbeddedGameWidget( - BaseGame()..add(AnimationComponent(size.x, size.y, animation)), - size: size, - ); - } - - /// Returns a regular Flutter widget representing this sprite, rendered with the specified size. - /// - /// This will create a [CustomPaint] widget using a [CustomPainter] for rendering the [Sprite] - /// Be aware that the Sprite must have been loaded, otherwise it can't be rendered - /// - @Deprecated('Use SpriteWidget instead') - widgets.CustomPaint spriteAsWidget(Size size, Sprite sprite) => - widgets.CustomPaint(size: size, painter: _SpriteCustomPainter(sprite)); -} - -class _SpriteCustomPainter extends widgets.CustomPainter { - final Sprite _sprite; - - _SpriteCustomPainter(this._sprite); - - @override - void paint(Canvas canvas, Size size) { - if (_sprite.loaded()) { - _sprite.render(canvas, width: size.width, height: size.height); - } - } - - @override - bool shouldRepaint(widgets.CustomPainter old) => false; } diff --git a/lib/widgets/animation_widget.dart b/lib/widgets/animation_widget.dart index b38053181..91b2b6c49 100644 --- a/lib/widgets/animation_widget.dart +++ b/lib/widgets/animation_widget.dart @@ -1,17 +1,23 @@ -import 'package:flutter/material.dart' hide Animation; -import 'package:flame/animation.dart'; +import 'package:flutter/material.dart'; +import 'package:flame/sprite_animation.dart'; import 'dart:math'; import '../anchor.dart'; import './sprite_widget.dart'; -class AnimationWidget extends StatefulWidget { - final Animation animation; +/// A [StatefulWidget] that render a [SpriteAnimation]. +class SpriteAnimationWidget extends StatefulWidget { + /// The [SpriteAnimation] to be rendered + final SpriteAnimation animation; + + /// The positioning [Anchor] final Anchor anchor; + + /// Should the [animation] be playing or not final bool playing; - AnimationWidget({ + SpriteAnimationWidget({ this.animation, this.playing = true, this.anchor = Anchor.topLeft, @@ -21,7 +27,7 @@ class AnimationWidget extends StatefulWidget { State createState() => _AnimationWidget(); } -class _AnimationWidget extends State +class _AnimationWidget extends State with SingleTickerProviderStateMixin { AnimationController _controller; double _lastUpdated; @@ -52,7 +58,7 @@ class _AnimationWidget extends State }); }); - widget.animation.onCompleteAnimation = _pauseAnimation; + widget.animation.onComplete = _pauseAnimation; if (widget.playing) { _initAnimation(); diff --git a/lib/widgets/sprite_widget.dart b/lib/widgets/sprite_widget.dart index d1c7ea78a..2a866b100 100644 --- a/lib/widgets/sprite_widget.dart +++ b/lib/widgets/sprite_widget.dart @@ -1,3 +1,4 @@ +import 'package:flame/widgets/animation_widget.dart'; import 'package:flutter/widgets.dart'; import 'package:meta/meta.dart'; import 'dart:math'; @@ -5,8 +6,14 @@ import 'dart:math'; import '../sprite.dart'; import '../anchor.dart'; +/// A [StatefulWidget] that renders a still [Sprite]. +/// +/// To render an animation, use [SpriteAnimationWidget]. class SpriteWidget extends StatelessWidget { + /// The [Sprite] to be rendered final Sprite sprite; + + /// The positioning [Anchor] for the [sprite] final Anchor anchor; SpriteWidget({ @@ -17,19 +24,19 @@ class SpriteWidget extends StatelessWidget { @override Widget build(_) { return Container( - child: CustomPaint(painter: _SpritePainer(sprite, anchor)), + child: CustomPaint(painter: _SpritePainter(sprite, anchor)), ); } } -class _SpritePainer extends CustomPainter { +class _SpritePainter extends CustomPainter { final Sprite _sprite; final Anchor _anchor; - _SpritePainer(this._sprite, this._anchor); + _SpritePainter(this._sprite, this._anchor); @override - bool shouldRepaint(_SpritePainer old) { + bool shouldRepaint(_SpritePainter old) { return old._sprite != _sprite || old._anchor != _anchor; }