diff --git a/doc/components.md b/doc/components.md index 0fca8ca74..e528b7928 100644 --- a/doc/components.md +++ b/doc/components.md @@ -14,13 +14,13 @@ The most commonly used implementation, `SpriteComponent`, can be created with a Sprite sprite = Sprite('player.png'); final size = Vector2.all(128.0); - var player = SpriteComponent.fromSprite(size, sprite); // width, height, sprite + var player = SpriteComponent.fromSprite(size, sprite); // screen coordinates - player.position = ... // Vector2(0.0, 0,0) by default + player.position = ... // Vector2(0.0, 0.0) by default player.angle = ... // 0 by default - player.render(canvas); // it will render only if the image is loaded and the x, y, width and height parameters are not null + player.render(canvas); // it will render only if the image is loaded and the position and size parameters are not null ``` In the event that you want to easily change the direction of your components rendering, you can also use @@ -54,20 +54,31 @@ This component uses an instance of the [Animation](/doc/images.md#Animation) cla This will create a simple three frame animation ```dart - List sprites = [0, 1, 2].map((i) => new Sprite('player_${i}.png')).toList(); - final size = Vector2(64.0, 64.0); + List sprites = [0, 1, 2].map((i) => Sprite('player_${i}.png')).toList(); + final size = Vector2.all(64.0); this.player = AnimationComponent(size, new Animation.spriteList(sprites, stepTime: 0.01)); ``` If you have a sprite sheet, you can use the `sequenced` constructor, identical to the one provided by the `Animation` class (check more details in [the appropriate section](/doc/images.md#Animation)): ```dart - final size = Vector2(64.0, 64.0); + final size = Vector2.all(64.0); this.player = AnimationComponent.sequenced(size, 'player.png', 2); ``` If you are not using `BaseGame`, don't forget this component needs to be update'd even if static, because the animation object needs to be ticked to move the frames. +## SvgComponent + +This component uses an instance of `Svg` class to represent a Component that has a svg that is rendered on the game: + +```dart + Svg svg = Svg('android.svg'); + SvgComponent android = SvgComponent.fromSvg(100, 100, svg); + android.x = 100; + android.y = 100; +``` + ## FlareActor Component *Note*: The previous implementation of a Flare integration API using `FlareAnimation` and `FlareComponent` has been deprecated. diff --git a/doc/examples/aseprite/lib/main.dart b/doc/examples/aseprite/lib/main.dart index 4c038c63f..3a511530a 100644 --- a/doc/examples/aseprite/lib/main.dart +++ b/doc/examples/aseprite/lib/main.dart @@ -24,7 +24,7 @@ class MyGame extends BaseGame { ); final spriteSize = Vector2.all(200); final animationComponent = SpriteAnimationComponent(spriteSize, animation) - ..position = size / 2 - Vector2(100, 100); + ..position = size / 2 - Vector2.all(100); add(animationComponent); } diff --git a/doc/examples/debug/lib/main.dart b/doc/examples/debug/lib/main.dart index 158bc5ade..9af8d3a13 100644 --- a/doc/examples/debug/lib/main.dart +++ b/doc/examples/debug/lib/main.dart @@ -20,7 +20,7 @@ class AndroidComponent extends SpriteComponent with Resizable { int xDirection = 1; int yDirection = 1; - AndroidComponent() : super.square(100, 'android.png'); + AndroidComponent() : super.fromImagePath(Vector2.all(100), 'android.png'); @override void update(double dt) { diff --git a/doc/examples/effects/combined_effects/lib/main.dart b/doc/examples/effects/combined_effects/lib/main.dart index 2e927a4be..c1c35a307 100644 --- a/doc/examples/effects/combined_effects/lib/main.dart +++ b/doc/examples/effects/combined_effects/lib/main.dart @@ -24,8 +24,8 @@ class MyGame extends BaseGame with TapDetector { MyGame() { final green = Paint()..color = const Color(0xAA338833); final red = Paint()..color = const Color(0xAA883333); - greenSquare = Square(green, 100, 100); - final redSquare = Square(red, 100, 100); + greenSquare = Square(green, Vector2.all(100)); + final redSquare = Square(red, Vector2.all(100)); add(greenSquare); add(redSquare); } diff --git a/doc/examples/effects/combined_effects/lib/square.dart b/doc/examples/effects/combined_effects/lib/square.dart index c6002ca22..93154bf4d 100644 --- a/doc/examples/effects/combined_effects/lib/square.dart +++ b/doc/examples/effects/combined_effects/lib/square.dart @@ -8,10 +8,9 @@ import 'package:flame/extensions/vector2.dart'; class Square extends PositionComponent { final Paint _paint; - Square(this._paint, double x, double y, {double angle = 0.0}) { - size = Vector2(width, height); - this.x = x; - this.y = y; + Square(this._paint, Vector2 position, {double angle = 0.0}) { + size = Vector2.all(100.0); + this.position = position; this.angle = angle; anchor = Anchor.center; } diff --git a/doc/examples/effects/infinite_effects/lib/main.dart b/doc/examples/effects/infinite_effects/lib/main.dart index ad1218f65..50e3422ec 100644 --- a/doc/examples/effects/infinite_effects/lib/main.dart +++ b/doc/examples/effects/infinite_effects/lib/main.dart @@ -26,9 +26,9 @@ class MyGame extends BaseGame with TapDetector { final green = Paint()..color = const Color(0xAA338833); final red = Paint()..color = const Color(0xAA883333); final orange = Paint()..color = const Color(0xAABB6633); - greenSquare = Square(green, 100, 100); - redSquare = Square(red, 200, 200); - orangeSquare = Square(orange, 200, 400); + greenSquare = Square(green, Vector2.all(100)); + redSquare = Square(red, Vector2.all(200)); + orangeSquare = Square(orange, Vector2(200, 400)); add(greenSquare); add(redSquare); add(orangeSquare); diff --git a/doc/examples/effects/infinite_effects/lib/square.dart b/doc/examples/effects/infinite_effects/lib/square.dart index c6002ca22..93154bf4d 100644 --- a/doc/examples/effects/infinite_effects/lib/square.dart +++ b/doc/examples/effects/infinite_effects/lib/square.dart @@ -8,10 +8,9 @@ import 'package:flame/extensions/vector2.dart'; class Square extends PositionComponent { final Paint _paint; - Square(this._paint, double x, double y, {double angle = 0.0}) { - size = Vector2(width, height); - this.x = x; - this.y = y; + Square(this._paint, Vector2 position, {double angle = 0.0}) { + size = Vector2.all(100.0); + this.position = position; this.angle = angle; anchor = Anchor.center; } diff --git a/doc/examples/effects/sequence_effect/lib/main.dart b/doc/examples/effects/sequence_effect/lib/main.dart index 0727f1eff..03ca751c4 100644 --- a/doc/examples/effects/sequence_effect/lib/main.dart +++ b/doc/examples/effects/sequence_effect/lib/main.dart @@ -23,7 +23,7 @@ class MyGame extends BaseGame with TapDetector { MyGame() { final green = Paint()..color = const Color(0xAA338833); - greenSquare = Square(green, 100, 100); + greenSquare = Square(green, Vector2.all(100)); add(greenSquare); } diff --git a/doc/examples/effects/sequence_effect/lib/square.dart b/doc/examples/effects/sequence_effect/lib/square.dart index c6002ca22..93154bf4d 100644 --- a/doc/examples/effects/sequence_effect/lib/square.dart +++ b/doc/examples/effects/sequence_effect/lib/square.dart @@ -8,10 +8,9 @@ import 'package:flame/extensions/vector2.dart'; class Square extends PositionComponent { final Paint _paint; - Square(this._paint, double x, double y, {double angle = 0.0}) { - size = Vector2(width, height); - this.x = x; - this.y = y; + Square(this._paint, Vector2 position, {double angle = 0.0}) { + size = Vector2.all(100.0); + this.position = position; this.angle = angle; anchor = Anchor.center; } diff --git a/doc/examples/gestures/lib/main_tapables.dart b/doc/examples/gestures/lib/main_tapables.dart index 1c37f9821..898f69a83 100644 --- a/doc/examples/gestures/lib/main_tapables.dart +++ b/doc/examples/gestures/lib/main_tapables.dart @@ -22,10 +22,9 @@ class TapableSquare extends PositionComponent with Tapable { bool _beenPressed = false; - TapableSquare({double y = 100, double x = 100}) { + TapableSquare({Vector2 position}) { size = Vector2.all(100); - this.x = x; - this.y = y; + this.position = position ?? Vector2.all(100); } @override @@ -52,7 +51,7 @@ class TapableSquare extends PositionComponent with Tapable { class MyGame extends BaseGame with HasTapableComponents { MyGame() { - add(TapableSquare(y: 100)); - add(TapableSquare(y: 250)); + add(TapableSquare()); + add(TapableSquare()..y = 250); } } diff --git a/doc/examples/isometric/lib/main.dart b/doc/examples/isometric/lib/main.dart index 769834026..9874ff04e 100644 --- a/doc/examples/isometric/lib/main.dart +++ b/doc/examples/isometric/lib/main.dart @@ -25,7 +25,8 @@ class Selector extends SpriteComponent { bool show = false; Selector(double s) - : super.fromSprite(s, s, Sprite('selector.png', width: 32, height: 32)); + : super.fromSprite( + Vector2.all(s), Sprite('selector.png', size: Vector2.all(32.0))); @override void render(Canvas canvas) { @@ -81,6 +82,6 @@ class MyGame extends BaseGame with MouseMovementDetector { final screenPosition = event.position.toVector2(); final block = base.getBlock(screenPosition); selector.show = base.containsBlock(block); - selector.setPosition(base.getBlockPosition(block) + topLeft); + selector.position = base.getBlockPosition(block) + topLeft; } } diff --git a/doc/examples/sound/lib/main.dart b/doc/examples/sound/lib/main.dart index 3db4a279c..bcb4b5623 100644 --- a/doc/examples/sound/lib/main.dart +++ b/doc/examples/sound/lib/main.dart @@ -52,6 +52,6 @@ class MyGame extends BaseGame { add(Ball(size) ..y = (size.y / 2) - 50 - ..size = Vector2(100, 100)); + ..size = Vector2.all(100)); } } diff --git a/doc/examples/sprites/lib/main.dart b/doc/examples/sprites/lib/main.dart index 685dd0752..cc7011b02 100644 --- a/doc/examples/sprites/lib/main.dart +++ b/doc/examples/sprites/lib/main.dart @@ -27,8 +27,10 @@ class MyGame extends BaseGame { void initSprites() async { final r = Random(); - List.generate(500, (i) => SpriteComponent.square(32, 'test.png')) - .forEach((sprite) { + List.generate( + 500, + (i) => SpriteComponent.fromImagePath(Vector2.all(32), 'test.png'), + ).forEach((sprite) { sprite.x = r.nextInt(size.x.toInt()).toDouble(); sprite.y = r.nextInt(size.y.toInt()).toDouble(); add(sprite); diff --git a/lib/components/flare_component.dart b/lib/components/flare_component.dart index 4e429aa04..5f6855448 100644 --- a/lib/components/flare_component.dart +++ b/lib/components/flare_component.dart @@ -30,7 +30,8 @@ class FlareComponent extends PositionComponent { } } - void updateSize(Vector2 newSize) { + @override + set size(Vector2 newSize) { super.size = newSize; if (loaded()) { _flareAnimation.size = size; diff --git a/lib/components/isometric_tile_map_component.dart b/lib/components/isometric_tile_map_component.dart index 39742a994..cb5de536a 100644 --- a/lib/components/isometric_tile_map_component.dart +++ b/lib/components/isometric_tile_map_component.dart @@ -93,17 +93,14 @@ class IsometricTileMapComponent extends PositionComponent { void render(Canvas c) { super.render(c); - final size = Vector2( - effectiveTileSize.toDouble(), - effectiveTileSize.toDouble(), - ); + final size = Vector2.all(effectiveTileSize.toDouble()); for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[i].length; j++) { final element = matrix[i][j]; if (element != -1) { final sprite = tileset.getTile(element); final p = getBlockPositionInts(j, i); - sprite.renderRect(c, p.toRect(size)); + sprite.renderRect(c, p.toPositionedRect(size)); } } } diff --git a/lib/components/position_component.dart b/lib/components/position_component.dart index 2956ca7a4..915829cec 100644 --- a/lib/components/position_component.dart +++ b/lib/components/position_component.dart @@ -1,4 +1,4 @@ -import 'dart:ui'; +import 'dart:ui' hide Offset; import 'package:meta/meta.dart'; import 'package:ordered_set/comparing.dart'; @@ -8,6 +8,7 @@ import '../anchor.dart'; import '../effects/effects.dart'; import '../game.dart'; import '../text_config.dart'; +import '../extensions/offset.dart'; import '../extensions/vector2.dart'; import 'component.dart'; @@ -41,9 +42,21 @@ abstract class PositionComponent extends Component { /// Width (size) that this component is rendered with. double get width => size.x; + set width(double width) => size.x = width; /// Height (size) that this component is rendered with. double get height => size.y; + set height(double height) => size.y = height; + + /// Get the top left position regardless of the anchor + Vector2 get anchorPosition { + return position - anchor.relativePosition.clone()..multiply(size); + } + + /// Set the top left position regardless of the anchor + set anchorPosition(Vector2 position) { + this.position = position + anchor.relativePosition.clone()..multiply(size); + } /// Angle (with respect to the x-axis) this component should be rendered with. /// It is rotated around its anchor. @@ -80,23 +93,13 @@ abstract class PositionComponent extends Component { /// Returns the relative position/size of this component. /// Relative because it might be translated by their parents (which is not considered here). - Rect toRect() { - return Rect.fromLTWH( - x - anchor.relativePosition.x * width, - y - anchor.relativePosition.y * height, - width, - height, - ); - } + Rect toRect() => anchorPosition.toPositionedRect(size); - /// Mutates x, y, width and height using the provided [rect] as basis. + /// Mutates position and size using the provided [rect] as basis. /// This is a relative rect, same definition that [toRect] use (therefore both methods are compatible, i.e. setByRect ∘ toRect = identity). void setByRect(Rect rect) { - position.setValues( - rect.left + anchor.relativePosition.x * rect.width, - rect.top + anchor.relativePosition.y * rect.height, - ); size.setValues(rect.width, rect.height); + anchorPosition = rect.topLeft.toVector2(); } double angleTo(PositionComponent c) => position.angleTo(c.position); @@ -125,9 +128,8 @@ abstract class PositionComponent extends Component { canvas.translate(x, y); canvas.rotate(angle); - final double dx = -anchor.relativePosition.x * width; - final double dy = -anchor.relativePosition.y * height; - canvas.translate(dx, dy); + final Vector2 delta = -anchor.relativePosition.clone()..multiply(size); + canvas.translate(delta.x, delta.y); // Handle inverted rendering by moving center and flipping. if (renderFlipX || renderFlipY) { diff --git a/lib/components/sprite_component.dart b/lib/components/sprite_component.dart index b6306371d..8ad04bec1 100644 --- a/lib/components/sprite_component.dart +++ b/lib/components/sprite_component.dart @@ -23,10 +23,7 @@ class SpriteComponent extends PositionComponent { SpriteComponent(); - SpriteComponent.square(double size, String imagePath) - : this.rectangle(Vector2(size, size), imagePath); - - SpriteComponent.rectangle(Vector2 size, String imagePath) + SpriteComponent.fromImagePath(Vector2 size, String imagePath) : this.fromSprite(size, Sprite(imagePath)); SpriteComponent.fromSprite(Vector2 size, this.sprite) { diff --git a/lib/extensions/rect.dart b/lib/extensions/rect.dart index adb11c599..5cdcdea1b 100644 --- a/lib/extensions/rect.dart +++ b/lib/extensions/rect.dart @@ -16,17 +16,6 @@ extension RectExtension on Rect { // Until [extension] will allow static methods we need to keep these functions // in a utility class class RectFactory { - /// Creates a [Rect] with the size of [Size] - static Rect fromSize(Size size) { - return Rect.fromLTWH(0, 0, size.width, size.height); - } - - /// Creates a [Rect] having its left upper corner in start and its right - /// bottom corner in end - static Rect fromVectors(Vector2 start, Vector2 end) { - return Rect.fromLTWH(start.x, start.y, end.x, end.y); - } - /// Creates bounds in from of a [Rect] from a list of [Vector2] static Rect fromBounds(List pts) { final double minx = pts.map((e) => e.x).reduce(min); diff --git a/lib/extensions/vector2.dart b/lib/extensions/vector2.dart index 114ab88c7..44997804e 100644 --- a/lib/extensions/vector2.dart +++ b/lib/extensions/vector2.dart @@ -19,9 +19,9 @@ extension Vector2Extension on Vector2 { /// argument [Vector2] Rect toPositionedRect(Vector2 size) => Rect.fromLTWH(x, y, size.x, size.y); - /// Creates a [Rect] starting in origo and going the [Vector2] + /// Creates a [Rect] starting in origin and going the [Vector2] Rect toRect() => Rect.fromLTWH(0, 0, x, y); - + /// Linearly interpolate towards another Vector2 void lerp(Vector2 to, double t) { setFrom(this + (to - this) * t); diff --git a/lib/sprite_animation.dart b/lib/sprite_animation.dart index d0f9aa502..09f0928e8 100644 --- a/lib/sprite_animation.dart +++ b/lib/sprite_animation.dart @@ -85,7 +85,7 @@ class SpriteAnimation { amountPerRow ??= amount; texturePosition ??= Vector2.zero(); frames = List(amount); - for (var i = 0; i < amount; i++) { + for (int i = 0; i < amount; i++) { final position = Vector2( texturePosition.x + (i % amountPerRow) * textureSize.x, texturePosition.y + (i ~/ amountPerRow) * textureSize.y, @@ -111,7 +111,7 @@ class SpriteAnimation { }) : assert(amountPerRow == null || amount >= amountPerRow) { amountPerRow ??= amount; frames = List(amount); - for (var i = 0; i < amount; i++) { + for (int i = 0; i < amount; i++) { final position = Vector2( texturePosition.x + (i % amountPerRow) * textureSize.x, texturePosition.y + (i ~/ amountPerRow) * textureSize.y,