feat(ui): 화면 및 컨트롤러 수익화 연동
- 앱 초기화에 광고/IAP 서비스 추가 - 게임 세션 컨트롤러 수익화 상태 관리 - 캐릭터 생성 화면 굴리기 제한 UI - 설정 화면 광고 제거 구매 UI - 애니메이션 패널 개선
This commit is contained in:
@@ -6,6 +6,8 @@ import 'package:flutter/services.dart' show KeyDownEvent, LogicalKeyboardKey;
|
||||
|
||||
import 'package:asciineverdie/data/game_text_l10n.dart' as game_l10n;
|
||||
import 'package:asciineverdie/data/skill_data.dart';
|
||||
import 'package:asciineverdie/src/core/engine/iap_service.dart';
|
||||
import 'package:asciineverdie/src/core/engine/return_rewards_service.dart';
|
||||
import 'package:asciineverdie/data/story_data.dart';
|
||||
import 'package:asciineverdie/l10n/app_localizations.dart';
|
||||
import 'package:asciineverdie/src/core/animation/ascii_animation_type.dart';
|
||||
@@ -28,6 +30,7 @@ import 'package:asciineverdie/src/features/game/widgets/equipment_stats_panel.da
|
||||
import 'package:asciineverdie/src/features/game/widgets/potion_inventory_panel.dart';
|
||||
import 'package:asciineverdie/src/features/game/widgets/task_progress_panel.dart';
|
||||
import 'package:asciineverdie/src/features/game/widgets/active_buff_panel.dart';
|
||||
import 'package:asciineverdie/src/features/game/widgets/return_rewards_dialog.dart';
|
||||
import 'package:asciineverdie/src/features/game/layouts/mobile_carousel_layout.dart';
|
||||
import 'package:asciineverdie/src/features/settings/settings_screen.dart';
|
||||
import 'package:asciineverdie/src/features/game/widgets/statistics_dialog.dart';
|
||||
@@ -246,6 +249,9 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
|
||||
// 오디오 볼륨 초기화
|
||||
_audioController.initVolumes();
|
||||
|
||||
// Phase 7: 복귀 보상 콜백 설정
|
||||
widget.controller.onReturnRewardAvailable = _showReturnRewardsDialog;
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -262,6 +268,7 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
_storyService.dispose();
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
widget.controller.removeListener(_onControllerChanged);
|
||||
widget.controller.onReturnRewardAvailable = null; // Phase 7: 콜백 정리
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -399,6 +406,21 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
return platform == TargetPlatform.iOS || platform == TargetPlatform.android;
|
||||
}
|
||||
|
||||
/// 복귀 보상 다이얼로그 표시 (Phase 7)
|
||||
void _showReturnRewardsDialog(ReturnReward reward) {
|
||||
// 잠시 후 다이얼로그 표시 (게임 시작 후)
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (!mounted) return;
|
||||
ReturnRewardsDialog.show(
|
||||
context,
|
||||
reward: reward,
|
||||
onClaim: (totalGold) {
|
||||
widget.controller.applyReturnReward(totalGold);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// 통계 다이얼로그 표시
|
||||
void _showStatisticsDialog(BuildContext context) {
|
||||
StatisticsDialog.show(
|
||||
@@ -486,6 +508,47 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
});
|
||||
}
|
||||
|
||||
/// 광고 부활 핸들러 (HP 100% + 아이템 복구 + 10분 자동부활)
|
||||
Future<void> _handleAdRevive() async {
|
||||
// 1. 부활 애니메이션 먼저 설정 (DeathOverlay 사라지기 전에)
|
||||
setState(() {
|
||||
_specialAnimation = AsciiAnimationType.resurrection;
|
||||
});
|
||||
|
||||
// 2. 광고 부활 처리 (HP 100%, 아이템 복구, 10분 자동부활 버프)
|
||||
await widget.controller.adRevive();
|
||||
|
||||
// 3. 애니메이션 종료 후 게임 재개
|
||||
final duration = getSpecialAnimationDuration(
|
||||
AsciiAnimationType.resurrection,
|
||||
);
|
||||
Future.delayed(Duration(milliseconds: duration), () async {
|
||||
if (mounted) {
|
||||
await widget.controller.resumeAfterResurrection();
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_specialAnimation = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// 속도 부스트 활성화 핸들러 (Phase 6)
|
||||
Future<void> _handleSpeedBoost() async {
|
||||
final activated = await widget.controller.activateSpeedBoost();
|
||||
if (activated && mounted) {
|
||||
_notificationService.show(
|
||||
GameNotification(
|
||||
type: NotificationType.info,
|
||||
title: game_l10n.speedBoostActive,
|
||||
duration: const Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final state = widget.controller.state;
|
||||
@@ -603,6 +666,11 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
navigator.popUntil((route) => route.isFirst);
|
||||
}
|
||||
},
|
||||
// 수익화 버프 (자동부활, 5배속)
|
||||
autoReviveEndMs: widget.controller.monetization.autoReviveEndMs,
|
||||
speedBoostEndMs: widget.controller.monetization.speedBoostEndMs,
|
||||
isPaidUser: widget.controller.monetization.isPaidUser,
|
||||
onSpeedBoostActivate: _handleSpeedBoost,
|
||||
),
|
||||
// 사망 오버레이
|
||||
if (state.isDead && state.deathInfo != null)
|
||||
@@ -610,12 +678,8 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
deathInfo: state.deathInfo!,
|
||||
traits: state.traits,
|
||||
onResurrect: _handleResurrect,
|
||||
isAutoResurrectEnabled: widget.controller.autoResurrect,
|
||||
onToggleAutoResurrect: () {
|
||||
widget.controller.setAutoResurrect(
|
||||
!widget.controller.autoResurrect,
|
||||
);
|
||||
},
|
||||
onAdRevive: _handleAdRevive,
|
||||
isPaidUser: IAPService.instance.isAdRemovalPurchased,
|
||||
),
|
||||
// 승리 오버레이 (게임 클리어)
|
||||
if (widget.controller.isComplete)
|
||||
@@ -759,18 +823,14 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
],
|
||||
),
|
||||
|
||||
// Phase 4: 사망 오버레이 (Death Overlay)
|
||||
// 사망 오버레이
|
||||
if (state.isDead && state.deathInfo != null)
|
||||
DeathOverlay(
|
||||
deathInfo: state.deathInfo!,
|
||||
traits: state.traits,
|
||||
onResurrect: _handleResurrect,
|
||||
isAutoResurrectEnabled: widget.controller.autoResurrect,
|
||||
onToggleAutoResurrect: () {
|
||||
widget.controller.setAutoResurrect(
|
||||
!widget.controller.autoResurrect,
|
||||
);
|
||||
},
|
||||
onAdRevive: _handleAdRevive,
|
||||
isPaidUser: IAPService.instance.isAdRemovalPurchased,
|
||||
),
|
||||
// 승리 오버레이 (게임 클리어)
|
||||
if (widget.controller.isComplete)
|
||||
|
||||
Reference in New Issue
Block a user