C++ SFML Text flickers when drawn - c++

I have an SFML RenderWindow, and when it closes, it'll display a confirmation message. I've run into this same problem a lot of times: the confirmation message (an sf::Text) is drawn when the Event::Closed is called, but it only stays when the event is called; I think till the click on the close button is registered (calling the close event); disappears in a flash (does that have something to do with the speed of C++?). How can I solve this? The text should be displayed after it's drawn, and shouldn't disappear, after calling the close event.
Here is the code (in main.cpp):
while (app.isOpen())
{
// Process events
sf::Event event;
while (app.pollEvent(event))
{
// Close window : exit
if (event.type == sf::Event::Closed)
{
app.clear();
Text close("Are you sure you want to close this?", Arial);
app.draw(close);
close.setCharacterSize(40);
close.setPosition(300, 300);
app.display();
}
}
// Clear screen
app.clear();
// Draw the sprite
app.draw(sprite);
app.draw(text);
text.setPosition(500, 500);
// Update the window
app.display();
}
The workaround gives me an error:
I made a function to do the work, but it gives me this error:
error: use of deleted function 'sf::RenderWindow::RenderWindow(const sf::RenderWindow&)'.
Here is the code. What am I doing wrong?

Keep an explicit variable with the state of the game, and change your game code based on that:
enum class GameState { Playing, Closing };
GameState phase = GameState::Playing;
while (app.isOpen()) {
// Process events
sf::Event event;
while (app.pollEvent(event)) {
// Close window : exit
if (event.type == sf::Event::Closed) {
phase = GameState::Closing;
}
}
// Clear screen
app.clear();
if (phase == GameState::Closing) {
Text close("Are you sure you want to close this?", Arial);
close.setCharacterSize(40);
close.setPosition(300, 300);
app.draw(close);
} else if (phase == GameState::Playing) {
app.draw(sprite);
app.draw(text);
text.setPosition(500, 500);
}
// Update the window
app.display();
}

Related

Detecting if a touch pressed, not if its down?

i will make a beat em up game with sfml c++ on mobilephone. So i need to use the Touch function. The problem I have is, what is the best way to detect when the Touch has been pressed, and only execute the code which should be executed when the key has been pressed once? I need it for an animation when the Player make a kick. Now its always repeating the spritesheet animation loop, i wanna fix that, here is the a piece if my code where i need it:
...
if(animHit == true){
if(plrClock.getElapsedTime().asSeconds() > 0.1)
{
animRec.x ++;
if(animRec.x * 103 >= plrtex.getSize().x)
animRec.x = 0;
plrClock.restart();
}
}
FloatRect touchButtonRect = btnSprite.getGlobalBounds();
// the Touch is pressed the button
if(touchButtonRect.contains(worldPos)){
animHit = true;
}
else
{
if(animRec.x * 412<= plrtex.getSize().x){
animHit = false;
}
}
You haven't shown the minimal amount of code needed to replicate the problem, but i think i know where the problem lies. You most likely are trying to get the touch in the while loop without any events. Events are the things that tell your program to run things at, well, a trigger of sorts. This trigger can be a mouse click, resize of window, keyboard buttons or touch events.
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <iostream>
using namespace std;
using namespace sf;
int main()
{
// create the window
sf::RenderWindow window(sf::VideoMode(800, 600), "My window");
window.setFramerateLimit(60);
// run the program as long as the window is open
while (window.isOpen())
{
// check all the window's events that were triggered since the last iteration of the loop
sf::Event event;
while (window.pollEvent(event))
{
if(event.type == sf::Event::Closed) window.close();
if (event.type == sf::Event::TouchBegan)
{
//do something
}
if (event.type == sf::Event::TouchEnded)
{
//do something
}
if (event.type == sf::Event::TouchMoved)
{
//do something
}
}
// clear the window with black color
window.clear(sf::Color::Black);
// draw everything here...
// end the current frame
window.display();
}
return 0;
}
With events you can use the triggers really well such as a screen touch. Using touchBegan it will record the single screen touch, even if you hold down the touch it will still be considered single touch.
Hope this helped.

Variable don't update from sfml event loop

I am using sfml library for my graphics. During paused I want to avoid drawing on the screen. I want to intercept a spacebar press using sf::Event::MouseButtonPressed. In the debug mode, the event is successfully intercepted but failed in normal execution, why? The bool variable 'paused' don't seemed to update.
while (window.isOpen()) {
Event event;
while (window.pollEvent(event)) {
/*..*/
if (event.type = Event::KeyPressed) {
if (event.key.code == Keyboard::Space) {
if (!paused) {
paused = true;// UDATE HERE
}
else
if (paused)
{
paused = false; // UDATE HERE
}
}
}
}
if (!paused) //// UDATE DONT SEEM TO AFFECT HERE
{
/* draw here */
}
}
Edited: Even tried by declaring the variable paused as atomic, but still don't work.
Use the Event::KeyReleased instead of the Event::KeyPressed as the key press gets called every loop that a key is down leading to many enters while the Release event is only called once per click.

How does window.clear() works in SFML when making a character move in the screen?

Well, I've been watching a tutorial on how to use SFML. I'm currently learning to move a sprite in the screen. Before adding window.clear(); every time I moved the sprite it left like a trail, like if the sprite was a brush. Then the tutorial man said to add window.clear BEFORE window.draw(player);
Could you please explain the logic behind that? Like, the window gets cleared, then draws the character and the displays it. Here is the code:
#include <SFML/Graphics.hpp>
#include <iostream>
int main() {
sf::RenderWindow window(sf::VideoMode(1920, 1080), "Screen", sf::Style::Default);
sf::RectangleShape player(sf::Vector2f(100.0f, 100.0f));
player.setFillColor(sf::Color::Green);
//run as long as the window is open
while (window.isOpen()) {
// check all the window's events that were triggered since the last iteration of the loop
sf::Event evnt;
while (window.pollEvent(evnt)) {
switch (evnt.type) {
case sf::Event::Closed:
window.close();
break;
case sf::Event::Resized:
printf("New window width: %i New window height: %i\n", evnt.size.width, evnt.size.height);
break;
case sf::Event::TextEntered:
if (evnt.text.unicode < 128) {
printf("%c", evnt.text.unicode);
}
}
// "close requested" event: we close the window
if (evnt.type == sf::Event::Closed)
window.close();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::W)){
player.move(0.0f, -0.1f);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::A)) {
player.move(-0.1f, 0.0f);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::S)) {
player.move(0.0f, 0.1f);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::D)) {
player.move(0.1f, 0.0f);
}
window.clear();
window.draw(player);
window.display();
}
return 0;
}
The logic behind sf::RenderWindow::clear() is actually quite simple. The reason you see a trail behind the sprite without clear is because you redraw the sprite again without getting rid of the old one. Clearing the screen gets rid of anything that was already on the screen, so you end up with a blank canvas to redraw everything on in its updated position. The character, which is your sprite, isn't actually moving, it is constantly getting redrawn in a new position on the window.

SFML - fluid screen update?

i'm starting with sfml 2.1 but i cant find how to make the program to run fluidly
i mean, the program its working but unless i do something, like pressing a button or moving the mouse, the main loop wont run,
here is an example for my main loop code
window.setFramerateLimit(30); // set max fps to 30
while (window.isOpen())
{
// this code ignores the framerate limit and doesnt runs when an event is found
while (window.pollEvent(event))
{
// this code works fine but it wont run unless the user presses a key or moves the mouse
}
}
any ideas?
The main loop does run, you aren't doing anything in it.
From the tutorials for 2.1:
while (window.isOpen())
{
// check all the window's events that were triggered since the last iteration of the loop
sf::Event event;
while (window.pollEvent(event))
{
// "close requested" event: we close the window
if (event.type == sf::Event::Closed)
window.close();
}
// clear the window with black color
window.clear(sf::Color::Black);
// draw everything here...
// window.draw(...);
// end the current frame
window.display();
}

Moving a sprite and handling events

I'm learning the SFML library at the moment but I'm a little lost on moving the sprite. Here's my main.cpp file:
#include <SFML/Graphics.hpp>
int main()
{
// Create the main window
sf::RenderWindow App(sf::VideoMode(800, 600), "SFML window");
// Load a sprite to display
sf::Texture Image;
if (!Image.LoadFromFile("cb.bmp"))
return EXIT_FAILURE;
sf::Sprite Sprite(Image);
// Define the spead of the sprite
float spriteSpeed = 10.f;
// Start the game loop
while (App.IsOpened())
{
// Process events
sf::Event Event;
while (App.PollEvent(Event))
{
// Close window : exit
if (Event.Type == sf::Event::Closed)
App.Close();
if (sf::Keyboard::IsKeyPressed(sf::Keyboard::Up))
Sprite.Move(spriteSpeed * App.GetFrameTime(), 0);
}
// Clear screen
App.Clear();
// Draw the sprite
App.Draw(Sprite);
// Update the window
App.Display();
}
return EXIT_SUCCESS;
}
But I get really slow, inconsistent movements, why isn't the sprite moving steadily around the screen? Also, seeing as how I plan to use the mouse to control the character how will I use the loop to make the character move towards where the user clicks?
You shouldn't be checking if the key is held down in the event loop.
SFML only posts one event when the key is first pressed down, and then another event when the key is released. In this case, your code is only checking if the key is held when an event occurs (such as moving your mouse, clicking, or anything else).
Moving the IsKeyPressed check out of the event loop, preferably below it, should fix the issue.
Making the sprite move towards your mouse is a more complicated issue, better suited for the Game Development StackExchange.