Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I have a problem with designing classes for my game which I create.

In my app, there is:

  • class CGame which contains all the information about game itself, e.g. screen width, screen height, etc. In the main() function I create a pointer to CGame instance.
  • class CGUIObject which includes fields specifying it's position and draw() method, which should know how to draw an object according to screen size.
  • class CGUIManager which is a singleton and it includes a list of CGUIObject's. For each object in a list it just calls draw() method.

For clarity's sake, I'll put some simple code:

class CGame
{  
   int screenWidth;
   int screenHeight;
};

class CGUIObject
{
   CPoint position;
   void draw();     // this one needs to know what is a screen's width and height
};

class CGUIManager   // it's a singleton
{
   vector<CGUIObject*> guiObjects;
   void drawObjects();
};

And the main.cpp:

CGame* g;

int main()
{
   g = new CGame();

   while(1)
   {
      CGUIManager::Instance().drawObjects();
   }

   return 0;
}

Now the problem is, that each CGUIObject needs to know the screen size which is held by CGame, but I find it very dumb to include pointer to CGame instance in every object.

Could anyone, please, tell me what would be the best approach to achieve this?

share|improve this question
2  
void draw(int screenWidth, int screenHeight). Keep it simple. –  ccxvii Nov 21 '12 at 15:14

2 Answers 2

up vote 1 down vote accepted

There are a few decent options:

  1. As stated by ccxvii. Pass the width/height of the canvas to CGUIObject::draw();
  2. Pass your CGame object to the draw()
  3. Make CGame a singleton
  4. Redefine what CGame is and store graphics information in something called CGraphicsManager.

But yeah.. keep it simple for now, I'd go with #1 or #2.

share|improve this answer

I certainly advocate Fabien & ccxvii's advice to keep it simple and passing values to the draw() method is certainly a very logical approach for something small.

In the case of a larger more complex game, you usually have some windows system that helps in abstracting away the OS's windowing implementation. If some other system needs to know if the game window gets resized, it adds a listener that can be used to notify those interested when that happens.

struct IWindowListener {
  virtual void OnWindowResized(IWindow* window);
};

class WindowManager {
public:
  void AddListener(IWindow* window, IWindowListener* listener);
  void RemoveListener(IWindow* window, IWindowListener* listener);

  ListenerList& getListeners(IWindow* window);
};

class Window : public IWindow {
public:
  Window(WindowManager* owner) : mOwner(owner) { }
  void AddListener(IWindowListener* l) { mOwner->AddListener(this, l); }
  void RemoveListener(IWindowListener* l) { mOwner->RemoveListener(this, l); }

  // some method that fires when window gets resized by OS
  // This notifies all listeners who have interest.
  void WindowResizeFinished() {
    ListenerList& listeners = mOwner->getListeners(this);
    ListenerList::iterator start = listeners.begin();
    ListenerList::const_iterator end = listeners.end();
    for(; start != end; ++start)
      (*start)->OnWindowResized(this);
  }
};

class GUIManager : public IWindowListener {
public:
  void OnWindowResized(IWindow* window) {
    mWidth = window->GetWidth();
    mHeight = window->GetHeight();
  }
};

// Somewhere in your Game's initializing code
mWindowManager = new WindowManager();
mGUIManager = new GUIManager();

mGameWindow = mWindowManager->CreateWindow("My Game", 800, 600, WNDPOS_CENTERED);
mGameWindow->AddListener(mGUIManager);

This allows you to apply things like Separation of Concerns and Single Responsibility Principals to keep your code clean and separated into logical modules.

Again, keep it simple to start is important but realize there are some nice design patterns using the observer pattern shown above that can really make your code look elegant and clean and remain modular, extendable, and easy to maintain.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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