Skip to main content
GameDev.net gamedev.net
🔒 Locked

Global variable or pass as class constructor variable?

Started by Silent Dragon Feb 20, 2007 at 12:09 PM 16 replies 2k views
Original Post
Silent Dragon
Silent Dragon
I was wondering if which is the 'better' way of having access to the graphics class in my design as follows? Main class creates graphics class (specifically HGE class using the HGE engine) and sets it up Main class sets up Game class and passes the HGE created class Game class passes the graphics to the current state class (to draw whatever the state is, i.e. menu, credits, actual game) Then the state can pass the class down again.. and so on I hope this makes sense. I've read things against using global variables, yet passing the graphics class down each time is lots of repetative code. Thanks for any replies =]
Winegums
Winegums
If you make the graphics class a singleton, you could have a pointer to it within the games class.

If I understand your question correctly then this would eleviate a lot of redundant passing.
Emmanuel Deloget
Emmanuel Deloget
Quote:
Original post by Silent Dragon
I was wondering if which is the 'better' way of having access to the graphics class in my design as follows?

Main class creates graphics class (specifically HGE class using the HGE engine) and sets it up
Main class sets up Game class and passes the HGE created class
Game class passes the graphics to the current state class (to draw whatever the state is, i.e. menu, credits, actual game)
Then the state can pass the class down again.. and so on

I hope this makes sense. I've read things against using global variables, yet passing the graphics class down each time is lots of repetative code.

Thanks for any replies =]


But seems to be needed in your design anyway. The reason you were told that Globals Were Bad is that you can't rely on the state of a global variable - because you can't know how it was modifed before you use it. This is especially true in concurrent programming, when two threads may try to modify/use the same variable at the same time.

If you have concerns about having to pass the same object to all the classes of your class hierarchy, maybe you have another problem. Maybe you ask too much to the said class (the HGE class has too many responsabilities. To correct that, encapsulate it in smaller classes with at most one responsability), or maybe your child class don't really need to deal with this object. The solution you have to is refactor your code, in order to improve the locality of the HGE instance (ie store it only where you need it). Read on this site for more about refactoring.

Regards,
Emmanuel Deloget
Emmanuel Deloget
Quote:
Original post by Winegums
If you make the graphics class a singleton, you could have a pointer to it within the games class.

If I understand your question correctly then this would eleviate a lot of redundant passing.


I tried to answer very fast to avoid this "appeal to the singleton pattern" kind of answer, but was obviously beaten.

Washu deals with the same exact issue in his singletonitis article. (read about the sound manager and the graphics manager).

Regards,
Silent Dragon
Silent Dragon
Quote:
Original post by Emmanuel Deloget
Quote:
Original post by Winegums
If you make the graphics class a singleton, you could have a pointer to it within the games class.

If I understand your question correctly then this would eleviate a lot of redundant passing.


I tried to answer very fast to avoid this "appeal to the singleton pattern" kind of answer, but was obviously beaten.

Washu deals with the same exact issue in his singletonitis article. (read about the sound manager and the graphics manager).

Regards,



Why did you try and avoid it? (Edit: just read the Washu post and see "Graphics Manager:
This one is the one true legitimate Singleton.". I have never used singletons before, and I'm not convinced to try just yet. I just like to see all points of view)
Thanks for the refactoring link btw, it seems that the sources link doesn't work though, so Google it is.

[Edited by - Silent Dragon on February 20, 2007 1:49:04 PM]
ToohrVyk
ToohrVyk
A global variable has some good arguments for it, especially in quick throwaway prototype code where the emphasis is on writing non-extensible, non-maintained code to prove or disprove a point, and is then thrown away.

However, global variables are only a means to delay your decisions about dependency handling. If you don't intend to throw your code away next week, then chances are that you'll have to work on that dependency problem anyway. Even more so if you intend to perform testing, or ensure reusability of components. So, in a serious project, I would suggest making the graphics a parameter of the classes that require it.

I'd say that, while technically correct, your approach to the problem is wrong. You should not be "passing down" an instance to subclasses in an attempt to imitate a global variable: instead, you should "receive" an instance from somewhere in order to use graphics. In short, a class should have no knowledge about the code that's using it: only about its parameters and interface.

As for singletons, I don't see any reason to use one here, since there seems to be no requirement for "one instance only".

Sneftel
Sneftel
Quote:
Original post by Silent Dragon
Main class creates graphics class (specifically HGE class using the HGE engine) and sets it up
Main class sets up Game class and passes the HGE created class
Game class passes the graphics to the current state class (to draw whatever the state is, i.e. menu, credits, actual game)
Then the state can pass the class down again.. and so on
Why should the game class have access to the graphics class? I understand that you can't have the graphics of a game without a game to draw, but certainly you can have a game which runs without graphics.
Zao
Zao
Quote:
Original post by Winegums
If you make the graphics class a singleton, you could have a pointer to it within the games class.

If I understand your question correctly then this would eleviate a lot of redundant passing.


So let me get this straight. You propose that he should make a singleton out of the graphics class, so he can store a pointer to it? Why not just store a pointer or a reference to an regular instance of the graphics class where needed? No need to make a glorified global abomination.
To make it is hell. To fail is divine.
Silent Dragon
Silent Dragon
Quote:
Original post by Sneftel
Quote:
Original post by Silent Dragon
Main class creates graphics class (specifically HGE class using the HGE engine) and sets it up
Main class sets up Game class and passes the HGE created class
Game class passes the graphics to the current state class (to draw whatever the state is, i.e. menu, credits, actual game)
Then the state can pass the class down again.. and so on
Why should the game class have access to the graphics class? I understand that you can't have the graphics of a game without a game to draw, but certainly you can have a game which runs without graphics.



Well the game class doesnt need it, it needs it to pass to the member class (the state). I know thats a bad design, but I have a reason..
When I started I wanted to use a 2D game engine that had reasonable documentation and tutorials. I was hoping for cross platform, but the engine I found to have decent documentation and a couple of tutorials was HGE. When I tried to implement this I could only get it working by initiating HGE before the game class, where I wanted it to be initiated IN the game class. I could show you the code to make it clearer, but that might not help so I'll leave it out for now.

I haven't designed big projects before, this is basically my first big OO aimed project so it's bound to have flaws in the design. I appreciate all the help on these forums :p
Sneftel
Sneftel
Quote:
Original post by Silent Dragon
Well the game class doesnt need it, it needs it to pass to the member class (the state). I know thats a bad design, but I have a reason

"I know that's a bad design" should never be followed by "but I have a reason". "I know that's a bad design" should be followed by "so I'll change it". You mentioned wanting to initiate HGE "in the game class". Again: Why should the game class know about HGE?
Silent Dragon
Silent Dragon
Quote:
Original post by Sneftel
Quote:
Original post by Silent Dragon
Well the game class doesnt need it, it needs it to pass to the member class (the state). I know thats a bad design, but I have a reason

"I know that's a bad design" should never be followed by "but I have a reason". "I know that's a bad design" should be followed by "so I'll change it".


Thats basically the reason why I created this thread. Since its that class thats being 'passed down', its that part of the design i'm trying to change. So I DID follow it by "so I'll change it", but its just HOW to change it that I'm struggling with.

Quote:
Original post by Sneftel
You mentioned wanting to initiate HGE "in the game class". Again: Why should the game class know about HGE?


The game class shouldnt know about HGE. Essentially the game class needs to know about the current game state, the current player and game databases (such as the item database) (thats all it needs in the design so far)
Sneftel
Sneftel
Alright. So you can have a GameGraphics class which knows about a Game, and an Application or whatever which owns both of them. This is the "Model/View/Controller" paradigm, which you should Google.
Silent Dragon
Silent Dragon
Ok, I've looked into all the ideas given here. Based on things i've read about singletons, I've decided that a better design is more advantageous than a 'quick fix'.

After hitting the drawing board trying to redesign my class structure I'm stuck yet again.

When looking into the "Model/View/Controller" paradigm, I can see how it basically works, I just don't see how the view gets the details it needs from the model. I know that it has a direct link, but wouldn't a class something like an SDL_Surface need to be made? That way the model creates a surface instance that details whats to be drawn, then the view draws it? Have I missed the point of it?

Thanks for your patience

[Edited by - Silent Dragon on February 20, 2007 7:57:01 PM]
Sneftel
Sneftel
Quote:
Original post by Silent Dragon
When looking into the "Model/View/Controller" paradigm, I can see how it basically works, I just don't see how the view gets the details it needs from the model. I know that it has a direct link, but wouldn't a class something like an SDL_Surface need to be made? That way the model creates a surface instance that details whats to be drawn, then the view draws it? Have I missed the point of it?

You have some of the point. The big thing is that the model has NOTHING AT ALL TO DO WITH GRAPHICS. It doesn't even know that SDL exists. You could run the program without even creating a view and somewhere in the computer there'd be little guys running around shooting at you, even though you'd never even create a window.

The view does EVERYTHING related to graphics. It asks the model where the guys are, and the model tells it where the guys are, and the view loads geometry representing guys and uses OpenGL to draw that geometry.
Silent Dragon
Silent Dragon
Quote:
Original post by Sneftel
You have some of the point. The big thing is that the model has NOTHING AT ALL TO DO WITH GRAPHICS. It doesn't even know that SDL exists. You could run the program without even creating a view and somewhere in the computer there'd be little guys running around shooting at you, even though you'd never even create a window.

The view does EVERYTHING related to graphics. It asks the model where the guys are, and the model tells it where the guys are, and the view loads geometry representing guys and uses OpenGL to draw that geometry.


Hmm I see. I thought as much, but it's the small details that get me :p Such as, how does the View know what to draw? Like if you had a Character class it would have position and handle events like move and so on (which would be the model?) but when you load the character wouldnt you want to load the character image (which would then make it part of the view?). With that said, keeping the model and view seperated seems difficult. Even so if you managed it for the character, if the character intereacted with the map (say moved onto a different one) then the view would then again need to have the new details of the maps contents and the model would need the map events.

Having written this and thought more and more I possibly see a way, but it wouldnt be nice I don't think, if the model simply stored the filename for the data that the view needs (like map file or character image), but then that would require file i/o every frame, and thats rediculous, right?


I'm sorry for the repetative questions, and I really appreciate your time, it's just not fully clear to me how it is implemented...yet.

Thanks again
Sneftel
Sneftel
Quote:
Original post by Silent Dragon
how does the View know what to draw? Like if you had a Character class it would have position and handle events like move and so on (which would be the model?) but when you load the character wouldnt you want to load the character image (which would then make it part of the view?)

A common method is a parallel hierarchy. Suppose you had a Game, which itself had a bunch of Characters. That would be your model. Now in your view, you have a GameGraphics and a bunch of CharacterGraphics. Whenever you add a Character to your Game, GameGraphics hears about it (because it's registererd as a listener) and creates a new CharacterGraphics to go with it. The CharacterGraphics, in turn, is the "mini-view" for the "mini-model" consisting only of that character.

Quote:
if the character intereacted with the map (say moved onto a different one) then the view would then again need to have the new details of the maps contents and the model would need the map events.

I'm not sure what you're saying here. Assuming we're talking about something like an FPS, and the "map" is a level, the view displays whichever map is active. It gets the information about which map is active from the model. Whenever the model changes the active map, the view loads the geometry corresponding to the new active map.

Quote:
I'm sorry for the repetative questions, and I really appreciate your time, it's just not fully clear to me how it is implemented...yet.

No prob. It can be a lot to get your head around.
Silent Dragon
Silent Dragon
Quote:
Original post by Sneftel
A common method is a parallel hierarchy. Suppose you had a Game, which itself had a bunch of Characters. That would be your model. Now in your view, you have a GameGraphics and a bunch of CharacterGraphics. Whenever you add a Character to your Game, GameGraphics hears about it (because it's registererd as a listener) and creates a new CharacterGraphics to go with it. The CharacterGraphics, in turn, is the "mini-view" for the "mini-model" consisting only of that character.


Sorry for the rather late reply, been busy with Uni work among other things. So to implement the listener, would it be a seperate thread? That checks if a new sprite has been created every so often and then if it has then the graphics class can load the file and knows to display it.

Thats my thoughts on it, could be wrong..since its getting late

Silent Dragon
Silent Dragon
After rethinking the thread idea and throwing it out the window, I came up with a design that could possibly work, although I would appreciate input on how feasible and decent the design is..

// Drawable data base class. This is a bass class for things like Player, Enemy and also things like MapData, Image or other things that are drawn// This class DOESNT draw the image or player etc, it just is a data structureclass DrawableData {   protected char *drawableDataFile;   protected int x,y,z;public:   setDrawableDataFile(char* file) { /* set it*/ }   char *getDrawableDataFile() { /*get it*/ }   // Getters and setters for x,y,h here}// Then an example that would implement..the map data classclass MapData : DrawableData{   // Map data things...no drawing still}// Then we have a Application class, this is the main part of the programclass Application {    // In constructor set up Game class, then pass the game class to a new instance of Graphics class    // Every frame run Game.run() Graphics.draw(); (or something like, depending on the function names..}// Game classclass Game {   // Game class has one current state which is held in a private variable   getState()   setState()   run() { state.run(); }}// would have an enum for state types..// State classclass State {    private DrawableData[] data;   // Depending what happens in this state will determine what is in the drawable data list.     getDrawableDataList() {return data;}   run() { /* do stuff.. */ }}// Graphics classclass Graphics{    Private DrawableData[] curFrameData; // List of objects drawn in the last frame    private Drawable *curFrameDrawable;    private Game* game;    draw()    {        State gameState = game->getState();        DrawableData *newData = gameState->getDrawableDataList();        loadDrawableList(newData); //this will update the curFrameData list by checking if entries with the same filename exist,         //any that are new are added to the curFrameDrawableList (by loading the file and creating an instance of the        // relevant class that extends Drawable (different from DrawableData))       // also any old not needed instances can be deleted        // Now the data has been loaded from the files and new instances of Drawable classes have been made the screen can be drawn        //Cycle through and draw each entry in the Drawable list    }    loadDrawableList(DrawableData *newData) { /* do stuff.. */ }}// Drawable class would be similar to DrawableData but would have a draw() function that uses something like SDL to actually draw the object


I know that is alot to look through, but if anyone can comment on that design i would appreciate it.

Thanks,
SD

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.