whatisthis?

javaScript. 자동 텍스트 RPG 게임 본문

PRACTICE/SELF

javaScript. 자동 텍스트 RPG 게임

thisisyjin 2022. 1. 27. 14:26

자동 텍스트 RPG 게임

 

 

index.html

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>텍스트 RPG</title>
    <link rel="stylesheet" href="style.css" />
</head>
<body>
    <div id="log"></div>
    <script src="app.js"></script>
</body>
</html>

 

 

style.css

* {
    margin: 0;
    box-sizing : border-box;
}

html {
    font-family:Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif;
    font-size: 16px;
    line-height: 2;
    color: #1f2d3d;
}

body {
    text-align: center;
    width: 100%;
    height: 100vh;
    background-color: #f8f9fb;
}

body::after {
    content: "text-RPG";
    display: block;
    margin-top: 50px;
    color: #463bc1;
    font-size: 12px;
    font-weight: 600;
}

 

 

app.js

// 메세지를 #log에 추가

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


// 캐릭터 생성자

let gameover = false;
let battle = false;

function Character(name, hp, att) {
    this.name = name;
    this.hp = hp;
    this.att = att;
}



// 메서드 ㅡ attacked / attack

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);
};



// 영웅 생성자 ㅡ Character 상속

function Hero(name, hp, att, lev, xp) {
    Character.apply(this, arguments);
    this.lev = lev || 1;    //(lev = 1)
    this.xp = xp || 0;      //(xp = xp)
}

Hero.prototype = Object.create(Character.prototype);
Hero.prototype.constructor = Hero;



// 메서드 ㅡ attacked / attack / gainXp(경험치)

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;          
    }
};


// 몬스터 생성자 ㅡ Character 상속

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;


// 몬스터 랜덤으로 만드는 함수

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



///// 게임 진행 ㅡ ( 전투 > 승리 > 경험치업 > 전투 > 승리 > 레벨업 > ... )


const hero = new Hero(prompt('이름을 입력하세요.'), 100, 10);
logMessage(hero.name + ' 님의 모험이 시작됩니다.');

while(!gameover) {
    const monster = makeMonster();
    logMessage(monster.name + '을 마주쳤습니다. 전투가 시작됩니다.', 'green');
    battle = true;
    while(battle) {
        hero.attack(monster);
        if(monster.hp > 0) {
            monster.attack(hero);
        }
    }
}

 


 

play Ex>

 

 

 

 

 


 

 

❗   javaScript 분석

 

 

1/ logMessage 함수

>> (메시지, 글자색)을 인수로 받음.

color값을 안주었을땐 (!color일때) , color = black.

 

// 메세지를 #log에 추가

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

- document.createElement로 div태그를 만들어 변수에 저장.

- innerHTML에 msg(파라미터로 받은값)을 저장하고

style.color을 color(파라미터로 받은값)으로 한다.

- #id의 자식태그로 지정. (appendChild) >> 부모.appendChild(자식)

 

 

 

2/ gameover과 battle

>> 나중에 변경되는 값이므로 const가 아닌 let 이용

let gameover = false;
let battle = false;

우선 둘다 false로 초기화하고,

 

게임오버가 아닐때, 즉 게임중일때는 while(!gameover)로 진행하고,

추후에 hp가 0이하가 되어 게임오버되었을 때는

gameover = true를 해서 while을 빠져나오게 한다.

 

배틀중일 때는 while(battle)로 진행하고

(여기서, 몬스터를 마주치고 > battle = true를 해서 > while(battle) 루프로 진행)

 

배틀이 끝나면 ( 이기거나 / 죽거나 - attacked 메서드의 마지막 부분에 battle = false로)

batlle = false로 while을 빠져나오게 한다.

Character
.prototype.attacked
Hero if(this.hp <= 0) { battle = false } 죽음 ( 패배 )
>> gameover = true
Monster if(this.hp <= 0) { battle = false } 몬스터 죽음 ( 승리 )
>> gainXp

🔺  gameover과 battle

 

 

3/ Character 생성자

- Monster과 Hero 둘 다 Character에 해당한다.

function Character(name, hp, att) {
    this.name = name;
    this.hp = hp;
    this.att = att;
}

매개변수로는 name, hp, att 세가지를 받고,

this에 인수로 받은 값들을 저장한다. (여기서, this는 생성자 본인)

 

 

3/ Character.prototype.method (attacked / attack)

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);
};

 

4/ Hero 생성자

- Character 생성자를 상속.

function Hero(name, hp, att, lev, xp) {
    Character.apply(this, arguments);
    this.lev = lev || 1;    //(lev = 1)
    this.xp = xp || 0;      //(xp = xp)
}

Hero.prototype = Object.create(Character.prototype);
Hero.prototype.constructor = Hero;

 

4/ Hero.prototype.method ( attacked / attack / gainXp )

Hero.prototype.attacked = function(damage) {
    this.hp -= damage;
    logMessage(this.name + ' 님의 체력이 ' + this.hp + ' 남았습니다.');
    if(this.hp <= 0){             // 내 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);       // target hp가 0이하 ㅡ 승리 (gainXp)
    }
};
죽음 ( 패배 )
>> gameover = true
battle = false;
gameover = true;
몬스터 죽음 ( 승리 )
>> gainXp
this.gainXp(target);
>>>  this.xp += target.xp
        this.lev++
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;          
    }
};

5/ Monster 생성자

- Character 생성자를 상속.

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/ 몬스터 랜덤 생성 함수

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

** 배열 안에 배열을 넣음. (인덱스 랜덤으로 뽑고 / 각 값을 인수로 사용할 수 있도록)

 

 

6/ 게임 진행

const hero = new Hero(prompt('이름을 입력하세요.'), 100, 10);
logMessage(hero.name + ' 님의 모험이 시작됩니다.');

while(!gameover) {
    const monster = makeMonster();      // monster 랜덤 추출
    logMessage(monster.name + '을 마주쳤습니다. 전투가 시작됩니다.', 'green');
    battle = true;             // 배틀 루프 시작
    while(battle) {                
        hero.attack(monster);          // monster.attacked()
        if(monster.hp > 0) {           // monster.hp가 0보다 크면 - moster도 hero 공격
            monster.attack(hero);    
        }
    }                       // battle = false면 루프 종료
}                           // gameover = true면 루프 종료

 


 

REFERENCE