Why does SFML window not show when window is in a class? - c++

I am trying to create a Screen class for SFML, however for some reason, the application works when using the Xcode example but as soon as I put the window into it's own class, it does not work. Why is this and how would I fix it?
Here is my code (adapted form the example):
Edit:
After reading the comments, I have changed to the following code. This still does not show a screen and the program still quits.
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include "ResourcePath.hpp"
class Screen{
public:
sf::RenderWindow window;
Screen(){
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window");
}
};
int main(int, char const**)
{
Screen* screen = new Screen();
// Set the Icon
sf::Image icon;
if (!icon.loadFromFile(resourcePath() + "icon.png")) {
return EXIT_FAILURE;
}
screen->window.setIcon(icon.getSize().x, icon.getSize().y, icon.getPixelsPtr());
// Load a sprite to display
sf::Texture texture;
if (!texture.loadFromFile(resourcePath() + "cute_image.jpg")) {
return EXIT_FAILURE;
}
sf::Sprite sprite(texture);
// Create a graphical text to display
sf::Font font;
if (!font.loadFromFile(resourcePath() + "sansation.ttf")) {
return EXIT_FAILURE;
}
sf::Text text("Hello SFML", font, 50);
text.setFillColor(sf::Color::Black);
// Load a music to play
sf::Music music;
if (!music.openFromFile(resourcePath() + "nice_music.ogg")) {
return EXIT_FAILURE;
}
// Play the music
music.play();
// Start the game loop
while (screen->window.isOpen())
{
// Process events
sf::Event event;
while (screen->window.pollEvent(event))
{
// Close window: exit
if (event.type == sf::Event::Closed) {
screen->window.close();
}
// Escape pressed: exit
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) {
screen->window.close();
}
}
// Clear screen
screen->window.clear();
// Draw the sprite
screen->window.draw(sprite);
// Draw the string
screen->window.draw(text);
// Update the window
screen->window.display();
}
return EXIT_SUCCESS;
}

You have a logic error in your constructor. The way you created it, you leave Screen::window uninitialized, and create another RenderWindow object which becomes inaccessible as soon as execution leaves constructor.
Instead, you should do
class Screen{
public:
sf::RenderWindow window;
Screen():
window(sf::VideoMode(800, 600), "SFML window") {}
};
Everything else should work as expected, unless it does not have any other bugs. If you're curious about the syntax I've used, you can visit this link.

Hard to say. Maybe your accessing a memory address that isn't part of your program? Try using unique pointers and make_unique to define some of your pointers.
For example:
std::unique_ptr<sf::RenderWindow> window;
window = std::make_unique<sf::RenderWindow>(sf::VideoMode(WIDTH, HEIGHT), "PushBlox",sf::Style::Default);
I did make a project using sfml before, so feel free to check out my code here --> https://github.com/FromAlaska/ComputerScience/tree/2017/Projects/Frontier

Related

SFML render window not appearing when running program

When attempting to run a program that is intended to bring forth a render window generated through the SFML library, it will successfully compile but refuse to actually launch a window. After several hours of debugging, I am unable to find where I may have potentially gone wrong in the code, and am now beginning to think it is a problem through my IDE (CLion). Nevertheless, the code used for the render window will be provided.
int main (int argc, const char * argv[])
{
// Create the main window
sf::RenderWindow* window = new sf::RenderWindow(sf::VideoMode(800, 600), "SFML window");
#ifdef SHAPE
sf::Shape s = sf::Shape::Rectangle(0, 0, 100, 100, sf::Color::Blue);
#else
sf::Image img; img.create(100, 100, sf::Color::Blue);
sf::Texture t; t.loadFromImage(img);
sf::Sprite s(t);
#endif
// Start the game loop
while (window->isOpen())
{
// Process events
sf::Event event;
while (window->pollEvent(event))
{
// Close window : exit
if (event.type == sf::Event::Closed)
window->close();
if (event.type == sf::Event::KeyPressed)
if (event.key.code == sf::Keyboard::Escape)
window->close();
else {
delete window;
window = new sf::RenderWindow(sf::VideoMode(800, 600), "SFML window");
}
}
// Clear screen
window->clear();
s.rotate(30.0);
window->draw(s);
// Update the window
window->display();
}
delete window;
return EXIT_SUCCESS;
}
#endif
One of the most common issue with CLion users and launching an application is that they forget to provide the necessary SFML DLLs, so the application never starts but closes with a return value 0xC0000135.
If you launch the executable directly via explorer, you'll get the more well-known message box which tells you which DLL exactly is missing.
The solution is to copy the necessary DLLs next to your executable in the CLion's output directory.

What is causing "SIGABRT" in Xcode?

I am running Xcode 11.5 on my mac OS X Catalina 10.15.3. I did all the steps to set up SFML in Xcode, and created a project with the standard SFML app template, using SFML from dylibs instead of frameworks (I couldn't get the app to build when I created it with frameworks). I haven't edited the code from the template, which contains this is main.cpp:
//
// Disclaimer:
// ----------
//
// This code will work only if you selected window, graphics and audio.
//
// Note that the "Run Script" build phase will copy the required frameworks
// or dylibs to your application bundle so you can execute it on any OS X
// computer.
//
// Your resource files (images, sounds, fonts, ...) are also copied to your
// application bundle. To get the path to these resources, use the helper
// function `resourcePath()` from ResourcePath.hpp
//
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
// Here is a small helper for you! Have a look.
#include "ResourcePath.hpp"
int main(int, char const**)
{
// Create the main window
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window");
// Set the Icon
sf::Image icon;
if (!icon.loadFromFile(resourcePath() + "icon.png")) {
return EXIT_FAILURE;
}
window.setIcon(icon.getSize().x, icon.getSize().y, icon.getPixelsPtr());
// Load a sprite to display
sf::Texture texture;
if (!texture.loadFromFile(resourcePath() + "cute_image.jpg")) {
return EXIT_FAILURE;
}
sf::Sprite sprite(texture);
// Create a graphical text to display
sf::Font font;
if (!font.loadFromFile(resourcePath() + "sansation.ttf")) {
return EXIT_FAILURE;
}
sf::Text text("Hello SFML", font, 50);
text.setFillColor(sf::Color::Black);
// Load a music to play
sf::Music music;
if (!music.openFromFile(resourcePath() + "nice_music.ogg")) {
return EXIT_FAILURE;
}
// Play the music
music.play();
// Start the game loop
while (window.isOpen())
{
// Process events
sf::Event event;
while (window.pollEvent(event))
{
// Close window: exit
if (event.type == sf::Event::Closed) {
window.close();
}
// Escape pressed: exit
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) {
window.close();
}
}
// Clear screen
window.clear();
// Draw the sprite
window.draw(sprite);
// Draw the string
window.draw(text);
// Update the window
window.display();
}
return EXIT_SUCCESS;
}
The app successfully builds, but the window won't open and I get following in my Threads tab:
I've read that SIGABRT can be caused by naming errors and such. I'm not that familiar with assembly so I was wondering if anyone can see the mistake here.

Can't load image with SFML

Am trying to load an image with SFML using Xcode, but everytime I run the program, the window (which has been created using the code) flashes and disappears...
Here's the code I am using:
#include <SFML/Graphics.hpp>
#include <iostream>
#define SCREEN_WIDTH 1024
#define SCREEN_HEIGHT 1024
int main()
{
sf::RenderWindow window(sf::VideoMode(SCREEN_WIDTH, SCREEN_HEIGHT), "Orsome Game");
while(window.isOpen())
{
sf::Event e;
while(window.pollEvent(e))
{
switch (e.type)
{
case sf::Event::Closed:
window.close();
break;
}
}
sf::Image image;
if(!image.loadFromFile("sprite.png")){
return -1;
}
window.clear(sf::Color(255,255,255));
window.display();
}
return EXIT_SUCCESS;
}
Have also put the image file where the c++ file is, but it still doesn't work!
I would put an sf::Style::Default in the RenderWindow arguments, straight after "Orsome Game" window name. Because you are using the pollEvent, that would allow you to exit the window by pressing the x button in the top right corner, like a default application layout.
Is the picture in the same directory as your solution file? Or your main.cpp?
It should be, of course.
And, maybe, try loading your image with Texture and Sprite, like this:
sf::Texture texture;
texture.loadFromFile("picturename.png");
sf::Sprite sprite;
sprite.setTexture(texture);
inside the while window is open loop.
To draw it:
// after window.clear() ...
//... your code
window.draw(sprite);
//... other things to draw
// and then, your window.display();
But, probably, your sf::Image should also work. Tell me how it goes
EDIT:
Try this code and see if the window opens.
Otherwise, that might be the problem of setting up the SFML on your computer and you will have to find some good tutorial on how to set it up properly! But let's see:
#include <SFML/Graphics.hpp>
#include <iostream>
using namespace sf;
int main()
{
RenderWindow window(VideoMode(640, 640), "Test", Style::Default);
while (window.isOpen()) {
Event _event;
while (window.pollEvent(_event)) {
switch (_event.type) {
case Event::Closed:
window.close();
break;
}
}
window.clear();
// draw
// ...
window.display();
}
return 0;
}

Using object outside class

I'm trying to create some classes containing textures&sprites using SFML.
When I create object of class in SFML library in my class - i cannot use that object in main.
I wonder how to display sprite in main (e.g.):
class MainMenu
{
public:
int DrawMenu(){
sf::Texture texture;
if (!texture.loadFromFile("idle.png"))
return EXIT_FAILURE;
sf::Sprite spritemenu(texture);
return 0;
}
};
int main()
{
// Create the main window
sf::RenderWindow app(sf::VideoMode(800, 600), "SFML window");
// Load a sprite to display
sf::Texture texture;
if (!texture.loadFromFile("cb.bmp"))
return EXIT_FAILURE;
sf::Sprite sprite(texture);
MainMenu menu;
// Start the game loop
while (app.isOpen())
{
// Process events
sf::Event event;
while (app.pollEvent(event))
{
// Close window : exit
if (event.type == sf::Event::Closed)
app.close();
}
// Clear screen
app.clear();
// Draw the sprite
app.draw(sprite);
menu.DrawMenu();
app.draw(spritemenu);
// Update the window
app.display();
}
return EXIT_SUCCESS;
}
Your DrawMenu function name is lying. It doesn't draw anything. It loads the texture and sprite.
DrawMenu should simply draw the menu sprite:
void DrawMenu(sf::RenderWindow& window) { // window = where to draw the menu
window.draw(spritemenu);
}
Now where do you load spritemenu? It stays the same through the lifetime of MainMenu, so it should naturally be instantiated in the constructor of MainMenu:
class MainMenu
{
public:
MainMenu() {
if (!texture.loadFromFile("cb.bmp"))
abort(); // or throw exception
spritemenu.setTexture(texture); // "initialize" spritemenu with texture
}
…
private:
sf::Texture texture; // Store these as member data, so they will be
sf::Sprite spritemenu; // kept alive through the lifetime of MainMenu.
};
Now when you do MainMenu menu; the texture and sprite will be initialized once, and not every time you call the draw function.
And when you need to draw the menu, simply call menu.DrawMenu(app); instead of menu.DrawMenu(); app.draw(spritemenu);.
The best way to do this is probably to pass app as an argument to DrawMenu, something like this:
class MainMenu {
public:
int DrawMenu(sf::RenderWindow& app){
sf::Texture texture;
if(!texture.loadFromFile("idle.png"))
return EXIT_FAILURE;
sf::Sprite spritemenu(texture);
app.draw(spritemenu);
return 0;
}
};
Then call menu.DrawMenu(app) instead of menu.DrawMenu().
Note that it's meaningless to return EXIT_FAILURE from any function other than main(); I suggest throwing an exception instead.
Also, it's silly to reload the menu every time you draw it. I suggest moving the loading to the MainMenu constructor.

Opening SFML window gives memory read error

I'm trying to open a SFML window, but every time it is launched it says "Access violation reading location: 0xCCCCCCC0." The error is occuring in the init() method. Relevant code:
class AirportGame {
private:
sf::RenderWindow window;
public:
void init();
int run();
/
void AirportGame::init() {
window.create(sf::VideoMode(800, 600), "SFML window");
}
int AirportGame::run() {
init();
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
}
}
}
return 0;
}
int main() {
AirportGame* app = new AirportGame();
return app->run();
}
It happens sometime after init, because the actual window is open. There is no mention in the debugger of 0xCCCCCC0.
Fixed it!
Turns out under the C++ pre-processor I set the definition to SFML_STATIC instead of SFML_DYNAMIC
Set window to a
RenderWindow *window;
and create it with
window = new sf::RenderWindow( /*your stuff or default initialize*/ );
and then call
window->create( /*your settings*/ );
if you didn't already initialize it.
From then on just access window using '->' instead of '.'