이 블로그는 광고 클릭 수익으로 운영됩니다!
괜찮으시다면 광고 차단을 풀어주세요 ㅠㅠ

게시글

강좌18 - JavaScript - 2년 전 등록 / 일 년 전 수정

자동 텍스트 RPG 만들기

조회수:
0
이 블로그는 광고 클릭 수익으로 운영됩니다!
괜찮으시다면 광고 차단을 풀어주세요 ㅠㅠ
이 블로그는 광고 클릭 수익으로 운영됩니다!
괜찮으시다면 광고 차단을 풀어주세요 ㅠㅠ

이번 시간에는 텍스트 RPG를 만들어보겠습니다. 그래픽 작업은 아직 못 하지만, 텍스트 RPG정도는 만들 수 있을 것 같습니다. html을 어느 정도 할 수 있다는 전제 하에 진행되지만, html을 못 한다면 그냥 복사 붙여넣기 하시면 됩니다. 중요한 건 자바스크립트 코드니까요.

<html>
<head>
<title>텍스트RPG</title>
</head>
<body>
<div id="log"></div>
<script>
// 여기에 자바스크립트 코드를 넣습니다.
</script>
</body>
</html>

이제는 콘솔에서 벗어나 html 파일에 만들 겁니다. 실행은 브라우저에서 할 거고요. 위의 코드를 복사해서 메모장에 붙여넣은 후 저장할 때 확장자가 html인 파일로 저장하세요.

다음 코드를 script에 넣으면 됩니다. 물론 아직은 화면에 아무것도 안 뜰 겁니다.

function logMessage(msg, color) {
  if (!color) { color = 'black'; }
  var div = document.createElement('div');
  div.innerHTML = msg;
  div.style.color = color;
  document.getElementById('log').appendChild(div);
}

메세지를 #log 태그에 추가하는 코드입니다. color 값을 따로 인자로 제공하면 해당하는 색의 에러 메시지가 표시됩니다.

var gameover = false;
var battle = false;
function Character(name, hp, att) {
  this.name = name;
  this.hp = hp;
  this.att = att;
}
Character.prototype.attacked = function (damage) {
  this.hp -= damage;
  logMessage(this.name + '의 체력이 ' + this.hp + '가 되었습니다');
  if (this.hp <= 0) {
    battle = false;
  }
};
Character.prototype.attack = function (target) {
  logMessage(this.name + '이 ' + target.name + '을 공격합니다');
  target.attacked(this.att);
};

일단 캐릭터들을 관장하는 캐릭터 생성자를 만들어줍니다. hp, att는 각각 체력, 공격력이고요. attack과 attacked 메소드는 각각 공격하고, 공격받는 겁니다. 공격받는 것을 보면, hp에 데미지를 받죠? 공격하는 것은 타겟에 공격력을 가합니다. 아, 그리고 게임오버와 전투중인지를 알려주는 변수 두 개를 만들었습니다.

이제 캐릭터를 상속하는 영웅과 몬스터를 만들겁니다.

function Hero(name, hp, att, lev, xp) {
  Character.apply(this, arguments);
  this.lev = lev || 1;
  this.xp = xp || 0;
}
Hero.prototype = Object.create(Character.prototype);
Hero.prototype.constructor = Hero;
Hero.prototype.attacked = function(damage) {
  this.hp -= damage;
  logMessage(this.name + '님의 체력이 ' + this.hp + '남았습니다');
  if (this.hp <= 0) {
    logMessage('죽었습니다. 레벨' + this.lev + '에서 모험이 끝납니다. F5를 눌러 다시 시작하세요', 'red');
    battle = false;
    gameover = true;
  }
};
Hero.prototype.attack = function (target) {
  logMessage(this.name + '님이 ' + target.name + '을 공격합니다');
  target.attacked(this.att);
  if (target.hp <= 0) {
    this.gainXp(target);
  }
};
Hero.prototype.gainXp = function(target) {
  logMessage('전투에서 승리하여 ' + target.xp + '의 경험치를 얻습니다', 'blue');
  this.xp += target.xp;
  if (this.xp > 100 + 10 * this.lev) {
    this.lev++;
    logMessage('레벨업! ' + this.lev + ' 레벨이 되었습니다', 'blue');
    this.hp = 100 + this.lev * 10;
    this.xp -= 10 * this.lev + 100;
  }
};

Hero가 Character을 상속하고 있습니다. 거기에 lev(레벨), xp(경험치) 속성이 추가되었네요. 그리고 원래 있던 attacked, attack 메소드를 확장했고, gainXp라는 메소드를 프로토타입에 하나 추가했습니다.

function Monster(name, hp, att, lev, xp) {
  Character.apply(this, arguments);
  this.lev = lev || 1;
  this.xp = xp || 10;
}
Monster.prototype = Object.create(Character.prototype);
Monster.prototype.constructor = Monster;

뭔가 프로그래밍하는 것 같나요? 이제 영웅과 몬스터를 만들었으니 게임 진행하는 알고리즘을 짜야겠죠? 단순하게 전투->승리->경험치획득->전투->승리->레벨업->전투->... 이런 반복이면 됩니다.

몬스터를 랜덤으로 만드는 함수입니다. 5종류 정도만 만들어보죠. 5종류 중에 골라서 몬스터 객체를 만듭니다.

function makeMonster() {
  var monsterArray = [
    ['rabbit', 25, 3, 1, 35],
    ['skeleton', 50, 6, 2, 50],
    ['soldier', 80, 4, 3, 75],
    ['king', 120, 9, 4, 110],
    ['devil', 500, 25, 6, 250]
  ];
  var monster = monsterArray[Math.floor(Math.random() * 5)];
  return new Monster(monster[0], monster[1], monster[2], monster[3], monster[4]);
}

흠.. 몬스터 중 하나가 밸런스 붕괴네요... 20% 확률로 게임오버...

var hero = new Hero(prompt('이름을 입력'), 100, 10);
logMessage(hero.name + '님이 모험을 시작합니다. 어느 정도까지 성장할 수 있을까요?');
while (!gameover) {
  var monster = makeMonster();
  logMessage(monster.name + '을 마주쳤습니다. 전투가 시작됩니다', 'green');
  battle = true;   while(battle) {
    hero.attack(monster);
    if (monster.hp > 0) {
      monster.attack(hero);
    }
  }
}

이렇게 텍스트RPG가 완성되었습니다. 밸런스는 조정하시면 됩니다. 어쩌다 보니 운빨 게임이 되어버렸네요. ㅎㅎ 새로고침하면서 몇 레벨까지 갈 수 있나 테스트해보세요. 그리고 자유롭게 게임을 패치해보세요.~

  • 다양한 스텟들 추가하기(명중률, 방어력 등등...) (힌트: 생성자에 추가하면 됩니다)
  • 자동 진행이 아닌 수동진행으로 만들기(힌트: 한 턴이 지날 때마다 멈추는 코드를 넣으면 됩니다)
  • 회복같은 메소드 추가해보기 (힌트: prototype에 추가하면 됩니다)

이제 초보를 벗어났으니 중급 강좌가 진행됩니다! 

투표로 게시글에 관해 피드백을 해주시면 많은 도움이 됩니다. 오류가 있다면 어떤 부분에 오류가 있는지도 알려주세요! 잘못된 정보가 퍼져나가지 않도록 도와주세요.
Copyright © 2016- 무단 전재 및 재배포 금지

댓글

12개의 댓글이 있습니다.
5시간 전
그렇군요 ㅠㅠ 항상 빠른 답변 감사합니다. 근데 이거 하나 떼는데 원래 시간이 오래 걸리나요....상속이랑 prototype 조금 헷갈려서 전강의랑 전전강의 가끔 참조해서 그런가 2~3일은 이것만 보고 있었던거같아요..
6시간 전
초보라 질문있는데요 이런 예제 공부할 때 코드가 어떤 역할을 하는지만 알고 넘어가면 되나요 아니면 안보고 짤 정도 되고 넘어가는게 좋을까요?
일단 공부를 코드 보고 이해하면서 몇번 짜는 식으로 하고 있습니다만...제대로 공부하고 있는지 모르겠네요 ㅠ
5시간 전
제 블로그만 보고는 안 보고 짤 정도 되기는 힘들고요. 그냥 예제 코드들 조금씩 수정해보고 하는 정도로만 하시고 넘어가세요.
7달 전
Hero.prototype.gainXp = function(target){
logMessage('You win !, so you get ' + target.xp + 'xp', 'blue');
this.xp += target.xp;

if(this.xp >= 100){
logMessage('Level up ' + this.lev, 'blue')
this.lev++;
this.xp -= target.xp;
this.hp += 30;
}
}

Hero.prototype.gainXp에서 if문에 왜 100 + 10 * this.lev로 하신거에요??? Level이 왜 최소한 110이상이어야 해요?? 최소110이상 Level up 조건문 충족이 어려울까봐 저는 위에처럼 수정했어요...
7달 전
Level이 110 이상이 아니라 Level 1일 때, 경험치가 110 이상입니다. Level 2일 때는 경험치 120 이상이고요. 레벨이 올라감에 따라 요구 경험치가 늘어나는 것을 구현하고자 한 것입니다.

코드는 필요에 따라 수정하시면 됩니다.
7달 전
하위 클래스를 상위 클래스에 확장할때마다 (Object.create) 명시적으로 상위클래스.prototype.constructor = 상위클래스 를 추가해야 하죠??
7달 전
그렇습니다. 상위클래스가 아니라 둘 다 하위클래스겠죠?
7달 전
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/create 아.. Hero.prototype.constructor === Hero 개발자가 직접 해야되는군요. 감사합니다..
7달 전
Hero.prototype = Object.create(Character.prototype);
Hero.prototype.constructor = Hero; 하위 클래스 Character 에 상위 클래스 Hero 확장했습니다. 그래서 Hero 메소드에 attack, attacked 메소드 확장이 되었는데요. (ex/ Hero.prototype.attack, Hero.prototype.attacked) 아래 Hero.prototype.constructor = Hero 왜 하신거에요?? 암묵적으로 Hero.prototype.constructor === Hero인데 왜 하신거에요???
7달 전
Hero.prototype.constructor는 Hero가 아닙니다. 이것은 자바스크립트 상속의 버그입니다. 모질라에서는 명시적으로 저 부분을 추가하여 버그 패치를 하길 권장하고 있습니다.
일 년 전
그냥 메모장에 확장자를 html로 저장하고 실행시키면 바로 실행이되는건가요?
실행이 안되길래 제가 혹시 오타냈을까봐 쭉 복사해서 저장했는데 실행이 안되네요..ㅠ
너무 초보라서 송구스럽네요..
일 년 전
실행했을 때 브라우저가 실행되나요?
일 년 전
네. 브라우저가 실행됩니다.
일 년 전
그 후에 프롬프트가 뜨면서 사용자명을 입력하게 되어있거든요. 위에서부터 차례대로 html, js 순으로 붙여넣으시면 돼요.
일 년 전
결과가 나왔다 로딩걸렸다 하는건 왜그러는 걸까요??
일 년 전
어떤 환경에서 로딩이 걸리는 지 설명 부탁드립니다!
일 년 전
댓글입력하는 텍스트에리아부분 z-index가 아래 댓글들보다 낮아서 인지 댓글들에 가려집니다
일 년 전
수정했습니다! 감사합니다!
일 년 전
수동진행으로 만들려면 어떡하죠? 멈추는걸 prompt로 멈추고 입력값에따라 계속진행할지 회복을할지 하는건데 진행순서에 맞게 진행되는게 아니고 아무것도 #log에 appendChild가 되지도 않고 prompt창만뜨고 입력하면 gameover=true; 되고 게임끝나야 그제서야 메세지들이 append 됩니다
일 년 전
이게 생각보다 어려습니다. 이 부분은 뒤에 턴제 게임 만들기를 참고하세요
일 년 전
네 알겠습니다ㅎㅎ
일 년 전
이런거 짤때는 충분히 생각하고 디테일하게 각 객체의 역할등을 기획?하고 코딩을 시작하는게 맞는건가요
일 년 전
네 기획하고 짜야합니다. 무턱대고 짰다가는 나중에 아예 처음부터 다시 시작해야하는 불상사가 생길 수도 있습니다.
일 년 전
다행이군요 그럼 제로조님은 어떤식으로 하나요? 머리만으론 턱없이 부족한데 펜으로 쓰고 하시는건가요?
일 년 전
아뇨. 그냥 머릿속으로 큰 틀만 기획하고 그 다음부터는 부닥쳐가면서 코딩합니다. 그리고 설계가 틀렸을 경우 주기적으로 코드를 갈아엎죠.
일 년 전
그렇군요 알겠습니다 감사합니다 ㅎㅎ 드디어 혼자서 해냈습니다 ㅠ 요 부분 혼자 구현해보려 첫 강의부터다시 3번정도는 했네요 ㅋㅋ 거의 외워져서 한거지만 그래도 많은 공부가 됬어요!!
일 년 전
축하드립니다! 직접 만들면서 하는 게 도움이 많이 돼요~
일 년 전
if (!color)은 정확이 어떤 뜻인가요 그리고 어떤경우에 이렇게 쓸수 있는지 알려주세요!
일 년 전
if (!color)은 처음 함수를 호출할 때 color을 인자로 입력하지 않으면 color가 undefined가 되기 때문에 !color는 true가 됩니다. 따라서 if문 안의 내용이 실행되죠.