Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Two screens, but the same window  (Read 3655 times)

0 Members and 1 Guest are viewing this topic.

Suggs

  • Newbie
  • *
  • Posts: 4
    • View Profile
    • Email
Two screens, but the same window
« on: January 30, 2013, 09:31:30 pm »
Hi,

The title makes very little sense but I couldn't think of any other way to describe my problem. I was doing a fair bit of C++ and I know pretty much the basics of most things (except pointers, those things are just so confusing for me), and I decided that I wanted to start doing graphical things. And SFML was right for me

Any way, I've been writing my game for about 3 or 4 days on and off, and I've run into several problems. I'm making functions, eg. my mainmenu() and game() functions. And they both include the header which is the window creation  (the sf::RenderWindow class). And what I want ideally to happen, is when you launch the .exe the main menu will appear, then if you click the start button it'll take you to the game. Without having to close the exe and launch another one.

I'm pretty sure this is possible but you never know.

SO in summary, my two problems are: How do I get two different functions that use the same window but in order. As I said earlier, you launch the game and then main menu comes up, click a button then bada bing badaboom you're playing the game.
And my seconds problem is how do I make a button (how ever, only answer this if you can be bothered, I'm pretty sure there are answers for this, but I haven't done much searching).

My Window.h
Code: [Select]

sf::RenderWindow window(sf::VideoMode(1920,1080),"Alpha");



And then I have the two functions that use that. And should I post the code for them or not? For my problem in question I don't think I need to but if it would help you understand what I'm blabbering on about then I will.

Both of my two functions
Code: [Select]
int mainmenu() and int game() use the Window.h include file so that they both use the same window, and they also both have a
Code: [Select]
while (window.isOpen()) in them.
I think that's my problem.


Any way, any help would be much appreciated and just ask if you need any more information :)

Suggs

  • Newbie
  • *
  • Posts: 4
    • View Profile
    • Email
Re: Two screens, but the same window
« Reply #1 on: January 30, 2013, 09:32:08 pm »
Forgot to mention, I'm using SFML 2.0

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: Two screens, but the same window
« Reply #2 on: January 30, 2013, 09:43:27 pm »
I was doing a fair bit of C++ and I know pretty much the basics of most things
I can assure you, you know nearly nothing about C++, not because you read the wrong thing, but because C++ is extremely complex and even after years of working with it, you can still learn something new every day. ;)
If you care to expand your knowledge, here is a good starting point. :)

As I said earlier, you launch the game and then main menu comes up, click a button then bada bing badaboom you're playing the game.
One often refers to it as state manager. Google will already tell you quite a lot about it and if you want to see an example, my SmallGameEngine could be one. :)

And my seconds problem is how do I make a button.
You can go from very basic to hard core. If you're game makes extensive use of GUI elements, you might want to take a look libraries that potentially work with SFML (see here).
For the most basic thing, you take a sf::RectangleShape and when the mouse position is within the rectangles shape bounding box, you highlight the 'button' and if you then detect a mouse press, you trigger an action.

Both of my two functions
Code: [Select]
int mainmenu() and int game() use the Window.h include file so that they both use the same window [...]
You should definitely read up on classes, it's the most powerful and central thing in C++. ;)

I'd also suggest to use the file ending .hpp, so you get a matching pair for C++ (.cpp/.hpp) and for pure C (.c/.h). ;)

Btw. if you post code use the code=cpp tag and if you want to post inline code use the tt tag.

Forgot to mention, I'm using SFML 2.0
An post edit would've been better... ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Two screens, but the same window
« Reply #3 on: January 30, 2013, 09:52:15 pm »
I use that approach(I might post it on the wiki or somewhere sometime..):
        edy::core::StateManager app;
        app.pushState(edy::core::State::Ptr(new edy::state::MenuState()));//push some first state
        app.mainRun();
Write your own PointerPack.h and *.cpp and your own states to that interface.
#pragma once
#include "PointerPack.h"
namespace edy{
        namespace core{
                class State
                {
                public:
                        virtual void run(PointerPack& pack)=0;
                        virtual ~State()=0{};
                        typedef std::unique_ptr<State> Ptr;
                };
                class StateManager
                {
                public:
                        void mainRun();//main function that runs top state
                        void pushState(State::Ptr state);//no need to play with raw ptr here either
                        void popTop(int amount=1);//=1 for convenience of removing 1 state
                        void leaveBottom(int amount=0);//=0 for convenience of closing up
                        std::size_t getStatesCount()const;
                        PointerPack& getPack();
                private:
                        std::vector<State::Ptr> m_Stack,m_DelStack;
                        PointerPack m_PointerPack;
                };
        }
}
#include "StateManager.h"
namespace edy{
        namespace core{
                void StateManager::mainRun()
                {
                        m_PointerPack.m_Manager=this;
                        while(!m_Stack.empty())
                        {
                                m_DelStack.clear();
                                m_Stack.back()->run(m_PointerPack);
                        }
                }
                void StateManager::pushState(std::unique_ptr<State> state)
                {
                        m_Stack.push_back(std::move(state));//i liked no std::move version more i think..
                }
                void StateManager::popTop(int amount)
                {
                        for(int i=0;i<amount;++i)
                        {
                                m_DelStack.push_back(std::move(m_Stack.back()));
                                m_Stack.pop_back();
                        }
                }
                void StateManager::leaveBottom(int amount)
                {
                        popTop(m_Stack.size()-amount);
                }
                std::size_t StateManager::getStatesCount()const
                {
                        return m_Stack.size();
                }
                PointerPack& StateManager::getPack()
                {
                        return m_PointerPack;
                }
        }
}
To not waste space I init everything just for scope of the run function using that template:
#ifndef EE_INITLOCK_H_INCLUDED
#define EE_INITLOCK_H_INCLUDED
//raii class to call init when constructed and uninit when leaving scope, for states, cleaner than abc with
//such functions to override and a class to call these two virtuals, in theory faster, leads to no repetition
//thatd happen if every state defined own lock to do exact same thing without virtuals
namespace edy{
        namespace sup{
                template <class T> class InitLock
                {
                public:
                        InitLock(T * target):m_Target(target)
                        {
                                m_Target->init();
                        }
                        ~InitLock()
                        {
                                m_Target->uninit();
                        }
                private:
                        T * m_Target;
                };
        }
}
#endif
Quote
I'd also suggest to use the file ending .hpp, so you get a matching pair for C++ (.cpp/.hpp) and for pure C (.c/.h). ;)
Who cares.. ::)
Back to C++ gamedev with SFML in May 2023

Suggs

  • Newbie
  • *
  • Posts: 4
    • View Profile
    • Email
Re: Two screens, but the same window
« Reply #4 on: January 30, 2013, 09:53:08 pm »

One often refers to it as state manager. Google will already tell you quite a lot about it and if you want to see an example, my SmallGameEngine could be one. :)


Thanks, that was my main problem. I had no idea what that sort of a thing would be called, it's hard to google things if you don't have a clue what it is you're supposed to google.

But when I said, I know a fair bit of everything, I didn't really mean that. I know how to use the basics (classes, functions, vectors etc etc..), and I can make simple-ish programs.
But you can never stop learning C++ (well you can, but you know what I mean) :b

Thanks for your help :)

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Two screens, but the same window
« Reply #5 on: January 31, 2013, 06:28:32 am »
Exploiter what do you think about my manager class, I'd not mind some input.
Back to C++ gamedev with SFML in May 2023

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: Two screens, but the same window
« Reply #6 on: January 31, 2013, 11:56:38 am »
Exploiter what do you think about my manager class, I'd not mind some input.
Although your PointerPack class is missing and I can give you some feedback on the provided code.

From the technical point it seems to be working good, i.e. I didn't see any mistakes, but I didn't test it.
From a code design perspective one can still change a few things.

The interface of the state manager is not very nice imho, personally I'd use something more like this:
            void run();//main function that runs top state
            void push(State::Ptr state);//no need to play with raw ptr here either
            void pop(int amount=1);//=1 for convenience of removing 1 state
            void leave(int amount=0);//=0 for convenience of closing up
            std::size_t count()const;
            PointerPack& pack()

You're missing const correctness in your state manager as well (const std::size_t, const int amount, ...).

Then for the state's destructor (virtual ~State()=0{};), I'm not even sure if you can define a function as pure virtual and then give it a body anyways. :-\

m_Stack.push_back(std::move(state));//i liked no std::move version more i think..
Don't be afraid of the use of std::move, it might seem a bit unintuitive in the beginning, but it's the right way to go. ;)

for(int i=0;i<amount;++i)
Always use unsigned int if your index can't get negative.
Also don't be afraid to use spaces every now and then, it will make your code much easier to read.

As I said, I don't know how you've implemented the PointerPack, but m_PointerPack.m_Manager=this; shows, that you've got a public member variable, which in nearly all cases is a bad thing and on top of that it's a pointer. A probably better way, would be to pass the deferenced this pointer to the constructor of the pointer pack, which internally holds a reference on the manager. Then you can provide access to the manager, with any kind of function.
Or wait, does pointer pack actually mean, a struct of raw pointers? :o
Well that'd be a lazy way around designing a nice engine. ;D
I mean you can do it in such a way (if you can't think of any nicer way), but use a proper class with the right safety mechanisms around it.

As for your InitLock, I've no idea what it's used for, but it seems highly like a hack and the fact that you rely on init and uninit functions doesn't sound good at all. Every class has its constructor and destructor, there's no need to define pseudo c-/d-tors and then use an InitLock to simulate the otherwise normal behavior. Besides the illogical handling, it'd guess that you could prevent quite a few compiler optimizations and make it easier for a user to wrongly use your classes. Just use the constructor and destructor of your classes instead. ;)
« Last Edit: January 31, 2013, 11:58:32 am by eXpl0it3r »
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Two screens, but the same window
« Reply #7 on: January 31, 2013, 05:34:16 pm »
Quote from: The FRex From The Past
Exploiter what do you think about my manager class, I'd not mind some input.
:-X :-X Right.. :-X :-X
Quote
shows, that you've got a public member variable
Friendship. ;D
Quote
You're missing const correctness in your state manager as well (const std::size_t, const int amount, ...).
No one does such 'const corectness' to built in types. Not STL, not SFML.
Quote
The interface of the state manager is not very nice imho, personally I'd use something more like this:
I'd rather be explicit enough to never be in doubt what my classes do.
Quote
Then for the state's destructor (virtual ~State()=0{};), I'm not even sure if you can define a function as pure virtual and then give it a body anyways. :-\
That's normal but only for destructors and shows intent clearly, it's also only way to make abc without any other pure virtal functions(not that I need that here but still shows intent clearly).
Quote
Just use the constructor and destructor of your classes instead. ;)
States get constructed and destructed at completely different times than time of calling init and uninit.
Top state can use that in it's run() to add gui elements, load textures and graphics, open files ect.
Quote
Don't be afraid of the use of std::move, it might seem a bit unintuitive in the beginning, but it's the right way to go. ;)
It causes bizzare errors when it's missing.
Quote
A probably better way, would be to pass the deferenced this pointer to the constructor of the pointer pack, which internally holds a reference on the manager. Then you can provide access to the manager, with any kind of function.
That's impossible with pack as member, init lists can't use 'this' pointer.
Quote
Well that'd be a lazy way around designing a nice engine. ;D
Not really:
namespace edy{
        namespace core{
                class StateManager;
                class PointerPack
                {
                public:
                        PointerPack();
                        sf::RenderWindow& getRenderer();//to clear, draw and display
                        sfg::Desktop& getGUI();//let's call desktop GUI, it's kind of most important element,ect.
                        sfg::SFGUI& getSFGUI();//in case we _really_ need it, probably not..(?)
                        StateManager& getManager();//to allow state changes
                        void drawGUI();//shortcut to avoid awkward contraptions and using sfg::sfgui
                        bool pollEvent(sf::Event& eve);//shortcut to not pass all events to gui maually
                        //get non gui event?? -nah? can use renderer for that
                private:
                        sf::RenderWindow m_RenderWindow;//our render window, safe in the claws of raii
                        sfg::SFGUI m_SFGUI;//as above
                        sfg::Desktop m_Desktop;//..
                        StateManager * m_Manager;//yes, RAW pointer, don't worry, this thing is allocated on the stack in main..
                        friend class StateManager;//we need manager's 'this', no need to expose methods to do that
                };
        }
}
« Last Edit: January 31, 2013, 05:37:36 pm by FRex »
Back to C++ gamedev with SFML in May 2023

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: Two screens, but the same window
« Reply #8 on: January 31, 2013, 05:47:13 pm »
No one does such 'const corectness' to built in types. Not STL, not SFML.
Well I don't care what others do. ;)

States get constructed and destructed at completely different times than time of calling init and uninit.
Top state can use that in it's run() to add gui elements, load textures and graphics, open files ect.
A class should be fully initialized after calling the constructor. ;)

It causes bizzare errors when it's missing.
Use clang, then you'll get nice errors. ;D

That's impossible with pack as member, init lists can't use 'this' pointer.
True
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Two screens, but the same window
« Reply #9 on: January 31, 2013, 05:54:59 pm »
Quote
Well I don't care what others do. ;)
Are you joking? There's no point in making built in types passed by copy const and const reference costs more or same to pass as int and adds the cost of fetching the value through it.
Quote
A class should be fully initialized after calling the constructor. ;)
I'd then have menu sfg::Window floating around all the time instead of just when menu state is in controll because it's added and removed in init and uninit.
Back to C++ gamedev with SFML in May 2023

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Two screens, but the same window
« Reply #10 on: January 31, 2013, 05:59:04 pm »
States get constructed and destructed at completely different times than time of calling init and uninit.
This leads to the question why you can't call them in constructor and destructor ;)

I know sometimes it's annoying to construct an object only when one has enough information to initialize it completely, and sometimes it's not possible at all. But in general, dependencies become much clearer if they are initialized completely, and in order. Same for the destruction, one should not have the possibility to forget cleanup functionality.

By the way, what is exactly the task of your PointerPack class? It holds GUI and render window, draws, manages states, polls events... Looks like there are too many responsibilities, which is also indicated by the generic name "PointerPack" due to lack of specific functionality. It is also badly encapsulated, instead of returning non-const references you could directly make the attributes public.

Well I don't care what others do. ;)
FRex is right here. Top-level CV qualifiers for parameters and return types have nothing to do with const correctness. See here for a detailed explanation.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Two screens, but the same window
« Reply #11 on: January 31, 2013, 06:06:56 pm »
Quote
It is also badly encapsulated, instead of returning non-const references you could directly make the attributes public.
I don't know if I'll leave the privates there or change it later so I just made these methods which will always work and fetch whatevers properly. I might add const overloads if I run into use case.
Quote
By the way, what is exactly the task of your PointerPack class?
It's a convinence class so that run doesn't look like (sfg::SFGUI& sfgui,sfg::Desktop& gui,StateManager& manager,sf::RenderWindow& renderer) and the draw gui and poll event just avoid contraptions like
pack.getSFGUI().Display(pack.getRenderer());
while(pack.getRenderer().pollEvent(eve)
{
pack.getGUI().HandleEvent(eve);
//..
}
vs.
pack.drawGUI();
while(pack.pollEvent(eve))
{
//..
}
Quote
This leads to the question why you can't call them in constructor and destructor ;)
Menu state would then always cause it's window to appear. And it must be on bottom of the stack. That's the point of this class, getting screens on top of each other and letting top one do the work and relinquish controll to ones below or add new ones when it's done.
Quote
manages states
It doesn't do that.

Thanks for the input guys.
« Last Edit: January 31, 2013, 11:58:58 pm by FRex »
Back to C++ gamedev with SFML in May 2023