1과 2의 뼈대는 1일차에 완성되었다고 생각한다.
1일차에 타일의 스프라이트가 추가된 지도를 다시 한 번 보자.
지금 지도 타일의 형식은 흙, 나무, 돌, 풀, 물로 되어 있다.
가장 간단하게 생각해서 플레이어를 해당 타일에 위치시키고, 어떠한 키를 통해 해당 타일에 오브젝트가 있다면 수집하는 것으로 판정해서 그림을 제거하고 인벤토리를 업데이트하는 방식이면 괜찮지 않을까?
먼저 해당 타일에 오브젝트가 있는지를 알아야 할 것 같다.
private drawDebugInfo(): void {
const { x, y } = this.player.getPlayable().position;
const ctx = this.debugCanvas.getContext("2d")!;
ctx.clearRect(0, 0, 400, 50);
ctx.font = "14px Arial";
ctx.fillStyle = "black";
const tileCoord = _whatTile(x, y);
ctx.fillText(
`X: ${Math.floor(x)}, Y: ${Math.floor(y)}, whatTile ${
MapObject[this.map.getMap()[tileCoord.col][tileCoord.row]]
}, tree: ${this.player.tree}`,
15,
25
);
}
해결책은 생각보다 간단했다. 캔버스를 하나 더 두던가, 아니면 하나의 캔버스를 쪼개서 디버그 정보 패널을 다는 것.
캔버스 클래스는 이미 만들어 두었으니, 충분히 캔버스 인스턴스를 두 개로 쪼개서 표시하는 것이 앞으로 훨씬 좋을 것 같다고 생각했다.
디버깅 캔버스를 따로 둔 것은 앞으로도 아주 유용할 거라고 생각한다. FPS라든지, NPC의 정보라든지 추가적인 정보를 표기하는데 유용할 것 같다.
private gatherResources() {
const currentTile = _whatTile(
this.player.getPlayable().position.x,
this.player.getPlayable().position.y
);
const mapData = this.map.getMap();
const tileValue = mapData[currentTile.col][currentTile.row];
// Create a mapping for gatherable tiles:
const gatherableTiles: {
[key: number]: { resource: string; newTile: number };
} = {
[MapObject.STONE]: { resource: "stone", newTile: MapObject.DIRT },
[MapObject.TREE]: { resource: "wood", newTile: MapObject.DIRT },
};
const action = gatherableTiles[tileValue];
if (action) {
// Update the tile and add the corresponding resource to the player.
const newMap = this.map.getMap();
newMap[currentTile.col][currentTile.row] = action.newTile;
this.player.setResource(action.resource, 1);
this.map.setMap(newMap);
}
}
해당 펑션이 추가되어 현재 타일이 어떤 타일인지 확인한 뒤 돌과 나무라면 플레이어의 이벤토리에서 1 늘리고, 기존 타일을 흙 타일로 바꾸도록 수정이 되었다.
여기까지 만들어놓고 보니... 생각보다 빠르게 목표를 달성했다는 느낌이 든다. 물론 중간에 한글로 쓰던 프롬프트를 영어로 바꾸긴 했다. 그렇다고 해도 여전히 빠른 속도이다.
남은 시간과 3일차는 앞으로의 추가 개발을 위해 하나의 거대한 main.ts 내부의 클래스들을 나누는 것이 될 것 같다.
사실 클린 스트럭쳐를 구현해보면 좋았겠지만, 내 자신의 이해도 부족으로 AI의 적절한 답을 얻을 수 없었다. 대신 직접 클래스를 기능별로 나누되 조언을 구하는 방향으로 진행하기로 하였다.
farmingV1-clean/src
├── assetLoader.ts // 스프라이트 및 리소스 로드
├── camera.ts // 화면 이동 및 카메라 기능
├── canvas.ts // 캔버스 생성 및 관리
├── constants.ts // 게임 내에서 사용하는 상수값 관리
├── gameEvent.ts // 게임 내 이벤트 및 상호작용 관리
├── index.d.ts // 타입 선언 파일 (TypeScript 전용)
├── main.ts // 게임의 진입점 (엔트리 포인트)
├── player.ts // 플레이어 클래스 및 애니메이션 로직
├── tileMap.ts // 타일맵 데이터 및 렌더링
├── utils.ts // 범용적인 유틸리티 함수 모음
작업을 통해 다음과 같이 클래스를 나눌 수 있었다. 이 과정에서는
3일차에서는 해당 나눠진 코드 베이스를 기반으로 추가적인 개선이 있을 것 같다.
1일차와 마찬가지로 설정한 목표에 대해 빠르게 진행되었음. 다만 중간에 AI가 잘못된 코드를 주는 경우가 있어 프롬프트를 영어로 바꾸어 진행하였음.
하지만 1일차와 다르게 조금씩 세세한 부분에서 에러가 있어 직접 조정한 부분이 있었음. 계속해서 이런 현상에 대해 주의할 필요가 있음.
references:
https://medium.com/better-programming/how-to-implement-a-typescript-web-app-with-clean-architecture-27c7eb745ab4
https://iamschulz.com/writing-a-game-in-typescript/#conclusion