whatisthis?
javaScript. 턴제 게임 - 텍스트 기반 RPG (上) 본문
턴제 게임 - 텍스트 기반 RGP
skill
- html / css
- javascript
지난 실습으로 해봤던 자동 텍스트 RPG 게임을 토대로 제작했음.
< 변경 사항 >
- 자동텍스트 RPG게임은 게임과 사용자의 interaction이 '이름 입력' 하나밖에 없었다면,
이번에 제작할 게임은 '턴(turn)'의 개념을 도입하여 매 턴마다 사용자와 인터렉션하도록 제작함.
- 게임이 자동으로 실행되었다면, 이번에는 싱글턴 객체를 활용하여 게임 시작을 하도록 함.
- 데이터 처리는 메소드 체이닝 패턴을 이용함. ( = 디자인패턴 中 자주 쓰임)
1 / 싱글턴 객체
- 객체 하나만 생성함.
- 전체 게임 객체를 싱글턴 객체로 만들어, 한 번만 실행되도록 함.
let TurnGame = (function() {
let instance;
let initiate = function(heroName) { // initiate 변수에 익명함수 저장
let hero = {
name: heroName,
lev: 1,
maxHp: 100,
hp: 100,
xp: 0,
att: 10
};
return { // showLevel, showXp, showHp, toogleMenu, setMessage 메서드를 가진 객체 반환
showLevel: function() {
document.getElementById('hero-level').innerHTML = hero.lev + 'lev';
return this;
},
showXp: function() {
let self = this; // setTimeout에선 this가 소멸되니까 미리 저장해둠
if (hero.xp > 15 * hero.lev) {
hero.xp -= 15 * hero.lev;
hero.maxHp += 10;
hero.hp = hero.maxHp;
hero.att += hero.lev;
hero.lev++;
window.setTimeout(function() { // setTimeout에선 저장해둔 this(self변수) 사용
self.setMessage('레벨업!');
}, 1000); // 1000ms 후에 실행
}
document.getElementById('hero-xp').innerHTML = 'XP: ' + hero.xp + '/' + 15 * hero.lev;
document.getElementById('hero-att').innerHTML = 'ATT: ' + hero.att;
return this.showLevel().showHp(); // 💡 메소드 체이닝
},
showHp: function() {
if (hero.hp < 0) {
return this.gameOver();
}
document.getElementById('hero-hp').innerHTML = 'HP: ' + hero.hp + '/' + hero.maxHp;
return this;
}, ////// 여기서부턴 toggleMenu , setMessage메서드
toggleMenu: function () { // toggleMenu 메서드
document.getElementById('hero-name').innerHTML = hero.name;
document.getElementById('start-screen').style.display = 'none'; // 시작화면 안보이게
if (document.getElementById('game-menu').style.display === 'block') { // 1️⃣ 게임메뉴 보이면
document.getElementById('game-menu').style.display = 'none'; // 게임메뉴 가리고
document.getElementById('battle-menu').style.display = 'block'; // 배틀메뉴 보이게
document.getElementById('battle-input').focus(); // 배틀 input태그에 포커스되게
} else { // 2️⃣ 게임메뉴 안보이면
document.getElementById('game-menu').style.display = 'block'; // 게임메뉴 보이게
document.getElementById('battle-menu').style.display = 'none'; // 배틀메뉴 가리고
document.getElementById('menu-input').focus(); // 메뉴 input태그에 포커스되게
}
return this;
},
setMessage: function(msg) {
document.getElementById('message').innerHTML = msg;
return this;
},
};
}; ////// 여기까지 객체 return
return {
getInstance: function(name) { // instance가 비어있으면(즉, 맨처음 호출시)에만
if (!instance) {
instance = initiate(name); // 맨처음 호출시에만 ㅡinitiate를 거침 ㅡ instance에 저장
}
return instance; // instance 반환
}
};
})();
document.getElementById('start-screen').onsubmit = function(e) { // 🎲 시작화면 폼 제출시 ㅡ 이름
var name = document.getElementById('name-input').value; // input의 value
e.preventDefault(); // submit 기본이벤트 막음
if (name && name.trim() && confirm(name + '으로 하시겠습니까?')) { // 확인, 취소중 선택
TurnGame.getInstance(name).showXp().toggleMenu(); // 💡 메소드 체이닝 ㅡ getInstance함수 호출
// showXp엔 return this.showLevel().showHp()가 되어있음
// toggleMenu엔 if-else문이 있음 (메뉴 없앴다가 생겼다가)
} else {
alert('이름을 입력해주세요'); // 취소 선택시
}
};
document.getElementById('game-menu').onsubmit = function(e) { // 🎲 게임메뉴 폼 제출시
var input = document.getElementById('menu-input');
var option = input.value; // option변수에 input태그 값 저장
e.preventDefault(); // submit 기본이벤트 막음 (순서 주의❗)
input.value = ''; // input값 초기화 (빈칸)
};
document.getElementById('battle-menu').onsubmit = function(e) { // 🎲 배틀메뉴 폼 제출시
var input = document.getElementById('battle-input');
var option = input.value; // 상동
e.preventDefault();
input.value = '';
};
크게 두가지 부분으로 나뉜다.
1. Turngame 싱글턴 객체
2. 이벤트리스너 (HTMLElements.onsubmit)
- 이벤트리스너는 각각
#start-screen
#game-menu
#battle-menu 에 연결하였다.
>> 이는 <form>태그이고, submit시 해당 함수가 동작하도록 함.
#game-menu와 #battle-menu는
마크업은 이미 해두었지만,
css의 display:none을 이용해 숨겨두고
필요한 경우에 보이도록 코딩한다.
TurnGame.getInstance(name).showXp().toggleMenu();
이 부분의 코드를 보면, instance 객체의 메소드를 연속해서 쓰고 있다.
>> Turngame.getInstance를 먼저 사용
>> Turngame.showXp를 사용
>> Turngame.toggleMenue를 사용
모두 instance 또는 this를 return 하도록 되어있음.
** 단, showXp는 showHP와 showLevel을 내부적으로 리턴함
return this.showLevel().showHp(); // showXp의 return값
- 계속해서 같은 객체(Turngame)를 리턴하기 때문에
그 객체의 메소드를 연속으로 체이닝 하듯이 사용할 수 있음.
>> 이런 패턴을 메소드 체이닝(Method Chaining) 이라고 한다.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>턴제 게임</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 src="./turn.js"></script>
</body>
</html>
다음 포스팅에서는
- 메뉴 선택 (#battle-menu중 1,2,3번을 선택하여 연동)
- 몬스터 데이터 처리 (monster)
에 대해 진행함.
REFERENCE
'PRACTICE > SELF' 카테고리의 다른 글
javaScript. 턴제 게임 - 텍스트 기반 RPG (下) (0) | 2022.01.31 |
---|---|
javaScript. 턴제 게임 - 텍스트 기반 RPG (中) (0) | 2022.01.31 |
project. (js) 자동 텍스트 RPG 게임 - (수정) (0) | 2022.01.29 |
project. (js) 숫자야구게임 - 웹 ver (수정) (0) | 2022.01.28 |
javaScript. 숫자야구게임 - 웹 ver. (1) | 2022.01.27 |