1
\$\begingroup\$

I'm creating my first game engine and I want help with organizing the Setup(), Update() and Draw() functions in the correct way.

Here is how my main() function looks like

/* BEGIN main() Function */
int main(int argc, char *argv[])
{
    prepareSetting(&settings);

    initEngine();

    setup();

    // Main loop

    while (!done)
    {
        update();
        draw();
    }

    SDL_Quit();
    return 0;
} /* END main()*/

The above approach requires me to declare the shared variables as global, which I think is not a good thing to do.

I was thinking about creating a ENGINE class which contains the setup(), update() and draw() functions and inheriting it. libcinder use this kind of approach. So should I use classes or leave them as it is. What is the best way to organize those functions?

What approach is used by professionals in the industry?

\$\endgroup\$
  • 2
    \$\begingroup\$ "Best" is highly subjective, depends on what you're trying to do. Please add some information regarding what exactly it is that you need (supported platforms, renderers, expected usage workflow and so on). \$\endgroup\$ – snake5 Dec 26 '15 at 14:32
  • \$\begingroup\$ I'm doing a similar work. I'm using global variables, mostly grouped into std::maps. There's no need to create a class for it... \$\endgroup\$ – Xriuk Dec 26 '15 at 14:42
1
\$\begingroup\$

Look into Entity component system ( https://en.wikipedia.org/wiki/Entity_component_system ) and similar Object Oriented Programming paradigms.

This can be done in C++, C, assembly, or just about any languages. I've included an example in plain C further down showing one way how OOP & virtual functions can be done in C, but C++ was designed to do this stuff for you.

The idea as applied to your situation is you have a list of objects and each object has a creation (setup/constructor) function, an update function, a draw function, and a destroy function (destructor).

And your main loop calls the update and draw functions of all active objects in the list.

So you have a base class / struct which declares the virtual functions (or function pointers in C) :

class EntityBase
{
public:
  virtual ~EntityBase() {}
  virtual void Update() {}
  virtual void Draw() {}
};

And then derived classes which override those functions:

class Bob : public EntityBase
{
public:
  // bob variables here
  int energy;

  void Bob() {
      energy = 10;
  }

  void ~Bob() {
    // clean up
  }
  void Update() {
    // update bob
  }
  void Draw() {
    // draw bob
  }
};

And your main loop can call the Draw & Update functions of all your objects as EntityBase without knowing the details.


in plain C it would be something like:

typedef struct EntityBase_ {
    void (*Destroy)(struct EntityBase_ *me);
    void (*Update)(struct EntityBase_ *me);
    void (*Draw)(struct EntityBase_ *me);
} EntityBase;

and creating an object Bob would be like:

typedef struct Bob_ {
    EntityBase base;

    // bob variables here
} Bob;

void Bob_Destroy(struct EntityBase_ *me){
    Bob *bob = (Bob *)me;
    // clean up code here

    free(me);
}

void Bob_Update(struct EntityBase_ *me){
    Bob *bob = (Bob *)me;

    // update bob here
}

void Bob_Draw(struct EntityBase_ *me){
    Bob *bob = (Bob *)me;

    // draw bob here
}


EntityBase *CreateBob()
{
    Bob *bob = (Bob *)malloc(sizeof(Bob));
    bob->base.Destroy = &Bob_Destroy;
    bob->base.Draw = &Bob_Draw;
    bob->base.Update = &Bob_Update;

    // initialize bob variables here

    return &(bob->base);
}

the main loop in C would do something like:

EntityBase *eb = entity_pointer_array[i];
eb->base.Update(eb);
eb->base.Draw(eb);
\$\endgroup\$
  • \$\begingroup\$ I opted for this solution and it is working great in my engine loop. Thanks for this awesome example code. \$\endgroup\$ – rajiv Dec 28 '15 at 5:02
0
\$\begingroup\$

Well, I would modify the main loop as follows:

while(!done)
{
    update();
    draw();
    present();
}

The "present" method is so the main loop synchronizes with the display's refresh rate. In that way, your game is optimal. Otherwise, you could be drawing frames that will never be seen by the player, which is a waste of CPU and GPU cycles.

An added benefit is that your game will run at a 60 fps.

That is what I did when I created my game engine.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.