From c55530d3bea7450b4b3d0b92a589140a2bd35a90 Mon Sep 17 00:00:00 2001 From: JiWoong Sul Date: Fri, 26 Dec 2025 17:52:43 +0900 Subject: [PATCH] =?UTF-8?q?fix(animation):=20WASM=20=EC=95=88=EC=A0=95?= =?UTF-8?q?=EC=84=B1=20=EB=B0=8F=20=EB=B6=80=ED=99=9C=20=EB=8F=99=EA=B8=B0?= =?UTF-8?q?=ED=99=94=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GamePlayScreen에 SchedulerBinding으로 setState 안전 처리 - AsciiAnimationCard에서 재개 시 specialAnimation 동기화 - 부활 시 isPaused와 specialAnimation 동시 변경 대응 --- lib/src/features/game/game_play_screen.dart | 14 +++++++++++++- .../game/widgets/ascii_animation_card.dart | 10 +++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/lib/src/features/game/game_play_screen.dart b/lib/src/features/game/game_play_screen.dart index 3cb9414..eaab7f6 100644 --- a/lib/src/features/game/game_play_screen.dart +++ b/lib/src/features/game/game_play_screen.dart @@ -1,6 +1,7 @@ import 'package:flutter/foundation.dart' show kIsWeb, defaultTargetPlatform, TargetPlatform; import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart' show SchedulerBinding, SchedulerPhase; import 'package:askiineverdie/data/game_text_l10n.dart' as game_l10n; import 'package:askiineverdie/data/skill_data.dart'; @@ -428,7 +429,18 @@ class _GamePlayScreenState extends State if (state != null) { _checkSpecialEvents(state); } - setState(() {}); + + // WASM 안정성: 프레임 빌드 중이면 다음 프레임까지 대기 + if (SchedulerBinding.instance.schedulerPhase == + SchedulerPhase.persistentCallbacks) { + SchedulerBinding.instance.addPostFrameCallback((_) { + if (mounted) { + setState(() {}); + } + }); + } else { + setState(() {}); + } } /// 캐로셀 레이아웃 사용 여부 판단 diff --git a/lib/src/features/game/widgets/ascii_animation_card.dart b/lib/src/features/game/widgets/ascii_animation_card.dart index 750d79a..89e5bc9 100644 --- a/lib/src/features/game/widgets/ascii_animation_card.dart +++ b/lib/src/features/game/widgets/ascii_animation_card.dart @@ -147,7 +147,15 @@ class _AsciiAnimationCardState extends State { _timer?.cancel(); _timer = null; } else { - // 재개: 애니메이션 재시작 (현재 프레임 유지) + // 재개 시: specialAnimation 동기화 (isPaused와 동시에 변경될 수 있음) + // 예: 부활 시 isPaused가 true→false로 바뀌면서 동시에 + // specialAnimation이 null→resurrection으로 변경됨 + if (widget.specialAnimation != _currentSpecialAnimation) { + _currentSpecialAnimation = widget.specialAnimation; + _updateAnimation(); // _updateAnimation이 타이머 재시작도 처리함 + return; + } + // 일반 재개: 애니메이션 재시작 (현재 프레임 유지) _restartTimer(); } return;