Skip to content

Commit

Permalink
fix: OpacityEffect rounding error calculation (#1933)
Browse files Browse the repository at this point in the history
When using OpacityEffect.fadeOut, the value of opacity at the end of the effect was non zero. I suspect that the rounding error calculation is wrong and this PR tried to simplify that logic.

Proof that this PR actually fixes the problem can be seen at the test results of 793415f and 5f3c591. First one just added a test for OpacityEffect.fadeOut and second added the actual fix.

Disclaimer: I don't fully understand this part of the code, so be extra vigilant while reviewing this PR.
  • Loading branch information
ufrshubham committed Sep 24, 2022
1 parent 205ac56 commit 4cfcfa6
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 9 deletions.
8 changes: 1 addition & 7 deletions packages/flame/lib/src/effects/opacity_effect.dart
Expand Up @@ -68,14 +68,8 @@ class OpacityEffect extends ComponentEffect<HasPaint> {
final currentAlpha = target.getAlpha(paintId: paintId);
final deltaAlpha =
(_alphaOffset * deltaProgress) + _roundingError * deltaProgress.sign;
final remainder = deltaAlpha.remainder(1.0).abs();
_roundingError = remainder >= 0.5 ? -1 * (1.0 - remainder) : remainder;
var nextAlpha = (currentAlpha + deltaAlpha).round();
if (nextAlpha < 0) {
_roundingError += nextAlpha.abs();
} else if (nextAlpha > 255) {
_roundingError += nextAlpha - 255;
}
_roundingError = (currentAlpha + deltaAlpha) - nextAlpha;
nextAlpha = nextAlpha.clamp(0, 255);
target.setAlpha(nextAlpha, paintId: paintId);
}
Expand Down
50 changes: 48 additions & 2 deletions packages/flame/test/effects/opacity_effect_test.dart
@@ -1,9 +1,8 @@
import 'dart:math';

import 'package:flame/components.dart';
import 'package:flame/effects.dart';
import 'package:flame/game.dart';
import 'package:flame/src/effects/controllers/effect_controller.dart';
import 'package:flame/src/effects/opacity_effect.dart';
import 'package:flame_test/flame_test.dart';
import 'package:flutter_test/flutter_test.dart';

Expand Down Expand Up @@ -142,6 +141,53 @@ void main() {
expect(component.children.length, 0);
});

flameGame.test(
'fade out',
(game) async {
final rng = Random();
final component = _PaintComponent();
await game.ensureAdd(component);

// Repeat the test 3 times
for (var i = 0; i < 3; ++i) {
await component
.add(OpacityEffect.fadeOut(EffectController(duration: 3)));

var timeElapsed = 0.0;
while (timeElapsed < 3) {
final dt = rng.nextDouble() / 60;
game.update(dt);
timeElapsed += dt;
}

expect(component.getOpacity(), 0.0);
component.setOpacity(1.0);
}
},
);

flameGame.test(
'infinite fade out',
(game) async {
final component = _PaintComponent();
await game.ensureAdd(component);

await component.add(
OpacityEffect.fadeOut(
EffectController(
duration: 3,
infinite: true,
),
),
);

for (var i = 0; i < 100; ++i) {
game.update(3);
expectDouble(component.getOpacity(), 0.0);
}
},
);

testRandom('a very long opacity change', (Random rng) async {
final game = FlameGame()..onGameResize(Vector2(1, 1));
final component = _PaintComponent();
Expand Down

0 comments on commit 4cfcfa6

Please sign in to comment.