Best way to provide access to objects in multiple layers of parent classes.

Ok, this may not be the best title but let me explain what I mean:

I have multiple classes, something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class GameState
{
	private:
		Graphics& _gfx;
		Player _player;
	public:
		GameState(Graphics& gfx) :_gfx(gfx){
		}
		void Render(){
			_player.Render();
		}
};
class Player
{
	private:
		Sprite _sprite;
	public:
		Player(){
		}
		void Render(){
			_sprite.Render();
		}
};
class Sprite
{
	public:
		Sprite(){
			// NEEDS access to Graphics object, to create texture etc
		}
		void Render(){
			// NEEDS access to Graphics object to draw etc
		}
};


Basically, Sprite needs access to the gfx object that is an aggregate in(of?) GameState (or the owner of GameState). (Is this the correct terminology?)
First it needs it in the constructor and second in Render().
Right now I am using super ugly global static accessors, like Graphics::GetInstance(). But I've read multiple times that this is bad and ugly and now I'm trying to refactor my code.
Would it be better to pass a reference to every object that is needed in the constructor, and keep it stored, like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class GameState
{
	private:
		Graphics& _gfx;
		Player _player;
	public:
		GameState(Graphics& gfx) :_gfx(gfx), _player(_gfx){
		}
};
class Player
{
	private:
		Graphics& _gfx;
		Sprite _sprite;
	public:
		Player(Graphics& _gfx) :_gfx(gfx){
		}
};

Or just pass it into every function that needs it? Like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class GameState
{
	private:
		Player _player;
	public:
		GameState(){
		}
		void Render(Graphics& _gfx){
			_gfx.DoStuff();
			_player.Render(_gfx);
		}
		void CreateNewTexture(Graphics& _gfx){
			_gfx.CreateNewTexture();
		}
};

Or is there another way?
Last edited on
Why do you have 3 classes, all with a render() function? I don't think I understand entirely how you're trying to go about this, but IMO you should have something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

class Player
{
     //stuff
     Sprite sprite;
}

class Sprite
{
     //sprite stuff
}

class GameState
{
     void Render(Sprite* sprite);
}


To render an object you really only need to pass a pointer to the Sprite class onto your GameState class... Render(Sprite* sprite) would then access the relevant members of the class, probably some information about the location and dimensions of the pixels on the sprite sheet, the screen position you'd like to display the sprite on, whether the sprite is rotated, etc.

I think this solution is nice because you don't need a bunch of overloaded functions to render different objects, e.g. the player's sprite, AI enemies' sprites, and the sprite for the current level could all be rendered by the same function.

Then you could have something like:

1
2
3
4
5
std::vector<Sprite*> spritesinscope;
for(int i = 0; i < spritesinscope.length(); i++)
{ 
     gamestate.render(spritesinscope[i]);
}


By the way, I am just a hobbyist working on a game of my own for fun and to bolster my programming skills a bit. This is a solution that I've come up with, since I encountered basically the same crisis that you're having right now. This may not be the optimal solution, but it's less cluttered than it could be I think.
Last edited on
Hmm yeah, this is my first big project and I have no real clue how to do this correctly, so I'm kind of just experimenting and learning everything through trial and error. Since this project has been going on for about 2 years, a lot of my older code is absolutely horrible and I'm trying to clean it up a bit :)

Anyway, regardless of how the rendering is done, the thing I'm trying to figure out is, if a heavily "nested" object NEEDS to access something further "up", what would be the best way to do so?
If I do it like you suggested, player might have another thing attached, like a weapon, and the weapon might have some kind of accessory, and that class would then still need to access GameState (or a dedicated Renderer class), to call it's Render function.
That's just an example, I might have even more convoluted hierarchies later on, who knows :)

If I do it like you suggested, player might have another thing attached, like a weapon, and the weapon might have some kind of accessory, and that class would then still need to access GameState (or a dedicated Renderer class), to call it's Render function.


I think you have it backwards; classes that contain a Sprite that needs rendering don't access GameState, GameState contains a Render(Sprite* sprite) function that renders any type of sprite, whether it belongs to an enemy, player controlled character, etc. Then you have a list of all the sprites that need rendering, and the members of the list are fed into the render function.


Anyway, regardless of how the rendering is done, the thing I'm trying to figure out is, if a heavily "nested" object NEEDS to access something further "up", what would be the best way to do so?


I'm too novice of a programmer to think about things this abstractly. Can you come up with a specific example?


Hmm yeah, this is my first big project and I have no real clue how to do this correctly, so I'm kind of just experimenting and learning everything through trial and error.


I think this is the best way to learn. I am a grad student in a non-computer related field but I figured it would help me to learn some programming on the side. I originally tried via books and MIT opencourseware, but didn't fully appreciate the topics or retain much of that information. It was only when I jumped into actually writing programs as a hobby that I started to learn a lot, and quickly.
Last edited on
But how would the player class add its sprite to the GameStates render list? Wouldn't it somehow need to access it to call gameState.AddSprite(mySprite) or something?

1
2
3
4
5
6
7
8
9
class Player
{
	private:
		Sprite sprite;
	public:
		Player(GameState& gameState){
			gameState.AddSprite(&sprite);
		}
}


Can you come up with a specific example?

I tried to provide one in my first post, but I don't know how to illustrate it more clearly. Never learned UML or anything like that.
I think of classes/objects kind of like folders.
http://imgur.com/9YS1bW8
So StateManager would "contain" an instance of GameState which in turn contains an instance of Level, which in turn contains instances of Enemies, which would then maybe want to query the level for collision info or something.

I'm probably approaching this in a completely backwards way, it could probably be done a lot better but that's not the point :)
What if an object deep down the "hierarchy" (don't know what else to call it) needs to know the size of the window, to display some text at the center of the window or who knows what? Window does have functions Window::GetWidth() and Window::GetHeight() but to access them inside of a Enemy object, a reference or pointer would need to get passed aaaall the way "down".

By the way, if anyone can tell me the correct terminology for what I'm trying to explain, please go ahead, I'ts hard trying to explain things without the correct words :)
Last edited on
Topic archived. No new replies allowed.