1

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;
}
iProgram
  • 6,057
  • 9
  • 39
  • 80
  • 1
    `sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window"); _window = &window;` is your bug. `window` no longer exists when the constructor finishes. – drescherjm Jan 20 '19 at 20:15
  • In your constructor, you assign class pointer to a **local** variable. This object is gone and dead when contructor finishes. – Yksisarvinen Jan 20 '19 at 20:15
  • 1
    Possible duplicate of [Can a local variable's memory be accessed outside its scope?](https://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope) – drescherjm Jan 20 '19 at 20:16
  • @drescherjm How would I fix this then? – iProgram Jan 20 '19 at 20:18
  • Change `sf::RenderWindow* _window;` to `sf::RenderWindow window;` and use your constructors initializer list to initialize `window` https://www.geeksforgeeks.org/when-do-we-use-initializer-list-in-c/ – drescherjm Jan 20 '19 at 20:19
  • `Screen screen = *new Screen();` is a bug as well. Use `Screen screen;` instead. – drescherjm Jan 20 '19 at 20:21
  • @drescherjm Yea, that doesn't work after changing the above code. Even if I remove the `*` – iProgram Jan 20 '19 at 20:21
  • After changing `_window` to `window` you need to change `_window->` to `window.` – drescherjm Jan 20 '19 at 20:23
  • @drescherjm I fixed the new Screen issue but the updated code with your changes still doesn't behave any differently. Ive updated the code in the edit. – iProgram Jan 20 '19 at 20:31
  • `sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window");` is wrong. You did not do what I told you. This creates a new local variable `window` that shadows the class member `window`. – drescherjm Jan 20 '19 at 20:33
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/187016/discussion-between-iprogram-and-drescherjm). – iProgram Jan 20 '19 at 20:34
  • 1
    `Screen() : window(sf::VideoMode(800, 600), "SFML window") {}` – drescherjm Jan 20 '19 at 20:35

2 Answers2

1

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.

Montreal
  • 2,143
  • 5
  • 18
  • 28
-1

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