From a17fe4cdfaafa071cfd2ab8ef8279b26b79f00a7 Mon Sep 17 00:00:00 2001 From: Luan Nico Date: Sun, 13 Oct 2024 12:09:29 -0400 Subject: [PATCH] fix: Fix SpriteBatch to comply with new drawAtlas requirement (#3338) Fix SpriteBatch to comply with new drawAtlas requirement Fixes: #3331 --- .../sprites/sprite_batch_load_example.dart | 5 ++ packages/flame/lib/src/sprite_batch.dart | 20 +++--- .../test/_goldens/sprite_batch_test_1.png | Bin 0 -> 173 bytes .../test/_goldens/sprite_batch_test_2.png | Bin 0 -> 147 bytes packages/flame/test/sprite_batch_test.dart | 67 ++++++++++++++++++ packages/flame_test/lib/src/test_golden.dart | 15 +++- 6 files changed, 98 insertions(+), 9 deletions(-) create mode 100644 packages/flame/test/_goldens/sprite_batch_test_1.png create mode 100644 packages/flame/test/_goldens/sprite_batch_test_2.png diff --git a/examples/lib/stories/sprites/sprite_batch_load_example.dart b/examples/lib/stories/sprites/sprite_batch_load_example.dart index eaf020792..ed242a013 100644 --- a/examples/lib/stories/sprites/sprite_batch_load_example.dart +++ b/examples/lib/stories/sprites/sprite_batch_load_example.dart @@ -20,6 +20,11 @@ class SpriteBatchLoadExample extends FlameGame { class MySpriteBatchComponent extends SpriteBatchComponent with HasGameReference { + MySpriteBatchComponent() + : super( + blendMode: BlendMode.srcOver, + ); + @override Future onLoad() async { final spriteBatch = await game.loadSpriteBatch('boom.png'); diff --git a/packages/flame/lib/src/sprite_batch.dart b/packages/flame/lib/src/sprite_batch.dart index 8dfddf95e..6b3beeec0 100644 --- a/packages/flame/lib/src/sprite_batch.dart +++ b/packages/flame/lib/src/sprite_batch.dart @@ -277,9 +277,7 @@ class SpriteBatch { _sources[index] = newBatchItem.source; _transforms[index] = newBatchItem.transform; - if (color != null) { - _colors[index] = color; - } + _colors[index] = color ?? _defaultColor; } /// Add a new batch item using a RSTransform. @@ -328,9 +326,7 @@ class SpriteBatch { : batchItem.source, ); _transforms.add(batchItem.transform); - if (color != null) { - _colors.add(color); - } + _colors.add(color ?? _defaultColor); } /// Add a new batch item. @@ -413,13 +409,19 @@ class SpriteBatch { final renderPaint = paint ?? _emptyPaint; + final hasNoColors = _colors.every((c) => c == _defaultColor); + final actualBlendMode = blendMode ?? defaultBlendMode; + if (!hasNoColors && actualBlendMode == null) { + throw 'When setting any colors, a blend mode must be provided.'; + } + if (useAtlas && !_flippedAtlasStatus.isGenerating) { canvas.drawAtlas( atlas, _transforms, _sources, - _colors.isEmpty ? null : _colors, - blendMode ?? defaultBlendMode, + hasNoColors ? null : _colors, + actualBlendMode, cullRect, renderPaint, ); @@ -441,4 +443,6 @@ class SpriteBatch { } } } + + static const _defaultColor = Color(0x00000000); } diff --git a/packages/flame/test/_goldens/sprite_batch_test_1.png b/packages/flame/test/_goldens/sprite_batch_test_1.png new file mode 100644 index 0000000000000000000000000000000000000000..7df9938744543f15639ad521759f2d766e6e94d9 GIT binary patch literal 173 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&L!3HFEdh;y=QjEnx?oJHr&dIz4a#)I;JVQ8u zpoSx*1IQ2eba4#Pn0R(lAlCr{4(G`ig||Il6TYQ>>B(=#1qS=4%xK`BIkU5AmzER5 zg131+&wDNJvl=?JyopVlv`TuS+M~p@Bf4))CQsSfbCG>R@8tQckDv7X*li#6C`Ms( TS$+0wpcM?Bu6{1-oD!M<4+}lf literal 0 HcmV?d00001 diff --git a/packages/flame/test/_goldens/sprite_batch_test_2.png b/packages/flame/test/_goldens/sprite_batch_test_2.png new file mode 100644 index 0000000000000000000000000000000000000000..fb7c6f5de7d9952f42188062990ec36349f04e95 GIT binary patch literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&L!3HFEdh;y=QjEnx?oJHr&dIz4a#)I;JVQ8u zpoSx*1IV}aba4#Pn3(+M|NsB>Y+4LzSrSg6%@GMaZf t.ty, 'ty', 1), ); }); + + const margin = 2.0; + const tileSize = 6.0; + + testGolden( + 'can render a batch with blend mode', + (game) async { + final spriteSheet = await loadImage('alphabet.png'); + final spriteBatch = SpriteBatch(spriteSheet); + + const source = Rect.fromLTWH(3 * tileSize, 0, tileSize, tileSize); + + spriteBatch.add( + source: source, + color: Colors.redAccent, + offset: Vector2.all(margin), + ); + + spriteBatch.add( + source: source, + offset: Vector2(2 * margin + tileSize, margin), + ); + + game.add( + SpriteBatchComponent( + spriteBatch: spriteBatch, + blendMode: BlendMode.srcOver, + ), + ); + }, + size: Vector2(3 * margin + 2 * tileSize, 2 * margin + tileSize), + backgroundColor: const Color(0xFFFFFFFF), + goldenFile: '_goldens/sprite_batch_test_1.png', + ); + + testGolden( + 'can render a batch without blend mode', + (game) async { + final spriteSheet = await loadImage('alphabet.png'); + final spriteBatch = SpriteBatch(spriteSheet); + + const source = Rect.fromLTWH(3 * tileSize, 0, tileSize, tileSize); + + spriteBatch.add( + source: source, + offset: Vector2.all(margin), + ); + + spriteBatch.add( + source: source, + offset: Vector2(2 * margin + tileSize, margin), + ); + + game.add( + SpriteBatchComponent( + spriteBatch: spriteBatch, + ), + ); + }, + size: Vector2(3 * margin + 2 * tileSize, 2 * margin + tileSize), + backgroundColor: const Color(0xFFFFFFFF), + goldenFile: '_goldens/sprite_batch_test_2.png', + ); }); } diff --git a/packages/flame_test/lib/src/test_golden.dart b/packages/flame_test/lib/src/test_golden.dart index 19bf55b70..410613688 100644 --- a/packages/flame_test/lib/src/test_golden.dart +++ b/packages/flame_test/lib/src/test_golden.dart @@ -34,13 +34,17 @@ void testGolden( PrepareGameFunction testBody, { required String goldenFile, Vector2? size, + Color? backgroundColor, FlameGame? game, bool skip = false, }) { testWidgets( testName, (tester) async { - final gameInstance = game ?? FlameGame(); + final gameInstance = game ?? + (backgroundColor != null + ? GameWithBackgroundColor(backgroundColor) + : FlameGame()); const myKey = ValueKey('game-instance'); await tester.runAsync(() async { @@ -73,3 +77,12 @@ void testGolden( } typedef PrepareGameFunction = Future Function(FlameGame game); + +class GameWithBackgroundColor extends FlameGame { + final Color _backgroundColor; + + GameWithBackgroundColor(this._backgroundColor); + + @override + Color backgroundColor() => _backgroundColor; +}