Page 1 of 1

Before I get Much Further Into Development...

Posted: Mon Apr 13, 2009 10:07 pm
by davidthefat
Is this the right way to use classes and stuff? I mean books only show you little snippets of using classes so Im asking here. Yes it will be a text based game, and not like the usual fight game, its more like a sim. Im taking it slowly cause I tried to jump right into SDL and other Graphic Libraries and I thought to my self, why not make it easier to make it in text version then translate into GUI after I get the core down...

main.cpp

Code: Select all

#include <iostream>
#include <fstream>
#include "NewGame.cpp"

int main()
{
	NewGame NG;
	NG.GetName();
	NG.GetBT();
	NG.DisplayName();
	NG.DisplayBT();
	NG.DisplayBF();
	system("PAUSE");
}
NewGame.cpp

Code: Select all

#include <iostream>
#include "NewGame.h"



void NewGame::GetName()
{
	std::cout << "Whats Your Name?\n";
	std::cin >> Name;
}
void NewGame::GetBT()
{
		std::cout << "What Body Type Are You?\n1 = Ectomorph\t2 = Mesomorph\t3 = Endomorph\n";
		std::cin >> BodyType;
		if (BodyType > 3 || BodyType < 1 )
		{
			std::cout << "WRONG NUMBER DUMBASS!\n";
			GetBT();
		}
		if (BodyType == 1)
		{
			BodyFat = 10;
		}
		if (BodyType == 2)
		{
			BodyFat = 15;
		}
		if (BodyType == 3)
		{
			BodyFat = 20;
		}

}
void NewGame::DisplayBT()
{
		if (BodyType == 1)
		{
			std::cout << "Ectomorph";
		}
		if (BodyType == 2)
		{
			std::cout << "Mesomorph";
		}
		if (BodyType == 3)
		{
			std::cout << "Endomorph";
		}
}
void NewGame::DisplayBF()
{
		std::cout << BodyFat;
}
void NewGame::DisplayName()
{
		std::cout << Name;
}
NewGame.h

Code: Select all

#include <iostream>

class NewGame
{
public:
	float BodyFat;
	int BodyType;
	char Name[10];
	void GetName();
	
	void GetBT();
	
	void DisplayBT();
	
	void DisplayBF();
	


	void DisplayName();
	
};


Not much done, but that only took like 20 minutes to code...

How do I use the Variables declared in my NewGame class from another one?

Re: Before I get Much Further Into Development...

Posted: Mon Apr 13, 2009 10:30 pm
by Ginto8
The way you have it, it won't compile. There are two things you can do: make NewGame.cpp into NewGame.h, and still #include it in main.cpp, or have the outline (variable declarations, function prototypes) in NewGame.h and define the functions in NewGame.cpp, but only #include NewGame.h in main.cpp. My recommendation is the second one. ;)

Re: Before I get Much Further Into Development...

Posted: Mon Apr 13, 2009 11:01 pm
by davidthefat
Ginto8 wrote:The way you have it, it won't compile. There are two things you can do: make NewGame.cpp into NewGame.h, and still #include it in main.cpp, or have the outline (variable declarations, function prototypes) in NewGame.h and define the functions in NewGame.cpp, but only #include NewGame.h in main.cpp. My recommendation is the second one. ;)
I just did that and I was going to edit my post, it look better too

Re: Before I get Much Further Into Development...

Posted: Tue Apr 14, 2009 12:07 am
by OverlordYertle
=) i think you're getting it pretty well. You don't need to #include <iostream> in NewGame.cpp, because it has already been included in NewGame.h (which is the correct place to put it). Anything you include in NewGame.h, your Newgame.cpp will also have it included :)

Before you get started i'd like to make a few tips if i may?

First, a little more general i feel. At the beginning of every .h file put

Code: Select all

#ifndef FILENAME_h
#define FILENAME_h
and for the last line in the header file put

Code: Select all

#endif
This is for the compiler, so it doesn't include files twice. It's really going to come in handy later in the game when things get complex but if you think about it now it will make your life easier in the future.

Second, you say you'd like to experiment with SDL in the future later, but not worry too much about it now. I think that's an excellent idea for just getting the basics down of how everything communicates and getting your game running. However, i would suggest you make a class with the only purpose of printing out to the screen. So like whenever you want to "cout << blah blah" don't. Instead have a "Graphic.h" or a "Display.h" something like that.

When you use them in your program have a command thats like "printer.Show('This string rules')" or something like that. In this display class (assuming its display.h for sense sake) you'd have a function such as:

Code: Select all

void Display::Show(string toPrint){
    cout << toPrint << endl;
}
Now i understand that may look really dumb right now. But if you have all your graphics in one method and the rest of your program, whenever it wants to show something, talks to this one method (Rather than using 'cout' anywhere you want.) it makes your life a lot easier when you try to change how you display visuals. Because lets say you start using SDL, as soon as your ready all you really have to do is change this one class around to comply with SDL! :mrgreen:
Like it might seem a little dumb now, but it makes your program so much more versatile later on.

I did this for my most important 2d game im working with now. And in the course of 2 days i switched from irrlicht (a 3d render program) to SDL and then to OpenGL and all i had to do was rework 2 classes. My draw class and my main (to initialize opengl and sdl etc). To switch between 3 completely different draw systems in 2 days and my code ran just fine game wise i feel is so valuable.

I do hope some of this helps you! and i wish you the best.

Re: Before I get Much Further Into Development...

Posted: Tue Apr 14, 2009 12:14 am
by davidthefat
OverlordYertle wrote:=) i think you're getting it pretty well. You don't need to #include <iostream> in NewGame.cpp, because it has already been included in NewGame.h (which is the correct place to put it). Anything you include in NewGame.h, your Newgame.cpp will also have it included :)

Before you get started i'd like to make a few tips if i may?

First, a little more general i feel. At the beginning of every .h file put

Code: Select all

#ifndef FILENAME_h
#define FILENAME_h
and for the last line in the header file put

Code: Select all

#endif
This is for the compiler, so it doesn't include files twice. It's really going to come in handy later in the game when things get complex but if you think about it now it will make your life easier in the future.

Second, you say you'd like to experiment with SDL in the future later, but not worry too much about it now. I think that's an excellent idea for just getting the basics down of how everything communicates and getting your game running. However, i would suggest you make a class with the only purpose of printing out to the screen. So like whenever you want to "cout << blah blah" don't. Instead have a "Graphic.h" or a "Display.h" something like that.

When you use them in your program have a command thats like "printer.Show('This string rules')" or something like that. In this display class (assuming its display.h for sense sake) you'd have a function such as:

Code: Select all

void Display::Show(string toPrint){
    cout << toPrint << endl;
}
Now i understand that may look really dumb right now. But if you have all your graphics in one method and the rest of your program, whenever it wants to show something, talks to this one method (Rather than using 'cout' anywhere you want.) it makes your life a lot easier when you try to change how you display visuals. Because lets say you start using SDL, as soon as your ready all you really have to do is change this one class around to comply with SDL! :mrgreen:
Like it might seem a little dumb now, but it makes your program so much more versatile later on.

I did this for my most important 2d game im working with now. And in the course of 2 days i switched from irrlicht (a 3d render program) to SDL and then to OpenGL and all i had to do was rework 2 classes. My draw class and my main (to initialize opengl and sdl etc). To switch between 3 completely different draw systems in 2 days and my code ran just fine game wise i feel is so valuable.

I do hope some of this helps you! and i wish you the best.
;) Thank you, In another forum, I have been told to just declare variables in the classes and add funtions it if and only if the data is proceesed in the class, but that guys isnt all that pro with it either, so your input?

BTW the post :
I'm never sure if I'm doing it the right way, and I'm also fairly new at this. But here's my two cents anyway.

Classes make objects. Each object you make should correlate to a "thing" in your program. A noun. An identifiable entity.

For games this is actually easier than for more abstract programs. I'm writing a little text-based game, too. I have these classes so far:

CCreature (an object that contains the stats that all creatures possess - like strength, hit points, and so on)
CPlayer (creates a player object - contains things like the players name, class, race, and so on. Inherits from CCreature. Contains a pointer to a CClass and CRace.)
CClass (the traits all classes have - number of attacks, a pointer to special abilities class)
CRace (the traits all races have - bonuses to abilities, etc)
CSpecial_Abilities (the traits shared by special abilities)

Each class has a collection of variables. Each object, or instance, of a class has those variables specified and is different from all other objects/instances of that class. Some of the classes contain functions, but only insomuch as they are required to process the data inside that class. For example, I have functions for setting the player's races and classes.

But for main game functions, when I want the game to do something, I handle that entirely without classes - I use functions.

The functions I have so far are:
fCalculatePlayerStats (players collect a lot of stat bonuses and penalties, so I have a function for calculating all of that and then passing the results to the Player object)
fInitCharacter (wipes the player object and gives it "default" settings)
fMenu (the main game menu - options to start a new game, load, quit, etc)
fNewGame (to start a new game - basically character creation)
fPlayerName (during character creation, called to bring up the interface for selecting or changing a new player name)
fPlayerRace (same, but selects a race)
fPlayerClass (ditto)
fSleep (wrote my own so I wouldn't have to include windows.h just to have a sleep function)
main (doesn't do squat but call the fMenu function - which in turn calls additional functions, and so on)


That's just an example of how I'm doing it. Hope it makes some sort of sense. I can post code snippits if you like.

Re: Before I get Much Further Into Development...

Posted: Tue Apr 14, 2009 12:42 am
by davidthefat
Edited codes

main.cpp

Code: Select all

#include <iostream>
#include <fstream>
#include "NewGame.h"
#include "Display.h"
#include "Game.cpp"

int main()
{
	NewGame NG;
	Display D;
	NG.GetName();
	NG.GetBT();
	D.cShow(NG.Name);
	D.fShow(NG.BodyFat);
			if (NG.BodyType == 1)
		{
			D.cShow("Ectomorph");
		}
		if (NG.BodyType == 2)
		{
			D.cShow("Mesomorph");
		}
		if (NG.BodyType == 3)
		{
			D.cShow("Endomorph");
		}

	system("PAUSE");

}

NewGame.cpp

Code: Select all

#include "NewGame.h"
void NewGame::GetName()
{
	std::cout << "Whats Your Name?\n";
	std::cin >> Name;
}
void NewGame::GetBT()
{
		std::cout << "What Body Type Are You?\n1 = Ectomorph\t2 = Mesomorph\t3 = Endomorph\n";
		std::cin >> BodyType;
		if (BodyType > 3 || BodyType < 1 )
		{
			std::cout << "WRONG NUMBER DUMBASS!\n";
			GetBT();
		}
		if (BodyType == 1)
		{
			BodyFat = 10;
		}
		if (BodyType == 2)
		{
			BodyFat = 15;
		}
		if (BodyType == 3)
		{
			BodyFat = 20;
		}

}
NewGame.h

Code: Select all

#ifndef NewGame_h
#define NewGame_h
#include <iostream>

class NewGame
{
public:
	float BodyFat;
	int BodyType;
	char Name[10];
	void GetName();
	void GetBT();
};
#endif
Display.h

Code: Select all

#ifndef Display_h
#define Display_h

#include <iostream>

class Display
{
public:
	void cShow(char toPrint[255]);
	void iShow(int toPrint);
	void fShow(float toPrint);
};
#endif
Display.cpp

Code: Select all

#include "Display.h"

void Display::cShow(char toPrint[255])
{
	std::cout << toPrint << std::endl;
}
void Display::iShow(int toPrint)
{
	std::cout << toPrint << std::endl;
}
void Display::fShow(float toPrint)
{
	std::cout << toPrint << std::endl;
}

Re: Before I get Much Further Into Development...

Posted: Tue Apr 14, 2009 6:43 am
by thejahooli
I would also make the display class a singleton. I've only just started using them (the thread is below yours) so I don't know much about them but doing this will allow you to put the 'show' functions inside your newgame class. This will help your code organised and, while it wont change the output, it will keep your code easy to read as everything is in their own class.

Re: Before I get Much Further Into Development...

Posted: Tue Apr 14, 2009 12:57 pm
by davidthefat
NVM, I figured it out, I think Im good to go on this project...


;) thanks on the help

Re: Before I get Much Further Into Development...

Posted: Tue Apr 14, 2009 3:07 pm
by MarauderIIC
I'm not sure that <iostream> should be in the header, actually. I don't have much formal education on header etiquette, but if you always #include everything that your myfile.cpp employs into the accompanying myfile.h, whenever you change something in myfile.h

(...which myfile2.h #includes which myfile3.h #includes -- notice myfile3.h now includes myfile2.h which includes myfile1.h so if you make a change in myfile1.h you have to recompile myfile3.cpp!)

...then you'll recompile your whole project all the time and your compile time will skyrocket. You may have noticed C++ is pretty slow to compile as it is. To keep compile times down, and therefore production hours up, I find it is better practice to #include as little as possible in headers. In fact, if I only use a reference or a pointer to a class in a header (myfile4.h), I just write a class prototype (class myClassName;) in it to avoid recompiling all .cpps (myfile4.cpp) linked with that header when the header linked with MyClassName (myclassname.h) is changed. This way if the MyClassName header changes, my other header (myfile4.h) and its associated .cpps aren't affected.

If you declare it as a complete type, such as

Code: Select all

class System {
MyClassName myMember;
};
Then you have to #include "MyClassName.h", there's no getting around it.

Additionally, you should #include standard headers (<iostream>) after you #include custom headers ("myfile.h"). This avoids you having a problem where you change the order of includes and suddenly your project doesn't compile. In fact, you should generally #include in the order of increasing dependencies where possible, your base header that #includes nothing to headers that #include that header or additional headers after it.

Hopefully this is readable. Also I recommend "using namespace std;" wherever needed unless there's a reason to not do it.

Re: Before I get Much Further Into Development...

Posted: Tue Apr 14, 2009 3:12 pm
by MarauderIIC
On a different topic:

It is "good practice" to have accessors. This avoids member variables from being set to invalid values, and also controls whether or not a member variable is read-only.

For instance,

Code: Select all

class NewGame
{
public:
   float BodyFat;
   int BodyType;
   char Name[10];
   void GetName();
   void GetBT();
};
"Should be" at least something like

Code: Select all

class NewGame
{
private:
    float bodyFat;
    int bodyType;
    char name[10];
public:
    const char* getName();
    int getBT();
    void setBT(int to);
};

Code: Select all

void setBT(int to) {
    if (to < 0)
        return;
    bodyType = to;
}
Also body type should probably be an enum.
It is near-universal that "get" returns something an "set" assigns something. I noticed you defined getBT as a function that sets something above, just replace my setBT with it. Or rename it to something to do with user input. Actually NewGame should probably have an inputBodyInfo() function and all the bodyfat bodytype stuff should be in a class Body { }; and NewGame should contain a Body body;, or something.

Re: Before I get Much Further Into Development...

Posted: Tue Apr 14, 2009 3:16 pm
by dandymcgee
Please do me a favor and replace

Code: Select all

system("PAUSE");
with

Code: Select all

cin.get();
or a similar equivalent. If you need to ask why: http://www.gidnetwork.com/b-61.html ;)

Re: Before I get Much Further Into Development...

Posted: Tue Apr 14, 2009 3:58 pm
by davidthefat
dandymcgee wrote:Please do me a favor and replace

Code: Select all

system("PAUSE");
with

Code: Select all

cin.get();
or a similar equivalent. If you need to ask why: http://www.gidnetwork.com/b-61.html ;)
I wasnt gonna leave that in, I just did it to see if it displays things correctly, in the final one, I wont use it

Re: Before I get Much Further Into Development...

Posted: Tue Apr 14, 2009 4:05 pm
by davidthefat
Heres what I got so far, I didnt change alot but seems alot better than before.

MarauderIIC I understand what you mean, but havent implanted it yet

planning on moving all the attribute variable tos a "stat" class and use function arguments in the "get" functions

main.cpp

Code: Select all

#include "NewGame.h"
#include "Display.h"
#include "Game.h"

int main()
{
	MainGame Gm;
	Gm.Game();
	return 0;
}
Game.cpp

Code: Select all

#include "Game.h"

void MainGame::Game()
{
	int temp;
	NewGame NG;
	Display D;
	D.cShow("1=Load\t2=New Game\n");
	std::cin >> temp;
	if (temp == 2)
	{
		NG.NewGameLoop();
	}
	D.DisplayMenu(NG.Name, NG.BodyFat, NG.BodyType);
			

	system("PAUSE");
}
Game.h

Code: Select all

#ifndef Game_h
#define Game_h

#include "NewGame.h"
#include "Display.h"

class MainGame
{
public:
	void Game();
};
#endif
NewGame.cpp

Code: Select all

#include "NewGame.h"
void NewGame::GetName()
{
	std::cout << "Whats Your Name?\n";
	std::cin >> Name;
}
void NewGame::GetBT()
{
		std::cout << "What Body Type Are You?\n1 = Ectomorph\t2 = Mesomorph\t3 = Endomorph\n";
		std::cin >> BodyType;
		if (BodyType > 3 || BodyType < 1 )
		{
			std::cout << "WRONG NUMBER DUMBASS!\n";
			GetBT();
		}
		if (BodyType == 1)
		{
			BodyFat = 10;
		}
		if (BodyType == 2)
		{
			BodyFat = 15;
		}
		if (BodyType == 3)
		{
			BodyFat = 20;
		}

}
void NewGame::NewGameLoop()
{
	GetName();
	GetBT();
}
NewGame.h

Code: Select all

#ifndef NewGame_h
#define NewGame_h
#include <iostream>

class NewGame
{
public:
	float BodyFat;
	int BodyType;
	char Name[10];
	void NewGameLoop();
	void GetName();
	void GetBT();
};
#endif
Display.cpp

Code: Select all

#include "Display.h"

void Display::cShow(char toPrint[255])
{
	std::cout << toPrint;
}
void Display::iShow(int toPrint)
{
	std::cout << toPrint;
}
void Display::fShow(float toPrint)
{
	std::cout << toPrint;
}
void Display::DisplayMenu(char toPrint[255], float toPrint1, int BT)
{
	cShow("Name:");
	cShow(toPrint);
	
	if (BT == 1)
	{
		cShow("\nBody Type:Ectomorph");
	}
	if (BT == 2)
	{
		cShow("\nBody Type:Mesomorph");
	}
	if (BT == 3)
	{
		cShow("\nBody Type:Endomorph");
	}
	cShow("\nBody Fat:");
	fShow(toPrint1);
}
Display.h

Code: Select all

#ifndef Display_h
#define Display_h

#include <iostream>
#include "NewGame.h"

class Display
{
public:
	void cShow(char toPrint[255]);
	void iShow(int toPrint);
	void fShow(float toPrint);
	void DisplayMenu(char toPrint[255], float toPrint1, int BT);
};
#endif

Re: Before I get Much Further Into Development...

Posted: Tue Apr 14, 2009 4:08 pm
by dandymcgee
Looking much better. 8-)
davidthefat wrote: I wasnt gonna leave that in, I just did it to see if it displays things correctly, in the final one, I wont use it
I was just pointing it out since this thread was about good practices. IMHO, you shouldn't use it ever, not even temporarily. ;)

Re: Before I get Much Further Into Development...

Posted: Wed Apr 15, 2009 5:45 pm
by eatcomics
dandymcgee wrote:Looking much better. 8-)
davidthefat wrote: I wasnt gonna leave that in, I just did it to see if it displays things correctly, in the final one, I wont use it
I was just pointing it out since this thread was about good practices. IMHO, you shouldn't use it ever, not even temporarily. ;)
agreed ;) wow somehow I havn't seen this topic... it's got a looooot of code in it though :lol: