프로젝트/[인프런] 게임 프로그래머 입문 올인원

[게임 프로그래머 입문 올인원] 함수와 디버깅 : TextRPG (15강)

순정법사 2023.09.06

A. TextRPG 연습하기

1. 게임 흐름

  1. 시작
  2. 로비 입장
  3. 직업 선택 123
  4. 필드 입장 12
  5. 몬스터 스폰
  6. 전투 12
  7. 후 결과에 따른 분기문...

 

a. 게임의 기본 구조

게임의 기본 구조는 while문으로 작성되어있음

 

📘 문법

void EnterLobby() {
	while (true) {
		//입력
		//로직 ----- 일부 로직이 서버에 분산되어 있다면 온라인 게임 / 싱글게임이면 X
		//출력 (아트 리소스)
	}
}

 

 

2. 코드 작성하기

a. 필드 생성

  1. 입장 하자마자 로비로 들어가야 하기 때문에 바로 EnterLobby 실행
  2. 직업 생성

 


void EnterLobby();

int main()
{
	EnterLobby();	//1.
}

void EnterLobby() {
	while (true) {
		cout << "--------------------" << endl;
		cout << "로비에 입장했습니다!" << endl;
		cout << "--------------------" << endl;

		//플레이어 직업 선택 - 별도의 기능 2.
		SelectPlayer();
	}
}

 

b. 직업 생성

  1. 직업을 골라주세요 출력
  2. 직업 타입 생성하기
  3. 직업, hp, attack, defence 선언하기
  4. 직업 입력받기
  5. 받은 값 PlayerType으로 변환 및 초기화하기
  6. 값에 따른 변수 초기화 하기
  7. 루프 문 종료 후 int a = 3에 break 걸고 오류 확인하기

 

//2. 직업 타입
enum PlayerType {
	PT_None = 0,
	PT_Knight = 1,
	PT_Archer = 2,
	PT_Mage = 3,
};

//스텟을 한번에 관리
struct StatInfo {
	int hp;
	int attack;
	int defence;
};

//C#에서는 int와 enum은 다르지만
//C++에서는 둘이 동일하기 때문에 지금은 아래와 같이 사용 
//3.
PlayerType playerType;
StatInfo playerStat;

void SelectPlayer();

int main()
{
	EnterLobby();
}

void EnterLobby() {
	while (true) {	//1.
		cout << "--------------------" << endl;
		cout << "로비에 입장했습니다!" << endl;
		cout << "--------------------" << endl;

		//플레이어 직업 선택 - 별도의 기능
		SelectPlayer();

		int a = 3;	//7.
	}
}

void SelectPlayer() {
	while (true) {
	cout << "--------------------" << endl;
	cout << "직업을 골라주세요!" << endl;
	cout << "(1) 기사 (2) 궁수 (3) 법사" << endl;
	cout << ">";

	int choice;
	cin >> choice;

	playerType = (PlayerType)choice;

	if (choice == PT_Knight) {
		cout << "기사 생성중..." << endl;
		playerStat.hp = 150;
		playerStat.attack = 10;
		playerStat.defence = 5;
		playerType = PT_Knight;
		break;
	}
	else if (choice == PT_Archer) {
		cout << "궁수 생성중..." << endl;
		playerStat.hp = 100;
		playerStat.attack = 15;
		playerStat.defence = 3;
		playerType = PT_Archer;
		break;
	}
	else if (choice == PT_Mage) {
		cout << "법사 생성중..." << endl;
		playerStat.hp = 80;
		playerStat.attack = 25;
		playerStat.defence = 0;
		playerType = PT_Mage;
		break;
	}
	else {
		//없어도 while문에서 반복해서 옳은 값을 입력받을때 까지 루프
	}
}

 

c. 필드 입장하기

  1. 몬스터가 생성되었다면 필드 입장 유무 받기
  2. 입장한다면 필드 입장 알림 후 플레이어 정보 알리기
  3. 몬스터 스폰
  4. 전투할지 도주할지 선택하기
  5. 전투하는 도중 플레이어 스텟이 0인경우 리턴하기

 

void EnterField();

...


void EnterLobby() {
	while (true) {
		cout << "--------------------" << endl;
		cout << "로비에 입장했습니다!" << endl;
		cout << "--------------------" << endl;

		//플레이어 직업 선택 - 별도의 기능
		SelectPlayer();

		cout << "--------------------" << endl;
		cout << "(1) 필드 입장 (2) 게임 종료" << endl;
		cout << "--------------------" << endl;

		int input;	//입장인지 아닌지 입력받기
		cin >> input;

		if (input == 1) {
			EnterField();
		} else {
			return;
		}
	}
}

void EnterField() {
	while(true){
		cout << "--------------------" << endl;
		cout << "필드에 입장했습니다!" << endl;
		cout << "--------------------" << endl;

		cout << "[PLAYER] HP : " << playerStat.hp << " / ATT : " << playerStat.attack << " / DEF : " << playerStat.defence << endl;
		
		//몬스터 스폰
		CreateRandomMonster();

		cout << "--------------------" << endl;
		cout << "(1) 전투 (2) 도주 " << endl;
		cout << "--------------------" << endl;

		int input;	//전투인지 아닌지 입력받기
		cin >> input;

		if (input == 1) {
			EnterBattle();

			if (playerStat.hp == 0) {
				return;
			}
		}
		else {
			return;
		}
	}
}

 

d-1. 몬스터 랜덤 생성

  1. main에 시드 생성 후 몬스터 랜덤 생성
  2. 몬스터 타입 생성하기
  3. 몬스터, hp, attack, defence 선언하기
  4. 랜덤값에 따른 MonsterType값 변환 및 초기화하기
  5. 루프 문 종료 후 int a = 3에 break 걸고 오류 확인하기

 

//2. 몬스터 타입
enum MonsterType {
	MT_None = 0,
	MT_Slime = 1,
	MT_Orc = 2,
	MT_Skeleton = 3,
};

MonsterType monsterType;
StatInfo monsterStat;

void CreateRandomMonster();

...

int main()
{
	srand((unsigned int)time(0)); //랜덤값의 시드값
	EnterLobby();
}

....


void CreateRandomMonster()
{
	int randomChoice = 1 + rand() % 3; //3. 1~3사이 숫자를 랜덤으로 가져옴

	switch (randomChoice) {	//4.
		case MT_Slime : 
			cout << "슬라임 생성중...! (HP:30 / ATT : 2 / DEF : 0)" << endl;
			monsterStat.hp = 30;
			monsterStat.attack = 2;
			monsterStat.defence = 0;
			monsterType = MT_Slime;
			break;
		case MT_Orc:
			cout << "오크 생성중...! (HP:80 / ATT : 15 / DEF : 5)" << endl;
			monsterStat.hp = 80;
			monsterStat.attack = 15;
			monsterStat.defence = 5;
			monsterType = MT_Orc;
			break;
		case MT_Skeleton:
			cout << "스켈레톤 생성중...! (HP:100 / ATT : 20 / DEF : 10)" << endl;
			monsterStat.hp = 100;
			monsterStat.attack = 20;
			monsterStat.defence = 10;
			monsterType = MT_Skeleton;
			break;
	}
}

 

d-2. 전투 시작

  1. 데미지 계산 (0보다 작을시 0으로 예외처리)
  2. 몬스터 공격 후 몬스터 체력 출력
  3. 몬스터 처리시 다음 처리
  4. 아닐시 플레이어 공격 후 플레이어 체력 출력
  5. 플레이어 사망 시 처리 

 

void EnterField();

...

void EnterBattle()
{
	while (true) {
		//나의 공격
		int damage = playerStat.attack - monsterStat.defence;	//1.
		if (damage < 0) {
			damage = 0;
		}

		monsterStat.hp -= damage;	//2.
		if (monsterStat.hp < 0) {
			monsterStat.hp = 0;
		}

		cout << "몬스터 남은 체력 : " << monsterStat.hp << endl;

		if (monsterStat.hp == 0) {	//3.
			cout << "몬스터를 처치했습니다!" << endl;
			WaitForNextKey();
			return;
		}

		//몬스터의 공격
		int damage2 = monsterStat.attack - playerStat.defence;	//4.
		if (damage2 < 0) {
			damage2 = 0;
		}

		playerStat.hp -= damage2;
		if (playerStat.hp < 0) {
			playerStat.hp = 0;
		}

		cout << "플레이어의 남은 체력 : " << playerStat.hp << endl;

		if (playerStat.hp == 0) {
			cout << "당신은 사망했습니다... GAME OVER" << endl;	//5.
			WaitForNextKey();
			return;
		}
	}
}

 

e. 사망하거나 게임이 끝날 시 처리

void WaitForNextKey();

...

void WaitForNextKey()
{
	cout << "계속하려면 1을 눌러주세요" << endl;
	cout << ">";

	int input;
	cin >> input;

	system("cls");	//내용을 정리
}

 

 

3. 전체 코드

a. 파일

GameCoding.cpp
0.00MB

 

b. 코드

#include <iostream>
using namespace std;

//직업 타입
enum PlayerType {
	PT_None = 0,
	PT_Knight = 1,
	PT_Archer = 2,
	PT_Mage = 3,
};

//몬스터 타입
enum MonsterType {
	MT_None = 0,
	MT_Slime = 1,
	MT_Orc = 2,
	MT_Skeleton = 3,
};

//스텟을 한번에 관리
struct StatInfo {
	int hp;
	int attack;
	int defence;
};

//C#에서는 int와 enum은 다르지만
//C++에서는 둘이 동일하기 때문에 지금은 아래와 같이 사용 
PlayerType playerType;
StatInfo playerStat;

MonsterType monsterType;
StatInfo monsterStat;

void EnterLobby();
void SelectPlayer();
void EnterField();
void CreateRandomMonster();
void EnterBattle();
void WaitForNextKey();

int main()
{
	srand((unsigned int)time(0)); //랜덤값의 시드값
	EnterLobby();
}

void EnterLobby() {
	while (true) {
		cout << "--------------------" << endl;
		cout << "로비에 입장했습니다!" << endl;
		cout << "--------------------" << endl;

		//플레이어 직업 선택 - 별도의 기능
		SelectPlayer();

		cout << "--------------------" << endl;
		cout << "(1) 필드 입장 (2) 게임 종료" << endl;
		cout << "--------------------" << endl;

		int input;	//입장인지 아닌지 입력받기
		cin >> input;

		if (input == 1) {
			EnterField();
		} else {
			return;
		}
	}
}

void SelectPlayer() {
	while (true) {
		cout << "--------------------" << endl;
		cout << "직업을 골라주세요!" << endl;
		cout << "(1) 기사 (2) 궁수 (3) 법사" << endl;
		cout << ">";

		int choice;
		cin >> choice;

		playerType = (PlayerType)choice;

		if (choice == PT_Knight) {
			cout << "기사 생성중..." << endl;
			playerStat.hp = 150;
			playerStat.attack = 10;
			playerStat.defence = 5;
			playerType = PT_Knight;
			break;
		}
		else if (choice == PT_Archer) {
			cout << "궁수 생성중..." << endl;
			playerStat.hp = 100;
			playerStat.attack = 15;
			playerStat.defence = 3;
			playerType = PT_Archer;
			break;
		}
		else if (choice == PT_Mage) {
			cout << "법사 생성중..." << endl;
			playerStat.hp = 80;
			playerStat.attack = 25;
			playerStat.defence = 0;
			playerType = PT_Mage;
			break;
		}
		else {
			//없어도 while문에서 반복해서 옳은 값을 입력받을때 까지 루프
		}
	}
}

void EnterField() {
	while(true){
		cout << "--------------------" << endl;
		cout << "필드에 입장했습니다!" << endl;
		cout << "--------------------" << endl;

		cout << "[PLAYER] HP : " << playerStat.hp << " / ATT : " << playerStat.attack << " / DEF : " << playerStat.defence << endl;
		
		//몬스터 스폰
		CreateRandomMonster();

		cout << "--------------------" << endl;
		cout << "(1) 전투 (2) 도주 " << endl;
		cout << "--------------------" << endl;

		int input;	//전투인지 아닌지 입력받기
		cin >> input;

		if (input == 1) {
			EnterBattle();

			if (playerStat.hp == 0) {
				return;
			}
		}
		else {
			return;
		}
	}
}

void CreateRandomMonster()
{
	int randomChoice = 1 + rand() % 3; //1~3사이 숫자를 랜덤으로 가져옴

	switch (randomChoice) {
		case MT_Slime : 
			cout << "슬라임 생성중...! (HP:30 / ATT : 2 / DEF : 0)" << endl;
			monsterStat.hp = 30;
			monsterStat.attack = 2;
			monsterStat.defence = 0;
			monsterType = MT_Slime;
			break;
		case MT_Orc:
			cout << "오크 생성중...! (HP:80 / ATT : 15 / DEF : 5)" << endl;
			monsterStat.hp = 80;
			monsterStat.attack = 15;
			monsterStat.defence = 5;
			monsterType = MT_Orc;
			break;
		case MT_Skeleton:
			cout << "스켈레톤 생성중...! (HP:100 / ATT : 20 / DEF : 10)" << endl;
			monsterStat.hp = 100;
			monsterStat.attack = 20;
			monsterStat.defence = 10;
			monsterType = MT_Skeleton;
			break;
	}
}

void EnterBattle()
{
	while (true) {
		//나의 공격
		int damage = playerStat.attack - monsterStat.defence;
		if (damage < 0) {
			damage = 0;
		}

		monsterStat.hp -= damage;
		if (monsterStat.hp < 0) {
			monsterStat.hp = 0;
		}

		cout << "몬스터 남은 체력 : " << monsterStat.hp << endl;

		if (monsterStat.hp == 0) {
			cout << "몬스터를 처치했습니다!" << endl;
			WaitForNextKey();
			return;
		}

		//몬스터의 공격
		int damage2 = monsterStat.attack - playerStat.defence;
		if (damage2 < 0) {
			damage2 = 0;
		}

		playerStat.hp -= damage2;
		if (playerStat.hp < 0) {
			playerStat.hp = 0;
		}

		cout << "플레이어의 남은 체력 : " << playerStat.hp << endl;

		if (playerStat.hp == 0) {
			cout << "당신은 사망했습니다... GAME OVER" << endl;
			WaitForNextKey();
			return;
		}
	}
}

void WaitForNextKey()
{
	cout << "계속하려면 1을 눌러주세요" << endl;
	cout << ">";

	int input;
	cin >> input;

	system("cls");	//내용을 정리
}

 

 

 


출처 : https://www.inflearn.com/course/%EA%B2%8C%EC%9E%84-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8-%EC%9E%85%EB%AC%B8-%EC%98%AC%EC%9D%B8%EC%9B%90-rookiss#curriculum

 

[게임 프로그래머 입문 올인원] C++ & 자료구조/알고리즘 & STL & 게임 수학 & Windows API & 게임 서버 -

어디부터 시작할지 막막한 게임 프로그래밍 입문자를 위한 All-In-One 커리큘럼입니다. C++, 자료구조/알고리즘, STL, 게임 수학, Windows API, 게임 서버 입문으로 이어지는 알찬 커리큘럼으로 게임 프

www.inflearn.com