refactor(shared): animation, l10n, theme 모듈을 core에서 shared로 이동
- core/animation → shared/animation - core/l10n → shared/l10n - core/constants/ascii_colors → shared/theme/ascii_colors - import 경로 업데이트
This commit is contained in:
760
lib/src/shared/animation/ascii_animation_data.dart
Normal file
760
lib/src/shared/animation/ascii_animation_data.dart
Normal file
@@ -0,0 +1,760 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:asciineverdie/src/shared/animation/ascii_animation_type.dart';
|
||||
|
||||
/// ASCII 애니메이션 프레임 데이터
|
||||
class AsciiAnimationData {
|
||||
const AsciiAnimationData({required this.frames, this.frameIntervalMs = 200});
|
||||
|
||||
/// 각 프레임 (문자열, 최소 5줄)
|
||||
final List<String> frames;
|
||||
|
||||
/// 프레임 간격 (밀리초)
|
||||
final int frameIntervalMs;
|
||||
}
|
||||
|
||||
/// 터미널 색상 테마
|
||||
enum AsciiColorTheme {
|
||||
/// 클래식 녹색 터미널
|
||||
green,
|
||||
|
||||
/// 엠버 (호박색) 터미널
|
||||
amber,
|
||||
|
||||
/// 화이트 온 블랙
|
||||
white,
|
||||
|
||||
/// 시스템 테마 (라이트/다크 모드 따름)
|
||||
system,
|
||||
}
|
||||
|
||||
/// 테마별 색상 데이터
|
||||
class AsciiThemeColors {
|
||||
const AsciiThemeColors({
|
||||
required this.textColor,
|
||||
required this.backgroundColor,
|
||||
});
|
||||
|
||||
final Color textColor;
|
||||
final Color backgroundColor;
|
||||
}
|
||||
|
||||
/// 테마별 색상 반환
|
||||
AsciiThemeColors getThemeColors(AsciiColorTheme theme, Brightness brightness) {
|
||||
return switch (theme) {
|
||||
AsciiColorTheme.green => const AsciiThemeColors(
|
||||
textColor: Color(0xFF00FF00),
|
||||
backgroundColor: Color(0xFF0D0D0D),
|
||||
),
|
||||
AsciiColorTheme.amber => const AsciiThemeColors(
|
||||
textColor: Color(0xFFFFB000),
|
||||
backgroundColor: Color(0xFF1A1000),
|
||||
),
|
||||
AsciiColorTheme.white => const AsciiThemeColors(
|
||||
textColor: Color(0xFFE0E0E0),
|
||||
backgroundColor: Color(0xFF121212),
|
||||
),
|
||||
AsciiColorTheme.system =>
|
||||
brightness == Brightness.dark
|
||||
? const AsciiThemeColors(
|
||||
textColor: Color(0xFFE0E0E0),
|
||||
backgroundColor: Color(0xFF1E1E1E),
|
||||
)
|
||||
: const AsciiThemeColors(
|
||||
textColor: Color(0xFF1E1E1E),
|
||||
backgroundColor: Color(0xFFF5F5F5),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
/// 몬스터 카테고리 (ASCII NEVER DIE 테마)
|
||||
enum MonsterCategory {
|
||||
/// 기본 버그 (Syntax Error, Type Mismatch 등)
|
||||
bug,
|
||||
|
||||
/// 멀웨어 (Virus, Worm, Trojan 등)
|
||||
malware,
|
||||
|
||||
/// 네트워크 위협 (Flood, DDoS, Injection 등)
|
||||
network,
|
||||
|
||||
/// 시스템 위협 (Kernel, Memory, Buffer 등)
|
||||
system,
|
||||
|
||||
/// 암호화/보안 (Encryption, Hash, Zero-Day 등)
|
||||
crypto,
|
||||
|
||||
/// AI/ML 위협 (Neural Network, Machine Learning 등)
|
||||
ai,
|
||||
|
||||
/// 보스 몬스터
|
||||
boss,
|
||||
}
|
||||
|
||||
/// 몬스터 이름으로 카테고리 결정 (ASCII NEVER DIE 테마)
|
||||
MonsterCategory getMonsterCategory(String? monsterBaseName) {
|
||||
if (monsterBaseName == null || monsterBaseName.isEmpty) {
|
||||
return MonsterCategory.bug;
|
||||
}
|
||||
|
||||
final name = monsterBaseName.toLowerCase();
|
||||
|
||||
// 보스 몬스터
|
||||
if (name.startsWith('boss:') ||
|
||||
name.contains('dragon') ||
|
||||
name.contains('hydra') ||
|
||||
name.contains('titan') ||
|
||||
name.contains('leviathan') ||
|
||||
name.contains('colossus') ||
|
||||
name.contains('emperor') ||
|
||||
name.contains('singularity') ||
|
||||
name.contains('primordial') ||
|
||||
name.contains('glitch god')) {
|
||||
return MonsterCategory.boss;
|
||||
}
|
||||
|
||||
// AI/ML 위협
|
||||
if (name.contains('neural') ||
|
||||
name.contains('ai ') ||
|
||||
name.contains('deep') ||
|
||||
name.contains('model') ||
|
||||
name.contains('adversarial') ||
|
||||
name.contains('training') ||
|
||||
name.contains('federated') ||
|
||||
name.contains('prompt') ||
|
||||
name.contains('hallucination')) {
|
||||
return MonsterCategory.ai;
|
||||
}
|
||||
|
||||
// 암호화/보안 위협
|
||||
if (name.contains('quantum') ||
|
||||
name.contains('zero day') ||
|
||||
name.contains('zero-day') ||
|
||||
name.contains('crypto') ||
|
||||
name.contains('hash') ||
|
||||
name.contains('blockchain') ||
|
||||
name.contains('homomorphic') ||
|
||||
name.contains('zero knowledge') ||
|
||||
name.contains('smart contract')) {
|
||||
return MonsterCategory.crypto;
|
||||
}
|
||||
|
||||
// 네트워크 위협
|
||||
if (name.contains('flood') ||
|
||||
name.contains('ddos') ||
|
||||
name.contains('dos') ||
|
||||
name.contains('injection') ||
|
||||
name.contains('sql') ||
|
||||
name.contains('xss') ||
|
||||
name.contains('csrf') ||
|
||||
name.contains('amplification') ||
|
||||
name.contains('tunnel') ||
|
||||
name.contains('shell') ||
|
||||
name.contains('backdoor') ||
|
||||
name.contains('c2') ||
|
||||
name.contains('beacon')) {
|
||||
return MonsterCategory.network;
|
||||
}
|
||||
|
||||
// 시스템 위협
|
||||
if (name.contains('kernel') ||
|
||||
name.contains('memory') ||
|
||||
name.contains('buffer') ||
|
||||
name.contains('stack') ||
|
||||
name.contains('heap') ||
|
||||
name.contains('overflow') ||
|
||||
name.contains('corruption') ||
|
||||
name.contains('segfault') ||
|
||||
name.contains('panic') ||
|
||||
name.contains('rootkit') ||
|
||||
name.contains('firmware') ||
|
||||
name.contains('bootkit')) {
|
||||
return MonsterCategory.system;
|
||||
}
|
||||
|
||||
// 멀웨어
|
||||
if (name.contains('virus') ||
|
||||
name.contains('worm') ||
|
||||
name.contains('trojan') ||
|
||||
name.contains('ransomware') ||
|
||||
name.contains('malware') ||
|
||||
name.contains('botnet') ||
|
||||
name.contains('cryptominer') ||
|
||||
name.contains('keylogger') ||
|
||||
name.contains('spyware') ||
|
||||
name.contains('dropper') ||
|
||||
name.contains('loader') ||
|
||||
name.contains('payload')) {
|
||||
return MonsterCategory.malware;
|
||||
}
|
||||
|
||||
// 기본: 버그
|
||||
return MonsterCategory.bug;
|
||||
}
|
||||
|
||||
/// 버그 전투 애니메이션 (기본 버그 모양)
|
||||
const battleAnimationBug = AsciiAnimationData(
|
||||
frames: [
|
||||
// 프레임 1: 대치
|
||||
'''
|
||||
o /\\_/\\
|
||||
/|\\ ( o.o )
|
||||
/ \\ > ^ <''',
|
||||
// 프레임 2: 접근
|
||||
'''
|
||||
o /\\_/\\
|
||||
/|\\ ( o.o )
|
||||
/ \\ > ^ <''',
|
||||
// 프레임 3: 공격 (근접)
|
||||
'''
|
||||
o_/ /\\_/\\
|
||||
/| ( >.< )
|
||||
/ \\ > ^ <''',
|
||||
// 프레임 4: 히트
|
||||
'''
|
||||
o **** /\\_/\\
|
||||
/|\\ *** ( X.X )
|
||||
/ \\ > ~ <''',
|
||||
// 프레임 5: 복귀 (승리 포즈)
|
||||
'''
|
||||
\\o/ /\\_/\\
|
||||
/|\\ ( -.-)
|
||||
/ \\ > ^ <''',
|
||||
],
|
||||
frameIntervalMs: 220,
|
||||
);
|
||||
|
||||
/// 마을/상점 애니메이션 (8줄 x 40자 고정)
|
||||
/// 캐릭터 위치: 머리=4, 몸통=5, 다리=6 (전투 애니메이션 기준)
|
||||
const townAnimation = AsciiAnimationData(
|
||||
frames: [
|
||||
// 프레임 1: 상점 앞 대기
|
||||
' ___________ \n'
|
||||
' / SHOP \\ \n'
|
||||
' | [======] | \n'
|
||||
' | @@@@ | \n'
|
||||
' | ITEMS | o \n'
|
||||
' | | /|\\ \n'
|
||||
' |___________| / \\ \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 2: 이동 중
|
||||
' ___________ \n'
|
||||
' / SHOP \\ \n'
|
||||
' | [======] | \n'
|
||||
' | @@@@ | \n'
|
||||
' | ITEMS | o \n'
|
||||
' | | /|\\ \n'
|
||||
' |___________| / \\ \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 3: 거래 시작
|
||||
' ___________ \n'
|
||||
' / SHOP \\ \n'
|
||||
' | [======] | \$ \n'
|
||||
' | @@@@ | \$ \n'
|
||||
' | ITEMS | o \$ \n'
|
||||
' | | /|\\ \n'
|
||||
' |___________| / \\ \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 4: 거래 중
|
||||
' ___________ \n'
|
||||
' / SHOP \\ \n'
|
||||
' | [<====>] | \$\$\$ \n'
|
||||
' | @@@@ | \$\$\$ \n'
|
||||
' | SOLD! | o \n'
|
||||
' | | /|\\ \n'
|
||||
' |___________| / \\ \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 5: 거래 완료
|
||||
' ___________ \n'
|
||||
' / SHOP \\ \n'
|
||||
' | [======] | + \n'
|
||||
' | @@@@ | + \n'
|
||||
' | ITEMS | \\o/ \n'
|
||||
' | | /|\\ \n'
|
||||
' |___________| / \\ \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
],
|
||||
frameIntervalMs: 280,
|
||||
);
|
||||
|
||||
/// 걷는 애니메이션 (8줄 x 40자 고정)
|
||||
const walkingAnimation = AsciiAnimationData(
|
||||
frames: [
|
||||
// 프레임 1: 양발 벌림
|
||||
' \n'
|
||||
' \n'
|
||||
' \n'
|
||||
' \n'
|
||||
' o \n'
|
||||
' /|\\ \n'
|
||||
' / \\ \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 2: 왼발 앞으로
|
||||
' \n'
|
||||
' \n'
|
||||
' \n'
|
||||
' \n'
|
||||
' o \n'
|
||||
' /|\\ \n'
|
||||
' /| \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 3: 두 발 모음
|
||||
' \n'
|
||||
' \n'
|
||||
' \n'
|
||||
' \n'
|
||||
' o \n'
|
||||
' /|\\ \n'
|
||||
' || \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 4: 오른발 앞으로
|
||||
' \n'
|
||||
' \n'
|
||||
' \n'
|
||||
' \n'
|
||||
' o \n'
|
||||
' /|\\ \n'
|
||||
' |\\ \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 5: 양발 벌림 (복귀)
|
||||
' \n'
|
||||
' \n'
|
||||
' \n'
|
||||
' \n'
|
||||
' o \n'
|
||||
' /|\\ \n'
|
||||
' / \\ \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
],
|
||||
frameIntervalMs: 180,
|
||||
);
|
||||
|
||||
/// 멀웨어 전투 애니메이션 (바이러스 모양)
|
||||
const battleAnimationMalware = AsciiAnimationData(
|
||||
frames: [
|
||||
// 프레임 1: 대치
|
||||
'''
|
||||
o /\\_/\\
|
||||
/|\\ ( o o )
|
||||
/ \\ /|=====|\\''',
|
||||
// 프레임 2: 접근
|
||||
'''
|
||||
o /\\_/\\
|
||||
/|\\ ( o o )
|
||||
/ \\ /|=====|\\''',
|
||||
// 프레임 3: 공격 (근접)
|
||||
'''
|
||||
o_/ /\\_/\\
|
||||
/| ( >.< )
|
||||
/ \\ /|=====|\\''',
|
||||
// 프레임 4: 히트
|
||||
'''
|
||||
o **** /\\_/\\
|
||||
/|\\*** ( X X )
|
||||
/ \\ /|=====|\\''',
|
||||
// 프레임 5: 복귀 (승리 포즈)
|
||||
'''
|
||||
\\o/ /\\_/\\
|
||||
/|\\ ( - - )
|
||||
/ \\ /|=====|\\''',
|
||||
],
|
||||
frameIntervalMs: 220,
|
||||
);
|
||||
|
||||
/// 네트워크 전투 애니메이션 (패킷 모양)
|
||||
const battleAnimationNetwork = AsciiAnimationData(
|
||||
frames: [
|
||||
// 프레임 1: 대치
|
||||
'''
|
||||
o O
|
||||
/|\\ /|\\
|
||||
/ \\ / | \\''',
|
||||
// 프레임 2: 접근
|
||||
'''
|
||||
o O
|
||||
/|\\ /|\\
|
||||
/ \\ / | \\''',
|
||||
// 프레임 3: 공격 (근접)
|
||||
'''
|
||||
o_/ O
|
||||
/| X|X
|
||||
/ \\ / | \\''',
|
||||
// 프레임 4: 히트
|
||||
'''
|
||||
o **** O
|
||||
/|\\ *** X|X
|
||||
/ \\ / | \\''',
|
||||
// 프레임 5: 복귀 (승리 포즈)
|
||||
'''
|
||||
\\o/ O
|
||||
/|\\ /|\\
|
||||
/ \\ / | \\''',
|
||||
],
|
||||
frameIntervalMs: 220,
|
||||
);
|
||||
|
||||
/// 시스템 전투 애니메이션 (커널 모양)
|
||||
const battleAnimationSystem = AsciiAnimationData(
|
||||
frames: [
|
||||
// 프레임 1: 대치
|
||||
'''
|
||||
o .-.
|
||||
/|\\ (o.o)
|
||||
/ \\ |=|''',
|
||||
// 프레임 2: 접근
|
||||
'''
|
||||
o .-.
|
||||
/|\\ (o.o)
|
||||
/ \\ |=|''',
|
||||
// 프레임 3: 공격 (근접)
|
||||
'''
|
||||
o_/ .-.
|
||||
/| (>.>)
|
||||
/ \\ |=|''',
|
||||
// 프레임 4: 히트
|
||||
'''
|
||||
o **** .-.
|
||||
/|\\*** (X.X)
|
||||
/ \\ |~|''',
|
||||
// 프레임 5: 복귀 (승리 포즈)
|
||||
'''
|
||||
\\o/ .-.
|
||||
/|\\ (-.-)
|
||||
/ \\ |=|''',
|
||||
],
|
||||
frameIntervalMs: 250,
|
||||
);
|
||||
|
||||
/// 암호화 전투 애니메이션 (자물쇠 모양)
|
||||
const battleAnimationCrypto = AsciiAnimationData(
|
||||
frames: [
|
||||
// 프레임 1: 대치
|
||||
'''
|
||||
o __/\\__
|
||||
/|\\ < (O)(O) >
|
||||
/ \\ \\ \\/ /''',
|
||||
// 프레임 2: 접근
|
||||
'''
|
||||
o __/\\__
|
||||
/|\\ < (O)(O) >
|
||||
/ \\ \\ \\/ /''',
|
||||
// 프레임 3: 공격 (근접)
|
||||
'''
|
||||
o_/ __/\\__
|
||||
/| < (X)(X) >
|
||||
/ \\ \\ \\/ /''',
|
||||
// 프레임 4: 히트
|
||||
'''
|
||||
o **** __/\\__
|
||||
/|\\***< (X)(X) >
|
||||
/ \\ \\ ~~ /''',
|
||||
// 프레임 5: 복귀 (승리 포즈)
|
||||
'''
|
||||
\\o/ __/\\__
|
||||
/|\\ < (-)(-)>
|
||||
/ \\ \\ \\/ /''',
|
||||
],
|
||||
frameIntervalMs: 200,
|
||||
);
|
||||
|
||||
/// AI 전투 애니메이션 (뉴럴넷 모양)
|
||||
const battleAnimationAI = AsciiAnimationData(
|
||||
frames: [
|
||||
// 프레임 1: 대치
|
||||
'''
|
||||
o .---.
|
||||
/|\\ ( o o )
|
||||
/ \\ ~~~~~''',
|
||||
// 프레임 2: 접근
|
||||
'''
|
||||
o .---.
|
||||
/|\\ ( o o )
|
||||
/ \\ ~~~~~''',
|
||||
// 프레임 3: 공격 (근접)
|
||||
'''
|
||||
o_/ .---.
|
||||
/| ( >.< )
|
||||
/ \\ ~~~~~''',
|
||||
// 프레임 4: 히트
|
||||
'''
|
||||
o **** .---.
|
||||
/|\\** ( X X )
|
||||
/ \\ ~~~~~''',
|
||||
// 프레임 5: 복귀 (승리 포즈)
|
||||
'''
|
||||
\\o/ .---.
|
||||
/|\\ ( - - )
|
||||
/ \\ ~~~~~''',
|
||||
],
|
||||
frameIntervalMs: 280,
|
||||
);
|
||||
|
||||
/// 보스 전투 애니메이션 (드래곤/보스 모양)
|
||||
const battleAnimationBoss = AsciiAnimationData(
|
||||
frames: [
|
||||
// 프레임 1: 대치
|
||||
'''
|
||||
o /\\ /\\
|
||||
/|\\ ( o V o )
|
||||
/ \\ \\ ~~~ /''',
|
||||
// 프레임 2: 접근
|
||||
'''
|
||||
o /\\ /\\
|
||||
/|\\ ( o V o )
|
||||
/ \\ \\ ~~~ /''',
|
||||
// 프레임 3: 공격 (근접)
|
||||
'''
|
||||
o_/ /\\ /\\
|
||||
/| ( X V X )
|
||||
/ \\ \\ ~~~ /''',
|
||||
// 프레임 4: 히트
|
||||
'''
|
||||
o ****/\\ /\\
|
||||
/|\\** ( X V X )
|
||||
/ \\ \\ ~~~ /''',
|
||||
// 프레임 5: 복귀 (승리 포즈)
|
||||
'''
|
||||
\\o/ /\\ /\\
|
||||
/|\\ ( - V - )
|
||||
/ \\ \\ ~~~ /''',
|
||||
],
|
||||
frameIntervalMs: 200,
|
||||
);
|
||||
|
||||
/// 몬스터 카테고리별 전투 애니메이션 반환
|
||||
AsciiAnimationData getBattleAnimation(MonsterCategory category) {
|
||||
return switch (category) {
|
||||
MonsterCategory.bug => battleAnimationBug,
|
||||
MonsterCategory.malware => battleAnimationMalware,
|
||||
MonsterCategory.network => battleAnimationNetwork,
|
||||
MonsterCategory.system => battleAnimationSystem,
|
||||
MonsterCategory.crypto => battleAnimationCrypto,
|
||||
MonsterCategory.ai => battleAnimationAI,
|
||||
MonsterCategory.boss => battleAnimationBoss,
|
||||
};
|
||||
}
|
||||
|
||||
/// 레벨업 축하 애니메이션 (8줄 x 40자 고정)
|
||||
/// 캐릭터 위치: 머리=4, 몸통=5, 다리=6 (전투 애니메이션 기준)
|
||||
const levelUpAnimation = AsciiAnimationData(
|
||||
frames: [
|
||||
// 프레임 1: 시작
|
||||
' * * * \n'
|
||||
' * * * \n'
|
||||
' * * \n'
|
||||
' \n'
|
||||
' * \\O/ * \n'
|
||||
' /|\\ \n'
|
||||
' * / \\ * \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 2: 별 확산
|
||||
' * * * \n'
|
||||
' * * \n'
|
||||
' * * \n'
|
||||
' \n'
|
||||
' * \\O/ * \n'
|
||||
' /|\\ \n'
|
||||
' * / \\ * \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 3: 레벨업 텍스트
|
||||
' * L E V E L U P ! * \n'
|
||||
' * * \n'
|
||||
' * * \n'
|
||||
' \n'
|
||||
' * \\O/ * \n'
|
||||
' /|\\ \n'
|
||||
' * / \\ * \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 4: 빛나는 캐릭터
|
||||
' * * * * * \n'
|
||||
' * * \n'
|
||||
' * * * * \n'
|
||||
' \n'
|
||||
' * \\O/ * \n'
|
||||
' * /|\\ * \n'
|
||||
' * / \\ * \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 5: 마무리
|
||||
' + \n'
|
||||
' +++ \n'
|
||||
' +++++ \n'
|
||||
' \n'
|
||||
' \\O/ \n'
|
||||
' /|\\ \n'
|
||||
' / \\ \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
],
|
||||
frameIntervalMs: 300,
|
||||
);
|
||||
|
||||
/// 퀘스트 완료 애니메이션 (8줄 x 40자 고정)
|
||||
/// 캐릭터 위치: 머리=4, 몸통=5, 다리=6 (전투 애니메이션 기준)
|
||||
const questCompleteAnimation = AsciiAnimationData(
|
||||
frames: [
|
||||
// 프레임 1: 퀘스트 깃발
|
||||
' [=======] \n'
|
||||
' || || \n'
|
||||
' || || \n'
|
||||
' ||_____|| \n'
|
||||
' \\O/ \n'
|
||||
' /|\\ \n'
|
||||
' / \\ \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 2: 승리
|
||||
' [QUEST!] \n'
|
||||
' || || \n'
|
||||
' || || \n'
|
||||
' ||_____|| \n'
|
||||
' \\\\O// \n'
|
||||
' /|\\ \n'
|
||||
' / \\ \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 3: 보상
|
||||
' COMPLETE! \n'
|
||||
' \n'
|
||||
' \n'
|
||||
' \$\$\$ \n'
|
||||
' \\O/ \$\$\$ \n'
|
||||
' /|\\ \$\$\$ \n'
|
||||
' / \\ \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 4: 축하
|
||||
' * * * * * \n'
|
||||
' \n'
|
||||
' \n'
|
||||
' * * * * * \n'
|
||||
' \\O/ +EXP \n'
|
||||
' /|\\ +GOLD \n'
|
||||
' / \\ \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 5: 마무리
|
||||
' [ VICTORY! ] \n'
|
||||
' \n'
|
||||
' \n'
|
||||
' \n'
|
||||
' \\O/ \n'
|
||||
' /|\\ \n'
|
||||
' / \\ \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
],
|
||||
frameIntervalMs: 350,
|
||||
);
|
||||
|
||||
/// Act 완료 애니메이션 (8줄 x 40자 고정)
|
||||
/// 캐릭터 위치: 머리=4, 몸통=5, 다리=6 (전투 애니메이션 기준)
|
||||
const actCompleteAnimation = AsciiAnimationData(
|
||||
frames: [
|
||||
// 프레임 1: 커튼
|
||||
' ______________________________ \n'
|
||||
' | A C T | \n'
|
||||
' | C O M P L E T E | \n'
|
||||
' |______________________________| \n'
|
||||
' \n'
|
||||
' \n'
|
||||
' \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 2: 캐릭터 등장
|
||||
' ______________________________ \n'
|
||||
' | * * * * * | \n'
|
||||
' | * * * * * | \n'
|
||||
' |______________________________| \n'
|
||||
' \\O/ \n'
|
||||
' /|\\ \n'
|
||||
' / \\ \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 3: 플롯 진행 표시
|
||||
' ______________________________ \n'
|
||||
' | PROLOGUE --> ACT | \n'
|
||||
' | STORY CONTINUES --> | \n'
|
||||
' |______________________________| \n'
|
||||
' \\O/ \n'
|
||||
' /|\\ \n'
|
||||
' / \\ \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 4: 축하
|
||||
' ______________________________ \n'
|
||||
' | * * * * * | \n'
|
||||
' | * * * * * | \n'
|
||||
' |______________________________| \n'
|
||||
' * \\O/ * \n'
|
||||
' /|\\ \n'
|
||||
' * / \\ * \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 5: 마무리
|
||||
' ______________________________ \n'
|
||||
' | +---------+ | \n'
|
||||
' | | NEXT | | \n'
|
||||
' |____| CHAPTER |_______________| \n'
|
||||
' \\O/ \n'
|
||||
' /|\\ \n'
|
||||
' / \\ \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
],
|
||||
frameIntervalMs: 400,
|
||||
);
|
||||
|
||||
/// 부활 애니메이션 (8줄 x 40자 고정)
|
||||
/// 어둠에서 빛으로, 캐릭터가 다시 일어남
|
||||
const resurrectionAnimation = AsciiAnimationData(
|
||||
frames: [
|
||||
// 프레임 1: 어둠
|
||||
' \n'
|
||||
' . . . . . . \n'
|
||||
' . . \n'
|
||||
' . R . I . P . \n'
|
||||
' . ___ . \n'
|
||||
' . |___| . \n'
|
||||
' . . . . . . \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 2: 빛이 비침
|
||||
' * \n'
|
||||
' . .|. . . . \n'
|
||||
' . | . \n'
|
||||
' . | . \n'
|
||||
' . _O_ . \n'
|
||||
' . /___\\ . \n'
|
||||
' . . . . . . \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 3: 일어나는 중
|
||||
' * * * \n'
|
||||
' . | . . . \n'
|
||||
' . | . \n'
|
||||
' . O . \n'
|
||||
' . /|\\ . \n'
|
||||
' . | | . \n'
|
||||
' . . . . . . \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 4: 서있음
|
||||
' * * * * * \n'
|
||||
' \n'
|
||||
' \n'
|
||||
' O \n'
|
||||
' /|\\ \n'
|
||||
' / \\ \n'
|
||||
' \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
// 프레임 5: 부활 완료
|
||||
' * RESURRECTED! * \n'
|
||||
' \n'
|
||||
' \n'
|
||||
' \\O/ \n'
|
||||
' /|\\ \n'
|
||||
' / \\ \n'
|
||||
' \n'
|
||||
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~',
|
||||
],
|
||||
frameIntervalMs: 600, // 5프레임 × 600ms = 3초
|
||||
);
|
||||
|
||||
/// 타입별 애니메이션 데이터 반환 (기본 전투는 bug)
|
||||
AsciiAnimationData getAnimationData(AsciiAnimationType type) {
|
||||
return switch (type) {
|
||||
AsciiAnimationType.battle => battleAnimationBug,
|
||||
AsciiAnimationType.town => townAnimation,
|
||||
AsciiAnimationType.walking => walkingAnimation,
|
||||
AsciiAnimationType.levelUp => levelUpAnimation,
|
||||
AsciiAnimationType.questComplete => questCompleteAnimation,
|
||||
AsciiAnimationType.actComplete => actCompleteAnimation,
|
||||
AsciiAnimationType.resurrection => resurrectionAnimation,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user