[Node.js_6기 본캠프] CH 2. 개인과제 트러블 슈팅_0823

2024. 8. 23. 21:13[Node.js_6기 본캠프 TIL]

▶ CH 2. Rogue like JAVASCRIPT! 개인 과제

 

드디어 player와 monster가 허공을 긁지 않고, 서로에게 딜을 넣을 수 있게 되었다. 한참 헤메이다가 구현한 기능인 만큼, 도전과제에 해당하는 Math.random()을 활용한 딜량 랜덤 요소까지 욕심이 났다. 제출일까지 구현 가능한 요소들을 최대한 건드려 볼 생각이다.

 

1) 이제 진짜 battle 시작!

class Player {
  constructor(player) {
    this.hp = 100;
    this.minPower = 10;
    this.maxPower = 15;
  }

  normal_ATK(monster) {
    let damage = Math.floor(Math.random() * (this.maxPower - this.minPower + 1)) + this.minPower;
    monster.hp -= damage;
    return damage;
  }

  counter_ATK(monster) {
    let damage = Math.floor(Math.random() * (this.maxPower - this.minPower + 1)) + this.minPower;
    monster.hp -= damage;
    return damage * 2;
  }

  ultimate_ATK(monster) {
    let damage = 999;
    monster.hp -= damage;
    return damage;
  }
}

 

class Player의 constructor의 값이 (player)로 채워진 상태로 처음 코드를 받았다보니, 계속 그 밑에 있던 attack() 함수에도 player나 공란으로 두고 테스트했었다. 공격의 주체가 player니까, 위에서도 그 값을 받고 있으니까 그게 맞는거라고 생각했던 것 같다. 그러나 결국 moster의 hp를 향한 함수여야 하기 때문에, 해당 칸에 monster 값을 채워야 한다는 것을 알았다.

 

attack 함수를 실행하면 1) 대미지가 계산되고 2) monster의 hp를 그만큼 깎아야 하기 때문에 damage를 먼저 선언했다. 처음엔 10의 고정값으로 두고, choice가 호출되는 부분에 const damageToMonster = player.attack을 선언해주니 진짜 딜이 들어가기 시작했다. 그 뒤로는 신나서 랜덤 요소를 부여하고, 스킬을 분리하기 시작했다.

 

 

2) 쉽지만은 않았던 랜덤 요소

정수값으로 처리해야 하기 때문에 Math.floor()처리를 해주고, Math.random()으로 임의의 값을 부여하되 최소 대미지/최대 대미지를 반영하기 위해 (this.maxPower - this.minPower + 1)를 곱해주고 this.minPower 를 한번 더 더해주었다. 

 

또한 스킬별로 성공 확률 및 대미지 계산식이 다르기 때문에 각각의 스킬을 구분하여 세팅했다. ultimate_ATK는 확률이 10% 만큼 하이리스크 하이리턴의 즉사기로 구성하여, 별도의 대미지 계산식 없이 999의 딜을 부여했다.

 

스킬 전반적으로 %와 대미지 증감식을 조정해야 할 것 같지만, 일단 구현되었음에 큰 기쁨을 느끼고 있다.

switch (choice) {
      case '1':
        const normal_damageToMonster = player.normal_ATK(monster);
        logs.push(chalk.blueBright('[ EVE의 물리 공격! ]'));
        logs.push(
          chalk.blueBright(`▶ 성공: 오염체에게 ${normal_damageToMonster} 의 대미지를 입혔다.`),
        );
        const damageToPlayer = monster.attack(player);
        logs.push(chalk.red('[ 오염체의 공격! ]'));
        logs.push(chalk.red(`[ 오염체에게 ${damageToPlayer} 의 대미지를 받았다.]`));
        logs.push(chalk.magentaBright(` `));
        break;
      case '2':
        if (rand_0_100(1) > 70) {
          const counter = player.counter_ATK(monster);
          logs.push(chalk.blueBright('[ EVE의 전류 방출! ]'));
          logs.push(chalk.blueBright(`▶ 성공: 오염체가 감전되어 일시적 행동 불가 상태가 되었다!`));
          logs.push(chalk.blueBright(`[ 오염체에게 ${counter} 의 대미지를 입혔다. ]`));
          logs.push(chalk.magentaBright(` `));
          break;
        } else {
          logs.push(chalk.blueBright('[ EVE의 전류 방출! ]'));
          logs.push(chalk.blueBright(`▶ 실패: 오염체에게 0 의 대미지를 입혔다.`));
          const damageToPlayer2 = monster.attack(player);
          logs.push(chalk.red('[ 오염체의 공격! ]'));
          logs.push(chalk.red(`[ 오염체에게 ${damageToPlayer2}의 대미지를 받았다.]`));
          logs.push(chalk.magentaBright(` `));
          break;
        }
      case '3':
        if (rand_0_100(1) > 90) {
          const ultimate = player.ultimate_ATK(monster);
          logs.push(chalk.blueBright('[ EVE의 방어 시스템 복구 시도! ]'));
          logs.push(chalk.blueBright(`▶ 성공: 오염체에게 ${ultimate}의 대미지를 입혔다.`));
          logs.push(chalk.magentaBright(` `));
          break;
        } else {
          const damageToPlayer3 = monster.attack(player);
          logs.push(chalk.blueBright('[ EVE의 방어 시스템 복구 시도! ]'));
          logs.push(chalk.blueBright(`▶ 실패: 오염체에게 0 의 대미지를 입혔다.`));
          logs.push(chalk.red('[ 오염체의 공격! ]'));
          logs.push(chalk.red(`[ 오염체에게 ${damageToPlayer3}의 대미지를 받았다.]`));
          logs.push(chalk.magentaBright(` `));
          break;
        }

 

또 하드코딩을 했나 고민이 되긴 하지만, 스킬을 성공/실패했을 경우에 따라 결과가 달라지는 것을 반영하기 위해 if 문을 사용했다. 조건문으로는 0부터 100까지 랜덤 숫자를 굴리는 함수 rand_0_100을 실행했을 때, 범위 안의 수를 뽑았는가-를 주었다. 해당 수치에 따라 성공시 로그, 실패시 로그를 분리해주었다. 처음에는 rand_0_100 함수를 빈 값으로 호출해서 함수식만 고스란히 노출되는 사고가 있기도 했다.

 

player와 moster의 딜을 주고 받는 과정을 명료하게 보여주기 위해서 log가 길어졌는데, 몇줄 이상 넘어가면 clear 해주는 기능이 필요할 것 같다. consle.clear()를 중간에 끼워넣는 방식으로는 구현되지 않아, 새로운 방법을 고민해야겠다.

 

 

 

3) 스테이지 클리어 시, 정비하는 설정이 있었는데요...

 

스테이지 클리어 자체는 기본 코드에서 무난하게 기능하고 있다. 문제는 그 사이에 player의 체력이 회복되는 등 정비하는 요소가 있어야 하는데, 그 부분을 어떻게 구현해야 할지 모르겠다. 첫날에 이리저리 조합했던 게임 오버와 게임 클리어 시 나오는 화면을 호출하는 것도 붙여넣지 못해서 고민이 많이 필요하다. 궁극기가 발동되면 바로 다음 스테이지 화면이 호출되는 것도 조정하고 싶다. 욕심이 너무 많은가 싶지만, 이왕 해보는 거 제법 그럴듯한 미니게임이 되었으면 좋겠다.