About using tgui and game states

Started by desocupado, 02 October 2015, 19:09:02

desocupado

Hello.

I'm begginer programmer, this might be more of a programming question than tgui specific, but please bear with me a bit.

What would be the best way to use tgui and game states?

My plan was to create a Game_State_Manager class, a Game_State class and specific Game_State derived classes, like Battle_Menu, Options, Inventory, etc.

The Game_State objects would be contained (and managed) by the Game_State_Manager class.

My idea was to pass a pointer of the tgui::Gui gui object created on the main() function to the Game_State_Manager, all the way to the derived classes. And in each derived class I would add the widegts necessary to the gui object. Upon exiting each game state, I would remove all the widgets from the gui object and add the ones from the next game state.

But I stumbled upon the widget declaration

tgui::Button::Ptr new_game_button(gui);

gui there is not a pointer, it's asking me for the actual object.

If I pass the object by copy, instead of using a pointer, then the gui object who is actually being asked to draw stuff (the one on the main function) won't actually receive the widgets, and thus won't draw anything.

I tried passing a reference instead of a pointer, but the compiler is not letting me store the reference in a variable inside Game_State_Manager, for some reason, it complains that I have to initialize references in the constructor initialization list (I have to confess I don't know what it's talking about :) )

I hope I was sufficiently clear, and I would like suggestions on how to proceed with the game states

I also would lke some clarification on what happens here: "tgui::Button::Ptr new_game_button(gui);" I checked the documentation, and it's a typedef for a sharedptr for a Button. Ok, but why does it need that gui parameter? Can anybody explain what's happening in a more detailed fashion?

texus

Quotegui there is not a pointer, it's asking me for the actual object.
The solution is actually very simple:
Code (cpp) Select
tgui::Button::Ptr new_game_button(*guiPtr);

Since the constructor takes a reference to a gui it won't even be copied in that line.

QuoteI checked the documentation, and it's a typedef for a sharedptr for a Button
You either checked the wrong documentation or you misinterpreted it. In v0.7-dev it is indeed a normal std::shared_ptr, but in v0.6 it is a typedef to my own custom smart pointer class.

Quotewhy does it need that gui parameter?
Constructing a widget goes in 3 steps (although you only need 2 lines):
(1) Constructing the widget (just executing the constructor, no theme/skin is loaded at this point)
(2) Loading the widget (specifying how the widget looks)
(3) Adding the widget to the gui

In tgui 0.6 and earlier, step (1) and (3) were done together, while step (2) is done with the load function. It is because (3) is done that the gui parameter is needed.
Code (cpp) Select
tgui::Button::Ptr button(gui);
button->load("TGUI/widgets/Black.conf");


In v0.7-dev I have changed the way widgets are loaded so that (1) and (2) happen together while (3) is a seperate step. Here it is more clear that you would just have to use '->' instead of '.' when gui is a pointer.
Code (cpp) Select
tgui::Button::Ptr button = theme->load("button");
gui.add(button);


I recommend v0.7-alpha2 for new projects btw, many things have been improved since v0.6.

Quotethe compiler is not letting me store the reference in a variable inside Game_State_Manager, for some reason, it complains that I have to initialize references in the constructor initialization list (I have to confess I don't know what it's talking about :) )
The constructor of a class consists of two parts: the initializer list and the constructor body. Before the body of the constructor is executed, all members of the class have already been initialized (although plain types like int are just random values). The reference has to already refer to a variable during this initialization step, it is already too late when the body of the constructor is executed. So it has to happen in the initializer list of which you find an example below (notice the ':' after the constructor).
Code (cpp) Select
class Test
{
public:
    Test(int& i);

private:
    int x;
    int y;
    int& z;
}

Test::Test(int& i) :
    x(i), // Give x the value of the variable i
    z(i) // Make z a reference to the variable i
{
}


Variable y is not mentioned in the initializer list, it has received default initialization. Since it is an int its value is undefined, but if it were a class then its default constructor (constructor that takes no parameters) would have been called.

Note that when a class has a reference as member, it becomes impossible to make copies of instances of that class. So using a pointer instead of a reference is sometimes better.

desocupado

Thank you very much! :D

I'll start using the 0.7 version.