Virtual Functions in a Class

D.V.D

Make a wish
Reaction score
73
Hello, I was looking at virtual functions and I was trying to use them to structure my gaming project to have the option of running multiple engines based on which was chosen upon startup or part way through with the use of a framework that gets overridden by the needed engine code. This would benefit not having to create a new visual studio project for every little graphics stuff I want to test out. The idea goes like this, I have a class that has the OpenGL engine running and it has virtual functions for rendering, or when a mouse is clicked, or when a keyboard event occurs, or any other standard glut functionality.
Code:
class GameFramework {
 
    public:
   
        virtual void OnMouseClick ();
        virtual void OnKeyboard ();
        virtual void OnRender ();
        //...etc
   
    private:
 
};
I have an object of this framework class created in the main.cpp function which executes the game loop and initializes the program. Now I want to have these functions get overwritten by some other game engines, but I don't want to have to specify which one gets overwritten in the code, but upon starting the program. So it would kinda be like a demo window pops up and asks you to choose which game to run out of a list of options, each one potentially overwritting the main frameworks functions but it isn't decided which one does so until I choose one in the demo program.
Code:
class GameFramework {
 
    public:
   
        virtual void OnMouseClick ();
        virtual void OnKeyboard ();
        virtual void OnRender ();
        //...etc
       
        void startup () {
            create window
            float chosen getinput();
            make class options[chosen] override class
        }
       
    private:
       
        std::vector <&GameEngine> options;
       
};
How would I do this because from my understanding, I'd have to do something like this:
Code:
class GameFramework :: Prespecified Game Engine {
 
    public:
   
        virtual void OnMouseClick ();
        virtual void OnKeyboard ();
        virtual void OnRender ();
        virtual void OnStartup ();
        //...etc
       
        void startup () {
            run OnStartup();
        }
       
    private:
       
        std::vector <&GameEngine> options;
       
};
Is there a way of getting around this? Im pretty sure there is, I just couldn't seem to figure it out.
 

camelCase

The Case of the Mysterious Camel.
Reaction score
362
Now I want to have these functions get overwritten by some other game engines, but I don't want to have to specify which one gets overwritten in the code, but upon starting the program.

I don't quite get what you're getting at..
You're going to have to specify which methods are overridden anyway..

That's the whole point of inheritance.
Code:
GameEngine* ge = nullptr;
int i = getInput();
switch (i) {
    case 0:
        ge = new GameEnginePacman();
        break;
    case 1:
        ge = new GameEngineMario();
        break;
    case 2:
        ge = new GameEngineSonic();
        break;
    default:
        //error
        return 0;
}
ge->run();
//run() continues until exit, in which case we exit the main loop
return 0;

If you don't want to override a method, you can choose not to. Just.. Simply don't.
You only HAVE to override methods that you specify as "pure virtual" or "abstract".
Code:
virtual void someMethod () = 0;

If you really want to do it like how I think you want to do it..
Code:
class GameEngine {
    public:
        void setMouseHandler (MouseHandler* handler);
        void setKeyboardHandler (KeyboardHandler* handler);
        void setRenderHandler (RenderHandler* handler);
 
        void run () {
            //Loop
                if (mouseHandler != nullptr) { mouseHandler->execute(); }
                if (keyboardHandler != nullptr) { keyboardHandler->execute(); }
                if (renderHandler != nullptr) { renderHandler->execute(); }
                //Sleep or sth
            //Endloop
        }
};
 

D.V.D

Make a wish
Reaction score
73
Sorry E3 was happening and I went completely off track. A bit off topic but man the way graphics have progressed in some games is outstanding! Especially seeing some of the fottage from ac4 and bf4 and the sony exclusives. Sucks for people like me who one day dream to program an engine like that even if it is impossible at this stage.

From your first example, Im having a bit of trouble understanding but would something like this be correct?

Code:
    struct GameEngine {
        public:
            virtual void OnMouseEvent ();
            virtual void OnKeyboardEvent ();
            virtual void OnRenderEvent ();
       
            void gameloop () {
                OnMouseEvent();
                OnKeyboardEvent();
                OnRenderEvent();
            }
    };
   
    struct Mario :: GameEngine {
        public:
            void OnMouseEvent () {
                ..Do stuff
            }
            void OnKeyboardEvent () {
                ..Do stuff etc.
            }
       
    }
   
    // struct Sonic, struct Pacman, etc.
   
    void main () {
        GameEngine* ge = nullptr; // Btw what is this? Is this just null?
        int i = getInput();
        switch (i) {
            case 0:
                ge = new Mario;
            case 1:
                ge = new Sonic;
            case 2:
                ge = new Pacman;
            default:
                return 0;
        }
        ge.gameloop();
        return 0;
    }

What's important to me is that no matter what game engine is running, it is all abstracted to the GameEngine struct so then I don't have to modify the stuff in the main function. Instead I only have to add the new game to the list if I want to add a new sonic or pacman game for example. Im very sure Im doing it wrong above because from what I understand, it works the other way for virtual functions. Rather than having all virtual structs go into the main struct, its the main struct that gets put into all the other structs that use him. Is there a way to do it the first way specified? (Im sorry its really hard for me to explain it so I'll post an example of the way I think its supposed to be, where as I want to reverse the order):

Code:
    struct GameEngine {
        public:
            virtual void OnMouseEvent ();
            virtual void OnKeyboardEvent ();
            virtual void OnRenderEvent ();
       
            void gameloop () {
                OnMouseEvent();
                OnKeyboardEvent();
                OnRenderEvent();
            }
    };
   
    struct Mario :: GameEngine {
        public:
            void OnMouseEvent () {
                ..Do stuff
            }
            void OnKeyboardEvent () {
                ..Do stuff etc.
            }
       
    }
   
    // struct Sonic, struct Pacman, etc.
   
    void main () {
        int i = getInput();
        switch (i) {
            case 0:
                Mario* ge = new Mario;
            case 1:
                Sonic* ge = new Sonic;
            case 2:
                Pacman* ge = new Pacman;
            default:
                return 0;
        }
        ge.gameloop();
        return 0;
    }
 

s3rius

Linux is only free if your time is worthless.
Reaction score
130
I think what you want to do is:

Code:
//This is your original game framework class
class GameFramework {
    public:
        virtual void OnMouseClick () = 0;
        virtual void OnKeyboard () = 0;
        virtual void OnRender () = 0;
        //...etc
   
        void startup () {
            create window
            float chosen getinput();
            make class options[chosen] override class
        }
   
    private:
        std::vector <&GameEngine> options;
};
 
class PacMan : public GameFramework{
    public:
        //Override functions
        virtual void OnMouseClick (){
            //Pacman doesn't use mouse, so nothing here
        }
        virtual void OnKeyboard (){
            if(key pressed was Down Arrow)
                pac.moveDownOneTile();
            if(key pressed was Up Arrow)
                ...
        }
        virtual void OnRender (){
            //render environment
            //render pac man
        }
     
    private:
        PacMan pac;
}
 
class SomeShooter : public GameFramework{
    public:
        //Override functions
        virtual void OnMouseClick (){
            if(mouse is over an enemy)
                //kill enemy
        }
        virtual void OnKeyboard (){
            //walking etc ..
        }
        virtual void OnRender (){
            //render environment
            //render enemies
            //render player
        }
     
    private:
        Player player;
        std::vector<Enemies> ..
        ..
}
 
//main function
void main(){
    GameFramework* game = new SomeShooter();
 
    while(true){
        if(keyboard was pressed) game->OnKeyboard();
        if(mouse was clicked) game->OnMouse();
        game->OnRender();
    }
}

But in the end you'll end up writing a ton of code again anyway. A comprehensive framework is much more sophisticated and much larger than that.
 

D.V.D

Make a wish
Reaction score
73
That seems to be what Im trying to do! Thanks Ill try it out. I understand its gotta be way more sophisticated and what not, but this is a start. Plus now I don't have to make a new project for every little demo I want to test out. Anyway's what would a comprehensive framework for games really need? You have an class for context, game and gameengine. Then if you want you could create a class for a standard forward and deferred render's that are part of game engine. Then you could include different techniques for each part of the render (lighting, reflection, depth pass, etc.). This helps mix stuff up and in theory, you can run a certain game and its assets with different techniques for lets say shadow mapping with the change of a constant or something like that. I have a long way to go before any of this stuff becomes the reality I want it to be, but if Im going to start, I thought having the framework finished first would help a lot in not having to redo code later on.
 

camelCase

The Case of the Mysterious Camel.
Reaction score
362
[ljass]nullptr[/ljass] is the type-safe version of the NULL macro.
Code:
#define NULL 0
class Class {};
 
int someMethod (int i);
int someMathod (Class* c);
 
int main () {
    Class* c;
    //The following are the same
    c = 0;
    c = NULL;
    c = nullptr;
 
    //The following shows the difference
    int i;
    i = 0; //Valid
    i = NULL; //Also valid
    i = nullptr; //Error
 
    someMethod(0); //someMethod(int)
    someMethod(NULL); //someMethod(int)
    someMethod(nullptr); //someMethod(Class*)
    return 0;
}
 

s3rius

Linux is only free if your time is worthless.
Reaction score
130
I thought having the framework finished first would help a lot in not having to redo code later on.

It won't :D
I started working on my own engine, GameSerf, like two years ago. Everytime I started a new project with this engine, I noticed that something was bad/missing. So I've rewritten everything several times. Nothing is as it was when I started.
After a while you get a basic grasp of what you actually need your engine to be able to, and how to implement it. I think that's best done via trying it out.

If you like to indulge in the topic, I have a nice resource.
Here's an excellent thesis about a OpenGL-based rendering engine. The first few pages are in German, but after that it's English.
Of course this is far beyond what you need for a small game engine, but in principle it's the same. And it gives nice insight into what a fully-fledged engine would look like if you were to focus on flexibility.
 

Accname

2D-Graphics enthusiast
Reaction score
1,462
I've given up on flexibility.
I tried to make my engine as flexible as possible but it took so damn much time i would have never finished my actual project.
Its sad but true.
 

D.V.D

Make a wish
Reaction score
73
It won't :D
I started working on my own engine, GameSerf, like two years ago. Everytime I started a new project with this engine, I noticed that something was bad/missing. So I've rewritten everything several times. Nothing is as it was when I started.
After a while you get a basic grasp of what you actually need your engine to be able to, and how to implement it. I think that's best done via trying it out.

If you like to indulge in the topic, I have a nice resource.
Here's an excellent thesis about a OpenGL-based rendering engine. The first few pages are in German, but after that it's English.
Of course this is far beyond what you need for a small game engine, but in principle it's the same. And it gives nice insight into what a fully-fledged engine would look like if you were to focus on flexibility.

Im looking through it now, complicated stuff :p but what I meant by a framework was never the complicated stuff they have here, but just something that ties in all the engines so I don't have to rewrite the main.cpp function to create the specified engine/game. It just seemed like an easier alternative to having new projects for each new technique/demo/tutorial I wanted to try out. Still, Ill give your pdf a read, maybe not all of it just because how long it is but to get an idea of what they're doing. If anything I might try implementing what they're doing this summer :D

I've given up on flexibility.
I tried to make my engine as flexible as possible but it took so damn much time i would have never finished my actual project.
Its sad but true.

Yeah, flexibility seems to be one of those extremely time consuming processes where having multiple people working on an engine starts to become extremely handy. We all want to program our own crysis graphics haha :p
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Varine Varine:
    How can you tell the difference between real traffic and indexing or AI generation bots?
  • The Helper The Helper:
    The bots will show up as users online in the forum software but they do not show up in my stats tracking. I am sure there are bots in the stats but the way alot of the bots treat the site do not show up on the stats
  • Varine Varine:
    I want to build a filtration system for my 3d printer, and that shit is so much more complicated than I thought it would be
  • Varine Varine:
    Apparently ABS emits styrene particulates which can be like .2 micrometers, which idk if the VOC detectors I have can even catch that
  • Varine Varine:
    Anyway I need to get some of those sensors and two air pressure sensors installed before an after the filters, which I need to figure out how to calculate the necessary pressure for and I have yet to find anything that tells me how to actually do that, just the cfm ratings
  • Varine Varine:
    And then I have to set up an arduino board to read those sensors, which I also don't know very much about but I have a whole bunch of crash course things for that
  • Varine Varine:
    These sensors are also a lot more than I thought they would be. Like 5 to 10 each, idk why but I assumed they would be like 2 dollars
  • Varine Varine:
    Another issue I'm learning is that a lot of the air quality sensors don't work at very high ambient temperatures. I'm planning on heating this enclosure to like 60C or so, and that's the upper limit of their functionality
  • Varine Varine:
    Although I don't know if I need to actually actively heat it or just let the plate and hotend bring the ambient temp to whatever it will, but even then I need to figure out an exfiltration for hot air. I think I kind of know what to do but it's still fucking confusing
  • The Helper The Helper:
    Maybe you could find some of that information from AC tech - like how they detect freon and such
  • Varine Varine:
    That's mostly what I've been looking at
  • Varine Varine:
    I don't think I'm dealing with quite the same pressures though, at the very least its a significantly smaller system. For the time being I'm just going to put together a quick scrubby box though and hope it works good enough to not make my house toxic
  • Varine Varine:
    I mean I don't use this enough to pose any significant danger I don't think, but I would still rather not be throwing styrene all over the air
  • The Helper The Helper:
    New dessert added to recipes Southern Pecan Praline Cake https://www.thehelper.net/threads/recipe-southern-pecan-praline-cake.193555/
  • The Helper The Helper:
    Another bot invasion 493 members online most of them bots that do not show up on stats
  • Varine Varine:
    I'm looking at a solid 378 guests, but 3 members. Of which two are me and VSNES. The third is unlisted, which makes me think its a ghost.
    +1
  • The Helper The Helper:
    Some members choose invisibility mode
    +1
  • The Helper The Helper:
    I bitch about Xenforo sometimes but it really is full featured you just have to really know what you are doing to get the most out of it.
  • The Helper The Helper:
    It is just not easy to fix styles and customize but it definitely can be done
  • The Helper The Helper:
    I do know this - xenforo dropped the ball by not keeping the vbulletin reputation comments as a feature. The loss of the Reputation comments data when we switched to Xenforo really was the death knell for the site when it came to all the users that left. I know I missed it so much and I got way less interested in the site when that feature was gone and I run the site.
  • Blackveiled Blackveiled:
    People love rep, lol
    +1
  • The Helper The Helper:
    The recipe today is Sloppy Joe Casserole - one of my faves LOL https://www.thehelper.net/threads/sloppy-joe-casserole-with-manwich.193585/
  • The Helper The Helper:
    Decided to put up a healthier type recipe to mix it up - Honey Garlic Shrimp Stir-Fry https://www.thehelper.net/threads/recipe-honey-garlic-shrimp-stir-fry.193595/

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top