fix: Fix SpriteBatch to comply with new drawAtlas requirement (#3338)

Fix SpriteBatch to comply with new drawAtlas requirement

Fixes: #3331
This commit is contained in:
Luan Nico
2024-10-13 12:09:29 -04:00
committed by GitHub
parent 0041604a89
commit a17fe4cdfa
6 changed files with 98 additions and 9 deletions

View File

@ -20,6 +20,11 @@ class SpriteBatchLoadExample extends FlameGame {
class MySpriteBatchComponent extends SpriteBatchComponent
with HasGameReference<SpriteBatchLoadExample> {
MySpriteBatchComponent()
: super(
blendMode: BlendMode.srcOver,
);
@override
Future<void> onLoad() async {
final spriteBatch = await game.loadSpriteBatch('boom.png');

View File

@ -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);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B

View File

@ -1,10 +1,14 @@
import 'dart:ui';
import 'package:flame/components.dart';
import 'package:flame/sprite.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter/material.dart' hide Image;
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import '_resources/load_image.dart';
class _MockImage extends Mock implements Image {}
void main() {
@ -56,5 +60,68 @@ void main() {
.having((t) => 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',
);
});
}

View File

@ -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<void> Function(FlameGame game);
class GameWithBackgroundColor extends FlameGame {
final Color _backgroundColor;
GameWithBackgroundColor(this._backgroundColor);
@override
Color backgroundColor() => _backgroundColor;
}