feat(canvas): Canvas 기반 ASCII 애니메이션 렌더러 구현

- JetBrains Mono 폰트 번들링 (Android/iOS 호환성)
- Paragraph 캐싱으로 GC 압박 최소화 (최대 256개 캐시)
- shouldRepaint layerVersion 기반 최적화
- willChange 동적 설정으로 메모리 절약
- 레이어 기반 합성 구조 (배경/캐릭터/몬스터/이펙트)
- hp_mp_bar 몬스터 HP 숫자 오버플로우 수정
This commit is contained in:
JiWoong Sul
2025-12-20 07:49:11 +09:00
parent cf8fdaecde
commit c07f77a02f
18 changed files with 2224 additions and 277 deletions

View File

@@ -31,12 +31,16 @@ class ResurrectionService {
required String killerName,
required DeathCause cause,
}) {
// 제물로 바칠 아이템 선택 (장착된 아이템 중 랜덤 1개)
// 제물로 바칠 아이템 선택 (무기 제외, 장착된 아이템 중 랜덤 1개)
final equippedItems = <int>[]; // 장착된 아이템의 슬롯 인덱스
for (var i = 0; i < Equipment.slotCount; i++) {
final slot = EquipmentSlot.values[i];
// 무기 슬롯은 제외
if (slot == EquipmentSlot.weapon) continue;
final item = state.equipment.getItemByIndex(i);
// 빈 슬롯과 기본 무기(Keyboard) 제외
if (item.isNotEmpty && item.name != 'Keyboard') {
// 빈 슬롯 제외
if (item.isNotEmpty) {
equippedItems.add(i);
}
}
@@ -130,6 +134,48 @@ class ResurrectionService {
),
);
// 4. 부활 후 태스크 시퀀스 설정 (큐에 추가)
// 순서: 마을 귀환 → 샵 정비 → 사냥터 이동 → 전투
final resurrectionQueue = <QueueEntry>[
const QueueEntry(
kind: QueueKind.task,
durationMillis: 3000, // 3초
caption: 'Returning to town...',
taskType: TaskType.neutral, // 걷기 애니메이션
),
const QueueEntry(
kind: QueueKind.task,
durationMillis: 3000, // 3초
caption: 'Restocking at shop...',
taskType: TaskType.market, // town 애니메이션
),
const QueueEntry(
kind: QueueKind.task,
durationMillis: 2000, // 2초
caption: 'Heading to hunting grounds...',
taskType: TaskType.neutral, // 걷기 애니메이션
),
];
// 기존 큐 초기화 후 부활 시퀀스만 설정
nextState = nextState.copyWith(
queue: QueueState(
entries: resurrectionQueue, // 기존 큐 완전 제거
),
// 현재 태스크를 빈 상태로 설정하여 큐에서 다음 태스크를 가져오도록 함
progress: nextState.progress.copyWith(
currentTask: const TaskInfo(
caption: '',
type: TaskType.neutral,
),
task: const ProgressBarState(
position: 0,
max: 1, // 즉시 완료되어 큐에서 다음 태스크 가져옴
),
currentCombat: null, // 전투 상태 명시적 초기화
),
);
return nextState;
}