feat(hall-of-fame): 명예의 전당 대폭 개선 및 장비/아이템 직렬화
- HallOfFameEntry에 finalEquipmentDetails 추가 (상세 장비 정보) - EquipmentItem/ItemStats에 toJson/fromJson 직렬화 추가 - 명예의 전당 상세 다이얼로그 UI 대폭 개선 - Canvas 타운/워킹 애니메이션 컴포저 개선 - 캐릭터 생성 화면 UI 개선 - 게임 텍스트 다국어 지원 확장
This commit is contained in:
@@ -1,11 +1,16 @@
|
||||
import 'package:askiineverdie/src/core/animation/canvas/ascii_cell.dart';
|
||||
import 'package:askiineverdie/src/core/animation/canvas/ascii_layer.dart';
|
||||
import 'package:askiineverdie/src/core/animation/race_character_frames.dart';
|
||||
|
||||
/// Canvas용 마을/상점 애니메이션 합성기
|
||||
///
|
||||
/// 마을 배경 + 상점 건물 + 캐릭터
|
||||
/// Phase 4: 종족별 캐릭터 프레임 지원
|
||||
class CanvasTownComposer {
|
||||
const CanvasTownComposer();
|
||||
const CanvasTownComposer({this.raceId});
|
||||
|
||||
/// 종족 ID (종족별 캐릭터 프레임 선택용)
|
||||
final String? raceId;
|
||||
|
||||
/// 프레임 상수
|
||||
static const int frameWidth = 60;
|
||||
@@ -67,9 +72,24 @@ class CanvasTownComposer {
|
||||
}
|
||||
|
||||
/// 캐릭터 레이어 생성 (z=2)
|
||||
/// Phase 4: 종족별 프레임 지원
|
||||
AsciiLayer _createCharacterLayer(int globalTick) {
|
||||
final frameIndex = globalTick % _shopIdleFrames.length;
|
||||
final charFrame = _shopIdleFrames[frameIndex];
|
||||
final frameIndex = globalTick % 4; // 4프레임 루프
|
||||
List<String> charFrame;
|
||||
|
||||
// 종족별 프레임 사용 시도
|
||||
if (raceId != null && raceId!.isNotEmpty) {
|
||||
final raceData = RaceCharacterFrames.get(raceId!);
|
||||
if (raceData != null) {
|
||||
// idle 프레임 직접 사용 (마을에서는 서있는 자세)
|
||||
final idleFrame = raceData.idle[frameIndex % raceData.idle.length];
|
||||
charFrame = idleFrame.lines;
|
||||
} else {
|
||||
charFrame = _shopIdleFrames[frameIndex];
|
||||
}
|
||||
} else {
|
||||
charFrame = _shopIdleFrames[frameIndex];
|
||||
}
|
||||
|
||||
final cells = _spriteToCells(charFrame);
|
||||
|
||||
|
||||
@@ -2,12 +2,17 @@ import 'package:askiineverdie/src/core/animation/background_data.dart';
|
||||
import 'package:askiineverdie/src/core/animation/background_layer.dart';
|
||||
import 'package:askiineverdie/src/core/animation/canvas/ascii_cell.dart';
|
||||
import 'package:askiineverdie/src/core/animation/canvas/ascii_layer.dart';
|
||||
import 'package:askiineverdie/src/core/animation/race_character_frames.dart';
|
||||
|
||||
/// Canvas용 걷기 애니메이션 합성기
|
||||
///
|
||||
/// 배경 스크롤 + 걷는 캐릭터
|
||||
/// Phase 4: 종족별 캐릭터 프레임 지원
|
||||
class CanvasWalkingComposer {
|
||||
const CanvasWalkingComposer();
|
||||
const CanvasWalkingComposer({this.raceId});
|
||||
|
||||
/// 종족 ID (종족별 캐릭터 프레임 선택용)
|
||||
final String? raceId;
|
||||
|
||||
/// 프레임 상수
|
||||
static const int frameWidth = 60;
|
||||
@@ -54,9 +59,24 @@ class CanvasWalkingComposer {
|
||||
}
|
||||
|
||||
/// 걷는 캐릭터 레이어 생성 (z=1)
|
||||
/// Phase 4: 종족별 프레임 지원
|
||||
AsciiLayer _createCharacterLayer(int globalTick) {
|
||||
final frameIndex = globalTick % _walkingFrames.length;
|
||||
final charFrame = _walkingFrames[frameIndex];
|
||||
final frameIndex = globalTick % 4; // 4프레임 루프
|
||||
List<String> charFrame;
|
||||
|
||||
// 종족별 프레임 사용 시도
|
||||
if (raceId != null && raceId!.isNotEmpty) {
|
||||
final raceData = RaceCharacterFrames.get(raceId!);
|
||||
if (raceData != null) {
|
||||
// idle 프레임을 기반으로 걷기 애니메이션 생성
|
||||
final idleFrame = raceData.idle[frameIndex % raceData.idle.length];
|
||||
charFrame = _animateWalking(idleFrame.lines, frameIndex);
|
||||
} else {
|
||||
charFrame = _walkingFrames[frameIndex];
|
||||
}
|
||||
} else {
|
||||
charFrame = _walkingFrames[frameIndex];
|
||||
}
|
||||
|
||||
final cells = _spriteToCells(charFrame);
|
||||
|
||||
@@ -68,6 +88,22 @@ class CanvasWalkingComposer {
|
||||
return AsciiLayer(cells: cells, zIndex: 1, offsetX: charX, offsetY: charY);
|
||||
}
|
||||
|
||||
/// idle 프레임 기반 걷기 애니메이션 생성
|
||||
/// 머리와 몸통은 유지, 다리만 걷는 동작으로 변경
|
||||
List<String> _animateWalking(List<String> idleLines, int frameIndex) {
|
||||
if (idleLines.length < 3) return idleLines;
|
||||
|
||||
// 머리(0)와 몸통(1)은 그대로 유지
|
||||
final head = idleLines[0];
|
||||
final body = idleLines[1];
|
||||
|
||||
// 다리 애니메이션 (4프레임) - 걷기 동작
|
||||
const legFrames = [' /| ', ' |\\ ', ' /| ', ' |\\ '];
|
||||
final legs = legFrames[frameIndex % legFrames.length];
|
||||
|
||||
return [head, body, legs];
|
||||
}
|
||||
|
||||
/// 문자열 스프라이트를 AsciiCell 2D 배열로 변환
|
||||
List<List<AsciiCell>> _spriteToCells(List<String> lines) {
|
||||
return lines.map((line) {
|
||||
|
||||
Reference in New Issue
Block a user