C++ Pixel Dungeon 클론 프로젝트 종합 계획서

계획 간 엇갈리는 부분 및 주요 참고사항

제공된 여러 계획 문서를 통합하며 다음과 같은 주요 사항 및 잠재적 불일치 지점을 확인했습니다:

팀원들은 이러한 사항들을 인지하고, 특히 일정 관리와 역할 협업에 주의를 기울여 프로젝트를 진행해야 합니다.

1. 프로젝트 개요

1.1 프로젝트 목표

본 프로젝트는 인기 로그라이크 게임인 Pixel Dungeon을 C++로 클론하는 것을 목표로 합니다. 6일 동안 5명의 개발자가 협업하여 게임의 핵심 기능을 구현하고, 플레이 가능한 MVP(Minimum Viable Product)를 완성하는 것이 최종 목표입니다 ([source: 426, 427]).

1.2 프로젝트 범위

1.3 주요 산출물

2. 마일스톤 계획 (기존 코드 확장 기반)

다음은 제공된 `PixelDungeonClone` 코드 베이스를 확장하여 진행하는 8단계 마일스톤 계획입니다 ([source: 111-337]).

마일스톤 1: 기존 코드 베이스 이해 및 확장 준비 (목표: ~1일)

M1 클래스 다이어그램 (기존 코드 베이스 구조 파악)

classDiagram class Game { +Run() +Update() +Render() +HandleInput() -map : Map -player : Player -renderer : Renderer -hWnd : HWND -hdc : HDC } class Map { +Load(filePath) bool +GetTileType(x, y) int +GetWidth() int +GetHeight() int -tiles : int[][] } class Renderer { +Init(hWnd) bool +Render(map, entities, camera) +DrawTile(graphicId, x, y, screenX, screenY) +DrawImage(graphicId, x, y, w, h) } class Entity { +x : int +y : int +graphicID : int +SetPosition(x, y) +GetPosition() : Vector2 } class Player { +Move(dx, dy, map) } Game --> Map Game --> Player Game --> Renderer Game --> Entity : manages Entity <|-- Player Renderer --> Map Renderer --> Entity %% 외부 라이브러리 사용은 Mermaid에서 직접적으로 표현 불가. 주석으로 대체. %% Game uses WinAPI functions (windows.h) %% Renderer uses GDI+ functions (gdiplus.h)

M1 시나리오 시퀀스 다이어그램: 게임 루프 및 기본 렌더링 (기존 코드 동작)

sequenceDiagram participant WinAPI participant AppEntry as AppEntry participant Game participant Renderer participant Map participant Player as Player WinAPI->>AppEntry: 윈도우 생성 메시지 (WM_CREATE 등) AppEntry->>Game: Game 객체 생성 및 초기화 AppEntry->>Game: Run() 호출 loop Game Loop (Game::Run) WinAPI->>WinAPI: 메시지 큐 처리 (DispatchMessage 등) alt 입력 메시지 (WM_KEYDOWN 등) WinAPI->>Game: 메시지 전달 (Game의 윈도우 프로시저) Game->>Game: HandleInput() 호출 및 처리 (Player 이동 등) end alt 화면 업데이트 메시지 (WM_PAINT 등) WinAPI->>Game: 메시지 전달 Game->>Game: Render() 호출 end Game->>Game: Update() 호출 (간단한 상태 업데이트 - 아직 턴, AI 없음) Game->>Renderer: Render(map, entities, ...) Renderer->>Map: 맵 데이터 요청 (GetTileType 등) Map-->>Renderer: 맵 데이터 Renderer->>Player: 플레이어 위치/그래픽 정보 요청 Player-->>Renderer: 위치/그래픽 Renderer->>Renderer: GDI+ 호출 (DrawTile, DrawImage 등) Renderer-->>WinAPI: 화면 업데이트 완료 (EndPaint 등) end

마일스톤 2: 턴 시스템 도입 및 Entity 확장 (목표: ~1.5일)

M2 클래스 다이어그램

classDiagram class Game { +Update() +AddActor(actor) -TurnManager turnManager -vector~Entity*~ actors } class Map { } class Renderer { +DrawText(text, x, y) } class Entity { +x int +y int +graphicID int +SetPosition(x, y) +GetPosition() Vector2 +Act(game) virtual +NeedsInput() virtual bool +isActive bool } class Player { +Move(dx, dy, map) +Act(game) override +NeedsInput() override bool } class Monster { +Act(game) override +NeedsInput() override bool } class TurnManager { +AddActor(actor) +ProcessTurns(game) +EndTurn() +GetCurrentActor() Entity* -vector~Entity*~ turnQueue -int currentActorIndex } Game "1" -- "1" TurnManager : has a Game "1" -- "*" Entity : manages (as actors) TurnManager "1" -- "*" Entity : manages turn queue Entity <|-- Player : inherits, overrides Act/NeedsInput Entity <|-- Monster : inherits, overrides Act/NeedsInput Renderer "1" -- "*" Entity : draws entity graphics & status(future) Renderer "1" -- "1" Game : draws UI text via Game

M2 시나리오 시퀀스 다이어그램: 플레이어 턴 종료 및 몬스터 턴 (대기)

sequenceDiagram participant Game participant TurnManager participant Player participant Monster participant Renderer participant WinAPI loop Game Loop (Game::Run/Update) Game->>TurnManager: GetCurrentActor() TurnManager-->>Game: CurrentActor (Player) Game->>Player: NeedsInput()? Player-->>Game: true Game->>TurnManager: EndTurn() TurnManager->>TurnManager: 다음 Actor 인덱스 계산 TurnManager-->>Game: 다음 턴 준비 완료 Game->>TurnManager: GetCurrentActor() TurnManager-->>Game: CurrentActor (Monster) Game->>Monster: NeedsInput()? Monster-->>Game: false Game->>Monster: Act(game) Monster-->>Game: Act() 완료 Game->>TurnManager: EndTurn() TurnManager->>TurnManager: 다음 Actor 인덱스 계산 (다시 Player) TurnManager-->>Game: 다음 턴 준비 완료 (Player 턴) Game->>Renderer: Render(...) Renderer-->>WinAPI: 화면 표시 end

마일스톤 3: 절차적 던전 생성 (목표: ~1.25일)

M3 클래스 다이어그램

classDiagram class Game { +InitializeGame() -Map map -DungeonGenerator dungeonGenerator } class Map { +Generate(generator, width, height) +GetRandomFloorTile() Vector2 +GetTileType(x, y) int +GetWidth() int +GetHeight() int -vector~vector~int~~ tiles } class Renderer { } class Entity { } class Player { } class Monster { } class TurnManager { } class DungeonGenerator { +Generate(width, height) vector~vector~int~~ -GenerateRooms() -ConnectRooms() } Game "1" -- "1" Map : has a Game "1" -- "1" DungeonGenerator : has a Map "1" -- "1" DungeonGenerator : is created by / receives data from Game "1" -- "*" Entity : places entities on map

M3 시나리오 시퀀스 다이어그램: 게임 시작 시 던전 생성 및 배치

sequenceDiagram participant AppEntry participant Game participant DungeonGenerator participant Map participant Player participant Monster participant TurnManager participant WinAPI AppEntry->>Game: InitializeGame() Game->>DungeonGenerator: Generate(width, height) DungeonGenerator->>DungeonGenerator: 방/복도 생성 알고리즘 실행 DungeonGenerator-->>Game: 생성된 맵 데이터 (vector>) Game->>Map: Generate(generatedData) Map-->>Game: Map 생성 완료 Game->>Map: GetRandomFloorTile() Map-->>Game: playerStartPos Game->>Player: SetPosition(playerStartPos) Game->>TurnManager: AddActor(player) Game->>Map: GetRandomFloorTile() Map-->>Game: monsterStartPos Game->>Monster: SetPosition(monsterStartPos) Game->>TurnManager: AddActor(monster) Game->>Game: Run() Game->>Game: Update() Game->>Game: Render() Game->>WinAPI: 화면 표시 요청

마일스톤 4: 시야 시스템 (FoV) 및 카메라 이동 (목표: ~1일)

M4 클래스 다이어그램

classDiagram class Game { +Update() -FieldOfView fov -Camera camera } class Map { +GetTileType(x, y) int +IsSolid(x, y) bool +SetTileVisibility(x, y, seen, explored) +IsTileSeen(x, y) bool +IsTileExplored(x, y) bool +GetWidth() int +GetHeight() int -vector~vector~int~~ tiles -vector~vector~bool~~ isSeen -vector~vector~bool~~ isExplored } class Renderer { +Render(map, entities, camera) +DrawTile(graphicId, x, y, screenX, screenY, isSeen, isExplored) +DrawImage(graphicId, x, y, w, h, isVisible) } class Entity { +x int +y int +graphicID int +IsVisible(map) bool } class Player { } class Monster { +Act(game) override } class TurnManager { } class DungeonGenerator { } class FieldOfView { +Calculate(map, startX, startY, radius) } class Camera { +Update(targetX, targetY, mapWidth, mapHeight, screenWidth, screenHeight) +GetRenderOffsetX() int +GetRenderOffsetY() int -x float -y float } Game "1" -- "1" FieldOfView : has a Game "1" -- "1" Camera : has a Game "1" -- "1" Renderer : passes camera FieldOfView "1" -- "1" Map : updates visibility state FieldOfView "1" -- "1" Player : uses player position Camera "1" -- "1" Player : follows player Renderer "1" -- "1" Camera : uses offset for drawing Renderer "1" -- "1" Map : reads map data and visibility Renderer "1" -- "*" Entity : reads entity data and visibility Entity "1" -- "1" Map : checks own visibility

M4 시나리오 시퀀스 다이어그램: 플레이어 이동 후 시야/카메라 업데이트 및 렌더링

sequenceDiagram participant Game participant Player participant Map participant FieldOfView participant Camera participant Renderer participant WinAPI Player->>Player: 위치 업데이트 완료 Game->>Game: 플레이어 이동 감지 Game->>FieldOfView: Calculate(map, player.x, player.y, radius) FieldOfView->>Map: 맵 타일 시야/탐험 상태 업데이트 요청 Map->>Map: isSeen, isExplored 배열 업데이트 Map-->>FieldOfView: 업데이트 완료 FieldOfView-->>Game: 시야 업데이트 완료 Game->>Camera: Update(player.x, player.y, ...) Camera->>Camera: 카메라 위치/오프셋 계산 Camera-->>Game: 업데이트 완료 Game->>Renderer: Render(map, entities, camera) Renderer->>Renderer: SetCameraOffset(camera.GetRenderOffsetX(), camera.GetRenderOffsetY()) Renderer->>Map: 맵 데이터 요청 (타일 타입, 시야/탐험 상태 포함) Map-->>Renderer: 맵 데이터 Renderer->>Renderer: 시야/탐험 상태와 오프셋 적용하여 맵 타일 그리기 Renderer->>Game: 엔티티 목록 요청 (actors) Game-->>Renderer: 엔티티 목록 (Player, Monsters) loop 각 Entity Renderer->>Entity: IsVisible(map)? Entity->>Map: IsTileSeen(entity.x, entity.y)? Map-->>Entity: 결과 Entity-->>Renderer: 가시성 결과 alt 가시성 결과 true Renderer->>Renderer: GDI+ 호출 (DrawImage - Entity 그리기) end end Renderer-->>WinAPI: 화면 업데이트 완료

마일스톤 5: 기초 전투 & 시각적 상태 표시 (목표: ~0.75일)

M5 클래스 다이어그램

classDiagram class Game { +HandleInput() +ProcessCombat(attacker, defender) } class Map { } class Renderer { +DrawHPBar(screenX, screenY, currentHP, maxHP, width) +DrawCombatMessage(text) } class Entity { +x int +y int +graphicID int +HP int +MaxHP int +AttackPower int +Defense int +Act(game) virtual +NeedsInput() virtual bool +isActive bool +TakeDamage(amount) +IsAlive() bool +Attack(target) virtual } class Player { +Move(dx, dy, map) +Act(game) override +NeedsInput() override bool +Attack(target) override } class Monster { +Act(game) override +NeedsInput() override bool +Attack(target) override } class CombatSystem { +ProcessAttack(attacker, defender) } Game "1" -- "*" Entity : manages (combat involves Entities) Game "1" -- "1" CombatSystem : has a (if separated) Entity <|-- Player Entity <|-- Monster Renderer "1" -- "*" Entity : draws HP status Renderer "1" -- "1" Game : draws combat messages via Game

M5 시나리오 시퀀스 다이어그램: 플레이어 공격 및 몬스터 사망 시각화

sequenceDiagram participant Game participant Player participant Monster participant Map participant CombatSystem participant Renderer participant WinAPI Game->>Game: 플레이어 이동 감지 Game->>Map: 이동 목표 위치에 몬스터 있는지 확인 Map-->>Game: Monster* 또는 nullptr alt Monster가 있는 경우 (공격 시도) Game->>CombatSystem: ProcessAttack(player, monster) CombatSystem->>Monster: TakeDamage(calculatedDamage) Monster->>Monster: HP 감소 Monster-->>CombatSystem: 업데이트 완료 CombatSystem-->>Game: 전투 결과 (사망 여부 등) Game->>Game: 전투 결과 처리 alt 몬스터 IsAlive() == false Game->>Game: 몬스터 isActive = false 또는 목록에서 제거 Game->>Renderer: DrawCombatMessage("Monster defeated!") end Game->>Renderer: DrawCombatMessage("Player attacks Monster!") Game->>Renderer: UpdateEntityStatusDisplay(player, monster) Game->>Renderer: Render(...) Renderer-->>WinAPI: 화면 표시 else Monster가 없는 경우 (일반 이동) Game->>Player: Move(dx, dy, map) end

마일스톤 6: 위협의 시작 - 몬스터 AI, 플레이어 사망 & 게임 오버 (목표: ~0.75일)

M6 클래스 다이어그램

classDiagram class Game { +Update() +HandleInput() +SetGameState(state) +RestartGame() -GameState currentGameState } class Map { } class Renderer { +DrawGameOverScreen() } class Entity { +x int +y int +graphicID int +HP int +MaxHP int +AttackPower int +Defense int +Act(game) virtual +NeedsInput() virtual bool +isActive bool +TakeDamage(amount) +IsAlive() bool +Attack(target) virtual +GetPosition() Vector2 } class Player { +Act(game) override +NeedsInput() override bool +TakeDamage(amount) +IsAlive() } class Monster { +Act(game) override +NeedsInput() override bool +Attack(target) override } class TurnManager { } class FieldOfView { +IsInSight(map, watcherX, watcherY, targetX, targetY, radius) bool } class CombatSystem { } Game "1" -- "*" Entity : manages (Act() called by Game/TurnManager) Entity <|-- Player Entity <|-- Monster : implements Act() AI Game "1" -- "1" FieldOfView : AI uses FoV via Game Monster "1" -- "1" Map : checks movement validity Monster "1" -- "1" Player : targets player Game "1" -- "1" Renderer : draws state-dependent screens

M6 시나리오 시퀀스 다이어그램: 몬스터 턴 행동 (AI) 및 플레이어 사망

sequenceDiagram participant Game participant TurnManager participant Monster participant Player participant Map participant FieldOfView participant CombatSystem participant Renderer participant WinAPI TurnManager->>Game: GetCurrentActor() TurnManager-->>Game: CurrentActor (Monster) Game->>Monster: Act(game) Monster->>FieldOfView: IsInSight(map, monster.pos, player.pos, radius) FieldOfView-->>Monster: 시야 확인 결과 alt 플레이어가 시야에 있는 경우 Monster->>Player: GetPosition() Player-->>Monster: 플레이어 위치 Monster->>Monster: 이동 또는 공격 결정 로직 alt 플레이어와 인접한 경우 (공격) Monster->>CombatSystem: ProcessAttack(monster, player) CombatSystem->>Player: TakeDamage(calculatedDamage) Player->>Player: HP 감소 Player-->>CombatSystem: 업데이트 완료 CombatSystem-->>Monster: 전투 결과 Game->>Renderer: DrawCombatMessage("Monster attacks!") Game->>Renderer: UpdateEntityStatusDisplay(player) Game->>Renderer: Render() alt Player IsAlive() == false (사망) Game->>Game: SetGameState(GameOver) Game->>Renderer: DrawGameOverScreen() Renderer-->>WinAPI: 화면 표시 Note over Game,WinAPI: 게임 루프 종료 또는 재시작 대기 end else 플레이어와 인접하지 않은 경우 (이동) Monster->>Monster: 플레이어 방향으로 이동 위치 계산 Monster->>Map: IsSolid(targetPos) Map-->>Monster: 결과 alt 이동 가능한 경우 Monster->>Monster: SetPosition(targetPos) Game->>Renderer: Render() end end else 플레이어가 시야에 없는 경우 Monster->>Monster: 무작위 이동 또는 대기 (간단 로직) end Monster-->>Game: Act() 완료 Game->>TurnManager: EndTurn()

마일스톤 7: 뜻밖의 발견 - 아이템 줍기 및 기본 인벤토리 UI (목표: ~0.75일)

M7 클래스 다이어그램

classDiagram class Game { +HandleInput() +ProcessItemPickup(player, item) } class Map { +GetItemAt(x, y) Item* +RemoveItemAt(x, y) +SpawnItem(item, x, y) -vector~Item*~ itemsOnMap } class Renderer { +Render(map, entities, camera, uiManager) +DrawItem(graphicId, x, y, screenX, screenY) } class Entity { } class Player { +Move(dx, dy, map) +AddItem(item) +GetInventory() Inventory* -Inventory inventory } class Monster { } class TurnManager { } class FieldOfView { } class Camera { } class Item { +name string +graphicID int +position Vector2 +IsConsumable() bool +Use(user) virtual } class HealthPotion { +IsConsumable() override bool +Use(user) override } class Inventory { +AddItem(item) +RemoveItem(item) +GetItems() const vector~Item*~& -vector~Item*~ items } class UIManager { +Update(game) +Render(renderer, camera) +HandleInput(keyCode) +IsInventoryOpen() const bool +GetInventory() const Inventory* -bool isInventoryOpen } Game "1" -- "1" Map : manages items on map Game "1" -- "1" Player : has inventory, picks up items Game "1" -- "1" UIManager : has a, manages UI state and input Map "1" -- "*" Item : contains items on map Player "1" -- "1" Inventory : has an inventory Inventory "1" -- "*" Item : contains items Item <|-- HealthPotion Game "1" -- "1" Renderer : passes UIManager UIManager "1" -- "1" Renderer : requests UI drawing UIManager "1" -- "1" Player : accesses player/inventory data UIManager "1" -- "1" Game : receives UI input (via Game.HandleInput)

M7 시나리오 시퀀스 다이어그램: 아이템 줍기 및 인벤토리 열기

sequenceDiagram participant InputHandler as InputHandler participant Game participant Player participant Map participant Item participant Inventory participant UIManager participant Renderer participant WinAPI InputHandler->>Game: 이동 요청 (예: 아이템 타일 방향) Game->>Player: Move(dx, dy, map) Player->>Map: 이동 가능 여부 확인 Map-->>Player: 결과 alt 이동 가능하고 타일에 Item이 있는 경우 Player->>Player: 위치 업데이트 Game->>Map: GetItemAt(player.x, player.y) Map-->>Game: Item* itemToPickup Game->>UIManager: ShowMessage("Picked up " + itemToPickup->name + "!") Game->>Player: AddItem(itemToPickup) Player->>Inventory: AddItem(itemToPickup) Inventory-->>Player: 추가 완료 Player-->>Game: 아이템 획득 완료 Game->>Map: RemoveItemAt(player.x, player.y) Map->>Map: 맵에서 아이템 제거 Game->>Game: 획득 처리 완료 end InputHandler->>Game: 인벤토리 열기/닫기 키 입력 Game->>UIManager: HandleInput(keyCode) UIManager->>UIManager: ToggleInventoryUI() UIManager-->>Game: 상태 변경 완료 Game->>Renderer: Render(map, entities, camera, uiManager) Renderer->>UIManager: Render(renderer, camera) alt UIManager IsInventoryOpen() == true UIManager->>Player: GetInventory() Player-->>UIManager: Inventory* UIManager->>Inventory: GetItems() Inventory-->>UIManager: 아이템 목록 UIManager->>Renderer: DrawUIWindow(...), DrawText(...) Renderer->>Renderer: UI 그리기 end Renderer-->>WinAPI: 화면 표시

마일스톤 8: 전리품 활용 - 아이템 사용 및 인벤토리 UI 상호작용 (목표: ~0.75일)

M8 클래스 다이어그램

classDiagram class Game { +HandleInput() +ProcessItemUse(user, item) } class Map { } class Renderer { +DrawInventoryItem(graphicId, screenX, screenY, isSelected) } class Entity { +x int +y int +graphicID int +HP int +MaxHP int +AttackPower int +Defense int +Act(game) virtual +NeedsInput() virtual bool +isActive bool +TakeDamage(amount) +IsAlive() bool +Attack(target) virtual +GetPosition() Vector2 +Heal(amount) } class Player { +Heal(amount) +UseItem(item) } class Monster { } class TurnManager { } class FieldOfView { } class Camera { } class Item { +name string +graphicID int +position Vector2 +IsConsumable() bool +Use(user) virtual } class HealthPotion { +IsConsumable() override bool +Use(user) override } class Inventory { +AddItem(item) +RemoveItem(item) +GetItems() const vector~Item*~& +GetItemByIndex(index) Item* +RemoveItemByIndex(index) } class UIManager { +Update(game) +Render(renderer, camera) +HandleInput(keyCode) +IsInventoryOpen() const bool +GetInventory() const Inventory* +GetSelectedItemIndex() const int -bool isInventoryOpen -int selectedItemIndex } Game "1" -- "1" UIManager : receives item use request Game "1" -- "1" Player : facilitates item use Game "1" -- "1" Player : handles item selection/use input Player "1" -- "1" Inventory : uses items from inventory Inventory "1" -- "*" Item : contains items Item <|-- HealthPotion : implements Use() UIManager "1" -- "1" Inventory : reads/interacts with inventory UIManager "1" -- "1" Renderer : requests UI drawing UIManager "1" -- "1" Player : accesses player/inventory data Entity <|-- Player : Player implements Heal from Entity

M8 시나리오 시퀀스 다이어그램: 인벤토리에서 물약 사용

sequenceDiagram participant InputHandler as InputHandler participant Game participant UIManager participant Inventory participant Player participant HealthPotion participant Renderer participant WinAPI participant UIOverlay as UIOverlay loop Game Loop (Game::Run) alt GameState == Playing && UIManager.IsInventoryOpen() InputHandler->>Game: 아이템 선택/사용 키 입력 Game->>UIManager: HandleInput(keyCode) UIManager->>UIManager: 선택된 아이템 인덱스 업데이트 OR 사용 요청 판단 alt 사용 요청인 경우 (예: Enter 키) UIManager->>UIManager: GetSelectedItemIndex() UIManager-->>Game: selectedItemIndex Game->>Player: GetInventory() Player-->>Game: Inventory* Game->>Inventory: GetItemByIndex(selectedItemIndex) Inventory-->>Game: HealthPotion* selectedItem Game->>Game: ProcessItemUse(player, selectedItem) Game->>HealthPotion: Use(player) HealthPotion->>Player: Heal(healAmount) Player->>Player: HP 업데이트 Player-->>HealthPotion: 회복 완료 HealthPotion-->>Game: Use() 완료 Game->>Player: GetInventory() Player-->>Game: Inventory* Game->>Inventory: RemoveItemByIndex(selectedItemIndex) Inventory-->>Game: 아이템 제거 완료 Game->>UIManager: ShowMessage("Used Health Potion!") Game->>UIManager: 인벤토리 UI 업데이트 요청 UIManager->>Renderer: 인벤토리 UI 다시 그리기 요청 Game->>Renderer: Render(...) Renderer-->>WinAPI: 화면 표시 end end end

마일스톤 8 이후 단계

위 8단계의 핵심 기능 구현 후, 기본적인 Pixel Dungeon의 '탐험-전투-아이템 사용-사망' 루프가 완성됩니다. 이후 단계는 다음과 같은 기능들을 추가할 수 있습니다 ([source: 338]):

C++ 초심자 고려 사항 (코드 확장 시)

  1. 기존 코드 분석: 제공된 코드의 클래스 역할, 함수 호출 관계, 실행 흐름을 디버거를 사용하며 충분히 파악합니다 ([source: 339-341]).
  2. 점진적 변경: 새로운 기능을 추가할 때는 최소한의 변경으로 시작하고, 한 번에 너무 많은 기능을 넣지 않습니다 ([source: 342, 343]).
  3. 클래스 책임: 기능 추가 시 어떤 클래스의 책임에 속하는지 고민하고, 필요시 클래스 분리를 고려합니다 ([source: 344, 345]).
  4. 스마트 포인터: 동적 할당된 객체(아이템, 액터 등) 관리에 `std::unique_ptr`나 `std::shared_ptr` 사용을 적극 검토하여 메모리 누수를 방지합니다 ([source: 101, 346, 347]).
  5. WinAPI와 게임 로직 분리: 게임 로직 구현 시 WinAPI 관련 코드는 특정 클래스/부분에만 국한되도록 노력합니다 ([source: 348, 349]).
  6. 함수 오버라이드 (`virtual`, `override`): 가상 함수와 `override` 키워드를 적절히 사용하여 다형성을 활용하고 실수를 방지합니다 ([source: 102, 350]).
  7. Const 정확성: 상태를 변경하지 않는 멤버 함수에 `const` 키워드를 붙여 안정성과 가독성을 높입니다 ([source: 103]).
  8. SOLID 원칙: 가능하면 단일 책임 원칙(SRP), 개방-폐쇄 원칙(OCP) 등 객체 지향 설계 원칙을 염두에 둡니다 ([source: 104, 105]).

3. 도메인별 상세 태스크

프로젝트는 다음 3개의 주요 도메인으로 구분되며, 각 도메인별 상세 태스크는 다음과 같습니다 ([source: 353]). (상세 목록은 `6day_plan_domain_tasks.txt` 참조)

3.1 시스템 개발 도메인

게임의 핵심 로직과 구조 담당. (Level 클래스, 턴 시스템, 던전 생성, 시야, 전투, AI, 아이템 시스템 등)

3.2 게임플레이 구현 도메인

사용자 경험과 게임 메커니즘 담당. (이동, 상호작용, 몬스터 배치, 던전 탐험, 전투/AI/아이템 테스트 및 밸런싱 등)

3.3 UI/콘텐츠 개발 도메인

시각적 요소와 사용자 인터페이스 담당. (UI 요소, 그래픽 리소스, 전투/상태/인벤토리 UI 및 피드백 등)

4. 역할 정의 및 담당자 프로필

효율적인 진행을 위해 5개의 핵심 역할을 정의했습니다 ([source: 471]). 각 역할은 특정 도메인에 집중하며 협업합니다.

4.1 프로젝트 리더 / 아키텍트

4.2 시스템 개발자

4.3 콘텐츠 생성 개발자

4.4 UI/UX 개발자

4.5 그래픽/렌더링 개발자

4.6 역할 간 협업 구조

페어 프로그래밍 세션 계획 예시

페어 프로그래밍 세션 참여 역할 일정 (예상) 기대 효과
Level 클래스 설계/구현 아키텍트 + 시스템 개발자 1일차 오후 핵심 클래스 설계/구현 품질 향상 ([source: 392])
던전 생성 알고리즘 콘텐츠 개발자 + 시스템 개발자 2일차 오전 알고리즘 최적화 및 통합성 확보 ([source: 393])
시야 시스템 구현 그래픽 개발자 + 시스템 개발자 2일차 오후 성능 및 정확성 향상 ([source: 394])
인벤토리 UI 연동 UI 개발자 + 콘텐츠 개발자 5일차 오전 사용성 및 기능 연동 개선 ([source: 395])

5. 프로젝트 일정 (6일 계획)

참고: 총 예상 작업 시간은 310인시(5인 팀 기준 약 7.75일)로 추정되나([source: 493]), 6일(2025-05-01 ~ 2025-05-06) 내 완료를 목표로 병렬 작업 및 최적화 방안을 적용합니다 ([source: 445]). 아래 간트 차트는 최적화 방안(사전 준비, 강화된 스크럼, 페어 프로그래밍, 기술 스파이크 등)을 반영하여 재구성한 예시입니다.

5.1 간트 차트 (Mermaid) - 최적화 반영 예시

gantt title C++ Pixel Dungeon 클론 프로젝트 - 6일 일정 (최적화 반영) dateFormat YYYY-MM-DD axisFormat %m-%d todayMarker off section 프로젝트 관리 프로젝트 킥오프 미팅 :milestone, m1, 2025-05-01, 0d 사전 준비 (코드 분석, 설계 초안) :crit, 2025-04-30, 1d 일일 스크럼 (Q&A, 리스크 평가 포함) :daily, 2025-05-01, 6d 페어 프로그래밍 세션 :active, 2025-05-01, 5d 기술 스파이크 세션 :active, 2025-05-01, 2d 중간 검토 회의 :milestone, m2, 2025-05-03, 0d 최종 검토 회의 :milestone, m3, 2025-05-06, 0d 프로젝트 완료 :milestone, m4, 2025-05-06, 0d section 기본 구조 & 시스템 (아키텍트, 시스템 개발자) 코드베이스 분석 & Level 설계 완성 :crit, task_sys1, 2025-05-01, 1d Level 클래스 & Actor 확장 :crit, task_sys2, after task_sys1, 1d 턴 시스템 구현 :crit, task_sys3, after task_sys2, 1d 전투 시스템 구현 :crit, task_sys4, 2025-05-03, 1d 몬스터 AI 구현 :crit, task_sys5, after task_sys4, 1d 게임 상태 관리 :crit, task_sys6, after task_sys5, 0.5d section 콘텐츠 생성 (콘텐츠 개발자, 시스템 개발자 지원) DungeonGenerator 설계 & 구현 :task_con1, 2025-05-01, 1.5d 액터 배치 로직 :task_con2, after task_con1, 0.5d Item 클래스 & 시스템 구현 :crit, task_con3, 2025-05-04, 2d section 그래픽/렌더링 (그래픽 개발자, 시스템 개발자 지원) 시야 계산 로직 & 상태 관리 :task_gfx1, 2025-05-02, 1.5d 카메라 시스템 구현 :task_gfx2, after task_gfx1, 0.5d 그래픽 리소스 관리 :task_gfx3, 2025-05-04, 1d section UI 개발 (UI 개발자, 그래픽 개발자 지원) UIManager 설계 & 구현 :task_ui1, 2025-05-01, 1d 기본 UI 요소 구현 (HP, 로그) :task_ui2, after task_ui1, 0.5d 전투 UI & 피드백 구현 :task_ui3, 2025-05-03, 1d 게임 상태 UI 구현 :task_ui4, after task_ui3, 0.5d 인벤토리 UI 구현 :task_ui5, 2025-05-05, 1d section 게임플레이 & 테스트 (전체 팀) 기본 상호작용 테스트 :test_p1, 2025-05-02, 0.5d 던전/몬스터 배치 테스트 :test_p2, after task_con2, 0.5d 시야/카메라 테스트 :test_p3, after task_gfx2, 0.5d 전투 시스템 테스트 :test_p4, after task_sys4, 0.5d 몬스터 AI 테스트 :test_p5, after task_sys5, 0.5d 아이템 시스템 테스트 :test_p6, after task_con3, 0.5d 시스템 통합 테스트 :crit, test_t1, 2025-05-05, 0.5d 버그 수정 & 최적화 :crit, test_t2, after test_t1, 0.5d 최종 테스트 & 검증 :crit, test_t3, 2025-05-06, 0.5d

5.2 주요 마일스톤 일정

5.3 일별 주요 작업 계획 (간트 차트 참고)

6. 계획 최적화 방안 요약

제한된 6일 내 성공적인 완료를 위해 다음과 같은 계획 최적화 방안을 적용합니다 ([source: 377-425]):

6.1 의존성 매트릭스 (예시)

주요 태스크 간의 선후행 관계를 명확히 하여 의존성을 관리합니다 ([source: 403]).

태스크 ID 설명 선행 태스크 후행 태스크 담당 역할 우선순위
1.1.3 Level 클래스 개념 설계 1.1.1, 1.1.2 1.2.1, 1.2.4, 1.3.3 아키텍트 최상
1.2.2 Actor 클래스 확장 1.2.1 1.2.3, 1.5.1, 1.6.1, 1.7.3 시스템 개발자 최상
1.3.2 던전 생성 알고리즘 구현 1.3.1 1.3.3, 2.3.2 콘텐츠 개발자
1.4.1 시야 계산 로직 추가 1.2.1 1.4.2, 1.4.5, 2.4.1 그래픽 개발자
3.1.1 UIManager 클래스 생성 - 3.1.2, 3.1.3, 3.3.1, 3.5.3 UI 개발자

6.2 중요 경로 (Critical Path)

프로젝트 완료 일정에 직접적인 영향을 미치는 핵심 태스크 경로입니다. 이 태스크들의 지연은 전체 프로젝트 지연으로 이어질 수 있으므로 집중 관리가 필요합니다 ([source: 409]).

  1. 기존 코드베이스 분석 (task_sys1 일부)
  2. Level 클래스 개념 설계 및 생성 (task_sys1 일부, task_sys2 일부)
  3. Actor 클래스 확장 (task_sys2 일부)
  4. 턴 시스템 구현 (task_sys3)
  5. 전투 시스템 구현 (task_sys4)
  6. 몬스터 AI 구현 (task_sys5)
  7. 아이템 시스템 구현 (task_con3)
  8. 통합 테스트 (test_t1, test_t2, test_t3)

관리 방안: 중요 경로 태스크 우선 처리, 추가 리소스 할당 고려, 일일 진행 상황 중점 모니터링, 지연 발생 시 즉시 대응 계획 가동.

6.3 C++ 초심자 지원 방안

팀원들의 C++ 학습 곡선을 완화하고 생산성을 높이기 위한 지원 방안입니다 ([source: 397]).

지원 항목 내용 담당 시기
C++ 핵심 개념 가이드 포인터, 메모리 관리, 클래스 상속 등 아키텍트 프로젝트 시작 전
코드 템플릿 모음 자주 사용되는 패턴 템플릿 아키텍트 프로젝트 시작 전
일일 Q&A 세션 15분 기술 질문 해결 시간 전체 팀 매일 스크럼 후
코드 리뷰 체크리스트 주요 오류 패턴 및 검토 포인트 아키텍트 프로젝트 시작 전

6.4 기술적 스파이크 세션

핵심/복잡 기능 구현 전에 기술적 리스크를 사전 검증하고 해결 방안을 확보하기 위한 짧은 탐색 세션입니다 ([source: 416]).

기술적 스파이크 목적 시기 (예상) 담당자
절차적 던전 생성 알고리즘 검증 및 성능 테스트 1일차 오후 콘텐츠 개발자 ([source: 418])
시야 계산 알고리즘 정확성 및 성능 검증 2일차 오전 그래픽 개발자 ([source: 419])
턴 기반 시스템 에너지 기반 턴 시스템 검증 2일차 오전 시스템 개발자 ([source: 420])
메모리 관리 동적 객체 관리 패턴 검증 (스마트 포인터 등) 1일차 오후 아키텍트 ([source: 421])

7. 프로젝트 관리 방안

7.1 가속화 방안 ([source: 455, 602])

7.2 안정화 방안 ([source: 456, 603])

7.3 리스크 관리

리스크 백업 계획 발동 조건 담당자
Level 클래스 설계 지연 임시 인터페이스로 병렬 개발 진행 1일차 종료 시 미완료 아키텍트 ([source: 412])
던전 생성 알고리즘 복잡성 단순화된 알고리즘으로 대체 2일차 오후까지 미해결 콘텐츠 개발자 ([source: 413])
시야 시스템 성능 이슈 최적화된 간소화 버전 적용 테스트 시 FPS 저하 발생 그래픽 개발자 ([source: 414])
통합 문제 발생 모듈별 독립 테스트 버전 유지 통합 테스트 실패 시스템 개발자 ([source: 415])

7.4 품질 관리