Class_Text RPG 게임 제작 (2)

화살표 함수와 this

앞에서 본 onGameMenuInput과 onBattleMenuInput은 모두 화살표 기능을 통해 구현됩니다.

함수를 화살표 함수로 구현하지 않고 addEventListener에서 호출하면 $gameMenu 또는 $gameMenu 값과 같은 것을 가리킵니다.

이는 addEventListener 함수가 받은 함수의 this 값을 자신의 this 매개변수로 설정하기 때문인데 이를 피하기 위해 화살표 함수를 사용합니다.

화살표 함수는 가장 가까운 상위 범위의 this를 그대로 가져와서 사용하므로 this가 예기치 않은 값을 가리키는 것을 방지합니다.

 updateHeroStat() {
    const { hero } = this;
    if (hero === null) {
      $heroName.textContent="";
      $heroLevel.textContent="";
      $heroHp.textContent="";
      $heroXp.textContent="";
      $heroAtt.textContent="";
      return;
    }
    $heroName.textContent = hero.name;
    $heroLevel.textContent = `${hero.lev}Lev`;
    $heroHp.textContent = `HP: ${hero.hp}/${hero.maxHp}`;
    $heroXp.textContent = `XP: ${hero.xp}/${15 * hero.lev}`;
    $heroAtt.textContent = `ATT: ${hero.att}`;
  }

이제 영웅을 생성할 때마다 그에 대한 정보가 화면에 표시됩니다.

위 코드를 추가하고 this.updateHeroStat();를 추가하여 명령어를 통해 직접 실행합니다.

다음으로 몬스터를 생성하고 몬스터 정보를 화면에 표시하고 몬스터가 나온다는 메시지를 표시해야 합니다.

      this.changeScreen('battle');
      const randomIndex = Math.floor(Math.random() * this.monsterList.length);
      const randomMonster = this.monsterList(randomIndex);
      this.monster = new Monster(
        this,
        randomMonster.name,
        randomMonster.hp,
        randomMonster.att,
        randomMonster.xp,
      );
      this.updateMonsterStat();
      this.showMessage(`몬스터와 마주쳤다.

${this.monster.name}인 것 같다!
`);

이것은 1단계 위험을 감수하기로 선택한 if 절의 내용입니다.

전투 모드를 변경하고 무작위 몬스터를 생성하십시오.

 updateMonsterStat() {
    const { monster } = this;
    if (monster === null) {
      $monsterName.textContent="";
      $monsterHp.textContent="";
      $monsterAtt.textContent="";
      return;
    }
    $monsterName.textContent = monster.name;
    $monsterHp.textContent = `HP: ${monster.hp}/${monster.maxHp}`;
    $monsterAtt.textContent = `ATT: ${monster.att}`;
  }
  showMessage(text) {
    $message.textContent = text;
  }

몬스터를 생성할 때 JSON.parse(JSON.stringify(object))를 사용하지 않습니다.

monsterList의 속성 값을 게임 개체와 함께 Monster 클래스에 넣습니다.

문자열 및 숫자와 같은 값은 딥 카피가 필요하지 않습니다.

다음으로 전투 메뉴에 1을 입력하여 몬스터를 공격합니다.

1번을 클릭하면 전투 메뉴를 구현하는 함수의 if 절에 다음 내용을 입력합니다.

const { hero, monster } = this;
      hero.attack(monster);
      monster.attack(hero);
      this.showMessage(`${hero.att}의 데미지를 주고, ${monster.att}의 데미지를 받았다.

`); this.updateHeroStat(); this.updateMonsterStat();

클래스로 작성된 코드는 기능별로 그룹화되어 있어 깔끔해 보입니다.

하지만 코드의 순서와 실행의 순서가 다르기 때문에 혼동을 일으키기 쉽습니다.

전투의 결과를 알고

공격을 누르면 서로 공격하기 때문에 먼저 HP가 0이 되는 쪽이 승자입니다.

주인공의 생명값이 0이 되면 게임이 종료되고, 몬스터의 생명값이 0이 되면 주인공은 경험치를 얻습니다.

주인공은 레벨업에 필요한 경험치를 획득하여 레벨업에 따라 혜택을 얻습니다.

const { hero, monster } = this;
      hero.attack(monster);
      monster.attack(hero);
      if (hero.hp <= 0) {
        this.showMessage(`${hero.lev} 레벨에서 전사. 새 주인공을 생성하세요.`);
        this.quit();
      } else if (monster.hp <= 0) {
        this.showMessage(`몬스터를 잡아 ${monster.xp} 경험치를 얻었다.

`); hero.getXp(monster.xp); this.monster = null; this.changeScreen('game'); } else { this.showMessage(`${hero.att}의 데미지를 주고, ${monster.att}의 데미지를 받았다.

`); } this.updateHeroStat(); this.updateMonsterStat();

이것은 전투에 1을 입력하는 코드입니다.

몬스터와 주인공의 체력에 따라 다른 조건문을 처리한다.

quit() 및 showMessage() 메서드는 각각 게임에서 구현되고 getXp 메서드는 Hero에서 구현됩니다.

그런데 이렇게 메소드를 작성하고 나면 Hero 클래스와 Monster 클래스가 공통점이 많다는 것을 알 수 있습니다.

그들의 이름, 체력, 공격력, 경험치 및 기타 속성은 일반적이며 공격 방법도 겹칩니다.

이러한 중복을 없애기 위해 상속이라는 개념이 생겨났습니다.

Hero 클래스와 Monster 클래스의 공통 부분을 새 클래스로 만들기만 하면 Hero 클래스와 Monster 클래스가 이 클래스를 가져와서 사용할 수 있는 이른바 상속입니다.

class Unit {
  constructor(game, name, hp, att, xp) {
    this.game = game;
    this.name = name;
    this.maxHp = hp;
    this.hp = hp;
    this.xp = xp;
    this.att = att;
  }
  attack(target) {
    target.hp -= this.att;
  }
}

Unit이라는 클래스를 만들었습니다.

Hero 및 Monster 클래스는 super를 사용하여 부모 클래스인 Unit의 속성을 사용할 수 있습니다.

class Hero extends Unit {
  constructor(game, name) {
    super(game, name, 100, 10, 0); // 부모 클래스의 생성자 호출
    this.lev = 1; // 그 외 속성
  }
  attack(target) {
    super.attack(target); // 부모 클래스의 attack
    console.log('주인공이 공격');// 부모 클래스 attack 외의 동작

  }
  ...
}

class Monster extends Unit {
  constructor(game, name, hp, att, xp) {
    super(game, name, hp, att, xp);
  }
}

Monster는 공격 방식을 생성하지 않고 부모 클래스에서 공격 방식을 직접 호출합니다.