back to home page

How to create a simple battle arena RPG in C++

Posted on December 29th, 2010

This tutorial will show you how to create a simple battle arena RPG in C++, The game will feature character creation, statistics, armor, weapon, money, store, and a few other game options that will allow your player to go through. It’s completely text-based and nothing fancy.This tutorial is for Eclipse users but any IDE should be fine… Netbeans, Bloodshead etc… The first thing to do is design, since this a tutorial design is already done. Take into account the objects that will need to be created while keeping this as simple as possible. This tutorial will cover the code and how the header file should reflect. Start by creating the following classes with cpp, and header files.

Game
Character
Enemy
Combat
along with main.cpp and main.h
Now that you have your 5 files ready it’s start to begin. Open main.cpp and add the following lines of code#include “main.h”

1
2
3
4
5
6
#include "main.h"

int main() {
   Game game;
   game.run();
}

As you can see above we create the object game, based off the class Game that we created, and you can already see there will be a method called run() that will initiate the game upon starting it.

Now let’s get started on Game.cpp, let’s first take into account what we want our players to see first. Game will include three functions run(), nav(), and shop() which are pretty much self-explanatory. Run initiates the game like a kick-off, and the nav is the navigation system for the game, this will allow the user to play through the game, view stats, rest, train his character etc.. Now the shop function is the function that will allow the player to buy new weapons and armors which will be defined by you. In this game we are going to keep it as simple as possible. This means that there will be a basic rule to keep it minimal, our weapons and armor won’t have any attributes just names, so we will use the weapons and armor variables as strings. Along with that the character can only hold one weapon and armor at a time. In a future tutorial I will go over how to give the weapons and armors attributes by creating objects for them, but for now let’s keep it simple. Let’s start with the run() method

In the run() function we will greet the player, take him to character creation, and ask the player if they’d like to review their character stats. Sounds simple enough, here’s what the method will look like (take note that the character creation is a method of the character itself, we will get to that later for now leave the character creation as is using the pointer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void Game::run() {
   character = new Character();
   cout << "Welcome to Killworld 2 \n\n";
   cout << "Beginning character creation process \n\n";
   character->create();
   cout << "Would you like to review your character status? (y)/(n): ";
   string review;
   cin >> review;
   if (review == "y") {
         character->status();
   } else {
      cout << "\n...Continuing to game \n";
   }
   menu();
}

The creation process and statistics are handled by the object character, which will be shown later in the tutorial.
Next function down is the navigation, this will be done in a loop so that the navigation screen is returned after each method the player is sent to in the game, like shop, battle etc…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void Game::menu() {
   string menuLoop = "true";
   while (menuLoop == "true") {
      cout << "\n Welcome to mortal realm, here you may begin your journey";
      cout << "\n (t)rain [cost 25 credits] \n (s)hop \n (i)nventory \n (r)est [cost 25 credits] \n (v)iew character status \n (b)attle \n (e)nd game \n";
      cout << "\n What do you wish to do? : ";
      cin >> wish;
      if (wish == "t") {
         character->train();
      } else if (wish == "s") {
         shop();
      } else if (wish == "i") {
         character->inventory();
      } else if (wish == "r") {
         character->rest();
      } else if (wish == "v") {
         character->status();
      } else if (wish == "b") {
         Combat combat;
         combat.buildBattle(character);
      } else if (wish == "e") {
         menuLoop == "false";
         cout << "...Game Over";
         exit(1);
      } else {
         cout << "Select an option!";
      }
   }
}

Ok as you can see the navigation has 7 options which are: (you can mod the nav to your liking)

train – this cost 25 moneys from the player
shop – allows the player to buy new weapons or armor
inventory – displays the characters current armor and weapon
rest – restores the characters health
view – allows the player to view their characters stats
battle – sends the player to the battle arena
end game – does…. yes it ends the game

Next is to create the shop, this is simple, look at the code below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
void Game::shop() {
   string buy;
   cout << "...Welcome to the shop, here you will be able to buy new weapons and armor\n...Note that your character is only capable of containing one armor and weapon at a time\n\n";
   cout << " Weapon Stock:\n (a)xe - 5 credits\n (m)-16 assualt rifle - 20 credits\n (g)reat sword - 25 credits\n";
   cout << " Armor Stock:\n (f)lack jacket - 20 credits\n";
   cout << "\n...Type the starting letter of the armor or weapon you'd like to buy: ";
   cin >> buy;
   if (buy == "a") {
      if (character->getCredits() >= 5) {
         cout << "\n...You bought the Axe.";
         character->takeWeapon("Axe");
      } else {
         cout << "\n...You do not have enough credits for this.";
      }
   } else if (buy == "m") {
      if (character->getCredits() >= 20) {
         cout << "\n...You bought the M-16 Assualt Rifle.";
         character->takeWeapon("M-16 Assualt Rifle");
      } else {
         cout << "\n...You do not have enough credits for this.";
      }
   } else if (buy == "g") {
         if (character->getCredits() >= 25) {
            cout << "\n...You bought the Great Sword.";
            character->takeWeapon("Great Sword");
         } else {
            cout << "\n...You do not have enough credits for this.";
         }
   } else if (buy == "f") {
         if (character->getCredits() >= 20) {
            cout << "\n...You bought the Flack Jacket.";
            character->takeArmor("Flack Jacket");
         } else {
            cout << "\n...You do not have enough credits for this.";
         }
   }
   cout << "\n...Transactions complete.\n";
}

Now that we have completed the Game.cpp file, please take not the default constructor and deconstructor should remain empty. The Game.h should match the functions and variables created in the cpp, the file should look something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#ifndef GAME_H_
#define GAME_H_
#include "Character.h"
#include "Enemy.h"
#include "Combat.h"

class Game {
public:
   Game();
   virtual ~Game();
   void run();
   void menu();
   void shop();
   string wish;
   Character* character;
   Enemy enemy;
};

#endif /* GAME_H_ */

Next it’s logical to start on the Character.cpp file, I’m going to summarize and skim through this bit, just examine the code and learn from it, of course there could be several improvements. Since the character will handle most methods there will be about 20 of them. I’m going to list each one with a little info on what they do.

defendAgainst() when the character defends against the enemy this function will be called.
takeDamage() when the character takes damage this function is called
status() when this is called it returns the characters status
getName() returns the character’s name
getHealth() returns the character’s health points
takeArmor() when the character defeats an enemy the player is given the option to take the enemies armor, if they chose to do so this function is called
takeWeapon() same as armor but takes the weapon instead
saveHealth() saves the character’s current health the a variable to be called later
resetHealth() resets the character’s health
resetHealthToZero() sets the character’s health to zero, well actually -50, but this makes the character dead
getSavedHealth() if the health was saved, this returns the health that was saved
getCredits() returns the character’s credits, which is in game money
getPower() returns character’s power
getArmor() returns character’s armor
getWeapon() returns character’s weapon
train() this method allows the character to train, in turn this increases the character’s power and health points
gainCredits() when the character gains credits at the end of combat if the character wins
inventory() displays the character’s current armor and weapon
rest() restores the character’s health
create() the character creation process

Character.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include "Character.h"

Character::Character() {
   // TODO contructo stub
}

Character::~Character() {
   // TODO Auto-generated destructor stub
}

void Character::defendAgainst(int edamage) {
   health -= edamage + 80;
}

void Character::takeDamage(int pow) {
   health -= pow;
}

void Character::status() {
   cout << "\n..." << name << "'s Status \n";
   cout << "...Credits: " << credits << "\n";
   cout << "...Power: " << power << "\n";
   cout << "...Health: " << health << "\n";
   cout << "...Weapon: " << weapon << "\n";
   cout << "...Armor: " << armor << "\n";
}

string Character::getName() {
   return name;
}

int Character::getHealth() {
   return health;
}

void Character::takeArmor(string enemyArmor) {
   armor = enemyArmor;
}

void Character::takeWeapon(string enemyWeapon) {
   weapon = enemyWeapon;
}

void Character::saveHealth(int currentHealth) {
   savedHealth = health;
}

void Character::resetHealth(int savedHealth) {
   health = savedHealth;
}

void Character::resetHealthToZero() {
   health = -50;
}

int Character::getSavedHealth() {
   return savedHealth;
}

int Character::getCredits() {
   return credits;
}

int Character::getPower() {
   return power;
}

string Character::getArmor() {
   return armor;
}

string Character::getWeapon() {
   return weapon;
}

void Character::train() {
   if (credits >= 25) {
         power = power + 50;
         health = health + 50;
         credits = credits - 25;
         cout << "\n...Your character has trained, by doing so their power and health points have gained an additional 50 points\n";
      } else {
         cout << "\n...Your character does not have enough credits to train.\n";
      }
   }
void Character::gainCredits() {
   credits = credits + 50;
}
void Character::inventory() {
   cout << "\n...Your character is holding:\n" << weapon << "\n" << armor << "\n";
}
void Character::rest() {
   if (credits >= 25) {
      health = 100;
      credits = credits - 25;
      cout << "\n...Your character has fully rested, health points were restored to 100\n";
   } else {
      cout << "\n...Your character does not have enough credits to rest.\n";
   }
}

void Character::create() {
   cout << "Enter a name for your character: ";
   cin >> name;
   cout << "\n...Your characters name is " << name << "\n";
   credits = 100;
   cout << "...Your character has " << credits << " credits\n";
   weapon = "Sword";
   cout << "...Your characters default weapon is the " << weapon << "\n";
   armor = "Shield";
   cout << "...Your characters default armor is a " << armor << "\n";
   health = 100;
   cout << "...Your characters has " << health << " health points\n";
   power = 100;
   cout << "...Your characters has " << power << " power points\n\n";
}

Ok the Character.h should reflect:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#ifndef CHARACTER_H_
#define CHARACTER_H_
#include
#include "StandardIncludes.h"
using std::string;

class Character {
public:
   Character();
   virtual ~Character();
   string name;
   int credits;
   string weapon;
   string armor;
   int power;
   int health;
   int getHealth();
   int savedHealth;
   int currentHealth;
   string enemyArmor;
   void takeArmor(string enemyArmor);
   string enemyWeapon;
   void takeWeapon(string enemyWeapon);
   void saveHealth(int savedHealth);
   void resetHealth(int savedHealth);
   void resetHealthToZero();
   int getSavedHealth();
   int getCredits();
   int getPower();
   string getArmor();
   string getWeapon();
   string getName();
   void create();
   void rest();
   void train();
   void status();
   void inventory();
   int edamage;
   void defendAgainst(int edamage);
   int pow;
   void takeDamage(int pow);
   void gainCredits();
};

#endif /* CHARACTER_H_ */

Next lets create the enemy, check the code out below for matchin cpp, and header file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include "Enemy.h"

Enemy::Enemy() { //default constructor
   // TODO Auto-generated constructor stub

}

Enemy::Enemy(string newEnemyName, string newEnemyWeapon, string newEnemyArmor, int newEnemyPower, int newEnemyHealth) {
   EnemyName = newEnemyName;
   EnemyWeapon = newEnemyWeapon;
   EnemyArmor = newEnemyArmor;
   EnemyPower = newEnemyPower;
   EnemyHealth = newEnemyHealth;
}

Enemy::~Enemy() {
   // TODO Auto-generated destructor stub
}
void Enemy::takeDamage(int damage) {
   EnemyHealth -= damage;
}
void Enemy::enemyStats() {
   cout << "\n...Enemy Name: " + getEnemyName() + "\n";
   cout << "...Enemy Power: " << getEnemyPower() << "\n";
   cout << "...Enemy Health: " << getEnemyHealth() << "\n";
   cout << "...Enemy Weapon: " + getEnemyWeapon() + "\n";
   cout << "...Enemy Armor: " + getEnemyArmor() + "\n";
}

string Enemy::getEnemyName() {
   return EnemyName;
}

string Enemy::getEnemyWeapon() {
   return EnemyWeapon;
}

string Enemy::getEnemyArmor() {
   return EnemyArmor;
}

int Enemy::getEnemyPower() {
   return EnemyPower;
}

int Enemy::getEnemyHealth() {
   return EnemyHealth;
}

now the header file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#ifndef ENEMY_H_
#define ENEMY_H_
#include "StandardIncludes.h"

class Enemy {
public:
   Enemy();
   Enemy(string newEnemyName, string newEnemyWeapon, string newEnemyArmor, int newEnemyPower, int newEnemyHealth);
   virtual ~Enemy();
   string getEnemyWeapon();
   string getEnemyArmor();
   string getEnemyName();
   int getEnemyPower();
   int getEnemyHealth();
   void enemyStats();
   int damage;
   void takeDamage(int damage);
private:
   string EnemyWeapon;
   string EnemyArmor;
   string EnemyName;
   int EnemyPower;
   int EnemyHealth;
};

#endif /* ENEMY_H_ */

Now the combat can be pretty complex, but with the simple logic of attack and defend this can be accomplished simply. In this game there are multiple enemies, each enemy has their own realm. Therefore I created a combat nav that will allow the player to go to the “realm” where they will meet their enemy, they will be given the option to compare their character’s stats to the enemy’s stats to see how they stack up before engaging in combat. Giving the player the option to choose if they wish to engage combat or run. The 3 main functions are:

createEnemies() this is where I created the enemies as with pointers to them
buildBattle() this is the nav which builds the battle and sets the enemy and realm the player will be battling in
battle() this is the actual battle logic, the code is attack or defend based, and depending on what the player chooses the action is done this is in a while loop on the basis of while the characers health is above 0, there are instances for if the enemy dies as well.

Check out the code below:

Combat.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include "Combat.h"

Combat::Combat() {
   // TODO Auto-generated constructor stub

}

Combat::~Combat() {
   // TODO Auto-generated destructor stub
}

Enemy* currentEnemy;
string currentRealm;

void Combat::createEnemies() {
   predator = new Enemy("Predator", "Plasma Caster", "Cloaking Device", 200, 400);
   lopan = new Enemy("Lo Pan", "Ancient Chinese Secret", "Ancient Tunic", 130, 330);
   vader = new Enemy("Darth Vader", "Red Lightsabre", "Dark Cloak", 300, 150);
   frank = new Enemy("Frank The Bunny", "Dark Void", "Bunny Suit", 400, 200);
   scorpion = new Enemy("Scorpion", "Ninja Sword", "Netherealm Armor Shard", 180, 300);
   sweettooth = new Enemy("Sweet Tooth", "Machine Gun", "Clown Suit", 150, 120);
}

void Combat::buildBattle(Character* character) {
   createEnemies();
   string selection;
   cout << "\n The portal to all six realms has opened before you, choose your destination wisely.";
   cout << "\n (h)ell \n (n)etherrealm \n (t)ime realm \n (s)pace realm \n (m)ortal realm \n (p)redator's realm";
   cout << "\n\n...Select a realm to travel to: ";
   cin >> selection;
   if (selection == "h") {
      currentRealm = "Hell";
      currentEnemy = sweettooth;
      battle(character);
   } else if (selection == "n") {
      currentRealm = "Netherrealm";
      currentEnemy = scorpion;
      battle(character);
   } else if (selection == "t") {
      currentRealm = "Time Realm";
      currentEnemy = frank;
      battle(character);
   } else if (selection == "s") {
      currentRealm = "Space Realm";
      currentEnemy = vader;
      battle(character);
   } else if (selection == "m") {
      currentRealm = "Mortal Realm";
      currentEnemy = lopan;
      battle(character);
   } else if (selection == "p") {
      currentRealm = "Predator's Realm";
      currentEnemy = predator;
      battle(character);
   }
}

void Combat::battle(Character* character) {
   string viewStats;
   string faceEnemy;
   string attack;
   string defend;
   string move;
   cout << "\n...Welcome to " + currentRealm + " your opponent is " + currentEnemy->getEnemyName() + "\n";
   cout << "...Would you like to view " + currentEnemy->getEnemyName() + "'s stats vs your stats? (y)/(n): ";
   cin >> viewStats;
   if (viewStats == "y") {
      currentEnemy->enemyStats();
      character->status();
   } else {
      cout << "\n...Very well.\n";
   }
   cout << "\n...Do you wish to face your opponent? (y)/(n): ";
   cin >> faceEnemy;
   if (faceEnemy == "y") {
      cout << "\n...FIGHT TO THE DEATH!\n";
      character->saveHealth(character->getHealth());
      string win;
      win = "n";
      while (character->getHealth() >= 1) {
         cout << "...(a)ttack or (d)efend: ";
         cin >> move;
         if (move == "a") {
            //player attacks
            cout << "\n..." + character->getName() + " attacks " + currentEnemy->getEnemyName() + " for " << character->getPower() << " power points using a " + character->getWeapon() + "\n";
            currentEnemy->takeDamage(character->getPower());
            cout << "..." + character->getName() + ": " << character->getHealth() << " health points | " + currentEnemy->getEnemyName() + ": " << currentEnemy->getEnemyHealth() << " health points\n\n";
            //enemy attacks
            cout << "\n..." + currentEnemy->getEnemyName() + " attacks " + character->getName() + " for " << currentEnemy->getEnemyPower() << " power points using a " + currentEnemy->getEnemyWeapon() + "\n";
            character->takeDamage(currentEnemy->getEnemyPower());
            cout << "..." + character->getName() + ": " << character->getHealth() << " health points | " + currentEnemy->getEnemyName() + ": " << currentEnemy->getEnemyHealth() << " health points\n\n";
         } else if (move == "d") {
            //player defends
            cout << "\n..." + character->getName() + " defends against " + currentEnemy->getEnemyName() + " and his " + currentEnemy->getEnemyWeapon() + "\n";
            character->defendAgainst(currentEnemy->getEnemyPower());
            cout << "..." + character->getName() + ": " << character->getHealth() << " health points | " + currentEnemy->getEnemyName() + ": " << currentEnemy->getEnemyHealth() << " health points\n\n";
            //enemy attacks
            cout << "\n..." + currentEnemy->getEnemyName() + " attacks " + character->getName() + " for " << currentEnemy->getEnemyPower() << " power points using a " + currentEnemy->getEnemyWeapon() + "\n";
            character->takeDamage(currentEnemy->getEnemyPower());
            cout << "..." + character->getName() + ": " << character->getHealth() << " health points | " + currentEnemy->getEnemyName() + ": " << currentEnemy->getEnemyHealth() << " health points\n\n";
         }
         if (currentEnemy->getEnemyHealth() < 0) {
            //enemy died
            character->resetHealthToZero();
            string takeEnemyGear;
            cout << "\n..." + currentEnemy->getEnemyName() + " has fallen in combat. Your character was victorious in combat.\n";
            cout << "...Would you like to take and attach " + currentEnemy->getEnemyName() + "'s armor and weapon? (y)/(n): ";
            cin >> takeEnemyGear;
            if (takeEnemyGear == "y") {
               cout << "\n..." + character->getName() + " attaches " + currentEnemy->getEnemyWeapon() + " and " + currentEnemy->getEnemyArmor() + "\n";
               character->takeWeapon(currentEnemy->getEnemyWeapon());
               character->takeArmor(currentEnemy->getEnemyArmor());
            } else {
               cout << "\n...Your gear remains the same.\n";
            }
            cout << "...You take " + currentEnemy->getEnemyName() + "'s credits.\n...+50 credits\n";
            character->gainCredits();
            win = "y";
         }
      }
      if (win == "y") {
         character->resetHealth(character->getSavedHealth());
      } else {
      //player died
      cout << "\n...Your character has died. You can restore his health points by resting.\n";
      }
   } else if (faceEnemy == "n") {
      cout << "..Sweat hard in training, so you don't bleed in the battle.\n";
   }
}

the matching header file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#ifndef COMBAT_H_
#define COMBAT_H_
#include "StandardIncludes.h"
#include "Enemy.h"
#include "Character.h"

class Combat {
public:
   Combat();
   virtual ~Combat();
   void buildBattle(Character*);
   void battle(Character*);
   string selection;
   string currentRealm;
   Enemy* predator;
   Enemy* lopan;
   Enemy* vader;
   Enemy* frank;
   Enemy* scorpion;
   Enemy* sweettooth;
   void createEnemies();
   string viewStats;
   string faceEnemy;
   string attack;
   string defend;
   string move;
   string win;
};

#endif /* COMBAT_H_ */

remember the constructor and deconstructor should remain blank. the only class with a constructor is enemy, you can review the code above.

This is the basic c++ battle arena rpg, from what you learned you should be able to take this piece and improve it. Likely to create weapons and armors with attributes, and possibly quests in the next tutorial which will be part 2.


Leave a Reply

    To syntax highlight code just use [cc lang="whatever language here"]your code here[/cc]