-
JavaScript 입문 : textRPG 만들기 - 사냥감 변경, 클래스간 상호 작용(클래스 상속)컴퓨터 알아가기/JavaScript 2022. 9. 11. 19:30728x90반응형
이 글은 제로초 TV의 자바스크립트 강좌를 기본으로 하고 있습니다.
지난시간 프로그래밍은 잘 작동이 되었지만 헌터가 계속적으로 사냥감을 획득하지 못하고 전사하는 경우가 발생이 되었습니다. 이는 설정해 놓은 동물들의 파워가 최초부터 워낙 강했기 때문인데요. 이 부분을 약간 수정하고 상호간 공격이 가능하도록 수정할 필요가 있습니다.
1. animalList 수정
좀 더 사냥감 획득이 용이하게 내용을 변경해 주었습니다.
이렇게 하고나니 브라우저상 어느 정도 싸움이 됩니다.
현재까지의 자바스크립트 코딩 내역입니다.
// 객체지향프로그램 (OOP) 활용 // 클래스로 재구성 3탄 - 모험: animal생성, 전투메뉴 생성은 이전완료, 전투메뉴중 공격 // animal의 공격력 조절, 게임이 안되니 수정 const $startScreen = document.querySelector('#start-screen'); const $screen = document.querySelector('#screen'); const $generalMenu = document.querySelector('#general-menu'); const $battleMenu = document.querySelector('#battle-menu'); const $message = document.querySelector('#message'); // 주인공 Status 연결 const $hunterStatus = document.querySelector('#hunter-status'); const $hunterName = document.querySelector('#hunter-name'); const $hunterLevel = document.querySelector('#hunter-level'); const $hunterPower = document.querySelector('#hunter-power'); const $hunterUpgrade = document.querySelector('#hunter-upgrade'); const $hunterAttack = document.querySelector('#hunter-attack'); // 적군 현황 연결 const $animalStatus = document.querySelector('#animal-status'); const $animalName = document.querySelector('#animal-name'); const $animalLevel = document.querySelector('#animal-level'); const $animalPower = document.querySelector('#animal-power'); const $animalUpgrade = document.querySelector('#animal-upgrade'); const $animalAttack = document.querySelector('#animal-attack'); // hunter와 animal을 class로 재구성 (OOP), 상호작용 및 상호접근 용이 class General { // 생성자는 대문자로, constructor(name) { // 이름 매개변수로 생성 this.animal = null; this.hunter = null; // new General(name)으로부터 받아서 this.animalList = [ {name: '멧돼지', power: 10, att: 10, upgrade: 10}, {name: '사자', power: 20, att: 15, upgrade: 20}, {name: '호랑이', power: 30, att: 20, upgrade: 30}, {name: '코끼리', power: 50, att: 40, upgrade: 50}, {name: '공룡', power: 100, att: 70, upgrade: 100}, ]; this.start(name); // General객체내 start시킴 } start(name) { // 특정 동작을 같이 묶는게 좋다 // addEventListener가 있으니까 여기서 this는 향후 화살표 함수로 받음 $generalMenu.addEventListener('submit', this.onGeneralMenuInput); $battleMenu.addEventListener('submit', this.onBattleMenuInput); this.changeScreen('general'); this.hunter = new Hunter(this, name); this.updateHunter(); } changeScreen(screen) { // screen 변하는 기능 한곳에 if (screen === 'start') { // 처음 시작이라는 표시, 어떤 단어도 OK $startScreen.style.display = 'block'; $generalMenu.style.display = 'none'; $battleMenu.style.display = 'none'; } else if (screen === 'general') { $startScreen.style.display = 'none'; $generalMenu.style.display = 'block'; $battleMenu.style.display = 'none'; } else if (screen === 'battle') { $startScreen.style.display = 'none'; $generalMenu.style.display = 'none'; $battleMenu.style.display = 'block'; } } // addEventListener가 붙으면 this는 화살표 함수로 풀어야 한다 (암기) // 화살표함수의 this는 밖에 있는 this를 그대로 가져옴 onGeneralMenuInput = (event) => { // start()에서 generalMenu 활성화 event.preventDefault(); const general = event.target['general-input'].value; // id가져와서 활성화, value는 text if (general === '1') { // 모험 this.changeScreen('battle'); // 전투메뉴로 만들고 console.log(this); // 여기서 this는 General // 랜덤하게 animal 생성 const randomIndex = Math.floor(Math.random() * this.animalList.length); const randomAnimal = this.animalList[randomIndex]; // new Animal( ) 생성 this.animal = new Animal( this, randomAnimal.name, randomAnimal.power, randomAnimal.att, randomAnimal.upgrade, ); this.updateAnimal(); this.showMessage(`사냥할 동물이 나타났다! ${this.animal.name}인것 같다!`); } else if (general === '2') { // 휴식 } else if (general === '3') { // 종료 this.quit(); } }; onBattleMenuInput = (event) => { // start()에서 battleMenu 활성화 event.preventDefault(); const battle = event.target['battle-input'].value; // id가져와서 활성화 if (battle === '1') { // 공격, 서로 공격 const { hunter, animal } = this; hunter.attack(animal); animal.attack(hunter); // 기본적인 공격 메시지 // this.showMessage(`헌터가 ${hunter.att}의 데미지를 주고 ${animal.att}의 데미지를 받았다.`); // 공격해서 나올수 있는 경우의 수를 고민 // 1. hunter power가 0이하면 전사 및 새로운 hunter생성 // 2. animal power가 0이하면 전사 및 animal의 upgrade power를 얻음 (get) // 3. 1,2가 아닌 경우 기본적인 공격메시지 송출 if (hunter.power <= 0) { // 1. this.showMessage(`${hunter.level}레벨에서 전사. 새 주인공을 생성하세요`); this.quit(); // 게임종료에 대한 함수 } else if (animal.power <= 0) { // 2. this.showMessage(`사냥에 성공하여 사냥감이 가지고 있는 ${animal.upgrade}의 힘을 얻었다.`); hunter.getUpgrade(animal.upgrade); // 사냥감 힘 얻는 함수, hunetr내 설정 this.animal = null; // 없어지고 this.changeScreen('general'); // 일반모드로 } else { // 3. this.showMessage(`헌터가 ${hunter.att}의 데미지를 주고 ${animal.att}의 데미지를 받았다.`); } // 각 상태가 업데이트되야 함 this.updateHunter(); this.updateAnimal(); } else if (battle === '2') { // 회복 } else if (battle === '3') { // 도망 : 일반메뉴로 전환 this.changeScreen('general'); } }; // hunter상태 update, 없으면 빈칸, 레벨과 파워변하는 상황 (초기선언) updateHunter() { const { hunter } = this; // 업데이트 할 변수선언, 구조분해할당 모습 if (hunter === null) { // hunter가 없으면 $hunterName.textContent = ''; $hunterLevel.textContent = ''; $hunterPower.textContent = ''; $hunterUpgrade.textContent = ''; $hunterAttack.textContent = ''; return; // return 하고 } // hunter가 있으면 $hunterName.textContent = hunter.name; $hunterLevel.textContent = `레벨: ${hunter.level}`; $hunterPower.textContent = `파워: ${hunter.power} / ${hunter.maxPower}`; $hunterUpgrade.textContent = `업그레이드: ${hunter.upgrade} / ${15 * hunter.level}`; $hunterAttack.textContent = `공격력: ${hunter.att} `; } updateAnimal() { const { animal } = this; // 업데이트 할 변수선언, 구조분해할당 모습 if (animal === null) { // animal이 없으면 $animalName.textContent = ''; $animalPower.textContent = ''; $animalAttack.textContent = ''; return; // return 하고 } // animal이 있으면 $animalName.textContent = animal.name; $animalPower.textContent = `파워: ${animal.power} / ${animal.maxPower}`; $animalAttack.textContent = `공격력: ${animal.att} `; } showMessage(text) { // 메시지 보이게 $message.textContent = text; } // 게임종료 quit() quit() { this.hunter = null; this.animal = null; this.updateHunter(); this.updateAnimal(); $generalMenu.removeEventListener('submit', this.onGeneralMenuInput); $battleMenu.removeEventListener('submit', this.onBattleMenuInput); general = null; } } class Hunter { // hunter는 General에 속하고 name도 속하는 constructor(general, name) { this.general = general; this.name = name; this.level = 1; this.maxPower = 100; this.power = 100; this.upgrade = 0; this.att = 10; } attack(target) { target.power -= this.att; } heal(animal) { this.power += 20; this.power -= animal.att; } // 사냥감 파워 획득 getUpgrade(upgrade) { this.upgrade += upgrade; // upgrade 될때마다 아래 if문을 한번씩 검토, 에러방지 if (this.upgrade >= this.level * 15) { // 경험치를 다 채우면 this.upgrade -= this.level * 15 // 레벨이 오르기 위한 필요power는 15이기에 레벨바뀌고 다시 0으로 세팅 this.level += 1; this.maxPower += 20; // upgrade되면 최대체력은 10늘어나고 this.att += 20; // upgrade되면 공격력도 10늘어나고 this.power = this.maxPower; // upgrade되면 최대체력은 현재체력으로 되고 this.general.showMessage(`레벨업 완료! 현재레벨 ${this.level}`); } } } class Animal { constructor(general, name, power, att, upgrade) { this.general = general; this.name = name; this.maxPower = power; this.power = power; this.att = att; this.upgrade = upgrade; } attack(target) { target.power -= this.att; } } // 게임 시작 프로그램 let general = null; // start-screen 활성화 $startScreen.addEventListener('submit', (event) => { event.preventDefault(); const name = event.target['name-input'].value; // hunter 이름 입력 general = new General(name); // 이름 입력받아 새로운 게임 만들기, 생성자 실행조건 new 필요 });
2. 클래스 상속 extends
Hunter와 Animal 클래스를 보면 공통된 항목을 발견할 수 있습니다. 이미 배웠듯이 super( )라는 부모클래스의 매개변수를 받는 메소드를 통하여 클래스 상속을 시킬 수 있습니다.
여기서 공통된 메소드인 attack(target)또한 부모클래스에 넣어 사용할 수 있습니다. class Unit이라는 부모클래스를 만들고 다음과 같이 작성하면 클래스 상속 처리가 됩니다.
이렇게 필요한 부모클래스로부터 내용을 상속받아 클래스간 상호작용을 하는 내용을 공부해 보았습니다. 이제는 연습만이 살 길인것 같습니다. 얼마나 많은 연습과 노력을 하느냐에 따라 이러한 코딩이 나의 것이 되느냐 아니면 단지 흉내만 내느냐의 문제로 나타날 것 같습니다.
클래스 상속이 적용된 최종 자바스크립트 코드입니다.
// 나머지 코드 작성 :휴식, 회복 // 휴식 : 체력 회복, 전투중에 체력을 20회복, 회복후 동물에게 한번 공격 당함, 최대체력 넘을 수 없음 // 클래스 상속 const $startScreen = document.querySelector('#start-screen'); const $screen = document.querySelector('#screen'); const $generalMenu = document.querySelector('#general-menu'); const $battleMenu = document.querySelector('#battle-menu'); const $message = document.querySelector('#message'); // 주인공 Status 연결 const $hunterStatus = document.querySelector('#hunter-status'); const $hunterName = document.querySelector('#hunter-name'); const $hunterLevel = document.querySelector('#hunter-level'); const $hunterPower = document.querySelector('#hunter-power'); const $hunterUpgrade = document.querySelector('#hunter-upgrade'); const $hunterAttack = document.querySelector('#hunter-attack'); // 적군 현황 연결 const $animalStatus = document.querySelector('#animal-status'); const $animalName = document.querySelector('#animal-name'); const $animalLevel = document.querySelector('#animal-level'); const $animalPower = document.querySelector('#animal-power'); const $animalUpgrade = document.querySelector('#animal-upgrade'); const $animalAttack = document.querySelector('#animal-attack'); // hunter와 animal을 class로 재구성 (OOP), 상호작용 및 상호접근 용이 class General { // 생성자는 대문자로, constructor(name) { // 이름 매개변수로 생성 this.animal = null; this.hunter = null; // new General(name)으로부터 받아서 this.animalList = [ {name: '멧돼지', power: 10, att: 10, upgrade: 10}, {name: '사자', power: 20, att: 15, upgrade: 20}, {name: '호랑이', power: 30, att: 20, upgrade: 30}, {name: '코끼리', power: 50, att: 40, upgrade: 50}, {name: '공룡', power: 100, att: 70, upgrade: 100}, ]; this.start(name); // General객체내 start시킴 } start(name) { // 특정 동작을 같이 묶는게 좋다 // addEventListener가 있으니까 여기서 this는 향후 화살표 함수로 받음 $generalMenu.addEventListener('submit', this.onGeneralMenuInput); $battleMenu.addEventListener('submit', this.onBattleMenuInput); this.changeScreen('general'); this.hunter = new Hunter(this, name); this.updateHunter(); } changeScreen(screen) { // screen 변하는 기능 한곳에 if (screen === 'start') { // 처음 시작이라는 표시, 어떤 단어도 OK $startScreen.style.display = 'block'; $generalMenu.style.display = 'none'; $battleMenu.style.display = 'none'; } else if (screen === 'general') { $startScreen.style.display = 'none'; $generalMenu.style.display = 'block'; $battleMenu.style.display = 'none'; } else if (screen === 'battle') { $startScreen.style.display = 'none'; $generalMenu.style.display = 'none'; $battleMenu.style.display = 'block'; } } // addEventListener가 붙으면 this는 화살표 함수로 풀어야 한다 (암기) // 화살표함수의 this는 밖에 있는 this를 그대로 가져옴 onGeneralMenuInput = (event) => { // start()에서 generalMenu 활성화 event.preventDefault(); const general = event.target['general-input'].value; // id가져와서 활성화, value는 text if (general === '1') { // 모험 this.changeScreen('battle'); // 전투메뉴로 만들고 console.log(this); // 여기서 this는 General // 랜덤하게 animal 생성 const randomIndex = Math.floor(Math.random() * this.animalList.length); const randomAnimal = this.animalList[randomIndex]; // new Animal( ) 생성 this.animal = new Animal( this, randomAnimal.name, randomAnimal.power, randomAnimal.att, randomAnimal.upgrade, ); this.updateAnimal(); this.showMessage(`사냥할 동물이 나타났다! ${this.animal.name}인것 같다!`); } else if (general === '2') { // 휴식 } else if (general === '3') { // 종료 this.quit(); } }; onBattleMenuInput = (event) => { // start()에서 battleMenu 활성화 event.preventDefault(); const battle = event.target['battle-input'].value; // id가져와서 활성화 if (battle === '1') { // 공격, 서로 공격 const { hunter, animal } = this; hunter.attack(animal); animal.attack(hunter); // 기본적인 공격 메시지 // this.showMessage(`헌터가 ${hunter.att}의 데미지를 주고 ${animal.att}의 데미지를 받았다.`); // 공격해서 나올수 있는 경우의 수를 고민 // 1. hunter power가 0이하면 전사 및 새로운 hunter생성 // 2. animal power가 0이하면 animal의 upgrade power를 얻음 (get) // 3. 1,2가 아닌 경우 기본적인 공격메시지 송출 if (hunter.power <= 0) { // 1. this.showMessage(`${hunter.level}레벨에서 전사. 새 주인공을 생성하세요`); this.quit(); // 게임종료에 대한 함수 } else if (animal.power <= 0) { // 2. this.showMessage(`사냥에 성공하여 사냥감이 가지고 있는 ${animal.upgrade}의 힘을 얻었다.`); hunter.getUpgrade(animal.upgrade); // 사냥감 힘 얻는 함수, hunetr내 설정 this.animal = null; // 없어지고 this.changeScreen('general'); // 일반모드로 } else { // 3. this.showMessage(`헌터가 ${hunter.att}의 데미지를 주고 ${animal.att}의 데미지를 받았다.`); } // 각 상태가 업데이트되야 함 this.updateHunter(); this.updateAnimal(); } else if (battle === '2') { // 회복 } else if (battle === '3') { // 도망 : 일반메뉴로 전환 this.changeScreen('general'); } }; // hunter상태 update, 없으면 빈칸, 레벨과 파워변하는 상황 (초기선언) updateHunter() { const { hunter } = this; // 업데이트 할 변수선언, 구조분해할당 모습 if (hunter === null) { // hunter가 없으면 $hunterName.textContent = ''; $hunterLevel.textContent = ''; $hunterPower.textContent = ''; $hunterUpgrade.textContent = ''; $hunterAttack.textContent = ''; return; // return 하고 } // hunter가 있으면 $hunterName.textContent = hunter.name; $hunterLevel.textContent = `레벨: ${hunter.level}`; $hunterPower.textContent = `파워: ${hunter.power} / ${hunter.maxPower}`; $hunterUpgrade.textContent = `업그레이드: ${hunter.upgrade} / ${15 * hunter.level}`; $hunterAttack.textContent = `공격력: ${hunter.att} `; } updateAnimal() { const { animal } = this; // 업데이트 할 변수선언, 구조분해할당 모습 if (animal === null) { // animal이 없으면 $animalName.textContent = ''; $animalPower.textContent = ''; $animalAttack.textContent = ''; return; // return 하고 } // animal이 있으면 $animalName.textContent = animal.name; $animalPower.textContent = `파워: ${animal.power} / ${animal.maxPower}`; $animalAttack.textContent = `공격력: ${animal.att} `; } showMessage(text) { // 메시지 보이게 $message.textContent = text; } // 게임종료 quit() quit() { this.hunter = null; this.animal = null; this.updateHunter(); this.updateAnimal(); $generalMenu.removeEventListener('submit', this.onGeneralMenuInput); $battleMenu.removeEventListener('submit', this.onBattleMenuInput); general = null; } } // 비숫한 캐릭터의 부모 class를 만들고 나머지는 상속시킴 // 부모클래스는 기본적 변수처리 class Unit { constructor(general, name, power, att, upgrade) { this.general = general; this.name = name; this.maxPower = power; this.power = power; this.att = att; this.upgrade = upgrade; } attack(target) { target.power -= this.att; } } // Hunter는 공통점빼고 정의 class Hunter extends Unit { constructor(general, name) { super(general, name, 100, 10, 0); this.level = 1; } // 사냥감 파워 획득 getUpgrade(upgrade) { this.upgrade += upgrade; // upgrade 될때마다 아래 if문을 한번씩 검토, 에러방지 if (this.upgrade >= this.level * 15) { // 경험치를 다 채우면 this.upgrade -= this.level * 15 // 레벨이 오르기 위한 필요power는 15이기에 레벨바뀌고 다시 0으로 세팅 this.level += 1; this.maxPower += 20; // upgrade되면 최대체력은 10늘어나고 this.att += 20; // upgrade되면 공격력도 10늘어나고 this.power = this.maxPower; // upgrade되면 최대체력은 현재체력으로 되고 this.general.showMessage(` 사냥에 성공하여 사냥감이 가지고 있는 ${upgrade}의 힘을 얻었다. 레벨업 완료! 현재레벨 ${this.level} `); } } } // animal도 공통점 빼고 정의 class Animal extends Unit { constructor(general, name, power, att, upgrade) { super(general, name, power, att, upgrade); } } // 게임 시작 프로그램 let general = null; // start-screen 활성화 $startScreen.addEventListener('submit', (event) => { event.preventDefault(); const name = event.target['name-input'].value; // hunter 이름 입력 general = new General(name); // 이름 입력받아 새로운 게임 만들기, 생성자 실행조건 new 필요 });
반응형'컴퓨터 알아가기 > JavaScript' 카테고리의 다른 글
JavaScript 입문 : 카드맞추기 게임 - 순서도 (0) 2022.09.27 JavaScript 입문 : textRPG 만들기 - 각 단계별 최종 작업 (0) 2022.09.13 JavaScript 입문 : textRPG 만들기 - 사냥모드 업데이트 및 성공한 사냥감 업그레이드 파워 얻기 (2) 2022.09.10 JavaScript 입문 : textRPG 만들기 - 헌터내역 및 동물내역 업데이트, 일반게임모드, 메시지 표시, 게임종료 메소드 (0) 2022.09.09 JavaScript 입문 : textRPG 만들기 - 클래스 이용하여 기본코드 재구성 (2) 2022.09.08