Skip to content

Commit

Permalink
fix: Fix SpriteBatch to comply with new drawAtlas requirement (#3338)
Browse files Browse the repository at this point in the history
Fix SpriteBatch to comply with new drawAtlas requirement

Fixes: #3331
  • Loading branch information
luanpotter authored Oct 13, 2024
1 parent 0041604 commit a17fe4c
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 9 deletions.
5 changes: 5 additions & 0 deletions examples/lib/stories/sprites/sprite_batch_load_example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down
20 changes: 12 additions & 8 deletions packages/flame/lib/src/sprite_batch.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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,
);
Expand All @@ -441,4 +443,6 @@ class SpriteBatch {
}
}
}

static const _defaultColor = Color(0x00000000);
}
Binary file added packages/flame/test/_goldens/sprite_batch_test_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/flame/test/_goldens/sprite_batch_test_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
67 changes: 67 additions & 0 deletions packages/flame/test/sprite_batch_test.dart
Original file line number Diff line number Diff line change
@@ -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() {
Expand Down Expand Up @@ -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',
);
});
}
15 changes: 14 additions & 1 deletion packages/flame_test/lib/src/test_golden.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
}

0 comments on commit a17fe4c

Please sign in to comment.