From e009ff1314e988ab13de600eeabc97d2944198e5 Mon Sep 17 00:00:00 2001 From: Wilhansen Li Date: Fri, 5 Dec 2025 22:36:12 +0800 Subject: [PATCH 1/3] feat: add TextBoxComponent::resetAnimation Enables resetting of the typewriter animation of the TextBoxComponent. Useful for changing lines without having to re-insert the component into the scene node, which causes undesired flashing. --- .../src/components/text_box_component.dart | 11 +++++++ .../components/text_box_component_test.dart | 29 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/packages/flame/lib/src/components/text_box_component.dart b/packages/flame/lib/src/components/text_box_component.dart index 57550985d04..97473a4daa4 100644 --- a/packages/flame/lib/src/components/text_box_component.dart +++ b/packages/flame/lib/src/components/text_box_component.dart @@ -408,4 +408,15 @@ class TextBoxComponent extends TextComponent { void skip() { boxConfig = boxConfig.copyWith(timePerChar: 0); } + + /// Rewind the typewriter effect to start from the first character again. + /// + /// Useful for reusing this component when changing lines so that the next + /// line does not show immediately. + /// Also resets the [onComplete] call state which will be called again + /// when the line is finished. + void resetAnimation() { + _lifeTime = 0; + _isOnCompleteExecuted = false; + } } diff --git a/packages/flame/test/components/text_box_component_test.dart b/packages/flame/test/components/text_box_component_test.dart index 67c81ce94c5..d29f15513d8 100644 --- a/packages/flame/test/components/text_box_component_test.dart +++ b/packages/flame/test/components/text_box_component_test.dart @@ -219,6 +219,35 @@ lines.''', expect(textBoxComponent2.finished, true); }); + testWithFlameGame( + 'TextBoxComponent resets animation to the start of text', + ( + game, + ) async { + final textBoxComponent1 = TextBoxComponent( + text: 'aaa', + boxConfig: const TextBoxConfig(timePerChar: 1.0), + ); + await game.ensureAdd(textBoxComponent1); + // forward time by 2.5 seconds + game.update(2.5); + expect(textBoxComponent1.finished, false); + // flush + game.update(0.6); + expect(textBoxComponent1.finished, true); + // reset animation + textBoxComponent1.resetAnimation(); + // 'finished' state should reset immediately + expect(textBoxComponent1.finished, false); + expect(textBoxComponent1.currentChar, 0); + expect(textBoxComponent1.currentLine, 0); + game.update(2.5); + expect(textBoxComponent1.finished, false); + game.update(0.6); + expect(textBoxComponent1.finished, true); + }, + ); + testGolden( 'Alignment options', (game, tester) async { From 9d158172e04042bbfbdbd7286c172bb3dea776fc Mon Sep 17 00:00:00 2001 From: Wilhansen Li Date: Mon, 22 Dec 2025 22:43:02 +0800 Subject: [PATCH 2/3] doc: add info on typing effect controls of TextBoxComponent --- doc/flame/rendering/text_rendering.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/flame/rendering/text_rendering.md b/doc/flame/rendering/text_rendering.md index 2dd4d0eb117..d082e96c8a1 100644 --- a/doc/flame/rendering/text_rendering.md +++ b/doc/flame/rendering/text_rendering.md @@ -89,6 +89,12 @@ If you want to change the margins of the box use the `margins` variable in the ` Finally, if you want to simulate a "typing" effect, by showing each character of the string one by one as if being typed in real-time, you can provide the `boxConfig.timePerChar` parameter. +To control the typing effect, call `skip` to show the entire text at once, and `resetAnimation` to +reset the typing effect back to the beginning without having to recreate the component. Do note +that `skip` sets `boxConfig.timePerChar` to `0` so when attempting to replay the typing effect +after calling `skip`, make sure to re-set the `boxConfig.timePerChar` right before or after +calling `resetAnimation`. + Example usage: ```dart From e4de6768156f370a81b4c40b08b3e613db2be662 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Tue, 23 Dec 2025 10:07:09 +0100 Subject: [PATCH 3/3] Retrigger tests