C++ Learning by Making an RPG Playground
Tags: cpp, gamedev
Published: 2020-12-06 04:15:44

---
title: C++ Learning by Making an RPG Playground
published: true
description: Learning C++
tags: cpp, gamedev
series: C++ Journey
//cover_image: https://direct_url_to_image.jpg
---

My favorite way to begin learning the syntax of a new language is to make a little RPG-type console game. As part of my quest to learn C++ I made one to fight random enemies. 

## How the Game Works
The player has 100 health, 10 strength, and can either attack or run. A random enemy will appear for the player to fight. Each enemy type has a different amount of health and their strength is 1/3 of whatever their health is.

This is a sample of how it plays. Each time you defeat an enemy a new random enemy will appear and you repeat until you either die or press 0 to quit.

```
============================================================

A Slime with 10HP and 3 strength approaches.
You have 100HP and 10 strength.


What would you like to do?
1. Attack
2. Run
0. Quit


Enter your selection: 1


You attack the Slime for 10 damage.

You defeated the Slime and received 8 gold.
You have 8 total gold.

============================================================

A Skelly with 20HP and 6 strength approaches.
You have 100HP and 10 strength.


What would you like to do?
1. Attack
2. Run
0. Quit


Enter your selection: 1


You attack the Skelly for 10 damage.
The Skelly strikes back for 6 damage.

============================================================

The Skelly has 10HP left.
You have 94HP and 10 strength.


What would you like to do?
1. Attack
2. Run
0. Quit


Enter your selection: 1


You attack the Skelly for 10 damage.

You defeated the Skelly and received 18 gold.
You have 26 total gold.

============================================================
```


## Code Explained
As I'm still learning and just playing around, this isn't the most optimized code at all. As I learn more I'll probably keep using this as a playground, adding more features and refactoring.

### Enums are cool
I briefly described enumerations in my previous [post](https://dev.to/robotspacefish/c-data-types-3i69) on C++ data types.

They basically allow you to use names instead of integers, but the names still represent an integer.

I used an enum to represent my character types:

`enum characterType { PLAYER, OGRE, GOBLIN, SLIME, SKELLY };`

Each type between the braces equals an integer that corresponds to their location: PLAYER = 0, OGRE = 1, etc.

Then I created a function to return a random integer between 1 and 4. I didn't want to return 0 because that would give me PLAYER. I actually didn't use PLAYER (yet), but I have it there just in case.

```
int randomEnemyType() 
{
    return rand() % 4 + 1;
}
```

This way I could get a random number and pass it into other functions, like this one:

```
int getHealthByType(int type) 
{
    switch (type) 
    {
        case OGRE:
            return 40;
        case GOBLIN:
            return 30;
        case SKELLY:
            return 20;
        case SLIME:
            return 10;
        default:
            return 0;
    }
}
```

If `type` is equal to 1 it will return `40` for `OGRE`, since `OGRE = 1`.

I also created another enum: `enum moveType { ATTACK = 1, RUN }`. When the player is prompted to enter their selection, if they select 1 it corresponds to ATTACK, and 2 corresponds to RUN.

### Enemy Class
I created the class `Enemy` which has 3 member variables: `health`, `type`, and `gold`. Since these are private I have some getter functions to retrieve the data when needed. When a new Enemy object (or instance) is created, the constructor runs and `type` is set from the `randomEnemyType` function, `health` is set by passing `type` into `getHealthByType`, and `gold` is set randomly with `rand() % 20`, which is the range 0 - 19.

```
class Enemy
{
public:
    Enemy()
    {
        type = randomEnemyType();
        health = getHealthByType(type);
        gold = rand() % 20;
    }
    
    void takeDamage(int str) 
    {
        health -= str;
    }
    
    int getStrength()
    {
        return maxHealth()/3;
    }
    
    void print()
    {
        std::cout << "Enemy Type: " << getEnemyTypeAsString(type) << ", health: " << health << "\n";
    }
    
    std::string getTypeString() 
    {
        return getEnemyTypeAsString(type);
    }
    
    void generateNew()
    {
        type = randomEnemyType();
        health = getHealthByType(type);
        gold = rand() % 20;
    }
    
    int getHealth() 
    {
        return health;
    }
    
    bool isDead() 
    {
        return health <= 0;
    }
    
    int maxHealth() 
    {
        return getHealthByType(type);
    }
    
    int getGold()
    {
        return gold;
    }
    
private:
    int health;
    int type;
    int gold;
};
```

I created the member function `generateNew` to set the enemy member variables to new values once an enemy is defeated instead of destroying and creating a new instance of `Enemy`. If I was writing this in JavaScript or Ruby I probably would've created a class method to create the instance but I'm still learning how to work with classes here.


### Main
In `main` I set a few variables for the player: `health`, `stength`, and `gold`. Since enemies also have these attributes I will refactor this. I'm thinking of something like a `Character` parent class to extend `Player` and `Enemy` from.

I also have a variable `input` of type integer which is set to whatever the user selection is. Then a `switch` statement handles what happens next. `enemy.takeDamage` runs, taking in the player's `strength`. In that Enemy member function the player's strength is subtracted from the enemy's health. If the enemy dies the player collects the enemy's gold and a new enemy is generated. If the enemy still lives it attacks the player and the `while` loop repeats, allowing the player to attack, run, or quit again.

```
switch (input) 
{
    case ATTACK:
	    std::cout << "\n\nYou attack the " << enemyType << " for " << strength << " damage.\n";
	    enemy.takeDamage(strength);
	    
	    if (enemy.isDead())
	    {
	        int enemyGold = enemy.getGold();
	        gold += enemyGold;
	        std::cout << "\nYou defeated the " << enemyType << " and received " << enemyGold << " gold.\n";
	        std::cout << "You have " << gold << " total gold.\n";
	        
	        enemy.generateNew();
	    } else {
	        health -= damage;
	        
	        std::cout << "The " << enemyType << " strikes back for " << damage << " damage.\n";
	        
	        if (health <= 0) {
	            std::cout << "\nYou died.\n";
	            return 0;
	        }
	    }
	    break;
	case RUN:
	    std::cout << "You are too scared of the " << enemyType << " and you run away.\n";
	    
	    enemy.generateNew();
	    break; 
}
```

## Bracket Sadness
I'm a fan of brackets because I like to know at a quick glance what belongs to a block of code. Personally, it's my preference to start the opening bracket for functions and blocks on the same line. From what I can tell it seems to be more standard in C++ to start your function/block brace on the following line, at least in Visual Studio and Unreal. I'm not a fan :( but I'm trying to get used to it. I read a point somewhere that someone made (maybe on Stack Overflow) that people tend to put a space between an opening block and the first line of code within it anyway, so why not use the opening bracket for that? That made sense to me, but I'm still going to be grumpy about it until I get used to it. 😆

---
That's the basic gist of the game so far. It's a pretty fun way to learn a new language. I think next I'll have to dig into arrays and add a player inventory!

## Further Reading
[Generate random number - rand](https://www.cplusplus.com/reference/cstdlib/rand/)

[Enumerations](https://docs.microsoft.com/en-us/cpp/cpp/enumerations-cpp)