Line data Source code
1 : import 'dart:ui'; 2 : 3 : import '../image_composition.dart'; 4 : import 'anchor.dart'; 5 : import 'assets/images.dart'; 6 : import 'extensions/offset.dart'; 7 : import 'extensions/vector2.dart'; 8 : import 'flame.dart'; 9 : import 'palette.dart'; 10 : 11 : /// A [Sprite] is a region of an [Image] that can be rendered in the Canvas. 12 : /// 13 : /// It might represent the entire image or be one of the pieces a spritesheet is composed of. 14 : /// It holds a reference to the source image from which the region is extracted, and the [src] 15 : /// rectangle is the portion inside that image that is to be rendered (not to be confused with the 16 : /// `dest` rect, which is where in the Canvas the sprite is rendered). 17 : /// It also has a [paint] field that can be overwritten to apply a tint to this [Sprite] (default is 18 : /// white, meaning no tint). 19 : class Sprite { 20 : Paint paint = BasicPalette.white.paint(); 21 : Image image; 22 : Rect src = Rect.zero; 23 : 24 4 : Sprite( 25 : this.image, { 26 : Vector2? srcPosition, 27 : Vector2? srcSize, 28 : }) { 29 4 : this.srcSize = srcSize; 30 4 : this.srcPosition = srcPosition; 31 : } 32 : 33 : /// Takes a path of an image, a [srcPosition] and [srcSize] and loads the sprite animation 34 : /// When the [images] is omitted, the global [Flame.images] is used 35 0 : static Future<Sprite> load( 36 : String src, { 37 : Vector2? srcPosition, 38 : Vector2? srcSize, 39 : Images? images, 40 : }) async { 41 0 : final _images = images ?? Flame.images; 42 0 : final image = await _images.load(src); 43 0 : return Sprite(image, srcPosition: srcPosition, srcSize: srcSize); 44 : } 45 : 46 0 : double get _imageWidth => image.width.toDouble(); 47 : 48 0 : double get _imageHeight => image.height.toDouble(); 49 : 50 0 : Vector2 get originalSize => Vector2(_imageWidth, _imageHeight); 51 : 52 24 : Vector2 get srcSize => Vector2(src.width, src.height); 53 : 54 4 : set srcSize(Vector2? size) { 55 8 : final actualSize = size ?? image.size; 56 12 : src = srcPosition.toPositionedRect(actualSize); 57 : } 58 : 59 16 : Vector2 get srcPosition => src.topLeft.toVector2(); 60 : 61 4 : set srcPosition(Vector2? position) { 62 16 : src = (position ?? Vector2.zero()).toPositionedRect(srcSize); 63 : } 64 : 65 : /// Same as [render], but takes both the position and the size as a single 66 : /// [Rect]. 67 : /// 68 : /// **Note**: only use this if you are already using [Rect]'s to represent both the position and 69 : /// dimension of your [Sprite]. If you are using [Vector2]s, prefer the other method. 70 0 : void renderRect( 71 : Canvas canvas, 72 : Rect rect, { 73 : Paint? overridePaint, 74 : }) { 75 0 : render( 76 : canvas, 77 0 : position: rect.topLeft.toVector2(), 78 0 : size: rect.size.toVector2(), 79 : overridePaint: overridePaint, 80 : ); 81 : } 82 : 83 : /// Renders this sprite onto the [canvas]. 84 : /// 85 : /// * [position]: x,y coordinates where it will be drawn; default to origin. 86 : /// * [size]: width/height dimensions; it can be bigger or smaller than the original size -- but it 87 : /// defaults to the original texture size. 88 : /// * [anchor]: where in the sprite the x/y coordinates refer to; defaults to topLeft. 89 : /// * [overridePaint]: paint to use. You can also change the paint on your Sprite instance. Default 90 : /// is white. 91 0 : void render( 92 : Canvas canvas, { 93 : Vector2? position, 94 : Vector2? size, 95 : Anchor anchor = Anchor.topLeft, 96 : Paint? overridePaint, 97 : }) { 98 0 : final drawPosition = position ?? Vector2.zero(); 99 0 : final drawSize = size ?? srcSize; 100 : 101 0 : final delta = anchor.toVector2()..multiply(drawSize); 102 0 : final drawRect = (drawPosition + delta).toPositionedRect(drawSize); 103 : 104 0 : final drawPaint = overridePaint ?? paint; 105 : 106 0 : canvas.drawImageRect(image, src, drawRect, drawPaint); 107 : } 108 : 109 : /// Return a new Image based on the [src] of the Sprite. 110 : /// 111 : /// **Note:** This is a heavy async operation and should not be called inside the game loop. 112 0 : Future<Image> toImage() async { 113 0 : final composition = ImageComposition() 114 0 : ..add(image, Vector2.zero(), source: src); 115 0 : return composition.compose(); 116 : } 117 : }