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

Author Topic: Switching between states  (Read 2186 times)

0 Members and 1 Guest are viewing this topic.

Wolff

  • Newbie
  • *
  • Posts: 22
    • View Profile
Switching between states
« on: August 10, 2018, 02:00:24 pm »
I had no idea how to summarise the problem in the title so I'll try better here.
I'm making something that looks like a menu of sorts.
In the first screen you choose a location and it operates when boolean variable loc_chosen is false. If you choose one and press enter it changes to true.
Then while loc_chosen is true another block of instructions can be executed in which you choose one of two options and when you press enter another boolean variable job_chosen changes from it's initial false to true. Then another block of instructions can be executed.

Outside of the loop is code for showing each "screen".
So when loc_chosen is false you can change between options, if you choose one the screen is grayed out and another set of options appear for loc_chosen being true.

That works fine but when I adden another boolean variable - job_chosen, that should change into true only after choosing an option on a previous screen everything went wrong.
It suddenly displays the last screen and somehow along the way job_chosen changes to true before I make that choice.
The moment I press enter on the first screen it immediately skips over next block of instructions and changes job_chosen to true. I've only just started using a debugger so I can't really locate the problem. It seems like the moment loc_chosen changes to true pressing enter carries over to the second block of instructions and triggers job_chosen = true. Im sorry for such a long post, but if anyone has an idea on how to fix it, it would mean a world to me.
if (event.type == sf::Event::KeyPressed)
                        {
                                if (!loc_chosen)
                                {
                                        switch (event.key.code)
                                        {
                                        case sf::Keyboard::Down:
                                        {
                                                if (location < 3) { location++; std::cout << location << std::endl; } break;
                                        }
                                        case sf::Keyboard::Up:
                                        {
                                                if (location > 0) { location--; std::cout << location << std::endl; } break;
                                        }
                                        case sf::Keyboard::Return:
                                        {
                                                st_number += std::to_string(location);
                                                std::cout << "LOC NUMBER: " << st_number << std::endl;
                                                loc_chosen = true; break;
                                        }
                                        }
                                }
                                if (loc_chosen)
                                {
                                        std::cout << linia_loc[location * 2] << std::endl;
                                        std::cout << linia_loc[(location * 2) + 1] << std::endl;
                                        switch (event.key.code)
                                        {
                                        case sf::Keyboard::Up:
                                                choice = 0;
                                                break;
                                        case sf::Keyboard::Down:
                                                choice = 1;
                                                break;
                                        case sf::Keyboard::Return:
                                                st_number += std::to_string(choice);
                                                std::cout << "LOC + CHOICE NUMBER: " << st_number << std::endl;
                                                job_chosen = true;
                                                break;
                                        }
                                }
                                /// here is the code for showing the different screen and on the bottom is
                                /// this code for drawing stuff when job_chosen is true
                 if (job_chosen)
                {
                        App.draw(s_gray);
                        App.draw(text_box);
                }                                     // this code gets exacuted immidiately after the first enter

 

Arcade

  • Full Member
  • ***
  • Posts: 230
    • View Profile
Re: Switching between states
« Reply #1 on: August 10, 2018, 03:44:30 pm »
Presumably most of this code is within a pollEvent() loop. Your "event" variable will not change until the next time through the loop. I'll distill your problem down to the few lines of code that matter. That might make it easier to see your problem. I made comments in the code to also help walk you through it.

// we'll assume loc_chosen is initially false and the user has pressed the return key.
if (!loc_chosen)
{
   switch (event.key.code)
   {
      case sf::Keyboard::Return:
      {
         loc_chosen = true; // User pressed return, so loc_chosen is now true
         break;
      }
   }
}
if (loc_chosen) // loc_chosen was set to true earlier, so we enter this if statement as well
{
   switch (event.key.code) // The event variable is still the same as before. Nothing has changed it.
   {
      case sf::Keyboard::Return:  // The event variable still contains return from before.
      {
         job_chosen = true;
        // You can (hopefully) now see that one press of the return key will always set both job_chosen and loc_chosen.
         break;
      }
   }
}

 

The quick way to fix your problem would be by changing that 2nd 'if' statement into an 'else'. That way you can't enter it until the next iteration of your pollEvent() loop. A possibly better solution would be to also use something slightly more sophisticated than multiple booleans to keep track of your state, like an enum for starters.

Wolff

  • Newbie
  • *
  • Posts: 22
    • View Profile
Re: Switching between states
« Reply #2 on: August 10, 2018, 05:16:03 pm »
It's still strange to me that one press of a key goes into two switch statemants but now I can see that my prediction was correct.
That's such an easy fix, I got hung up on finding out why that I didnt think that such a simple solution as changing it to else would work! Thanks a lot!
If you have any more time to spare could you elaborate how using enum would change anything or how would that look like?
I havn't got much occasions to really play around with enums but it seems like yes I could just name the states there and use them, but without changing if to else wouldn't the issue be the same?

Arcade

  • Full Member
  • ***
  • Posts: 230
    • View Profile
Re: Switching between states
« Reply #3 on: August 10, 2018, 07:30:04 pm »
I'm glad I could help.

Quote
It's still strange to me that one press of a key goes into two switch statemants
I might be easier for you to understand if we replace the event variable with just an integer. Your code would then be similar to this
int a = 5;
bool loc_chosen = false;
bool job_chosen  = false;

switch (a)
{
   case 5:
   {
      loc_chosen = true;
      break;
   }
}
if (loc_chosen)
{
   switch (a)
   {
      case 5:
      {
         job_chosen = true;
         break;
      }
   }
}
 
As you can see, 'a' never changes, so there's no reason why you wouldn't end up in the same 'case' for each switch statement.


Quote
could you elaborate how using enum would change anything
I didn't elaborate too much in my first post because there are many ways to handle states in a program. I didn't mean that it would fix your problem directly, just that it might make your logic a little easier to follow and extend. Using enums is just one option that is pretty simple and straightforward, but there are many other more sophisticated (and possibly overkill) options too for tracking state. You're right that you will still need some 'else' statements, but just using one variable for state tracking is a little easier to wrap your head around than using multiple booleans. Basically, the enum would just look something like this
enum class eState
{
   ShowMenu1,    // Equivalent to !loc_chosen && !job_chosen
   ShowMenu2,    // Equivalent to loc_chosen && !job_chosen
   DoOtherThings // Equivalent to loc_chosen && job_chosen
};
 
and then you could make a variable of type eState instead of your current booleans to track what state you're in.

Wolff

  • Newbie
  • *
  • Posts: 22
    • View Profile
Re: Switching between states
« Reply #4 on: August 11, 2018, 03:27:01 am »
Thank you so much for your time and help!
Now I understand the problem and a way to improve my code. Thanks once again!