JavaScript 강의를 듣고 Text 형식의 게임을 만들어 보는 프로젝트를 가졌다.
기본적으로 제공된 리소스에서 주어진 필수+도전 과제가 있고, 추가로 기능을 넣어도 되었다.
이름은 던전밥이 생각나서 DungeonLife 라는 이름으로 대충 작명했다.
예전부터 턴제형식의 게임을 좋아했었는데 주어진 리소스와 과제들을 보니 턴제형식과 잘 어울릴 것 같아서 에픽세븐의 '비올레토' 라는 캐릭과 비슷한 능력으로 Player를 만들고 스테이지를 공략하는 게임을 만들어 볼 예정이다.
Player
비올레토는 여러 자버프와 디버프를 겸한 도적이다.
눈에 띄는 능력이 있다면 패시브로 스택이 존재하며, 회피를 하면 스택이 충전되고 풀스택이 되면 궁극기 쿨타임이 초기화된다. 궁극기를 사용하면 현재 있는 모든 스택을 사용하고 사용한 스택에 비례하여 대미지를 준다.
여기서 채용하고 싶은 점은 회피와 궁극기이다.
공격을 받으면 일정 확률로 회피를 하고, 회피에 성공하면 스택이 충전된다.
궁극기를 가지고 있고, 쿨타임이 있으며 스택이 모두 차면 쿨타임이 초기화된다. 스택에 비례하여 데미지를 입힌다.
Monster
몬스터의 경우 일단 단일 몬스터로 제한하여 구현해볼 예정이다.
몬스터도 동일하게 회피와 방어가 존재하고, 각종 디버프를 가진 몬스터를 만들어 볼 예정이다.
ex) 공격 성공 시 일정확률로 명중 감소, 공격 성공 시 일정 확률로 공격력 감소
버프와 디버프
버프와 디버프는 모두 1턴으로 제한하여 적용할 예정이다.
그러면 받았는데 턴이 종료된 상태면 소용없는거 아닌가?
=> 이 부분은 Player와 Monster 클래스에 별도로 버프와 디버프의 속성을 넣어주어 관리할 예정이다. 그러면 버프와 디버프가 남아 있는 경우는 다음 턴에서도 유효하다.
=> 이러면 누적이 될 수 있는데 누적은 되지 않고 1턴으로 제한되도록 할 예정이다.
종료 조건
게임의 종료 조건은 2가지이고, 스테이지에서는 player와 monster 의 체력을 확인하여 종료될 수 있도록 해주었다.
monster.hp <= 0
, 스테이지 클리어player.hp <= 0
, 게임 패배currentStage >= totalStage
, 게임 승리스탯
Player와 Monster의 공통적인 부분이 있어 class로 묶었다.
현재 구현한 내용만 한다면
class Unit {
constructor(name, hp, minDamage, maxDamage, type, speed) {
this.name = name;
this.hp = hp;
this.minDamage = minDamage;
this.maxDamage = maxDamage;
this.unitType = type;
this.speed = speed;
}
}
(속성)
(행동)
1. attack() : 다른 인스턴스를 공격하는 메서드이다.
추가로, Player의 경우 더 많은 속성과 행동이 추가될 수 있다.
(방어, 스킬 등)
기타 설정
Class 활용
class Unit {
}
class Player extends Unit {
}
class monster extends Unit {
}
// 스테이지에 관련된 속성과 메서드가 있는 클래스
class Stage {
}
// 배틀에 관련된 속성과 메서드가 있는 클래스
class Battle {
}
async / await 활용
await stage.startStage(player, monster);
const result = stage.checkStage(player, monster);
if (result === false) {
break;
}
else if (result === true) {
stage.currentStage++;
}
for(let i=0; i<turnOrder.length; i++) {
await turnOrder[i].action(player, monster, logs);
const isBattleEnd = await Battle.endCheck(player, monster);
if(isBattleEnd === true) {
return true;
}
}
Current Issue
이렇게 Class 로 구분하다 보니 Log에
이런식으로 [0]~[2] 까지 한 스테이지에 있던 상황이 모두 출력되지 않는 상황이다.
(현재상황)
이렇게 [0]~[10] 로그가 없고 [11]~[12] 까지(바로 직전 상황)만 나오는 상황이어서 이 부분을 어떻게 처리할지 고민중이다.
발생 원인은
class Stage {
constructor(player, stageLength) {
this.logs = [];
}
async startStage(player, monster) {
console.clear();
while (player.hp > 0 || monster.hp > 0) {
console.clear();
console.log(chalk.magentaBright(`=== Stage ${this.currentStage} ===`));
console.log(chalk.inverse(`\n${monster.name}을 조우했다!`));
const turnOrder = Battle.checkTurn(player, monster);
this.displayStatus(player, monster, turnOrder);
this.logs.forEach((log) => console.log(log));
const battleEnd = await Battle.battleStart(player, monster, turnOrder, this.logs);
if(battleEnd) {
break;
}
}
}
위 코드에서 Stage라는 클래스에 로그들을 모아둘 logs를 선언 및 초기화를 해주고,
startStage(스테이지 시작) 마다 콘솔창을 초기화 시켜주는 상황이다.
때문에 내가 만약 1. 공격 2. 방어 3. 도망
여기서 번호를 선택하면 다음에 어떤 상태가 되었는지 로그로 확인도 못하고 바로 초기화되어 다음 배틀의 상태로그가 출력되는 상태인 것이다.
각 함수에 다 logs.push 하면 this.logs.forEach((log) => console.log(log));
호출되면서 나오니까 attack 이라던가 어떤 행동이나 상태가 바뀔때마다 로그를 넣어주고 싶지만...
더 효율적으로 할 수 있는 방법이 없을까 하면서 고민하고 있는 상태이다.