School Assignment? Project Due Tomorrow? Chat LIVE With A Programming Expert!

Welcome to Dream.In.Code
Become an Expert!

Join 307,005 Programmers for FREE! Get instant access to thousands of experts, tutorials, code snippets, and more! There are 1,990 people online right now. Registration is fast and FREE... Join Now!




Make a text combat game in C++

 
Reply to this topicStart new topic

> Make a text combat game in C++, plays like pokémon/final fantasy where you fight a monster

crazyjugglerdrummer
Group Icon



post 31 Mar, 2009 - 01:29 PM
Post #1


Greetings Earthlies, this is crazyjugglerdrummer with the first in a hopefully long series of game tutorials. As mentioned in the title, this game plays something like pokémon, final fantasy, and many others I’m sure, making a combat system. This is all text based, but could later be adapted to run with fancier visual input/output. This is the beating heart of the program, the eyes, ears, and skin can be worked out later.

This game was my first real C++ project and I’ve been at it for a while. The first rewrite added object oriented techniques and the second rewrite fixed most of the object mistakes I’d make previously. The rewrites were horribly annoying as I had to completely reorganize the code and build it up almost from scratch again each time. I’m going to try to design these tutorials with as little of that as possible and a logical learning progression, so once code gets written, it shouldn’t have to be reorganized too much.

Every feature I wanted to add to the game required me to look in a new chapter of my C++ book, so this tutorial will compose of the apex of those efforts. I gradually added functions, then objects, then inheritance one after another. So to spare you the rewrites we are going to start with object-oriented code from the very beginning. These tutorials will use loops, functions, objects, inheritance, and vectors thoroughly (though this first tutorial will be simpler and not use all of them). Don’t let any of those scare you off! If you don’t understand any of them at all, look through some of the other tutorials here in this forum and come back to this when you have. This program is a good example of those and how to use them.


So, without further adieu, on to the actual program. We are going to make a combat system in which you fight a monster. Other tutorials will gradually add on to this, stuffing more features into the game. We need to have classes for monsters, characters, and the combat. These classes overlap profusely, so proper header files and implementations are essential. We are going to start with the Monster class as its the easiest.

So lets think of how to make a monster: What are the its properties? What does it do? How does it interact with other objects in the game? First we’ll need some variables for our monster to store our monster’s health, name, and damage. Name will be a string, and the other two will be integers. We need a method for the monster to attack a character, and a constructor that will set the instance variables. So know we have:
CODE

//monster.h
#ifndef Monster_h //header guards
#define Monster_h

#include <iostream>
using namespace std;

#include "Character.h" //we’ll make this in a second
#include “main.h”      //to be explained later
class Monster
    {
    public:
        string name;
        short health;
        short damage;

        Monster(string newName, int newHealth, int newDamage);
    
        void attack(Character&);
    };
#endif


Now we have a header file for our monster class with a constructor and an attack method.

Next we have to make the Character.h that we mentioned. This is going to look pretty much like the Monster class, except with a few extra features for the character.
CODE

//Character.h
#ifndef Character_h
#define Character_h

#include "Monster.h" //we just made this
#include "main.h"    //I’ll get to this (I promise)

#include <iostream>
using namespace std;

class Character
    {
    public:
        string name;
        short health;
        short damage;
        short arrows;

        Character(string newName);

        void attack(Monster& target);
        
        void rangedAttack(Monster& target);
    };
#endif


The extra method rangedAttack and variable arrows are to allow our character to attack in multiple ways, making the game more interesting.

Now we’re going to make a combat class, which will primarily serve to house all of our combat related methods and members. We need to contain the monster the character is fighting, while passing the character as a parameter (we’re going to pass the Character around the functions a lot). We have a combat1 function to contain the cycle of the combat and a combatChoice to display the options the character has available to them.
CODE

//Combat.h
#ifndef Combat_h
#define Combat_h

#include <iostream>
using namespace std;

#include "Character.h"
#include "Monster.h"

class Combat
    {public:
        Monster& M;
        
        Combat(Character& C);
        
        void combatChoice(Character& C);
        
        void combat1(Character& C);
    };
#endif


This class is going to be a little more complex than the others as it has a Monster address as an instance variable. We also have a constructor to implement which will initialize the Monster variable.


So now onto that main.h thing I mentioned. Since our Monster class includes the Character class and vice versa, one can’t be defined without the other. The compiler tries to define the first one, which can’t be defined because the first one hasn’t been defined. This leads to general confusion and a few “NOT DEFINED” errors. So we need to tell the compiler what they classes are so its header files can live happily ever after. So we make a simple header file, that will be implemented by the other header files.
CODE

#ifndef main_h
#define main_h

class Monster;
class Character;

#endif


Monster and Character are the only classes we really need here, as they are the only classes that include the file. The rest of the inclusions are normal.


So, now we can actually implement some stuff. Lets start with the Monster and its attack method. We need to subtract the monster’s damage from the Character’s health that we passed by reference, and display some information about what happened in the attack. We make a very simple constructor, that merely sets the instance variables to the arguments passed to it. So we have:
CODE

#include “Monster.h”

void Monster::attack(Character& target)
{
    target.health-=damage;
    cout << name << " attacks " << target.name << " doing " << damage << " damage!" << endl;
    cout << name << " health: " << health << endl;
}

Monster::Monster(string newname, int newHealth, int newDamage)
{
    name=newname;
    health=newHealth;
    damage=newDamage;
}    


This should all be contained in a .cpp file, as it is the implementation for the monster.

Next, we create Character.cpp, with similar methods. We have an attack method, a similar ranged attack method, a display, and a constructor. The rangedAttack method will subtract its damage from the Monster’s health, then decrement the number of arrows the Character has. If the Character’s out of arrows, we display a message.
CODE

#include "Character.h"

void Character::attack(Monster& target)
{
    target.health-=damage;
    cout << name << " attacks the " << target.name << " doing " << damage << " damage!" << endl;
    cout << name << " health: " << health << endl;
}

void Character::rangedAttack(Monster& target)
{
    if (arrows == 0 )
        cout << name << " is out of arrows!" << endl;
    else
    {
        short rangedDamaged=3;
        target.health-=rangedDamaged;
        arrows--;
        cout << name << " shoots " << target.name << " doing " << rangedDamaged << " damage!" << endl;
    }
}

Character::Character(string newname)
{
    name=newname;
    health=100;
    damage=3;
    arrows=5;
}

void Character::display()
{
    cout << name << "  health: " << health << "  arrows: " << arrows << endl;
}


Notice that all the display statements that involve variables have a space before the next strings that is displayed, so the line doesn’t just show up as one big word.

Now we can implement the Combat class, which serves as the container for our combat members and functions. The combat constructor will simply initialize the Character’s opponent. Combat1 is just a loop that repeatedly has the monster attack the character, then gives the Character the chance to choose what to do next, by means of the combatchoice function. CombatChoice just uses a menu switch with two different options. We loop as long as one of the members of the combat is alive, and when one “dies” we display what occurred.
CODE

#include "Combat.h"
#include "Monster.h"
#include "Character.h"

Combat::Combat(Monster& newM) : M(newM)
{
}

void Combat::combatChoice(Character& C)
{
    
    C.display();
    cout << "What do you do? 1 attack, 2 fire arrow" << endl;
    short choice;
    cin >> choice;
    switch (choice)
    {
        case 1:
            C.attack(M);
            break;
            
        case 2:
            C.rangedAttack(M);
            break;
    }
}


void Combat::combat1(Character& C)
{
    
    while  (M.health>0 && C.health>0 )
    {
        
        M->attack(C);
        
        combatChoice(C);
        
    }
    if (M.health<0) //use -> for pointer
        cout << "Congratulations! You killed the monster!" << endl;
    if (C.health<0) //and use a dot for reference
        cout << "YOU HAVE DIED! GAME OVER" << endl;;
    
}



The Combat’s constructor may look a little weird, as it doesn’t have a body. All the constructor does is set the M instance variable to the address that gets passed to it. This is done in the style of an initializer list.

Last, but not least we have main, which is very simple as it makes a monster, constructs a combat from that monster, makes a character, and calls combat1 on that Character. (it doesn’t actually implement main.h)
CODE

#include <iostream>
using namespace std;

#include "Monster.h"
#include "Character.h"
#include "Combat.h"


Monster goblin("goblin",50,2);//declare Monster type outside of main


int main (int argc, char * const argv[]) {
    
    Character C("George"); //variable name C doesn’t matter as we pass by ref
    
    Combat combat(goblin);

    combat.combat1(C);
    
    cout << “thanks for playing!” << endl;

    return 0;
}


We don’t really need iostream or the Monster.h and Character.h as they are included elsewhere and passed on to main, but we’ll include them anyway as some will be used anyway and its easier to keep track of what is used where when they are included specifically.

You can create the combat outside of main if you want, but in future tutorials we’ll create the combat inside of main.

So there you have it, the basics of a simple combat game! I hope this you’ve enjoyed this tutorial and that is has been helpful! If it hasn’t (and you have constructive criticism to make) or any other comments, questions, concerns, please post them here. Thanks for reading!

Happy Coding! smile.gif


Stay tuned for the next tutorial where we add random numbers to the combat system. Later, we will design an item system with weapons, spells, and healing items. We will add inheritance, inheriting both Character and Monster from a Being class. There will also be extensive uses of vectors, so brush up on those for the next part!
Go to the top of the page
+Quote Post


Register to Make This Ad Go Away!

asvati
*



post 29 Apr, 2009 - 01:24 AM
Post #2
sorry, but have you checked that this actually works? I typed it inn myself and got a bunch of errors, 20+ or so, after that I tryed to just copy and paste all of it, but still got 16 errors, by going through them I have narrowed them down to 3. One thing I noticed is that you havent included string? anyway, heres my errors:

combat.cpp(5) : error C2511: 'Combat::Combat(Monster &)' : overloaded member function not found in 'Combat'
combat.cpp(27) : fatal error C1004: unexpected end-of-file found
main.cpp(18) : error C2664: 'Combat::Combat(Character &)' : cannot convert parameter 1 from 'Monster' to 'Character &'

combat.cpp:
CODE
#include "Combat.h"
#include "Monster.h"
#include "Character.h"

Combat::Combat(Monster& newM) : M(newM)
{
}

void Combat::combatChoice(Character& C)
{
    
    C.display();
    cout << "What do you do? 1 attack, 2 fire arrow" << endl;
    short choice;
    cin >> choice;
    switch (choice)
    {
        case 1:
            C.attack(M);
            break;
            
        case 2:
            C.rangedAttack(M);
            break;
    }
}


main.cpp:
CODE
#include <iostream>
#include <string>
using namespace std;

#include "Monster.h"
#include "Character.h"
#include "Combat.h"



Monster goblin("goblin",50,2);//declare Monster type outside of main


int main (int argc, char * const argv[]) {
    
    Character C("George"); //variable name C doesn’t matter as we pass by ref
    
    Combat combat(goblin);

    combat.combat1(C);
    
    cout << "thanks for playing!" << endl;

    return 0;
}
Go to the top of the page
+Quote Post

crazyjugglerdrummer
Group Icon



post 12 May, 2009 - 04:03 PM
Post #3
Its good to know people are watching biggrin.gif . It compiled fine under Xcode GCC on mac os x, which included string automatically I think. I probably should've tested some other compilers... The line in Combat.h is a blatant typo on my part, it should read
CODE

Combat(Monster& C);


Did including <string> fix your other thirteen errors?

Thanks for keeping me honest wink2.gif
Go to the top of the page
+Quote Post

scooterfort
*



post 25 May, 2009 - 10:58 AM
Post #4
Nice system bro I like it. Thats a LOT of code tho ahahah
Go to the top of the page
+Quote Post

crazyjugglerdrummer
Group Icon



post 10 Jun, 2009 - 07:22 AM
Post #5
Part 2 Link
Go to the top of the page
+Quote Post

macmc2
*



post 25 Jun, 2009 - 02:46 PM
Post #6
so wait im suppossed to put all those codes in my compiler right
i think
sorry im kind of an idiot
Go to the top of the page
+Quote Post

crazyjugglerdrummer
Group Icon



post 26 Jun, 2009 - 11:24 AM
Post #7
You're not an idiot any more than we all were/are starting out. Yes: you need to make separate class files for each one, naming them the appropriate thing (monster.h and monster.cpp, combat.h and combat.cpp). The code must go into the appropriate file for it.

I definitely admit that I could've made this task a lot easier by posting all the code and what file it goes into at the end of the tutorial. I will make this and several other improvements as soon as we can edit our own tutorials. (feature coming soon, see DIC user suggestions )

I will say that this is probably not the greatest project for anyone to try when just starting out. Look at some of the other tutorials on the web and on DIC on C++. Try making some of your own simpler programs, like black jack and a date converter, then come back to this one. biggrin.gif

This post has been edited by crazyjugglerdrummer: 26 Jun, 2009 - 11:36 AM
Go to the top of the page
+Quote Post

Jaakuuta
Group Icon



post 18 Jul, 2009 - 12:03 AM
Post #8
Hello... I tried both sections of your tutorial...
I like them, but I have a few comments.
First, they need a bit of editing, the code didn't work outright, I had to do a bit of debugging before it compiled correctly.
Notably, a few things were left out of your tutorial that had to be added.
Also, even though this is only a beginner's tutorial, you didn't use any kind of data hiding to help prevent unwanted side-effects...
Aside from a few other little inconsistencies (using newname on one variable but newAttackBonus on another, and using health and mp, rather than hp and mp) This was actually pretty good.
Oh, and one more thing, a few of the include files as was mentioned before were not specified. Although my compiler auto-imported for strings I still needed to include stdlib.h to use the rand() function.
Go to the top of the page
+Quote Post

crazyjugglerdrummer
Group Icon



post 18 Jul, 2009 - 07:59 AM
Post #9
Yes, I agree with you. This was one of my first programming tutorials and it needs some improvement. However, Dream in code does not offer us the feature of editing our posts after a certain amount of time. Hopefully we'll get this feature soon!

This post has been edited by crazyjugglerdrummer: 24 Jul, 2009 - 05:38 PM
Go to the top of the page
+Quote Post


Fast ReplyReply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 


Lo-Fi Version Time is now: 11/21/09 06:56AM

Live Help!

Be Social

Dream.In.Code RSS Feed Dream.In.Code LinkedIn Group Follow Us On Twitter Fan Us On Facebook

Tutorials

Programming

Web Development

Reference Sheets

Code Snippets

DIC Chatroom

Bye Bye Ads

Monthly Drawing

Thumb Drive

Top Contributors

Top 10 Kudos This Month