2022. 11. 2. 11:42ㆍ자바스크립트
*본 게시물은 길벗IT의 [Let's Get IT 자바스크립트]를 토대로 만들어졌습니다. 저작권은 길벗IT에게 있습니다.
이번시간에는 클래스를 중점적으로 배웠다. RPG게임은 보통 캐릭터를 성장시키는 게임인데, 텍스트 RPG게임은 그래픽없이 글로만 하는 것이다. 모험, 휴식, 종료 등의 일반모드와, 적을 공격하고 체력을 회복하거나 도망가는 전투모드를 할 수 있는 게임이다.
+전체코드는 맨 하단에 있다.
window, this, 참조/깊은복사/얕은복사, 클래스, 클래스 상속에 대해 배웠다.
1) window는 브라우저를 가리키는 객체로, doument와 console도 이에 포함된다.
node에는 global이 들어있고(global.consoleLog), 브라우저에는 window가 들어있다(window.consoleLog). 두 개의 환경에 따라 전역객체의 역할을 하는 window와 global이 차이가 나기 때문에 globalThis가 만들어졌다.
> 즉, window 대신에 globalThis를 사용할 수 있고 node랑 window 모두에서 돌아간다.
2) this는 상황에 따라 다른 값을 가진다. 기본적으로 this는 window객체를 가리키는데, 어떤 때에 따라 달라지기도 한다.
-객체.메서드 안의 this는 객체를 가리킨다.
-특정 메서드는 콜백 함수의 this를 바꿔준다.
-this가 바뀌는 것을 원치 않는다면 화살표 함수를 사용한다.
3) 객체를 대입하면 참조가 되고, 원시값을 대입하면 복사가 된다. 객체를 대입해서 복사가 되고 싶다면?
: 다른 방법으로 깊은 복사와 얕은 복사 중 선택할 수 있음.
const array = [{ j: 'k' }, { l: 'm'}];
const reference = array; //참조
const shallowCopy = [...array] //얕은 복사
const deepCopy = JSON.parse(JSON.stringify(array)); //깊은 복사
console.log(array === reference); //true
console.log(array[0] === reference[0]); //true
console.log(array === shallowCopy); //false
console.log(array[0] === shallowCopy[0]); //true
console.log(array === deepCopy); //false
console.log(array[0] === deepCopy[0]); //false
4) 클래스는 객체를 생성하는 템플릿 문법이다. 서로 상호작용할 수 있게 구성되어 있고, 상속을 통해 중복을 제거할 수 있다.
5) 클래스는 extends 예약어로 상속할 수 있다. 상속하는 클래스는 부모 클래스가 되고, 상속받는 클래스는 자식 클래스가 된다. super을 통해 부모 생성자와 부모 메서드에 접근할 수 있다.
∙∙∙
constructor(game, name){
super(game, name, 100, 10, 0); //부모 클래스의 생성자 호출
∙∙∙
}
attack(target){
super.attck(target); //부모 클래스의 attack
}
+전체 코드를 첨부한다.
<html lang="en">
<head>
<meta charset="UTF-8">
<title>텍스트 RPG</title>
</head>
<body>
<form id="start-screen">
<input id="name-input" placeholder="이름을 입력하세요!" />
<button id="start">시작</button>
</form>
<div id="screen">
<div id="hero-stat">
<span id="hero-name"></span>
<span id="hero-level"></span>
<span id="hero-hp"></span>
<span id="hero-xp"></span>
<span id="hero-att"></span>
</div>
<form id="game-menu" style="display: none;">
<div id="menu-1">1.모험</div>
<div id="menu-2">2.휴식</div>
<div id="menu-3">3.종료</div>
<input id="menu-input" />
<button id="menu-button">입력</button>
</form>
<form id="battle-menu" style="display: none;">
<div id="battle-1">1.공격</div>
<div id="battle-2">2.회복</div>
<div id="battle-3">3.도망</div>
<input id="battle-input" />
<button id="battle-button">입력</button>
</form>
<div id="message"></div>
<div id="monster-stat">
<span id="monster-name"></span>
<span id="monster-hp"></span>
<span id="monster-att"></span>
</div>
</div>
<script>
const $startScreen = document.querySelector('#start-screen');
const $gameMenu = document.querySelector('#game-menu');
const $battleMenu = document.querySelector('#battle-menu');
const $heroName = document.querySelector('#hero-name');
const $heroLevel = document.querySelector('#hero-level');
const $heroHp = document.querySelector('#hero-hp');
const $heroXp = document.querySelector('#hero-xp');
const $heroAtt = document.querySelector('#hero-att');
const $monsterName = document.querySelector('#monster-name');
const $monsterHp = document.querySelector('#monster-hp');
const $monsterAtt = document.querySelector('#monster-att');
const $message = document.querySelector('#message');
class Game {
constructor(name) {
this.monster = null;
this.hero = null;
this.monsterList = [
{ name: '슬라임', hp: 25, att: 10, xp: 10 },
{ name: '스켈레톤', hp: 50, att: 15, xp: 20 },
{ name: '마왕', hp: 150, att: 35, xp: 50 },
];
this.start(name);
}
start(name) {
console.log(this);
$gameMenu.addEventListener('submit', this.onGameMenuInput);
$battleMenu.addEventListener('submit', this.onBattleMenuInput);
this.changeScreen('game');
this.hero = new Hero(this, name);
this.updateHeroStat();
}
changeScreen(screen) {
if (screen === 'start') {
$startScreen.style.display = 'block';
$gameMenu.style.display = 'none';
$battleMenu.style.display = 'none';
} else if (screen === 'game') {
$startScreen.style.display = 'none';
$gameMenu.style.display = 'block';
$battleMenu.style.display = 'none';
} else if (screen === 'battle') {
$startScreen.style.display = 'none';
$gameMenu.style.display = 'none';
$battleMenu.style.display = 'block';
}
}
onGameMenuInput = (event) => {
event.preventDefault();
const input = event.target['menu-input'].value;
if (input === '1') { // 모험
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}인 것 같다!`);
} else if (input === '2') { // 휴식
this.hero.hp = this.hero.maxHp;
this.updateHeroStat();
this.showMessage('충분한 휴식을 취했다.');
} else if (input === '3') { // 종료
this.showMessage(' ');
this.quit();
}
}
onBattleMenuInput = (event) => {
event.preventDefault();
const input = event.target['battle-input'].value;
if (input === '1') { // 공격
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();
} else if (input === '2') { // 회복
const { hero, monster } = this;
hero.hp = Math.min(hero.maxHp, hero.hp + 20);
monster.attack(hero);
this.showMessage('체력을 조금 회복했다!');
this.updateHeroStat();
} else if (input === '3') { // 도망
this.changeScreen('game');
this.showMessage('부리나케 도망쳤다!');
this.monster = null;
this.updateMonsterStat();
}
}
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}`;
}
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;
}
quit() {
this.hero = null;
this.monster = null;
this.updateHeroStat();
this.updateMonsterStat();
$gameMenu.removeEventListener('submit', this.onGameMenuInput);
$battleMenu.removeEventListener('submit', this.onBattleMenuInput);
this.changeScreen('start');
game = null;
}
}
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;
}
}
class Hero extends Unit {
constructor(game, name) {
super(game, name, 100, 10, 0);
this.lev = 1;
}
attack(target) {
super.attack(target); // 부모 클래스의 attack
// 부모 클래스 attack 외의 동작
}
heal(monster) {
this.hp += 20;
this.hp -= monster.att;
}
getXp(xp) {
this.xp += xp;
if (this.xp >= this.lev * 15) { // 경험치를 다 채우면
this.xp -= this.lev * 15; // xp: 5, lev: 2, maxXp: 15
this.lev += 1;
this.maxHp += 5;
this.att += 5;
this.hp = this.maxHp;
this.game.showMessage(`레벨업! 레벨 ${this.lev}`);
}
}
}
class Monster extends Unit {
constructor(game, name, hp, att, xp) {
super(game, name, hp, att, xp);
}
}
let game = null;
$startScreen.addEventListener('submit', (event) => {
event.preventDefault();
const name = event.target['name-input'].value;
game = new Game(name);
});
</script>
</body>
</html>
+ 실행하면!
'자바스크립트' 카테고리의 다른 글
[Let’s Get IT 자바스크립트 프로그래밍] 11장 이벤트 루프 이해하기_카드 짝 맞추기 게임 (0) | 2022.11.16 |
---|---|
[Let's Get IT 자바스크립트]9장 이차원 배열 다루기_틱택토 게임 (0) | 2022.11.01 |