Polymorphism, Classes, Inheritance, Enumerators etc
Polymorphism, Classes, Inheritance, Enumerators etc
Hello everyone,
as you may well know I am a n00b at C++ and I wanted to sort some stuff out and I thought I may as well figure this out here. How much is to much. How should I restrict my code within functions, should I have a function for everything I can think of or limit it to purpose.
Also in my classes should my constructors deal with the creation of the irrlicht device etc, or should I use the constructor to declare variables etc and save a boot function to declare the device etc.
Should I use a object of my class to run my game, GameManager Game. Well I think this one answers itself. But should I use the object to call each function like
Game.boot();
Game.play();
Or like I do currently should I just use
Game.boot();
and then
boot() when it ends goes straight to the play();
I have heard about base classes and classes steaming of this via inheritance how does this exactly work, I know I may have father, child classes or Human and john. but how can this relate to game programming, for example how can I get this to work with a game manager (or should I even do this?) e.g Class GameManager // Base Class, Class GameManagerAudio.
Should I even use polymorphisms in Game Coding, it seems to be great at confusing people or should I limit it to only really obvious situations like
void calculate (int a, int b);
void calculate (float a, float b);
What is the best way to manage the game loop? What I do at the moment is declare a enumerator in my GameManager called States make a instance of this State GameState and then in my GameLoop, if GameState == MENU then goto the menu function.
or if GameState == MENU_AUDIO the goto menuaudio() and within that function at the end of its purpose i have Gamestate == Menu so the sound plays then goes into the menu.
How does the inheritance work behind the base class principle, and what is dimond inheritance, I know that its when the inheritance links back up in a diamond but is this a problem or a good thing?
Should I use arguments within my functions within a game, and how and why?
Thanks for all the help, I know its a lot of n00b but someone has to beat it out of me, I am trying but answering this may be like running my n00b out onto a highway and hitting him with a mac truck.
Thanks!
as you may well know I am a n00b at C++ and I wanted to sort some stuff out and I thought I may as well figure this out here. How much is to much. How should I restrict my code within functions, should I have a function for everything I can think of or limit it to purpose.
Also in my classes should my constructors deal with the creation of the irrlicht device etc, or should I use the constructor to declare variables etc and save a boot function to declare the device etc.
Should I use a object of my class to run my game, GameManager Game. Well I think this one answers itself. But should I use the object to call each function like
Game.boot();
Game.play();
Or like I do currently should I just use
Game.boot();
and then
boot() when it ends goes straight to the play();
I have heard about base classes and classes steaming of this via inheritance how does this exactly work, I know I may have father, child classes or Human and john. but how can this relate to game programming, for example how can I get this to work with a game manager (or should I even do this?) e.g Class GameManager // Base Class, Class GameManagerAudio.
Should I even use polymorphisms in Game Coding, it seems to be great at confusing people or should I limit it to only really obvious situations like
void calculate (int a, int b);
void calculate (float a, float b);
What is the best way to manage the game loop? What I do at the moment is declare a enumerator in my GameManager called States make a instance of this State GameState and then in my GameLoop, if GameState == MENU then goto the menu function.
or if GameState == MENU_AUDIO the goto menuaudio() and within that function at the end of its purpose i have Gamestate == Menu so the sound plays then goes into the menu.
How does the inheritance work behind the base class principle, and what is dimond inheritance, I know that its when the inheritance links back up in a diamond but is this a problem or a good thing?
Should I use arguments within my functions within a game, and how and why?
Thanks for all the help, I know its a lot of n00b but someone has to beat it out of me, I am trying but answering this may be like running my n00b out onto a highway and hitting him with a mac truck.
Thanks!
Programming Blog: http://www.uberwolf.com
Oh also I am doing a course at AIE on Game programming and reading C++ for dummies and I have STL Programming from the ground up. In other words I am trying.
Programming Blog: http://www.uberwolf.com
-
FuzzYspo0N
- Posts: 914
- Joined: Fri Aug 03, 2007 12:43 pm
- Location: South Africa
- Contact:
Im gonna try reply best i can, lol
I never restirct my code i let it run freeHow should I restrict my code within functions, should I have a function for everything I can think of or limit it to purpose.hah, i think limiting your code to purpose is logical, having a function
can be useful, because it has a set purpose.Code: Select all
add(a, b) { return a+b; }
but having a function likethats not the best option, you have to code repetitively to get a result which, with one extra function can make your code a lot easier to create, read and manage.Code: Select all
doMaths() { int tmp = ga+gb; tmp *= 5; int tmp1 = gc + gd; }
This doesnt mean seperate EVERY single thing into its own function, for example. in my Project SCR i am using the following functions for the menu :
Its not a seperate class, as it is part of the g_game class already (see, the menu is what spawns the game, in my opinion it is somewhat a parent of whatever the game is running at the time. All aspects of most games spawn from the main menu)
Now, i have a g_game::Init(fullscreen,sound,driver,etc) function
That handles HOW i want the game to initialise. Either way it inistialises ALL the game code initialises there, including the menu. That doesnt mean 100 lines of random code... i Have a function called g_m_loadMenuAssets() which loads the menu, a g_m_resetMenu() to make sure all animations and stuff are set right, and i call g_game::run() which manages the game state as you speicified (case GS_MENU , GS_INGAME, GS_LOADING)
I dont know if the above helps, but im hoping it sheds SOME light on seperation of code from each other.
This all depends on what you like. I prefer to make my variables public to my game class.. so i can always refer to it as g_game->device g_game->driverAlso in my classes should my constructors deal with the creation of the irrlicht device etc, or should I use the constructor to declare variables etc and save a boot function to declare the device etc.
It makes sense because its global, all ALL aspects of your main game code can see it. My GUI class falls under the game code, but atm is external so i say fs_gui::Init(ittlichtdevice device) which gives me acces to every feature of my game engine, with one passed variable. Passing your device around to external classes is how you manage to use the variables within your game code, such as driver (device->getVideoDriver())
If you use it like that , it makes a lot more code so inside my fsgui class i make a IrrlichtDevice* fsgui_globaldevice; and within my gui::init code i just say fsgui_globaldevice = device; which comes from the g_game class.
Also,
its up to where u initialise your device and variables, most logically i would use the function that u already have made for that, g_game::Init(fullscreen,sound,driver,etc)
This means you have all the information you need(you can also read the setttings file, for resolution and other settings) apllying it all to the new device you are creating.
this speaks for itself as u say. my main.cpp code only has the following concept :Should I use a object of my class to run my game
init loads all the relevant stufff for the game to begin (ie the menu) and then runs the main loop, checking states for what to render (and i use a function for that too)Code: Select all
#include "game_engine.h" void main() { g_game* game; game->init(); //my init class has a blank init as well (explained next time) game->run(); game->shutdown(); }
I guess, i would more easily exaplin with code. Let me get SCR code tidyed and commented and i will upload it to show you how i wud administrate the game states in a state machine that is simplistic for games, but extendable for most things.
I dunno if im rambling or helping, i had a spare second. lolI think its a matter of understanding what the point of inheritance is. A simple example as u said is human.inheritance
EVERY single human on this planet, has a mass. they also have a weight.
now i need a Male class, for the male human, he is a human, so he also has a weight and mass. This means i dont have to go and REcreate all the same functions i can inherit them from my human class.Code: Select all
class human{ public : int getMass(); int getWeight(); private: int weight; int mass; }
so,a blank class? it actually has stuff in it , for example.Code: Select all
class male : human { public: private: }
male* John;
now i may call John->getWeight() and John->getHeight() because they are human after all.
It makes sense to use inheritance for most things, the trick is figuring out what the base class has that EVERY single element below it will have as well. Thats where polymorphism and overriding functions comes in too.
Example : A male has a height to weight ratio, based on his age. A females height to wieght ratio is different (it uses a different constant). For example
Its not polymorphism its just important understanding it.Code: Select all
int human::calculateHeightWeightRatio() { //some fake calculation for a standard object, such as a plank, with a weight and height. return weight/height; } int male::calculateHeightWeightRatio() { //now a male has a different formula to compensate for muscles and body fat, which dont affect the height so its a very specific formula but the base class needs the same function return (weight/height) * massindex * 1.2; //all fake stuff }
Polymorphism has some great uses, ESPECIALLY in games... here is a VERY simple use of polymorphism and overloading.
Its a simple and crap example, but your code is a lot more functional then having 50 classes for game asset loading, when u only have one overloaded function it can work for all version of the function.Code: Select all
function loadAssets(); //this function loads assets according to the function u are calling void loadAssets(guiname,guisize,position); //loads a std GUI layout void loadAssets(mapname,mapsize,playercount); //loads a multiplayer map for the game
Thanks for all the help, I would love to see that source you were talking about, I am looking for a finished structred game. I might look at the old irrWizard source as well.
um one other quick question,
Public, Private and Protected. I know that Public is available to everything within it and that protected is available to friends of that class but what is the purpose and use of this.
Also in my GameManager.h it looks like this
In my Int Main its a simple as you discussed, Game.boot(); or Game->boot();
Now, what is currently happening is the game goes to boot and it sets the values for all the devices. And then it goes to a loader which loads all the texutres and sounds. Then it goes to a intro screen and then a menu.
The Enumerators are used as IF statments within the gameloop e.g
if (GameState == MENU)
{
menu();
}
But is this wrong to do seeing as the Menu() uses gui->addImage and gui->addButton.
In other words should I have more than one game loop for different things. And should I have 2 devices one for the menu and one for the game?
Thanks
um one other quick question,
Public, Private and Protected. I know that Public is available to everything within it and that protected is available to friends of that class but what is the purpose and use of this.
Also in my GameManager.h it looks like this
Code: Select all
// GameManager.h
#ifndef H_GAMEMANAGER
#define H_GAMEMANAGER
#include "Library.h"
// Irrlicht Namespace
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
// IrrKlang Namespace
using namespace irrklang;
// Game Manager Class
class GameManager: public IEventReceiver
{
public:
enum State // The States of the Game
{
INTRO,
INTRO_AUDIO,
MENU,
MENU_AUDIO,
MENU_SUPPORT,
MENU_CREDITS,
CREDITS_AUDIO,
GAME_AUDIO,
GAME,
EXIT
};
State GameState; // Initialize the Game
// Declare Irrlicht Device and Environment
IrrlichtDevice* device;
ISceneManager* smgr;
IGUIEnvironment* gui;
IVideoDriver* driver;
ISoundEngine* engine;
// Audio Declarations
ISoundSource* IntroAudio;
ISoundSource* MenuAudio;
ISoundSource* GameAudio;
ISoundSource* CreditsAudio;
//Button Declaration
IGUIButton *Play_Button;
IGUIButton *Support_Button;
IGUIButton *Options_Button;
IGUIButton *Credits_Button;
IGUIButton *Quit_Button;
IGUIButton *Menu_Button;
// Font Declaration
IGUIFont* font_gui;
// Texture Declaration
ITexture* logo_texture;
ITexture* menu_texture;
ITexture* credits_header;
ITexture* menu_header;
// Game Function Declaration
//System Functions
void boot(void);
void loader(void);
void exit(void);
// Loaders
void audioloader(void);
void textureloader(void);
// Game Gui Functions
void logo(void);
void logoaudio(void);
void menu(void);
void menusupport(void);
void menuoptions(void);
void menucredits(void);
void menuaudio(void);
void creditsaudio(void);
//Game Functions
void game(void);
void mapspawn(void);
void movement(void);
void gameaudio(void);
void hud(void);
void ai(void);
void gameloop(void);
bool OnEvent(const SEvent& event)
{
if (event.EventType == EET_GUI_EVENT)
{
s32 id = event.GUIEvent.Caller->getID();
switch(event.GUIEvent.EventType)
{
case EGET_BUTTON_CLICKED:
if (id == 101)
{
GameState == GAME_AUDIO;
break;
}
if (id == 102)
{
break;
}
if (id == 103)
{
break;
}
if (id == 104)
{
GameState = CREDITS_AUDIO;
break;
}
if (id == 105)
{
device->drop();
engine->drop();
break;
}
if (id == 106)
{
GameState = MENU_AUDIO;
}
break;
default:
break;
}
}
return false;
}
};
#endif
Now, what is currently happening is the game goes to boot and it sets the values for all the devices. And then it goes to a loader which loads all the texutres and sounds. Then it goes to a intro screen and then a menu.
The Enumerators are used as IF statments within the gameloop e.g
if (GameState == MENU)
{
menu();
}
But is this wrong to do seeing as the Menu() uses gui->addImage and gui->addButton.
In other words should I have more than one game loop for different things. And should I have 2 devices one for the menu and one for the game?
Thanks
Programming Blog: http://www.uberwolf.com
Actually friends can even access private data ;-)dejai wrote: um one other quick question,
Public, Private and Protected. I know that Public is available to everything within it and that protected is available to friends of that class but what is the purpose and use of this.
One purpose is encapsulation. In short you can say - the less access a class has from the outside the easier will it be to use it.
You simply don't have to look anymore at anything protected or private when using the class. Another reason you try to have as little public functions as possible is that by making functions public you sort of tell everyone (including yourself) that this functions are ok to use from everywhere. So as soon as you change one of those it means every place where you used the function needs also to be changed.
Another purpose is access control. For example you see often that all variables are protected and have get/set functions to access them. It's disputed if this is a good thing to do, but the reason is that every access to those variables now goes through a point which you control. So if you make for example your 'GameState' private and use getter/setters you could make sure that you change the menu correspondingly each time the gamestate is changed. You will no longer accidentally change it and forget to update the gui.
For a start I would say use private for everything unless you can't avoid to make something protected/public.
You should only have one gameloop and also only one device.dejai wrote: In other words should I have more than one game loop for different things. And should I have 2 devices one for the menu and one for the game?
Thanks
You can use update functions if you need more things which run all the time. Like UpdateGui(), UpdateSound(), etc. which are called in your gameloop.
One general hint: Make small classes.
Having one big class GameManger which does everything is a bad idea in the long run. You wouldn't need classes at all in this case.
The most obvious thing to do in your case is to split off the gui and the sound. Just put everything belonging to the gui in one class and everything about sound in another. Then create two objects for those classes in your mainclass. Later on you will probably want to split classes even further. For example you usually have one class for every dialog.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
This is just my way of doing it, but I start building fences when too many sheep are in the pasture so to speak. If I write similar code more than once, I make a function. If things start getting messy, I make a class to get rid of some of it. I think the inheritance thing is overdone, but you really need it when you put similar objects in the same container.
Your number one concern is not writing a game bigger than you can finish. As you write more games, you'll develop a reusable system.
Your number one concern is not writing a game bigger than you can finish. As you write more games, you'll develop a reusable system.
Ok thanks for all the help, I have been looking at the irrwizard framework, and to Start of I think I will have the following classes:
CGame(Base Class)
CGameGUI
CGameAudio
But Should I make another class for the Game itself, and should I use that extra class for my loop?
so CGame..
Thanks for the help
I am looking at the irrWizard framework and this is certainly helping me 
CGame(Base Class)
CGameGUI
CGameAudio
But Should I make another class for the Game itself, and should I use that extra class for my loop?
so CGame..
Thanks for the help
Programming Blog: http://www.uberwolf.com
Nice topic... let me have a go at it too
I'm programming a game myself, it's my very first game and it's gonna be an rpg (yeah I know, a quite "big" project, but I don't expect to finish it anytime soon anyways) and after a LOT of thinking I came up with this idea:
In my main.cpp my game has the initialization for everything (yeah I know you might disagree, since you all have uber small mains which call game classes, but what's the point in using a totally different class and just have the main with 3 lines of code? let's use it I say!
) and then inside the main I initialize a fixed number of "scene" classes, all of a different type inherited from the MotherScene class. This MotherScene class is just a pure virtual class with the most basic virtual function every scene needs (like virtual void run(); or virtual void initScene(); or virtual void loadNextScene(); ). Then I have another huge (yes it's huge but that's how it's gonna be) class called MainDatabase class, it keeps the basic informations regarding EVERY scene in the game, so it will keep the coordinates for the character, the number of items in the inventory, but also the last FMV played and the number of enemies killed for example. But most important of all, it keeps track of the current scene playing (using a currentSceneID variable).
Then in my main, as I said, I have one object for every class, then cycle through a switch inside a loop (the Game loop) which checks using the database object to see the scene I am into in that moment, then enters in the appropriated draw loop and handles the appropriated events. When a scene changes (using the loadNextScene(); function) it changes the currentSceneID variable inside MainDatabase class, so the following loop will change too.
I know that is a weird way of doing it (at least in my opinion, after reading your methods) but that's the most versatile thing I could think of all by myself, there are probably better ways of doing it but I already started this way
what do you think?
Also if I want to add scene types I can just add that in the main and go through a check in the loop, without having to modify huge parts of codes... and for the savegames I can just store the MainDatabase object into a file and then load it, it will resume the game from the part I had saved it
opinions?
I'm programming a game myself, it's my very first game and it's gonna be an rpg (yeah I know, a quite "big" project, but I don't expect to finish it anytime soon anyways) and after a LOT of thinking I came up with this idea:
In my main.cpp my game has the initialization for everything (yeah I know you might disagree, since you all have uber small mains which call game classes, but what's the point in using a totally different class and just have the main with 3 lines of code? let's use it I say!
Then in my main, as I said, I have one object for every class, then cycle through a switch inside a loop (the Game loop) which checks using the database object to see the scene I am into in that moment, then enters in the appropriated draw loop and handles the appropriated events. When a scene changes (using the loadNextScene(); function) it changes the currentSceneID variable inside MainDatabase class, so the following loop will change too.
I know that is a weird way of doing it (at least in my opinion, after reading your methods) but that's the most versatile thing I could think of all by myself, there are probably better ways of doing it but I already started this way
what do you think?
Also if I want to add scene types I can just add that in the main and go through a check in the loop, without having to modify huge parts of codes... and for the savegames I can just store the MainDatabase object into a file and then load it, it will resume the game from the part I had saved it
Every class has its own data stored in it when I'm using it, it's just that when I need to destory (aka change) every scene to start another scene, I didn't know where to put those important information (like if I open the item menu, then when I exit it I should go back where I was -the town map for example- and that info can't be found in the map scene class because it's been destroyed already so i just take the info from the database and store them into the mapscene class). That way I can just have one object for every scene class, without making multiple object of the same class (like, If i have 5 fmvs, I don't have to make 5 MovieScene objects, I just allocate and play them when I need, all in the same MovieScene object).MasterGod wrote:@Morgawr: Having MainDatabase class to save info about every object in the scene is not a good opinion IMO but every object should save information bout itself.
Making a "MainDatabase" class for save game and such could be better but still should be designed smartly..
Obviously yes, the MainDB class will be structured in the right way, else it'd just be a huge mess
Now it sounds more useable, good thinkingMorgawr wrote:Every class has its own data stored in it when I'm using it, it's just that when I need to destory (aka change) every scene to start another scene, I didn't know where to put those important information (like if I open the item menu, then when I exit it I should go back where I was -the town map for example- and that info can't be found in the map scene class because it's been destroyed already so i just take the info from the database and store them into the mapscene class). That way I can just have one object for every scene class, without making multiple object of the same class (like, If i have 5 fmvs, I don't have to make 5 MovieScene objects, I just allocate and play them when I need, all in the same MovieScene object).MasterGod wrote:@Morgawr: Having MainDatabase class to save info about every object in the scene is not a good opinion IMO but every object should save information bout itself.
Making a "MainDatabase" class for save game and such could be better but still should be designed smartly..
Obviously yes, the MainDB class will be structured in the right way, else it'd just be a huge mess
