feat(front): 프론트 화면 개선 및 설정 저장소 추가
- front_screen_animation.dart: 프론트 화면 애니메이션 추가 - settings_repository.dart: 설정 저장소 구현 - front/widgets/: 프론트 화면 위젯 분리 - mobile_carousel_layout.dart: 모바일 레이아웃 개선 - app.dart: 앱 설정 개선 - game_text_l10n.dart: 텍스트 추가
This commit is contained in:
169
lib/src/features/front/widgets/hero_vs_boss_animation.dart
Normal file
169
lib/src/features/front/widgets/hero_vs_boss_animation.dart
Normal file
@@ -0,0 +1,169 @@
|
||||
import 'dart:async';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:askiineverdie/src/core/animation/front_screen_animation.dart';
|
||||
|
||||
/// 프론트 화면용 Hero vs Glitch God ASCII 애니메이션 위젯
|
||||
///
|
||||
/// 작은 용사가 거대한 Glitch God에 맞서는 루프 애니메이션
|
||||
/// 항상 검은 배경에 흰색 텍스트, 특수 효과만 컬러로 표시
|
||||
class HeroVsBossAnimation extends StatefulWidget {
|
||||
const HeroVsBossAnimation({super.key});
|
||||
|
||||
@override
|
||||
State<HeroVsBossAnimation> createState() => _HeroVsBossAnimationState();
|
||||
}
|
||||
|
||||
class _HeroVsBossAnimationState extends State<HeroVsBossAnimation> {
|
||||
int _currentFrame = 0;
|
||||
Timer? _timer;
|
||||
final Random _random = Random();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_startAnimation();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_timer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _startAnimation() {
|
||||
_timer = Timer.periodic(
|
||||
const Duration(milliseconds: frontScreenAnimationIntervalMs),
|
||||
(_) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_currentFrame =
|
||||
(_currentFrame + 1) % frontScreenAnimationFrameCount;
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// 글리치 효과: 랜덤 문자 대체
|
||||
String _applyGlitchEffect(String frame) {
|
||||
// 10% 확률로 글리치 효과 적용
|
||||
if (_random.nextDouble() > 0.1) return frame;
|
||||
|
||||
const glitchChars = '@#\$%&*!?~';
|
||||
final chars = frame.split('');
|
||||
final glitchCount = _random.nextInt(5) + 1;
|
||||
|
||||
for (var i = 0; i < glitchCount; i++) {
|
||||
final pos = _random.nextInt(chars.length);
|
||||
if (chars[pos] != ' ' && chars[pos] != '\n') {
|
||||
chars[pos] = glitchChars[_random.nextInt(glitchChars.length)];
|
||||
}
|
||||
}
|
||||
|
||||
return chars.join();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final frame = _applyGlitchEffect(
|
||||
frontScreenAnimationFrames[_currentFrame],
|
||||
);
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 16),
|
||||
decoration: BoxDecoration(
|
||||
// 항상 검은 배경
|
||||
color: Colors.black,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(
|
||||
color: Colors.white24,
|
||||
width: 1,
|
||||
),
|
||||
// 은은한 글로우 효과
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.cyan.withValues(alpha: 0.15),
|
||||
blurRadius: 20,
|
||||
spreadRadius: 2,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
// ASCII 애니메이션 (흰색 텍스트)
|
||||
FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
child: Text(
|
||||
frame,
|
||||
style: const TextStyle(
|
||||
fontFamily: 'JetBrainsMono',
|
||||
fontSize: 10,
|
||||
height: 1.1,
|
||||
color: Colors.white,
|
||||
letterSpacing: 0,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
// 하단 효과 바 (컬러)
|
||||
_buildEffectBar(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 하단 효과 바: 글리치/전투 효과 시각화
|
||||
Widget _buildEffectBar() {
|
||||
// 프레임에 따라 색상 변화
|
||||
final colors = [
|
||||
Colors.cyan,
|
||||
Colors.purple,
|
||||
Colors.red,
|
||||
Colors.cyan,
|
||||
Colors.yellow,
|
||||
Colors.purple,
|
||||
];
|
||||
final currentColor = colors[_currentFrame % colors.length];
|
||||
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
// 왼쪽 검 아이콘 (용사)
|
||||
Icon(
|
||||
Icons.flash_on,
|
||||
size: 14,
|
||||
color: Colors.yellow.withValues(alpha: 0.8),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
// 중앙 효과 바
|
||||
Expanded(
|
||||
child: Container(
|
||||
height: 3,
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Colors.transparent,
|
||||
currentColor.withValues(alpha: 0.7),
|
||||
Colors.white.withValues(alpha: 0.9),
|
||||
currentColor.withValues(alpha: 0.7),
|
||||
Colors.transparent,
|
||||
],
|
||||
),
|
||||
borderRadius: BorderRadius.circular(2),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
// 오른쪽 보스 아이콘
|
||||
Icon(
|
||||
Icons.whatshot,
|
||||
size: 14,
|
||||
color: Colors.red.withValues(alpha: 0.8),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user