Menu State problem

So I basically have three classes I'm working with right now. State, MainMenuState (which is a child of State), and StateManager that has the job to switch between states.

When I call my MainMenuState in my main loop by itself (without going though the state manager) the buttons appear and draw like normal. But when I try to use my state manager nothing appears on the screen. No errors, but no buttons like before.

Knowing this, it's not the Button class or MainMenuState classes fault. At least, it probably isn't it might be the inhertence's fault but I'm not sure.

Here's the 3 classes -

State:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class State
{
protected:
	int stateId;
public:
	virtual ~State()
	{
	}

	virtual void Update(sf::RenderWindow& Window)
	{
	}
	virtual void Draw(sf::RenderWindow& Window)
	{
	}
};


MainMenuState:

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
34
class MainMenuState : public State
{
private:
	Button * buttonPlay;
	Button * buttonExit;
	Button * buttonSettings;
public:
	MainMenuState()
	{
		stateId = 0;

		buttonPlay = new Button("Play", sf::Vector2f(screenW / 2, 200), 30);
		buttonExit = new Button("Exit", sf::Vector2f(screenW / 2, 400), 30);
		buttonSettings = new Button("Settings", sf::Vector2f(screenW / 2, 300), 30);
	}

	~MainMenuState()
	{
	}

	void Update(sf::RenderWindow& Window)
	{
		buttonPlay->Update(Window);
		buttonExit->Update(Window);
		buttonSettings->Update(Window);
	}

	void Draw(sf::RenderWindow& Window)
	{
		buttonPlay->Draw(Window);
		buttonExit->Draw(Window);
		buttonSettings->Draw(Window);
	}
};


StateManager:

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 StateManager
{
private:
	std::vector<State> states;

	int currentStateId;
public:
	StateManager()
	{
		currentStateId = 0;

		MainMenuState menuState;
		states.push_back(menuState);
	}

	~StateManager()
	{
	}

	void NewCurrentState(int newStateId)
	{
		currentStateId = newStateId;
	}

	void Run(sf::RenderWindow& Window)
	{
		states[currentStateId].Update(Window);
		states[currentStateId].Draw(Window);
	}



};


> Button * buttonPlay;
unnecessary dynamic allocation
also, leak.

> std::vector<State> states;
object slicing.
I made the button a pointer because I'm planning to move these classes into headers/cpp files, and the button class doesn't have a constructer without paramaters. Do you think I should change that or would it be ok to keep the pointers? I changed it to delete all the pointers I made in my destructer.

Thanks for the reference to object slicing. I actually did this mistake before and asked a simiular question on here about it. I changed std::vector<Stack*> stacks; so that every stack will be a pointer now, and it works! I kind of understand why, but can you explain to me why in my situation? I never really grasped the concept of allocating memory - espiecally with base and child classes.
kong288 wrote:
I made the button a pointer because I'm planning to move these classes into headers/cpp files, and the button class doesn't have a constructer without paramaters.
Neither of these is a valid reason to use a pointer, unless you have some strange cyclic dependency?
kong288 wrote:
Thanks for the reference to object slicing. I actually did this mistake before and asked a simiular question on here about it. I changed std::vector<Stack*> stacks; so that every stack will be a pointer now, and it works! I kind of understand why, but can you explain to me why in my situation? I never really grasped the concept of allocating memory - espiecally with base and child classes.
Each element in the vector is of the type you specified in the template argument. If you're not careful, you can copy-construct a base class object from a derived class object. This is why the Clone Pattern exists.

Also, keep in mind that derived classes almost always use more memory than their base classes. Each element in a vector/array/etc. has the same size: the size of the sole type you specified.

You may also want to review the reason for making destructors virtual with inheritance.
Last edited on
I don't think I can just do this in my header:
Button button(param)

It never seemed to work in a header file if I put params into it.

Besides if I'm not careful, is the way I'm doing this "wrong"? It actually works perfectly right now and allthough my code is longer and a little more complicated in reading, it seems a lot better than what I was doing before.

I will. I was always told to do virtual ~() but I didn't really know why.

And should I put the actual game as a state as well? And then have game states for if a menu is open while the game is playing it could pop up and let the user choose something?


kong288 wrote:
I don't think I can just do this in my header:
Button button(param)

It never seemed to work in a header file if I put params into it.
Look up constructor initializer lists.
1
2
3
4
5
6
MainMenuState::MainMenuState()
: button1(params)
, button2(params)
, button3(params)
{
}
I'm not sure how to respond to the rest of your post.
Last edited on
Topic archived. No new replies allowed.