flame
flame copied to clipboard
Inconsistency with OpacityEffect.fadeOut
Current bug behaviour
When using OpacityEffect.fadeOut()
the final alpha/opacity of target does not reach 0 sometimes. Most of the times it is not even visible, but I've seen cases where the alpha stays at 30 or even 73, making the target still visible.
Expected behaviour
At the end of fadeOut target should be completely hidden.
Steps to reproduce
Add fadeOut effect to simple rectangle component and print out the alpha/opacity values from onFinishCallback
. Here is a simple code to do this:
main() {
runApp(
MaterialApp(
home: Scaffold(
body: GameWidget(
game: SimpleGame(),
),
),
),
);
}
class SimpleGame extends FlameGame {
@override
Future<void>? onLoad() async {
camera.viewport = FixedResolutionViewport(Vector2(640, 360));
final rect = RectangleComponent(
position: size / 2,
size: Vector2.all(32),
);
add(rect);
rect.add(
OpacityEffect.fadeOut(
LinearEffectController(3),
)..onFinishCallback = () {
print(rect.getAlpha());
print(rect.getOpacity());
},
);
return super.onLoad();
}
}
Flutter doctor output
Output of: flutter doctor -v
[√] Flutter (Channel stable, 2.10.5, on Microsoft Windows [Version 10.0.22000.556], locale en-US)
• Flutter version 2.10.5 at C:\apps\android\flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 5464c5bac7 (8 days ago), 2022-04-18 09:55:37 -0700
• Engine revision 57d3bac3dd
• Dart version 2.16.2
• DevTools version 2.9.2
[√] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
• Android SDK at C:\apps\android
• Platform android-31, build-tools 30.0.2
• ANDROID_HOME = C:\apps\android
• ANDROID_SDK_ROOT = C:\apps\android\cmdline-tools\tools
• Java binary at: C:\apps\openjdk-11.0.2_windows-x64_bin\jdk-11.0.2\bin\java
• Java version OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
• All Android licenses accepted.
[√] Chrome - develop for the web
• Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe
[√] Visual Studio - develop for Windows (Visual Studio Community 2022 17.1.5)
• Visual Studio at C:\Program Files\Microsoft Visual Studio\2022\Community
• Visual Studio Community 2022 version 17.1.32414.318
• Windows 10 SDK version 10.0.22000.0
[!] Android Studio (not installed)
• Android Studio not found; download from https://developer.android.com/studio/index.html
(or visit https://flutter.dev/docs/get-started/install/windows#android-setup for detailed instructions).
[√] VS Code (version 1.66.2)
• VS Code at C:\Users\Ryuzaki\AppData\Local\Programs\Microsoft VS Code
• Flutter extension version 3.38.1
[√] Connected device (3 available)
• Windows (desktop) • windows • windows-x64 • Microsoft Windows [Version 10.0.22000.556]
• Chrome (web) • chrome • web-javascript • Google Chrome 100.0.4896.127
• Edge (web) • edge • web-javascript • Microsoft Edge 91.0.864.54
[√] HTTP Host Availability
• All required HTTP hosts are available
! Doctor found issues in 1 category.
More environment information
Log information
Enter log information in this code block
More information
Can confirm as well. Running very similar code but on a sprite, I am getting 0.05, 0.0, 0.047058823529411764, etc. for opacity. I am not certain how big of a deal it is, because the image is gone when it gets called, but for all the work we did to make sure we were in the first tick of the animation, I would think this would be important as well. I will try and take a look at it later unless you guys have an idea of what might be the cause.
Edit: So did some timing on the effects.dart class where onFinishCallback
is registered. Its varying amounts due to the concept of calling it just before finish and it just depends on what dt
was.
Notes from the relevant files:
/// If the controller is still running, the return value will be 0. If it
/// already finished, then the return value will be the "leftover" part of
/// the [dt]. That is, the amount of time [dt] that remains after the
/// controller has finished. In all cases, the return value can be positive
/// only when `completed == true`.
And because in @ufrshubham example and in my case, we are using SequenceEffect:
/// Used for SequenceEffect. This is similar to `update()`, but cannot be
/// paused, does not obey [removeOnFinish], and returns the "leftover time"
/// similar to `EffectController.advance`.
As such, I am not certain Opacity will ever get to true 0 unless by happen stance because its the last tick called prior to removing the component from Parent. I guess I am asking, is this really a bug or just an unavoidable consequence?
I guess I am asking, is this really a bug or just an unavoidable consequence?
It's a bug, and it should be fixed
I am a bit confused with the logic for _roundingError
in OpacityEffect.apply()
. If it is just the rounding error caused while converting currentAlpha + deltaAlpha
to integer, shouldn't this
var nextAlpha = (currentAlpha + deltaAlpha).round();
_roundingError = (currentAlpha + deltaAlpha) - nextAlpha;
be the easiest way to calculate rounding error?
This change does seem to solve the problem and other opacity effect tests also pass.