게임 구동에 있어 창크기에 따라 불편함이 있을 수 있기 때문에 처음 가동 시 창크기를
지정하였다.
Mac 환경의 경우 지원하지 않아 운영체제가 Mac일 때에는 경고문을 출력한다.
async function Initial() {
if (process.platform === "win32") {
// 최초 창크기 설정
execSync(`mode con: cols=100 lines=50`);
// 인코딩 방식 설정
execSync('chcp 65001').toString();
} else {
console.log("윈도우 환경에 호환되는 프로그램입니다.");
console.log("타 운영체제의 경우 동작하지 않을 수 있습니다.")
wait(3000);
}
}
사망시 기존에는 게임이 종료되었다.
game.js가 종료되었을 때 server.js로 돌아가게끔 처리하였다.
처음엔 동기 처리하지 않아서 문제가 발생했으나 바로 해결했다.
// start.js start 함수 부분
export async function start() {
while (true) {
Initial();
displayLobby();
await handleUserInput();
}
}
// game.js 는 게임이 종료될경우 return;
4판을 클리어할 때 마다 보너스 스탯창이 뜨게 되고 체력회복, 공격력증가, 방어력 증가를 선택할
수 있다.
수치의 경우 수정이 필요할 듯 싶다.
일단은 최소 구현이기 때문에 이정도로 일단 마무리 짓고, 나중에 난이도에 따라 보너스 스탯도
조정하면 좋을 것 같다.
async function bonusAbility(player, monster) {
// 1. 체력 회복 = 현 스테이지 몬스터 최대 공격력의 5배
// 2. 공격력 증가 = 현재 최대공격력의 30% 증가
// 3. 방어력 증가 = 방어력 3% 증가
console.log('\n'.repeat(15));
const line = chalk.magentaBright('='.repeat(100));
console.log(line);
console.log(
chalk.cyan(
figlet.textSync(' '.repeat(20) + 'Bonus Track !!', {
font: 'Standard',
horizontalLayout: 'default',
verticalLayout: 'default'
})
)
);
console.log(chalk.magentaBright('='.repeat(100)));
const bonusList = `| 1. 체력 (${monster.maxAtt * 5}만큼 회복) | 2. 공격력 (${Math.floor(player.maxAtt * 0.3)}만큼 증가) | 3.방어력 3 증가) |`;
chalk.yellow(console.log(
' '.repeat((85 - bonusList.length) / 2) + bonusList
));
console.log(chalk.magentaBright('='.repeat(100)) + '\n');
async function inputBonus(player, monster) {
const choice = readlineSync.question('당신의 선택은?');
switch (choice) {
case '1':
player.hp += monster.maxAtt * 5;
console.log(`체력이 ${monster.maxAtt * 5} 만큼 회복되었습니다!`);
await wait(1000);
break;
// 체력 일정량 회복, 해당 스테이지 몬스터의 최대공격력 5배만큼 회복한다.
case '2':
const attAdd = Math.floor(player.maxAtt * 0.3);
player.minAtt += attAdd;
player.maxAtt += attAdd;
console.log(`공격력이 ${attAdd} 만큼 증가 되었습니다!`);
await wait(1000);
break;
// 공격력이 최대 공격력의 0.3배만큼 증가한다.
case '3':
player.defense += 3;
console.log(`방어력이 3% 증가 되었습니다!`);
await wait(1000);
break;
// 방어력의 경우 고정으로 3% 증가한다.
default:
console.log(chalk.red('올바른 선택을 하지 않아 보너스 트랙이 소멸되었습니다.'));
await wait(1000);
break;
}
}
await inputBonus(player, monster);
console.clear();
}
방어력의 경우 매 스테이지마다 1씩 증가하며, 최초 방어력은 1%이다.
battle 함수 내에서 플레이어와 몬스터 클래스의 attack함수를 호출하여 기본 공격력을 구하고
방어력을 곱하여 계산한다.
클래스에서 계산하여 내보내주는 함수를 만들면 좋겠지만, 추후에 변경해보겠다...
async stageAbility(stage) {
//체력은 스테이지에 비례하여 증가함. 랜덤(50 ~ 100) / 스테이지
const addHp = Math.floor(((Math.random() * 51) + 50) / stage);
this.hp += addHp;
// 공격력은 현재 체력대비 * 0.1~0.2 배 상승
const addAtt = Math.floor(this.hp * (Math.floor(Math.random() * 11 + 10) / 100));
// 방어력은 스테이지당 1% 증가
this.defense++;
// 성공보상 출력 및 보상 반영
console.log(`스테이지 성공보상으로 체력이 ${addHp}만큼 증가, 공격력이 ${addAtt} 만큼 증가, 방어력이 1% 증가하였습니다!! `)
this.minAtt += addAtt;
this.maxAtt += addAtt;
}
// 공격 스위치문 일부
switch (choice) {
// 일반공격
case '1':
const attP = player.attack() * ((100 - monster.defense) / 100);
const attM = monster.attack() * ((100 - player.defense) / 100);
monster.hp -= Math.floor(attP);
pushLog(logs, chalk.green(`[${hour}:${new Date().getMinutes()}:${new Date().getSeconds()}] 몬스터에게 ${Math.floor(attP)} 만큼 피해를 입혔습니다.`));
player.hp -= Math.floor(attM);
pushLog(logs, chalk.red(`[${hour}:${new Date().getMinutes()}:${new Date().getSeconds()}] 몬스터로부터 ${Math.floor(attM)} 만큼 피해를 받았습니다.`));
break;
// 10% 확률로 공격 2번 진행, 실패 시 플레이어만 뚜까 맞음.
case '2':
const ddRand = Math.floor(Math.random() * 101);
if (ddRand <= 10) {
pushLog(logs, chalk.blue(`-------------------------------------------`));
pushLog(logs, chalk.blue(`더블공격 성공!`));
let attP = player.attack() * ((100 - monster.defense) / 100);
monster.hp -= Math.floor(attP);
pushLog(logs, chalk.blue(`[${hour}:${new Date().getMinutes()}:${new Date().getSeconds()}] 몬스터에게 ${Math.floor(attP)} 만큼 피해를 입혔습니다.`));
attP = player.attack() * ((100 - monster.defense) / 100);
monster.hp -= Math.floor(attP);
pushLog(logs, chalk.blue(`[${hour}:${new Date().getMinutes()}:${new Date().getSeconds()}] 몬스터에게 ${Math.floor(attP)} 만큼 피해를 입혔습니다.`));
pushLog(logs, chalk.blue(`-------------------------------------------`));
} else {
const attM = monster.attack() * ((100 - player.defense) / 100);
player.hp -= Math.floor(attM);
pushLog(logs, chalk.red(`-------------------------------------------`));
pushLog(logs, chalk.red(`더블공격 실패....`));
pushLog(logs, chalk.red(`[${hour}:${new Date().getMinutes()}:${new Date().getSeconds()}] 몬스터로부터 ${Math.floor(attM)} 만큼 피해를 받았습니다.`));
pushLog(logs, chalk.red(`-------------------------------------------`));
}
break;
default:......
}
난이도는 하급, 중급, 상급 모드로 3가지가 있으며, 아직은 플레이어의 시작 체력과 공격력, 최대 스테이지만 바뀌는 수준이다.
위에도 써놓았지만, 여러 요인을 건들이면 더 괜찮을 것 같다.
// data.js에 난이도 객체가 저장되어 있다.
export let level = {
cur : 2,
kor : function(){
return this.cur===1 ? '하급' : this.cur===2 ? '중급' : '상급';
}
};
//game.js 내 일부
if(level.cur===1){
stageNum = 10;
player.hp = 150;
player.minAtt = 25;
player.maxAtt = 30;
}else if(level.cur === 2){
stageNum = 15;
player.hp = 100;
player.minAtt = 20;
player.maxAtt = 25;
}else{
stageNum = 20;
player.hp = 100;
player.minAtt = 15;
player.maxAtt = 20;
}
// 원래 옵션 만들려고했던 js인데 난이도로 바꾼 option.js
import chalk from 'chalk';
import figlet from 'figlet';
import readlineSync from 'readline-sync';
import { level } from "./data.js";
function displayOption() {
console.clear();
// 타이틀 텍스트
console.log(
chalk.cyan(
figlet.textSync(' '.repeat(22) + 'Level Setting', {
font: 'Standard',
horizontalLayout: 'default',
verticalLayout: 'default'
})
)
);
// 상단 경계선
const line = chalk.white('='.repeat(100));
const levelText = `현재 난이도는 ${level.kor()} 입니다.`;
console.log(line);
// 난이도 표시
console.log(chalk.green('\n'+ ' '.repeat((90-levelText.length)/2) +'변경할 난이도를 선택해주세요'+'\n'));
console.log(line);
console.log(chalk.yellow('\n\n'+ ' '.repeat((92-levelText.length)/2) +levelText+'\n\n'));
console.log(line);
// 옵션들
console.log(`\n`+' '.repeat(48) +chalk.blue('1.') + chalk.white(`하급`));
console.log(' '.repeat(48) +chalk.blue('2.') + chalk.white(`중급`));
console.log(' '.repeat(48) +chalk.blue('3.') + chalk.white(`상급`));
console.log(' '.repeat(46) +chalk.blue('4.') + chalk.white(' 돌아가기')+'\n');
// 하단 경계선
console.log(line,'\n');
// 하단 설명
console.log(chalk.gray('1-4 사이의 수를 입력한 뒤 엔터를 누르세요.\n'));
}
// 유저 입력을 받아 처리하는 함수
function optionInput() {
const choice = readlineSync.question('입력: ');
switch (choice) {
case '1':
level.cur = 1;
option();
break;
case '2':
level.cur = 2;
option();
break;
case '3':
level.cur = 3;
option();
break;
case '4':
break;
default:
console.log(chalk.red('올바른 선택을 하세요.'));
option(); // 유효하지 않은 입력일 경우 다시 입력 받음
break;
}
}
export function option() {
displayOption();
optionInput();
}
업적은 게임이 끝날 때마다 클리어 한 스테이지와 난이도를 data.js에 저장한다.
그리고 메인-업적 확인하기 메뉴에서 확인할 수 있다.
// achieve.js 내 코드
import chalk from 'chalk';
import figlet from 'figlet';
import readlineSync from 'readline-sync';
import { stageLogArr } from "./data.js";
import { wait } from './game.js';
async function arrPrint() {
console.clear();
// 타이틀 텍스트
console.log(
chalk.cyan(
figlet.textSync(' '.repeat(15) + 'Achievements', {
font: 'Standard',
horizontalLayout: 'default',
verticalLayout: 'default'
})
)
);
// 상단 경계선
const line = chalk.white('='.repeat(100));
console.log(line);
console.log(' '.repeat(35) + chalk.yellowBright.bold('지금까지 깨신 기록입니다!'));
// 설명 텍스트
console.log(chalk.green(' '.repeat(34) + '기록은 10개까지 저장됩니다!'));
console.log(line);
if (stageLogArr.length > 0) {
stageLogArr.forEach((stage, i) => {
console.log(' '.repeat(25) + `${i + 1}번째 기록은 ${stage[0]}모드에서 ${stage[1]} 스테이지까지 깨셨네요!`);
});
} else {
console.log(' '.repeat(35) + '깨신 기록이 없어요 ㅠ..ㅠ');
}
// 하단 경계선
console.log(line, '\n');
// 하단 설명
console.log(chalk.gray('1. 되돌아가기'));
}
function achieveInput() {
const choice = readlineSync.question('입력 : ');
switch (choice) {
case '1':
console.log(chalk.red('메뉴로 되돌아갑니다.'));
break;
default:
console.log(chalk.red('메뉴로 되돌아갑니다.'));
break;
}0
}
export async function achieveInfo() {
await arrPrint();
achieveInput();
await wait(1000);
}
// game.js 일부
stageLogArr.push([level.kor(), stage]);
위에 gif에 많이 등장했다.
표시할 로그의 수만큼 배열을 공란으로 채우고
추가될때마다 shift후 push한다.
// 함수와 일부 코드
function pushLog(arr, str) {
arr.shift();
arr.push(str);
}
let logs = new Array(30).fill("");
pushLog(logs, chalk.green(`[${hour}:${new Date().getMinutes()}:${new Date().getSeconds()}] 몬스터에게 ${Math.floor(attP)} 만큼 피해를 입혔습니다.`));