C++ sfml receives close event just after window opens - c++

I am trying to follow a SFML tutorial from this link, however, for some reason my application seems to be caling the close event as soon as my program enters into the event loop.
Here is my code.
#include <SFML/Graphics.hpp>
#include <iostream>
// Here is a small helper for you ! Have a look.
#include "ResourcePath.hpp"
int main()
{
sf::RenderWindow Window(sf::VideoMode(500,400),"SFML tutorial");
/* Or we can do this
* sf::RenderWindow Window
* Window.create (sf::VideoMode(800,600),"SFML tutorial");
*/
//Game loop
while(Window.isOpen())
{
sf::Event Event;
while(Window.pollEvent(Event));
{
if(Event.type == sf::Event::Closed)
{
Window.close();
std::cout << "Close" << std::endl;
}
}
}
return 0;
}
For some reason as soon as my program enters the event loop it receives a sf::Event::Closed event. I have done some research and this is not because the window is too big for my screen.
To fix my issue I have had to ad a int variable canClose to 0 then modify the event loop to this.
if(Event.type == sf::Event::Closed)
{
if(canClose == 1)
{
Window.close();
} else {
canClose = 1;
}
}
After I do this the window now opens and runs as expected.
P.S this is made using xcode and the SFML template.
Edit:
Just made a new xcode SFML project and removed some code in it to make a empty window and it seems to whork. Code looks exactly the same. This seams strange because it is exactly the same code.

From what i have seen, do not use an if statement for checking events, use a switch statement. Also Use a while(window.isOpen()) when trying to poll events
Have you read through the tutorials on http://www.sfml-dev.org ? Because i can guarantee that it is the best source for learning sfml. Use it before using another source.

Your problem is that you declared the variable Event Event type, you have to change the name of the variable to lowercase.
in this way
#include <SFML/Graphics.hpp>
#include <iostream>
// Here is a small helper for you ! Have a look.
#include "ResourcePath.hpp"
int main()
{
sf::RenderWindow Window(sf::VideoMode(500,400),"SFML tutorial");
/* Or we can do this
* sf::RenderWindow Window
* Window.create (sf::VideoMode(800,600),"SFML tutorial");
*/
//Game loop
while(Window.isOpen())
{
sf::Event event;
while(Window.pollEvent(event));
{
if(event.type == sf::Event::Closed)
{
Window.close();
std::cout << "Close" << std::endl;
}
}
}
return 0;
that way you will not have any problems

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.

SFML starting a new song once another song is complete

#include <iostream>
#include <SFML/Window.hpp>
#include <SFML/Window/Event.hpp>
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Audio/Music.hpp>
using namespace std;
int main (){
sf::RenderWindow window(sf::VideoMode(800, 600), "My Window");
sf::Music music;
if (!music.openFromFile("Music/Fallen-Down.ogg"))
return EXIT_FAILURE;
music.play();
// if(!music.openFromFile("Music/CORE.ogg"))
// return EXIT_FAILURE;
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();
}
if(music.getStatus() == 0)
music.play();
window.clear(sf::Color(255, 255, 255, 0));
window.display();
}
return EXIT_SUCCESS;
}
I have my basic window which opens and plays a song. All I want to do is play the next song "CORE.ogg" when the first song "Fallen-Down"is finished playing. I have tried using the getStatus() function from the SFML Documentation which I believe returns an integer corresponding to the status of the song from an enum defined as
enum Status {Stopped, Paused, Playing}
I check which number it returns and if it returns 0 i was hoping it would play again. It's in the window loop so it should be checking at the end of every loop the status of the song...
If you want the music to play again, then you need to stop() the current music, even though it has come to its own end, because that will rewind the music back to the beginning.
if(music.getStatus() == sf::SoundSource::Status::Stopped)
{
music.stop(); // rewind to beginning
music.play();
}
BTW you should use sf::SoundSource::Status::Stopped rather than 0 as it may change value in a future version or on another platform.
If you want to play different music, you need to load it:
if(music.getStatus() == sf::SoundSource::Status::Stopped)
{
music.openFromFile("Music/CORE.ogg");
music.play();
}

Launching a new window in SFML (C++)

This semester we have to make a game in C++. As a junior in game development in C++ I choosed SFML for graphics (Is that a good choice ? ). All started well, I made my menu and my button and so on. But when I click on this button my window is just closed. And I want to lauch a new window. Anyone can help me ?
Thanks.
#include <iostream>
#include <SFML/Graphics.hpp>
#include "Button.h"
#include "game.h"
using namespace std;
int main() {
sf::RenderWindow window;
sf::Color Color;
sf::Vector2i centerWindow((sf::VideoMode::getDesktopMode().width / 2) - 445, (sf::VideoMode::getDesktopMode().height / 2) - 480);
window.create(sf::VideoMode(900, 900), "SFML Textbox", sf::Style::Titlebar | sf::Style::Close);
window.setPosition(centerWindow);
window.setKeyRepeatEnabled(true);
sf::Font font;
if (!font.loadFromFile("font.ttf"))
std::cout << "Font not found!\n";
//Création de l'image
sf::Texture texture[1];
texture[0].loadFromFile("logo.jpg");
sf::RectangleShape rectangle;
sf::Sprite sprite[1];
rectangle.setSize(sf::Vector2f(750,182));
sprite[0].setTexture(texture[0]);
sprite[0].setPosition(100,50);
//Création du texte
sf::Text text;
text.setFont(font);
text.setCharacterSize(20);
text.setColor(sf::Color(200,0,0));
text.setString("~Made by Théo Manea - 2019/2020 Paris-Sud University~");
text.setStyle(sf::Text::Bold);
text.setPosition(300,850);
//Création du bouton
Button btn1("Jouer", { 200, 100 }, 30, sf::Color::Green, sf::Color::White);
btn1.setFont(font);
btn1.setPosition({ 350, 300 });
//Main Loop:
while (window.isOpen()) {
sf::Event Event;
//Event Loop:
while (window.pollEvent(Event)) {
switch (Event.type) {
case sf::Event::Closed:
window.close();
case sf::Event::MouseMoved:
if (btn1.isMouseOver(window)) {
btn1.setBackColor(sf::Color(200,0,0));
}
else {
btn1.setBackColor(sf::Color(6,164,154));
}
break;
case sf::Event::MouseButtonPressed:
if (btn1.isMouseOver(window)) {
Squadro squadro;
window.close();
}
}
}
window.clear(sf::Color::White);
btn1.drawTo(window);
window.draw(rectangle);
window.draw(sprite[0]);
window.draw(text);
window.display();
}
}
And my game.h :
'''
#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED
#include <iostream>
#include <SFML/Graphics.hpp>
using namespace std;
class Squadro{
private:
public:
void Test();
void MainFunctions();
};
void Squadro::Test()
{
cout << "okkkkkkkkkkkkkkkkkkkk" << endl;
}
void Squadro::MainFunctions()
{
sf::Window window(sf::VideoMode(800, 600), "My window");
// 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))
{
// "close requested" event: we close the window
if (event.type == sf::Event::Closed)
window.close();
}
}
}
#endif // GAME_H_INCLUDED
'''
N.B : I know it's maybe a dumbie question but I need help ! Thanks :D
In general, SFML can be an as good choice for graphics library as can be SDL, Allegro, etc. you just have to use it right (yes, that's the hard part, I know. :)) But that's really subjective, so off-topic here. Let's get to your issue…
The problem is this part:
if (btn1.isMouseOver(window)) { // This is true, if the cursor is over the button
Squadro squadro; // Here you create an object of the other class that shows its own window
window.close(); // now you close the "main" window
} // once you reach this line, "squadro" is destroyed as well, since we're leaving the scope ({...}) it's defined in.
Can this be fixed? Of course. All you have to do is ensure that your Squadro object doesn't get destroyed immediately (plus the outer program code has to ensure it keeps running/updating the Squadro code as well. This can get a bit tricky, so in general I'd recommend sticking to one window only.
Here's the structure I'd use:
For your simple game you should first of all look into two basic concepts:
Main Loop: Have your program run within one main loop (i.e. "while the window is open and the game is running, repeat this"), within which you first process events (such as mouse movement or keyboard presses) and then you update your game and finally draw it.
Finite State Machine: Which allows your game to have different screens or states (but it can also be used for more basic elements such as buttons, enemies, objects, levels, etc.).
A website (and book!) I'd absolutely recommend is Game Programming Patterns. It might be a bit tricky to understand everything at once as a starter, but this website will explain you most important concepts that can make developing your game (of any scale) significantly easier. Just keep in mind the best or most complex approach might be overkill based on the scope and size of your game.
If you want to know more about finite state machines, definitely have a look at their section about it.
Without going too much into details, here's a basic template for a main Game class one might use with SFML (code is simplified/condensed; this is basically what you have already:
class Game {
private:
sf::RenderWindow mWindow;
public:
Game() {
mWindow.create({640, 480}, "My Game");
// Other initialization code
}
~Game() {
// Code to shutdown the game
}
// This is your main game loop
int run() {
while (mWindow.isOpen()) {
handleEvents();
updateGame();
drawGame();
}
return 0;
}
private:
handleEvents() {
// Event handling as you do already
}
updateGame() {
// Update the game
}
drawGame() {
// Draw the game
}
}
In your program's main() you now just have to create an object of the Game class and tell it to run:
int main(int argc, char **argv) {
Game myGame;
return myGame.run();
}
Now to the actual finite state machine. There are many different approaches to this, but the most basic one is just using one variable and an enumeration to identify the current state of the game. Add both to the class:
```cpp
enum GameState {
TitleScreen = 0,
MainGame,
GameOver
} mCurrentState;```
When initializing the game, you set a default state:
```cpp
mCurrentState = TitleScreen;
And now, if you want to switch to a different screen, all you have to do is update this variable, e.g. when the player clicks on a "Start" button:
mCurrentState = MainGame;
The three functions from your main loop, handling events, updating the game, and drawing everything, can then use this variable to determine what to do:
drawGame() {
switch (mCurrentState) {
case TitleScreen:
// Draw the title screen here
break;
case MainGame:
// Draw the actual game here
break;
case GameOver:
// Draw the game over screen here
break;
}
}
In a very similar way, you can give your button it's own internal state as well:
enum ButtonState {
Idle = 0,
Hovered,
Pushed
} mCurrentState;```

Unable to store text in SFML 2.4

I am using sfml library for some sort of graphic work and I want to store the text that I have entered using keyboard but it shows an error
please tell me how it is possible:
#include <SFML/Graphics.hpp>
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s="";
sf::Window window(sf::VideoMode(800, 200), "Ludo",sf::Style::Default);
window.setKeyRepeatEnabled(false);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
window.close();
}
else if (event.type == sf::Event::EventType::TextEntered)
{
s += event.type.unicode;
}
}
window.display();
}
return 0;
}
the error is:
sf::Event event, expression must have a class type
Your problem is this line:
s += event.type.unicode;
event.type is a field describing the type of event (you've used it in the case checking above).
What you then tried is accessing a member unicode, which obviously fails, because type is not a class or struct here. What you actually want is the field sf::Event::text, which is a struct.
As such, this line would have to look like this:
s += event.text.unicode;

SFML textEntered not working properly

so today I started looking into SFML and I found it quite interesting so decided to learn how to play with it, but I am already hitting some problems, I am trying to use textEntered event, but it is not working properly, it shows complete nonsense and text writes itself even without me pressing any key. Heres link
Code
#include <SFML/Graphics.hpp>
#include <iostream>
int main()
{
sf::RenderWindow window(sf::VideoMode(400, 400), "SFML works!");
std::string display;
sf::Font font;
font.loadFromFile("arial.ttf");
sf::Text text;
text.setFont(font);
text.setCharacterSize(30);
text.setStyle(sf::Text::Bold);
text.setColor(sf::Color::Red);
text.setPosition(50, 50);
while (window.isOpen())
{
sf::Event Revent;
while (window.pollEvent(Revent))
{
if (sf::Event::TextEntered)
{
std::cout << static_cast<char>(Revent.text.unicode);
//text.setString(display);
}
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
{
window.close();
}
window.clear();
//window.draw(text);
window.display();
}
return 0;
}
You wrote if (sf::Event::TextEntered), which evaluates to true (since it's not equal to 0).
You probably meant
if (Revent.type == sf::Event::TextEntered).
Using Revent.text is undefined behavior in this case (when you're not sure what type of event Revent contains) because sf::Event is an union, so only one of its members is usable at a time. You can read more about SFML events here.