Sign in to follow this  
filipe

Class design

Recommended Posts

Hello there. I have recently made my first DirectX game, a pong clone, by working on top of a tutorial. In the rush to get things working, I didn't organize things into classes, and just added global variables (which I understand is not recommended) and stuffed other data into the original DX window class from the tutorial. Now I'm trying to design a class structure to put everything neatly into, but I'm having trouble with the linkage between my Window class, which handles Win32 and DirectX, and my Game class, which handles logical game data and the state (which is an enumeration). I'm thinking of giving the Window class a pointer to the Game class so it can access the game state, but I'm not sure about this. Any suggestions or advice?

Share this post


Link to post
Share on other sites
you could extern your class object, so other files could use it.

//Aclass.cpp
class A
{
int a;
public: A(int a_){ a = a_; }

};
extern A a_class;

//main.cpp

A a_class(2);

Share this post


Link to post
Share on other sites
Does your window class handle the actual drawing?

Either way, the graphics code (and especially the window managment code) should not know about the different game states.

You should look into the MVC (Model-view-controller) design pattern which is created to solve this problem by separating the game mechanics from the rendering. The pattern divides your system into three different parts, the model, controller and the view. The controller controls (e.g. trough key presses) the model (which contains the game play code) and the view renders the model.

Oh, and while tnutty's advice will work, you would end up with global data, which is what you're trying to avoid. ;)

Share this post


Link to post
Share on other sites
Tried virtual inheritance?

class A{}; //put 'globals' in here

class B: virtual A{};
class C: virtual A{};

//this class obtains a copy of B, C, and ONE copy of A.
//changes to A made in B are reflected in C
class D: public B, public C{
};


shared data between classes, no globals.
I dont know if this is the design you want to take, but it is nifty to know about, for example,

class Window{};

class shared{
protected: Window window;
};

class graphics: virtual shared{};
class input:virtual shared{};
class sound:virtual shared{};
class game:public graphics, public input, public sound{};

in this case all of our utility classes have access to the window.

Virtual inheritance design can get tricky you need to think it out well.

[Edited by - nickak2003 on July 23, 2009 3:19:11 PM]

Share this post


Link to post
Share on other sites
Quote:

shared data between classes, no globals.

This is not really a situation where inheritance is desirable at all. Furthermore, while the objects in the shared base class are not globals in the C++ sense, they are still globals in every other sense. You have slightly different ways to control access to them, but they still suffer the same fundamental downsides.

This is not a good approach.

Quote:

I'm thinking of giving the Window class a pointer to the Game class so it can access the game state, but I'm not sure about this. Any suggestions or advice?

I would do it the other way around, since the Game is a higher level entity than the Window (you'd want to use the same Window, which presumably is where your window-handling and perhaps rendering is handled, in a different game). Pass the Window object (by reference) to the Game object when you construct it. This makes your dependency between Game/Window explicit and clear. For example

int main() {
Window window( "My Game Window", 800, 600 ); // Or whatever.
Game game( window );

game.Run();
}

Share this post


Link to post
Share on other sites
I thought the downside of globals was lack of access control -- and I had thought that explicit access control through inheritance mechanisms sorted that out -- maybe not.

I have been using diamonds and multi-layered diamonds for sometime and thought that they were not bad - why is this a bad approach?


class Window{};

class CommonComponents{
public: CommonComponents(){}
private: CommonComponents{ Window window1){}
friend class Game;

public: Window window;
};

class Graphics: virtual CommonComponents{}
class Input: virtual CommonComponents{}

class Game: Graphics, Input, virtual CommonComponents{
public: Game():CommonComponents( Window(800,600) ){}
};


teehee

[Edited by - nickak2003 on July 24, 2009 2:15:16 PM]

Share this post


Link to post
Share on other sites
Quote:

I thought the downside of globals was lack of access control

One of. Arguably the biggest.

Quote:

and I had thought that explicit access control through inheritance mechanisms sorted that out

If you're not programming in an OO fashion, it can.

If you are, it is "sorting the issue out" at the cost of abusing inheritance within the OO paradigm. Inheritance should represent is-a relationships in general, and the relationships expressed should semantically make sense in the object model. You're not using inheritance here to convey a sane is-a relationship in the object model (although you can make appropriate class naming decisions to make the resulting English statement seem sane, it -- like the common "square is-a rectangle" example -- is typically bad OO). You're just using it as a crude hack to implement access control; a better way would be constructor or even setter DI (I dislike setter DI in general though, personally).

In general one should favor composition over inheritance; in this case there are better ways to control your dependencies than abusing inheritance.

Furthermore, you're still allowing the global property to taint your dependencies, propagating them down into systems that may not need them. You're restricting access a little better from complete global access, sure, but you're inheriting the globals into extremely high-level systems, so you've still got a similar kind of dependency bleed.

Quote:

I have been using diamonds and multi-layered diamonds for sometime and thought that they were not bad

In fact, diamonds in the inheritance graph are considered quite bad. There's a reason the pattern is called the "deadly diamond," the "dreaded diamond," or the "diamond problem." It's ugly, it produces bloated, confusing object layouts, forces you to use oft-misunderstood aspects of the language (virtual inheritance), and often is symptomatic of very poor OO design choices (as in your example).

Certainly there are use-cases for them. This isn't one of them; certainly not for a beginner.

[Edited by - jpetrie on July 24, 2009 5:08:20 PM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this