4 Replies - 641 Views - Last Post: 20 January 2011 - 07:10 AM Rate Topic: -----

#1 MidnightMindz  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 2
  • Joined: 17-January 11

Some Questions Regarding a Txt Based RPG

Posted 17 January 2011 - 07:50 PM

I'm an absolute beginner at programming and new to the forum, but like many, I adore games. So based on what I learned, I wanted to see how far I could get in trying to make a simplistic rpg. My focus was not complicated algorithms or a nice interface, for as nice as that would be, I lack the experience, so my intention was just to put together for the most part the bare-bone minimum of an rpg, excluding story elements, to understand what it's like. The two most important things for this project is writing it with classes and having a simple battle system. I think that's manageable with 150-300 lines max.

First off... I ran into some problems at the very beginning, and after making some changes got it to work, but I'm not sure why. This is the original code:

#include <iostream>

using namespace std;
// It won't compile like this, until I declare the Stats functions outside the class as well, why is this?

class mob {

    public:
    void Stats (int Hp, int Atk, int Def, int Dex);
};

class Char {

    public:
    char Name[10];
    void Stats (int Hp, int Atk, int Def, int Dex);
};
void Char::Stats()

int main()
{
    mob Witch, Ogre;
    Witch.Stats (10, 10, 10, 10);
    Ogre.Stats (15, 5, 9, 4);
    Char Char;
    Char.Name;
    cin >> Char.Name;
    cout << Char.Name;
    return 0;
}


Here is how far I've gotten so far and to what most of my other questions will pertain to:
#include <iostream>
#include <string>
using namespace std;

class mob {

    public:
    char *Name [10];
    void Stats (int, int, int, int, int);

};

class Your {

    public:
    char Name[10];
    void Stats (int, int, int, int, int);
};

void mob::Stats(int Hp, int Atk, int Def, int Dex, int Spd)
{
    Hp;
    Atk;
    Def;
    Dex;
    Spd;
};

void Your::Stats(int Hp, int Atk, int Def, int Dex, int Spd)
{
    Hp;
    Atk;
    Def;
    Dex;
    Spd;
};

int main()
{
    mob Witch, Ogre;
    Your Char;
    Witch.Name = {"Witch"};
    Witch.Stats (10, 10, 10, 10, 10);
    Ogre.Name = {"Ogre"};
    Ogre.Stats (15, 5, 9, 4, 7);

    Char.Name;
    cout << "Input a name: \n";
    cin >> Char.Name;
    cout << "Your name is: " << Char.Name << endl;
    int MyHp, MyAtk, MyDef, MyDex, MySpd;
    Char.Stats (MyHp, MyAtk, MyDef, MyDex, MySpd);
    cout << "Input your Health Points: (1-15) ";
    cin >> MyHp;
    cout << "Input your Atk Power: (1-15) ";
    cin >> MyAtk;
    cout << "Input your Def Power: (1-15) ";
    cin >> MyDef;
    cout << "Input your Dexterity: (1-15) ";
    cin >> MyDex;
    cout << "Input your Speed: (1-15) ";
    cin >> MySpd;
    cout << "\nAre you ready to fight?(Yes or No)" << endl;
    int Value = 1;
    string Response;
    while (Value != 0) {
        cin >> Response;
        if (Response == "Yes") {
        Value = 0;}
        else "Are you ready now?"; }

    cout << "\nThen let's begin." << endl;
    cout << "Your first opponent is " << Witch.Name << endl << endl;
    cout << "Ready... Set... Rumble!! " << endl;

    return 0;
}



So I've done a couple baddies and stats, but I'm having a hard time figuring out how to use these to fight with.

1. To find out who goes first, I was going to include an if statement comparing my speed to the mobs, but how do I do input the speed from Witch.Stats into the if statement?
2. How would I go about changing Witch.Name on line 73 to something more flexible, so that the name of the monster would be called up like a variable(like (variable-name).Name) so based on some score system it would be able to decide who I'm fighting next.

I obviously need more then that for the game but I'll figure out the rest for myself. I've heard of DirectX and OpenGL, but I won't feel ready to start learning that until I get a better handle on C++. Finally, can anyone recommend any header files that could be used for games, offer any tips, or suggest any useful books to read on the subject?

Is This A Good Question/Topic? 0
  • +

Replies To: Some Questions Regarding a Txt Based RPG

#2 anonymous26  Icon User is offline

  • D.I.C Lover

Reputation: 0
  • View blog
  • Posts: 3,638
  • Joined: 26-November 10

Re: Some Questions Regarding a Txt Based RPG

Posted 18 January 2011 - 12:12 PM

Hi and welcome to </dream.in.code> . There are several issues with your code that I will address in turn. I'll be referring directly to the latest version of your code posted.

#include <iostream>
#include <string>
using namespace std;

class mob {

    public:
    char *Name [10];
    void Stats (int, int, int, int, int);

};

class Your {

    public:
    char Name[10];
    void Stats (int, int, int, int, int);
};

void mob::Stats(int Hp, int Atk, int Def, int Dex, int Spd)
{
    Hp;
    Atk;
    Def;
    Dex;
    Spd;
};

void Your::Stats(int Hp, int Atk, int Def, int Dex, int Spd)
{
    Hp;
    Atk;
    Def;
    Dex;
    Spd;
};

int main()
{
    mob Witch, Ogre;
    Your Char;
    Witch.Name = {"Witch"};
    Witch.Stats (10, 10, 10, 10, 10);
    Ogre.Name = {"Ogre"};
    Ogre.Stats (15, 5, 9, 4, 7);

    Char.Name;
    cout << "Input a name: \n";
    cin >> Char.Name;
    cout << "Your name is: " << Char.Name << endl;
    int MyHp, MyAtk, MyDef, MyDex, MySpd;
    Char.Stats (MyHp, MyAtk, MyDef, MyDex, MySpd);
    cout << "Input your Health Points: (1-15) ";
    cin >> MyHp;
    cout << "Input your Atk Power: (1-15) ";
    cin >> MyAtk;
    cout << "Input your Def Power: (1-15) ";
    cin >> MyDef;
    cout << "Input your Dexterity: (1-15) ";
    cin >> MyDex;
    cout << "Input your Speed: (1-15) ";
    cin >> MySpd;
    cout << "\nAre you ready to fight?(Yes or No)" << endl;
    int Value = 1;
    string Response;
    while (Value != 0) {
        cin >> Response;
        if (Response == "Yes") {
        Value = 0;}
        else "Are you ready now?"; }

    cout << "\nThen let's begin." << endl;
    cout << "Your first opponent is " << Witch.Name << endl << endl;
    cout << "Ready... Set... Rumble!! " << endl;

    return 0;
}



1. Your stats should be initialized in the constructor of each respective class like this:

class mob {

    public:
        mob(int Hp, int Atk, int Def, int Dex, int Spd) : 
            mobHp(Hp), mobAtk(Atk), mobDef(Def), mobSpd(Spd)
        {}
        char *Name [10];
    
    private:
        int mobHp, mobAtk, mobDef, mobDex, mobSpd;

};



And you will initialize your other class in a similar fashion. When you create an instance of your class it will now look like this:

mob Witch(10, 10, 10, 10, 10);



or

mob Witch = mob(10, 10, 10, 10, 10);



This will initialize your stats as the object is created, rather than the alternative method you were attempting.

2. You might want to consider creating a struct for your stats variables

struct GAMESTATS
{
  int MyHp, MyAtk, MyDef, MyDex, MySpd;
};



So that you can pass them to functions as a single GAMESTATS object. You can access the individual variables like this.

GAMESTATS myStats;

myStats.MyHp = 20;



as an example.

Revise your code as per these recommendations and see where we go from there. :)
Was This Post Helpful? 2
  • +
  • -

#3 Kilorn  Icon User is offline

  • XNArchitect
  • member icon



Reputation: 1355
  • View blog
  • Posts: 3,528
  • Joined: 03-May 10

Re: Some Questions Regarding a Txt Based RPG

Posted 18 January 2011 - 12:22 PM

There are also numerous MUD codebases written in C++ that might be a good reference point for you to check out. Just run a simple google search for C++ MUD codebase, and I'm sure you'll find something.
Was This Post Helpful? 0
  • +
  • -

#4 MidnightMindz  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 2
  • Joined: 17-January 11

Re: Some Questions Regarding a Txt Based RPG

Posted 19 January 2011 - 10:43 PM

@ButchDean - Your help was invaluable. Thanks for the tips.
@Kilorn - That's a great suggestion. After I finish with this project, I'm going back to studying and reviewing the basics. With that said, looking at MUDs would be a great way of seeing some ways programmers applied their ideas to making games.

To update on where I am with my code, I eliminated classes all together for struc, organized all of it to be more readable, and have done part of the battle system. After I finish that, I intend to polish the game some more until I'm satified. Although, while working on it, I also managed to run into an obstacle I can't find my way around. In the MyHit() and MobHit() functions, the random values don't change through the course of the programs execution. Any suggestions?

 // What I've got so far.

#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;

struct GameStats {
    int Hp;
    int Atk, Def, Dex, Spd, Damage;
    GameStats (int mobHp, int mobAtk, int mobDef, int mobDex, int mobSpd) :
    Hp(mobHp), Atk(mobAtk), Def(mobDef), Dex(mobDex), Spd(mobSpd)
    {}
};

struct Name {
    char Name[10];
    char *Witch;
    char *Ogre;
    };

GameStats Witch (10, 10, 10, 10, 10);
GameStats Ogre (15, 5, 9, 4, 7);
GameStats Char (0, 0, 0, 0, 0);
Name mob;
Name MyChar;

void MyAttack() {
    Char.Damage = Char.Atk - Witch.Def;
    Witch.Hp -= Char.Damage;
    cout << endl << MyChar.Name << " dealt " << Char.Damage << " to " << mob.Witch << "." << endl;

    cout << endl << mob.Witch << " has " << Witch.Hp << " left." << endl;
    cout << "You have " << Char.Hp << " left." << endl;
    };

void MobAttack() {
    Witch.Damage = Witch.Atk - Char.Def;
    Char.Hp -= Witch.Damage;
    cout << endl << mob.Witch << " dealt " << Witch.Damage << " to " << MyChar.Name << "." << endl;

    cout << endl << "You have " << Char.Hp << " left." << endl;
    cout << mob.Witch << " has " << Witch.Hp << " left." << endl;
    };

void MyHit() {
    int hitChance, hitMiss, r;
    hitChance = r * Char.Dex;
    hitMiss = 2 * Witch.Dex;
    if (hitMiss < hitChance)
        MyAttack();
    else
    cout << "\nYou miss." << endl;
        };

void MobHit() {
    int hitChance, hitMiss, r;
    hitChance = r * Witch.Dex;
    hitMiss = 2 * Char.Dex;
    if (hitMiss < hitChance)
        MobAttack();
    else
        cout << "\nEnemy misses." << endl;
        };


int main()
{
    mob.Witch = "Witch";
    mob.Ogre = "Ogre";
    cout << "Input a name: \n";
    cin >> MyChar.Name;
    cout << "Your name is: " << MyChar.Name << endl;
    cout << "Input your Health Points: (1-15) ";
    cin >> Char.Hp;
    cout << "Input your Atk Power: (1-15) ";
    cin >> Char.Atk;
    cout << "Input your Def Power: (1-15) ";
    cin >> Char.Def;
    cout << "Input your Dexterity: (1-15) ";
    cin >> Char.Dex;
    cout << "Input your Speed: (1-15) ";
    cin >> Char.Spd;
    cout << "\nAre you ready to fight?(Yes or No)" << endl;

    int Value = 1;
    string Response;
    while (Value != 0) {
        cin >> Response;
        if (Response == "Yes") {
        Value = 0;}
        else {cout << "Are you ready now?";}
        }

    cout << "\nThen let's begin." << endl;
    cout << "Your first opponent is the " << mob.Witch << "!" << endl << endl;
    cout << "Ready... Set... Rumble!! " << endl << endl;

    bool Turn;
    if(Char.Spd > Witch.Spd){
      cout << "You make the first move." << endl;
      MyHit();
      Turn = true;}
    else {
      cout << "The " << mob.Witch << "attacks." << endl;
      MobHit();
      Turn = false;}

    while (Char.Hp && Witch.Hp > 0) {
      srand(time(0));
      if (Turn == false) {
        int r = (rand() % 3) + 1;
        MyHit();
        Turn = true;
       }
       else {
        int r = (rand() % 3) + 1;
        MobHit();
        Turn = false; }
    }

    return 0;
} 

This post has been edited by MidnightMindz: 19 January 2011 - 10:46 PM

Was This Post Helpful? 0
  • +
  • -

#5 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5760
  • View blog
  • Posts: 12,574
  • Joined: 16-October 07

Re: Some Questions Regarding a Txt Based RPG

Posted 20 January 2011 - 07:10 AM

It's not about OO, it's about organizing code. A lot of this is eliminating repetition.

Your code actually lends itself very strongly to OO. You have a Mob. You have a Player, which is essntially a Mob with extra. You may have special Mobs in the future. By having a base classe, you can allow all all variants in the mobs.

Also, if you're using globals, you're probably doing something wrong. :P

Here's how I'd organize the above code:
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>

using namespace std;

class Mob {
private:
	std::string name;
protected:
	int hp, atk, def, dex, spd, damage;
public:
	Mob(const std::string &name, int hp, int atk, int def, int dex, int spd);
	const std::string &getName() const { return name; }
	/*
	int getHp() const { return hp; }
	int getAtk() const { return atk; }
	int getDef() const { return def; }
	int getDex() const { return dex; }
	*/
	int getSpd() const { return spd; }
	void showStatus() const;
	bool isAlive() const;
	virtual void applyDamage(int);
	virtual int defend(int hitChance, int atk);
	virtual void attack(Mob &);
};

class Player : public Mob {
public:
	Player(const std::string &name, int hp, int atk, int def, int dex, int spd);
	void fight(Mob mob);
};


Player getPlayerFromUser() {
	int hp, atk, def, dex, spd, damage;
	string name;
	
	cout << "Input a name: \n";
	cin >> name;
	cout << "Your name is: " << name << endl;
	cout << "Input your Health Points: (1-15) ";
	cin >> hp;
	cout << "Input your Atk Power: (1-15) ";
	cin >> atk;
	cout << "Input your Def Power: (1-15) ";
	cin >> def;
	cout << "Input your Dexterity: (1-15) ";
	cin >> dex;
	cout << "Input your Speed: (1-15) ";
	cin >> spd;
	return Player(name, hp, atk, def, dex, spd);
}

void getReady() {
	cout << "\nAre you ready to fight?(Yes or No)" << endl;

	while (true) {
		string Response;
		cin >> Response;
		if (Response == "Yes") { return;}
		cout << "Are you ready now?";
	}
}

Mob getRandomMob() {
	static Mob mobs[] = { 
		Mob("Witch", 10, 10, 10, 10, 10),
		Mob("Ogre", 15, 5, 9, 4, 7),
	};
	return mobs[rand() % sizeof(mobs)/sizeof(Mob)];
}

void userGame() {
	Player player(getPlayerFromUser());

	getReady();
	player.fight(getRandomMob());
}

void testGame() {
	Player player("Fred",100,15,15,15,15);

	player.fight(getRandomMob());
}

int main() {
	srand(time(0)); // never call this more than once
	
	testGame();
	return 0;
}


Mob::Mob(const std::string &_name, int _hp, int _atk, int _def, int _dex, int _spd) :
	name(_name), hp(_hp), atk(_atk), def(_def), dex(_dex), spd(_spd) {
}

void Mob::showStatus() const {
	cout << endl << getName() << " has " << hp << " left." << endl;
}

void Mob::applyDamage(int damage) {
	if (damage<0) { 
		cout << endl << "error, can't apply negative damage" << endl;
		return;
	}
	hp -= damage;
	if (hp<0) { hp = 0; }
}

bool Mob::isAlive() const { return hp>0; }

void Mob::attack(Mob &defender) {
	int r = (rand() % 3) + 1;
	int hitChance = r * dex;
	int damage = defender.defend(hitChance, atk);
	if (damage==0) {
		cout << endl << getName() << " misses " << defender.getName() << endl;
	} else {
		cout << endl << getName() << " dealt " << damage << " to " << defender.getName() << "." << endl;
		defender.showStatus();
		showStatus();
	}
}

int Mob::defend(int hitChance, int attackerAtk) {
	int hitMiss = 2 * dex;
	if (hitMiss < hitChance) {
		int damage = attackerAtk - def;
		applyDamage(damage);
		return damage;
	}
	return 0;
}


Player::Player(const std::string &name, int hp, int atk, int def, int dex, int spd) :
	Mob(name, hp, atk, def, dex, spd) { }
	
void Player::fight(Mob mob) {
	Mob &player = *this;
	cout << "\nThen let's begin." << endl;
	cout << "Your opponent is the " << mob.getName() << "!" << endl << endl;
	cout << "Ready... Set... Rumble!! " << endl << endl;

	bool playerTurn = (player.getSpd() > mob.getSpd());
    if(playerTurn){
		cout << "You make the first move." << endl;
	} else {
		cout << "The " << mob.getName() << " attacks." << endl;
	}

    while (player.isAlive() && mob.isAlive()) {
		if (playerTurn) {
			player.attack(mob);
		} else {
			mob.attack(player);
		}
		playerTurn = !playerTurn;
	}
}


Was This Post Helpful? 0
  • +
  • -

Page 1 of 1