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

Author Topic: sf::Event::MouseButtonPressed issues  (Read 1720 times)

0 Members and 1 Guest are viewing this topic.

Kedirin

  • Newbie
  • *
  • Posts: 2
    • View Profile
sf::Event::MouseButtonPressed issues
« on: October 23, 2013, 03:45:17 pm »
I am working on SFML Game From Scratch Tutorial on page http://www.gamefromscratch.com/page/Game-From-Scratch-CPP-Edition.aspx.  I have everything working and have been modifying it for fun.

Part of this tutorial you write a basic menu screen that has a Play Game button and an Exit Game button.  The screen overlays on top of the game with just a simple .png file that shows the two button.  You then create two rectangles in the locations of the buttons and watch for mouse button pressed events while the screen is up.

Everything works fine when I'm running in Debug mode on Visual Studio 2012 Express but when I switch to Release mode the Play Game button will not work properly.  I have to click multiple times while moving the mouse at the same time over the button for it to eventually go back to the game.  I've set break points and the function always returns the correct value when I'm clicking play but the menu screen persists.

Here is the Menu Code
#include "MenuScreen.h"
#include <iostream>

MenuScreen::MenuResult MenuScreen::Show( sf::RenderWindow& window )
{
        // Load menu image from file
        sf::Texture image;
        image.loadFromFile( "Assets/Graphics/MainMenu.png" );
        sf::Sprite sprite( image );

        // Setup clickable regions

        // Play menu item coordinates
        MenuItem playButton;
        playButton.rect.top = 80;
        playButton.rect.height = 140;
        playButton.rect.left = 0;
        playButton.rect.width = 600;
        playButton.action = Play;

        // Exit menu item coordinates
        MenuItem exitButton;
        exitButton.rect.top = 221;
        exitButton.rect.height = 110;
        exitButton.rect.left = 0;
        exitButton.rect.width = 600;
        exitButton.action = Exit;

        menuItems.push_back( playButton );
        menuItems.push_back( exitButton );

        window.draw( sprite );
        window.display();

        return GetMenuResponse( window );      
}

MenuScreen::MenuResult MenuScreen::HandleClick( int x, int y )
{
        std::list<MenuItem>::iterator it;
       
        for( it = menuItems.begin(); it != menuItems.end(); it++ )
        {
                sf::Rect<int> menuItemRect = (*it).rect;
                if( x > menuItemRect.left
                        && x < menuItemRect.left + menuItemRect.width
                        && y > menuItemRect.top  
                        && y < menuItemRect.height + menuItemRect.top )
                {                      
                        return(*it).action;
                }
        }
        return Nothing;
}

MenuScreen::MenuResult MenuScreen::GetMenuResponse( sf::RenderWindow& window )
{
        sf::Event menuEvent;

        while( true )
        {
                while( window.pollEvent( menuEvent ) )
                {
                        if( menuEvent.type == sf::Event::MouseButtonPressed )
                        {
                                return HandleClick( menuEvent.mouseButton.x,menuEvent.mouseButton.y );
                        }
                        else if( menuEvent.type == sf::Event::Closed )
                        {
                                return Exit;
                        }
                }
        }
}
 


Here is the show menu screen function
void Game::ShowMenuScreen()
{
        MenuScreen mainMenu;
        MenuScreen::MenuResult result = mainMenu.Show( mainWindow );
        switch( result )
        {
                //sf::sleep( sf::seconds(.5) );
                case MenuScreen::Play:
                        gameState = Game::Playing;
                        // Restarted clock here to prevent a huge time lapse in Update functions.
                        clock.restart();
                        break;                 
                case MenuScreen::Exit:
                        gameState = Game::Exiting;
                        break;
                default:
                        Game::ShowMenuScreen();
                        break;
        }
}
 

Here is the PlayGame function that will call ShowMenuScreen when Esc is pressed
void Game::PlayGame()
{
        sf::Event currentEvent;
        float timeSinceLastUpdate = 0.0f;
       
        while( mainWindow.isOpen() )
        {
                mainWindow.pollEvent(currentEvent);                            
                timeSinceLastUpdate += clock.restart().asSeconds();
                while( timeSinceLastUpdate > timePerFrame )
                {
                        mainWindow.pollEvent(currentEvent);                    
                        timeSinceLastUpdate -= timePerFrame;
                        mGameObjectManager.UpdateAll( timePerFrame );                  
                }              
                if( currentEvent.type == sf::Event::KeyPressed )
                {
                        if( currentEvent.key.code == sf::Keyboard::Escape )
                        {
                                ShowMenuScreen();
                                // Reset TimeSinceLastUpdate here to effectively pause game while in menus.
                                timeSinceLastUpdate = 0.0f;                            
                                break;
                        }
                }
                if( currentEvent.type == sf::Event::Closed )
                {
                        gameState = Game::Exiting;
                }
                Render();
        }
}
 


States
void Game::GameLoop()
{
        switch(gameState)
        {
        case Game::ShowingMenu:
                {
                        ShowMenuScreen();
                        break;
                }
        case Game::ShowingSplash:
                {
                        ShowSplashScreen();
                        break;
                }
        case Game::Playing:
                {
                        PlayGame();
                        break;                 
                }
        case Game::Exiting:
                {
                        mainWindow.close();
                        break;
                }
        }      
}
 

Main Game Loop
while( !IsExiting())
{
        GameLoop();
}
 

Any help on this is appreciated, I've been beating my head on this for some time now and don't want to give up on it.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10822
    • View Profile
    • development blog
    • Email
Re: sf::Event::MouseButtonPressed issues
« Reply #1 on: October 23, 2013, 03:57:12 pm »
void Game::PlayGame()
{
        sf::Event currentEvent;
        float timeSinceLastUpdate = 0.0f;
       
        while( mainWindow.isOpen() )
        {
                mainWindow.pollEvent(currentEvent);                            
                timeSinceLastUpdate += clock.restart().asSeconds();
                while( timeSinceLastUpdate > timePerFrame )
                {
                        mainWindow.pollEvent(currentEvent);                    
                        timeSinceLastUpdate -= timePerFrame;
                        mGameObjectManager.UpdateAll( timePerFrame );                  
                }              
                if( currentEvent.type == sf::Event::KeyPressed )
                {
                        if( currentEvent.key.code == sf::Keyboard::Escape )
                        {
                                ShowMenuScreen();
                                // Reset TimeSinceLastUpdate here to effectively pause game while in menus.
                                timeSinceLastUpdate = 0.0f;                            
                                break;
                        }
                }
                if( currentEvent.type == sf::Event::Closed )
                {
                        gameState = Game::Exiting;
                }
                Render();
        }
}
 
This is not how event polling was intended to work and is most likely the cause of your troubles. You should always clear out the event queue by calling while(window.pollEvent(event)), that way all the events will be directly process and you don't run danger in dropping an event or running behind the actual events.
See the official tutorial(s) for the specific details.

It may or may not be the cause of your issues, but it should be fixed first. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Kedirin

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: sf::Event::MouseButtonPressed issues
« Reply #2 on: October 23, 2013, 04:06:26 pm »
Ok thanks.  I have a hunch that it's polling related just by the way it's acting so I will start there.