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

Author Topic: Any easy sfml way to break the clear-draw-display routine? [SOLVED]  (Read 8085 times)

0 Members and 1 Guest are viewing this topic.

Mark

  • Guest
Hello guys, I switched to SFML 2.1 from SDL 2 because of the lack of tutorials there and since then I experienced only two things that I could do in SDL and couldn't do here (and much more stuff that is exclusive for SFML and makes it really cool and easy to use! ;D). I'm quite sure there is a workaround but is there an easy one?

In SDL, I could have a menu with some nice buttons and when user takes mouse over one I only need to redraw that button with other sprite and flip the screen (display). That's all. In SFML, I have to clear everything, then redraw a huge 1280x720 background, then draw all the changed buttons and display the updated screen. Now what with:
  • Power efficiency? I know about the power of the GPUs and CPUs these days but anyways, why waste power when the user decides to fool around his mouse bouncing all over the screen, making the PC redraw that huge background so many times? We could redraw only one button!
  • Code efficiency? All that clearing and redrawing takes more lines of code... At least for me. And with more lines there are more chances for bugs to appear.
The sprites and textures tutorial told that I shouldn't try to overcome this obstacle because that causes double buffering and can make bugs happen (they happen all the time I try to break the routine) and stuff but why I was able to make my own routine in SDL? Any simple bool switching function to change it?

Don't take me seriously if you find this silly or something, I'm totally new in graphics programming...
I can make the thing done but I am wondering if I can do it in a simpler way  :)
« Last Edit: December 11, 2013, 12:43:33 pm by Mark »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11038
    • View Profile
    • development blog
    • Email
Re: Any easy sfml way to break the clear-draw-display routine?
« Reply #1 on: December 11, 2013, 12:00:31 pm »
SFML was not designed that way, because SFML was created for realtime applications, I suggest you use SFML the way it was intended to work.

  • Power efficiency? I know about the power of the GPUs and CPUs these days but anyways, why waste power when the user decides to fool around his mouse bouncing all over the screen, making the PC redraw that huge background so many times? We could redraw only one button!
  • Code efficiency? All that clearing and redrawing takes more lines of code... At least for me. And with more lines there are more chances for bugs to appear.
The amount of time require to determine which part needs to be redrawn and the work arounds needed to make it possible with SFML render both arguments invalid.
If you simply copy your code from SDL to SFML and then argue about code efficiency you're already on the wrong track. SDL is a C library thus it does things the C way, while SFML is a modern C++ library and although C++ is a superset of C, modern C++ and C don't have much in common. With that said, all you need is a refactoring of your code base and you'll soon see that redrawing the whole scene every frame makes quite a few complicated logic parts in your code vanish, thus essentially making your code easier to understand and maintain.

Any simple bool switching function to change it?
Nope.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Mark

  • Guest
Thanks, SOLVED!
« Reply #2 on: December 11, 2013, 12:42:34 pm »
Understood it, sir!  :) Actually, it's getting easier after I get used to SFML. After all, it's only my second day with it.
I optimized the menu with a bool for each button, wasMouseOnThatButtonXThePreviousTimeUserMovedMouse (of course, the real name is much shorter). A new screen update is performed only if the states of buttons are changed (not every time user moves his mouse). That's an improvement!

Thanks really much!

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11038
    • View Profile
    • development blog
    • Email
Re: Thanks, SOLVED!
« Reply #3 on: December 11, 2013, 12:46:35 pm »
A new screen update is performed only if the states of buttons are changed (not every time user moves his mouse).
What are you doing the rest of the time, when there's not button change?
If you're not processing events, Windows and other OS might mark your application as unresponsive.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Mark

  • Guest
Re: Any easy sfml way to break the clear-draw-display routine? [SOLVED]
« Reply #4 on: December 11, 2013, 12:55:27 pm »
I wait for a new event again. I don't know, I was holding the program open for at least two minutes and got no errors with program functioning correctly, only a bad return value of int main(), I'm guessing it's because I don't close the window and textures and sprites and you know, it's only a test program and it's working.

By the way, I don't want to spam the forum with new small topics so I'm going to ask a new little question that caused me no problem and I solved it, I'm just curious why this happened (if the reason if simple of course, otherwise I'm not going to understand it for sure  :D) :
Why I get a white screen after the first window.waitEvent(event) statement?
    window.clear(sf::Color::Black);
    window.draw(swatSprite);
    window.draw(buttonPlay);
    window.draw(buttonExit);
    window.display();
    // I see a normal screen for awhile.
    while (!quit)
    {
        bool statesChanged = false;
        bool firstMenuOver = false;
        window.waitEvent(event);
        // Stuff. Screen is white, gets back to normal after I hover any invisible white button.
    }
 
It starts functioning correctly after I add this piece of code in the start of a while cycle.
if (firstTime)
{
      window.clear(sf::Color::Black);
      window.draw(swatSprite);
      window.draw(buttonPlay);
      window.draw(buttonExit);
      window.display();
      firstTime = false;
}
 
« Last Edit: December 11, 2013, 01:00:44 pm by Mark »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11038
    • View Profile
    • development blog
    • Email
Re: Any easy sfml way to break the clear-draw-display routine? [SOLVED]
« Reply #5 on: December 11, 2013, 01:03:07 pm »
Ah yeah if you're using waitEvent then it's okay, because you're still processing all events, so the OS won't freak out. ;D

No idea why it would turn white, but is that snippet complete? Since quit will never change.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Mark

  • Guest
Re: Any easy sfml way to break the clear-draw-display routine? [SOLVED]
« Reply #6 on: December 11, 2013, 01:08:16 pm »
Nope.  Actually, there is no quit bool, it's an infinite loop that gets breaked when user exits the program (Alt+F4, etc), or user clicks mouse on any button. I added that bool to make it more clear.

How do I free textures, sprites and stuff? The return value of main is still incorrect even though I started closing the window... I've found no sf::FreeTexture(&sf::Texture) function or anything like that. I think that is causing me the wrong return value.

Full code of the menu cycle (continued from the if(firstTime) statement):
// Return false means to quit the program. As the menu is not finished yet (there will be
// a submenu), everything returns false or breaking (that leads to exit too).
if (event.type == sf::Event::Closed) return false;
if (event.type == sf::Event::MouseMoved)
{
   if (event.mouseMove.x >= 790 && event.mouseMove.x <= 990 && event.mouseMove.y >= 200 && event.mouseMove.y <= 300)
   {
       if (playHovered != true) statesChanged = true;
       playHovered = true;
   } else
   {
       if (playHovered == true) statesChanged = true;
       playHovered = false;
   }
   if (event.mouseMove.x >= 1050 && event.mouseMove.x <= 1250 && event.mouseMove.y >= 250 && event.mouseMove.y <= 350)
   {
       if (exitHovered != true) statesChanged = true;
       exitHovered = true;
   } else
   {
       if (exitHovered == true) statesChanged = true;
       exitHovered = false;
   }
   if (statesChanged == true)
   {
       window.clear(sf::Color::Black);
       window.draw(swatSprite);
       if (playHovered) window.draw(buttonPlayH); else window.draw(buttonPlay);
       if (exitHovered) window.draw(buttonExitH); else window.draw(buttonExit);
       /// if (playHovered || exitHovered) hovering.play(); Sounds are not ready yet...
       window.display();
   }
}
if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left)
{
   if (event.mouseButton.x >= 790 && event.mouseButton.x <= 990 &&
       event.mouseButton.y >= 200 && event.mouseButton.y <= 300) toSubMenu = true; else
   if (event.mouseButton.x >= 1050 && event.mouseButton.x <= 1250 &&
       event.mouseButton.y >= 250 && event.mouseButton.y <= 350) return false;
}
     if (toSubMenu) break; /// And sound clicking.play(); but no sounds yet..
}
return false;
 
Code editing done.
« Last Edit: December 11, 2013, 01:28:13 pm by Mark »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11038
    • View Profile
    • development blog
    • Email
Re: Any easy sfml way to break the clear-draw-display routine? [SOLVED]
« Reply #7 on: December 11, 2013, 01:46:51 pm »
SFML uses RAII, thus there's no need to free things. As soon as it goes out of scope it will get released.

You wrong exit code is most likely the cause of closing your application by force rather than the normal and defined way. If you want a normal termination of your application, you'll have to process the sf::Event::Closed event and set your quit boolean to true.

    window.clear(sf::Color::Black);
    window.draw(swatSprite);
    window.draw(buttonPlay);
    window.draw(buttonExit);
    window.display();

    while (!quit)
    {
        bool statesChanged = false;
        bool firstMenuOver = false;
        if(window.waitEvent(event))
        {
            if(event.type == sf::Event::Closed)
            {
                window.close();
                quit = true;
            }
        }
    }

And never close the application by closing the console.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Mark

  • Guest
Re: Any easy sfml way to break the clear-draw-display routine? [SOLVED]
« Reply #8 on: December 11, 2013, 01:58:25 pm »
As long as my program works fine I'll be satisfied by any return value  :)
I'll experiment with the return values more after I complete my first real SFML project.
That RAII makes things much easier  :D

Raincode

  • Full Member
  • ***
  • Posts: 118
    • View Profile

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Any easy sfml way to break the clear-draw-display routine? [SOLVED]
« Reply #10 on: December 11, 2013, 03:21:39 pm »
To extend a bit on the first answer:

Power efficiency? I know about the power of the GPUs and CPUs these days but anyways, why waste power when the user decides to fool around his mouse bouncing all over the screen, making the PC redraw that huge background so many times? We could redraw only one button!
Reduce the frame rate (frame limit, VSync, sleep) if you're concerned about power. What quickly eats up battery is a CPU core running to capacity.

Code efficiency? All that clearing and redrawing takes more lines of code... At least for me. And with more lines there are more chances for bugs to appear.
No, it's exactly the opposite way. Re-rendering to the window only partially requires a more complex logic, to figure out where objects have been. If moving objects are involved, you would need to trace their past positions, which is very annoying.

Read also the big red box in this tutorial.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development: