This commit is contained in:
2025-12-02 01:35:39 +09:00
parent ae1ebdc6bf
commit 45c6185d3e
20 changed files with 1104 additions and 92 deletions
+26
View File
@@ -0,0 +1,26 @@
## 13. 아이템 옵션: 상태이상 부여 (Stun, Vulnerable, Bleed, DefenseForbidden)
### 목표
아이템에 상태이상 부여 옵션을 추가하고, 캐릭터가 이를 관리할 수 있도록 시스템을 구축한다.
### 구현 내용
1. **`StatusEffectType``StatusEffect` 정의 (lib/game/model/status_effect.dart)**
* 기존 `entity.dart`에 정의되어 있던 `StatusEffectType` (Enum)과 `StatusEffect` (Class)를 `lib/game/model/status_effect.dart` 파일로 분리하여 순환 참조 문제를 해결하고 모듈성을 높였다.
* `StatusEffectType`에는 `stun` (기절), `vulnerable` (취약), `bleed` (출혈), `defenseForbidden` (방어불가)가 포함되었다.
* `StatusEffect` 클래스는 `type`, `duration`, `value` 필드를 가진다.
2. **`Character` 클래스 업데이트 (lib/game/model/entity.dart)**
* `Character` 클래스에 `List<StatusEffect> statusEffects` 필드를 추가하여 현재 적용 중인 상태이상 목록을 관리할 수 있도록 했다.
* 상태이상을 추가하는 `addStatusEffect(StatusEffect newEffect)` 메서드를 추가했다 (기존 효과가 있다면 갱신).
* 상태이상의 지속 시간을 업데이트하고 만료된 효과를 제거하는 `updateStatusEffects()` 메서드를 추가했다.
* 특정 상태이상 보유 여부를 확인하는 `hasStatus(StatusEffectType type)` 헬퍼 메서드를 추가했다.
3. **`Item` 클래스 업데이트 (lib/game/model/item.dart)**
* 아이템이 부여할 수 있는 상태이상의 종류, 확률, 지속시간, 강도를 정의하는 `ItemEffect` 클래스를 새로 추가했다.
* `Item` 클래스에 `List<ItemEffect> effects` 필드를 추가하여 아이템이 가질 수 있는 상태이상 부여 옵션을 정의할 수 있도록 했다. 이 필드는 생성자에서 `this.effects = const []`로 기본 초기화된다.
### 다음 단계
* `item_table.dart`에 상태이상 옵션을 포함한 아이템 데이터를 추가.
* `BattleProvider`에서 아이템의 `ItemEffect`를 기반으로 전투 중 상태이상을 발동시키고, `Character``statusEffects`를 관리하는 로직 구현.
* `BattleProvider`에서 각 상태이상(`stun`, `vulnerable`, `bleed`, `defenseForbidden`)의 실제 효과를 적용하는 로직 구현.
@@ -0,0 +1,27 @@
## 14. BattleProvider에 상태이상 로직 통합 및 아이템 데이터 추가 준비
### 목표
상태이상 시스템을 BattleProvider에 통합하고, 상태이상을 가진 아이템을 게임에 추가하기 위한 준비를 마친다.
### 구현 내용
1. **`BattleProvider`의 상태이상 로직 통합 (lib/providers/battle_provider.dart)**
* `StatusEffect` 관련 정의 (`lib/game/model/status_effect.dart`)를 임포트했다.
* **턴 시작 시 효과 처리 (`_processStartTurnEffects`):**
* 캐릭터의 턴 시작 시 호출되어 출혈(Bleed) 데미지를 적용하고, 기절(Stun) 상태 여부를 체크하여 캐릭터의 행동 가능 여부를 결정한다.
* 기절 상태인 경우, 캐릭터는 해당 턴에 아무런 행동도 할 수 없다.
* **턴 종료 시 효과 갱신:**
* `playerAction``_enemyTurn` 메서드 내에서 턴 종료 시 `Character.updateStatusEffects()`를 호출하여 모든 상태이상의 `duration`을 감소시키고 만료된 효과를 제거한다.
* **공격 시 상태이상 부여 (`_tryApplyStatusEffects`):**
* 공격이 성공했을 때, 공격자(`player`)가 장착한 아이템들의 `ItemEffect` 목록을 순회한다.
*`ItemEffect``probability`에 따라 랜덤하게 상태이상을 굴려 피격자(`enemy`)에게 `Character.addStatusEffect()`를 통해 상태이상을 부여한다.
* **취약(Vulnerable) 효과 적용 (`_applyDamage`):**
* `_applyDamage` 메서드 내에서 피격자가 `vulnerable` 상태일 경우, 최종 데미지를 1.5배 증폭시킨다.
* **방어불가(DefenseForbidden) 효과 적용 (`playerAction`):**
* `playerAction` 메서드 초반에 플레이어가 `defenseForbidden` 상태일 경우, 방어 행동을 선택할 수 없도록 막는 로직을 추가했다.
2. **`Character` 클래스 `onHitEffects` getter 추가 (lib/game/model/entity.dart) - 미실현**
* 이전 대화에서 `Character``onHitEffects` getter를 추가하여 모든 장비의 효과를 모아주는 것을 논의했으나, `_tryApplyStatusEffects``attacker.equipment.values`를 직접 순회하는 방식으로 구현되면서 현재는 미실현 상태이다. 필요시 추후 리팩토링될 수 있다.
3. **상태이상을 가진 아이템 데이터 추가 준비:**
* 다음 단계로 `lib/game/data/item_table.dart`에 상태이상 효과를 가진 새로운 아이템들을 추가할 예정이다. 이 아이템들은 게임 시작 시 플레이어 인벤토리에 지급되어 테스트에 활용될 것이다.
+20
View File
@@ -0,0 +1,20 @@
## 15. UI 개선: 아이템 옵션 및 상태이상 표시
### 목표
새로 추가된 아이템의 상태이상 부여 옵션을 `InventoryScreen`에서 확인할 수 있게 하고, 전투 중(`BattleScreen`) 캐릭터에게 적용된 상태이상을 시각적으로 표시한다.
### 구현 내용
1. **ItemEffect 설명 텍스트 생성 로직**
* `ItemEffect` 클래스(혹은 `Item` 클래스)에 효과 정보를 읽기 쉬운 문자열(예: "Stun 20% (1 turn)")로 변환하는 헬퍼 메서드 또는 Getter를 추가한다.
2. **InventoryScreen 수정**
* 아이템 상세 정보 팝업(혹은 리스트 아이템)에 기존 스탯(공격력, 방어력 등) 외에 `effects` 리스트를 순회하며 상태이상 옵션을 표시하는 UI를 추가한다.
3. **BattleScreen 수정**
* **Active Status 표시:** 플레이어와 적의 정보 패널(HP 바 근처)에 현재 적용 중인 상태이상(`stun`, `bleed` 등)을 텍스트나 아이콘 형태(여기선 텍스트 칩 형태)로 표시한다.
* (선택 사항) 장착된 무기의 효과를 전투 화면에서도 알 수 있다면 좋지만, 우선순위는 현재 상태이상 상태(Active Status) 표시에 둔다.
### 예상 결과
* 인벤토리에서 "Stunning Hammer"를 클릭하면 "Atk: 10" 밑에 "Chance to Stun: 20% (1t)" 같은 설명이 보인다.
* 전투 중 적에게 기절을 걸면, 적 이름/HP 근처에 "[Stun: 1t]" 태그가 나타난다.
@@ -0,0 +1,21 @@
## 16. 상태이상 지속 턴 계산 로직 조정 (플레이어 턴 기준)
### 목표
상태이상(특히 적에게 부여된 디버프)의 지속 턴 계산 방식을 플레이어 턴을 기준으로 조정하여, 게임 플레이의 직관성을 높인다.
### 문제점 인식
이전 구현에서는 적에게 부여된 디버프의 지속 시간이 적의 턴이 종료될 때 감소했다. 이로 인해 아이템 설명에 "2턴 지속"이라고 명시된 효과가 실제 플레이어 체감 상으로는 1번의 공격 기회만 제공하는 등, 직관성과 밸런스 문제가 발생할 수 있었다. 플레이어는 자신이 부여한 디버프가 '자신의 턴'을 기준으로 유지되기를 기대한다.
### 구현 내용
1. **적의 상태이상 지속 턴 감소 로직 이동 (lib/providers/battle_provider.dart)**
* 기존 `_enemyTurn` 메서드에서 적의 `enemy.updateStatusEffects()` 호출을 제거했다. 이는 적이 행동을 마칠 때 상태이상이 감소하던 로직을 없앤다.
* `playerAction` 메서드의 **시작 부분**에 `enemy.updateStatusEffects()` 호출을 추가했다.
* **결과:** 이제 적에게 걸린 상태이상의 지속 시간은 **플레이어의 턴이 시작될 때**마다 1씩 감소한다. 이는 플레이어가 자신의 턴이 시작될 때 '시간이 흘렀다'고 인식하는 직관적인 흐름에 맞추어진다.
### 기대 효과
* 플레이어는 적에게 부여한 디버프의 남은 턴 수를 자신의 턴 흐름에 맞춰 보다 직관적으로 이해하고 전략을 세울 수 있다.
* 예: "2턴 지속" 취약 디버프를 걸었을 때, 다음 내 턴에 공격하면 여전히 디버프가 유효한 것을 확인할 수 있다. (단, 부여된 턴 포함 2턴인 경우 여전히 1회 공격이므로, 2회 공격 혜택을 위해서는 아이템의 지속시간 데이터를 3턴 등으로 조정할 필요가 있을 수 있다.)
### 다음 단계
* 플레이어 테스트를 통해 상태이상 턴 계산 로직의 체감 및 밸런스를 검증하고, 필요시 아이템의 지속시간 데이터를 조정한다.
+26
View File
@@ -0,0 +1,26 @@
## 17. 인벤토리 아이템 버리기 기능 (상점 기능 확장 대비)
### 목표
인벤토리(Bag)에 있는 아이템을 선택하여 삭제(버리기)할 수 있는 기능을 추가한다. 이 과정에서 실수로 버리는 것을 방지하기 위한 확인 다이얼로그를 구현하며, 향후 상점(판매) 기능 추가 시 UI 및 로직을 재활용할 수 있는 구조를 고려한다.
### 구현 내용
1. **BattleProvider 수정 (lib/providers/battle_provider.dart)**
* `discardItem(Item item)` 메서드 추가: 인벤토리 리스트에서 해당 아이템을 제거하고 로그를 남긴다.
* 이 메서드는 추후 `sellItem` 등과 유사한 구조를 가지게 된다.
2. **InventoryScreen 수정 (lib/screens/inventory_screen.dart)**
* **인터랙션 변경:** 가방(Bag)의 아이템 클릭 시, 기존에는 바로 '장착 확인창'이 떴으나, 이제는 **'아이템 옵션 메뉴(SimpleDialog)'**가 먼저 뜨도록 변경한다.
* **아이템 옵션 메뉴:**
* 옵션 1: **Equip** (기존 장착 로직 연결)
* 옵션 2: **Discard** (버리기 확인창 연결)
* (추후 Sell 옵션이 이곳에 추가될 수 있음)
* **버리기 확인 다이얼로그 (`_showDiscardConfirmationDialog`):**
* "정말 버리시겠습니까?" 메시지와 아이템 정보를 보여준다.
* 확인 시 `provider.discardItem(item)`을 호출한다.
* 이 다이얼로그 구조는 제목과 콜백 함수만 바꾸면 '판매 확인창'으로도 쉽게 재활용 가능하다.
### 예상 결과
* 인벤토리 아이템 클릭 -> [Equip, Discard] 메뉴 팝업.
* Discard 선택 -> "Discard [Item Name]?" 확인 팝업.
* Confirm -> 아이템 삭제 및 로그 출력.
@@ -0,0 +1,32 @@
## 18. 스테이지 클래스 도입 및 스테이지 타입(상점, 엘리트, 휴식) 구현
### 목표
단순 `int`로 관리되던 스테이지 시스템을 `Stage` 클래스와 `StageType`으로 리팩토링하여 다양한 게임 모드(상점, 보스/엘리트, 휴식)를 지원할 수 있는 기반을 마련한다.
### 구현 내용
1. **Stage 모델 정의 (lib/game/model/stage.dart)**
* `StageType` Enum: `battle`, `elite` (또는 boss), `shop`, `rest`.
* `Stage` Class:
* `type`: 스테이지 종류.
* `enemy`: 전투/엘리트 스테이지용 적 캐릭터 객체.
* `shopItems`: 상점 스테이지용 판매 아이템 리스트.
2. **BattleProvider 리팩토링 (lib/providers/battle_provider.dart)**
* `Stage currentStage` 객체를 관리하도록 변경.
* `_spawnEnemy()` 메서드를 `_generateNextStage()`로 대체 및 확장.
* **스테이지 생성 규칙 (예시):**
* 10, 20 스테이지... : **Elite/Boss**
* 5, 15 스테이지... : **Shop** (아이템 3개 랜덤 생성)
* 8, 18 스테이지... : **Rest** (체력 회복 기회)
* 그 외: **Battle** (일반 몬스터)
* 상점 기능을 위한 `buyItem(Item item)`, `sellItem(Item item)` 메서드 준비 (UI 연결은 추후).
3. **UI 대응 (BattleScreen)**
* `currentStage.type`에 따라 화면을 다르게 그릴 수 있도록 `build` 메서드 내 분기 처리.
* 우선 Battle 타입 외의 경우(Shop, Rest)에는 간단한 "Coming Soon" 또는 기본 UI 틀을 표시하여 에러를 방지한다.
### 기대 효과
* 게임의 흐름이 다채로워짐.
* 상점 구현을 위한 데이터 구조가 마련됨 (판매 기능 구현 가능).
* 추후 이벤트나 스토리 컷신 등을 스테이지 단위로 끼워 넣기 쉬워짐.
+30
View File
@@ -0,0 +1,30 @@
## 19. 상점 판매 기능 및 골드 시스템 구현
### 목표
캐릭터에게 화폐(Gold) 개념을 도입하고, 상점 스테이지(`StageType.shop`)에 진입했을 때 인벤토리에서 아이템을 판매하여 골드를 획득하는 기능을 구현한다.
### 구현 내용
1. **Character 모델 수정 (lib/game/model/entity.dart)**
* `int gold` 필드를 추가한다 (기본값: 0 또는 초기 자금).
2. **Item 모델 및 가격 책정 로직 (lib/game/model/item.dart, lib/game/data/item_table.dart)**
* `Item` 클래스에 `int price` 필드를 추가한다.
* 모든 아이템 데이터(`ItemTable`)에 일일이 가격을 적는 대신, `ItemTemplate.createItem()` 메서드 내부에서 스탯(ATK, HP, DEF)을 기반으로 가격을 자동 산출하는 공식을 적용하여 효율성을 높인다.
* 공식 예시: `(atk * 10) + (hp * 2) + (armor * 5) + (effects.length * 20)`.
3. **BattleProvider 수정 (lib/providers/battle_provider.dart)**
* `sellItem(Item item)` 메서드 구현:
* 인벤토리에서 아이템 제거.
* 아이템 가격만큼 플레이어 `gold` 증가.
* 로그 기록 ("Sold [Item] for [Price] G").
4. **InventoryScreen 수정 (lib/screens/inventory_screen.dart)**
* 화면 상단(스탯 영역)에 현재 보유 `Gold` 표시.
* 아이템 클릭 시 뜨는 `_showItemActionDialog` 수정:
* 현재 스테이지가 `StageType.shop`일 경우에만 **[Sell]** 버튼을 활성화(또는 표시).
* **판매 확인 다이얼로그:** "Sell [Item] for [Price] G?" 확인 창 구현.
### 예상 결과
* 상점 스테이지에서 인벤토리를 열면 아이템을 팔아 골드를 모을 수 있다.
* 모은 골드는 추후 아이템 구매 기능에 사용된다.
@@ -0,0 +1,27 @@
## 20. 메인 메뉴 및 캐릭터 선택 화면 구현
### 목표
게임 실행 시 바로 전투 화면으로 진입하지 않고, 메인 타이틀 화면과 캐릭터 선택 과정을 거쳐 게임에 진입하도록 흐름을 변경한다.
### 구현 내용
1. **Main Menu Screen (lib/screens/main_menu_screen.dart)**
* 게임 타이틀 ("Colosseum's Choice") 표시.
* [START] 버튼: 누르면 캐릭터 선택 화면으로 이동.
2. **Character Selection Screen (lib/screens/character_selection_screen.dart)**
* 플레이어블 캐릭터(직업) 목록을 보여준다.
* 현재는 기본 "Warrior" (기존 initBattle 스탯) 하나만 제공한다.
* 캐릭터 카드/버튼 클릭 시:
* `BattleProvider.initializeBattle()`을 호출하여 게임 데이터를 초기화한다.
* `MainWrapper`(게임 메인 화면)로 이동한다 (`Navigator.pushReplacement`).
3. **Main Entry Point 수정 (lib/main.dart)**
* 앱의 `home``MainWrapper`에서 `MainMenuScreen`으로 변경한다.
4. **BattleProvider 수정 (lib/providers/battle_provider.dart)**
* 생성자에서 `initializeBattle()`을 호출하지 않도록 변경한다 (게임 시작 시 명시적으로 호출하기 위함).
* `initializeBattle` 메서드가 호출될 때 기존 데이터가 확실히 초기화되도록 보장한다.
### 예상 결과
* 앱 실행 -> 메인 메뉴 -> Start -> 캐릭터 선택(Warrior) -> 게임 시작(1스테이지)