SFML community forums

Help => Graphics => Topic started by: ralligood2 on July 03, 2015, 11:34:56 pm

Title: Problem with a Drawable splash to draw to window [SOLVED]
Post by: ralligood2 on July 03, 2015, 11:34:56 pm
Hi everyone, hopefully this is the right area for this post.
Could someone take a look at my code and see why the splash will not show in the window? I'm not getting any errors, it just won't show in the window. I've read the example from the docs, some other problems like what I'm trying to do but I'm stilling having some problems. Thanks for any help.

Code from splash.h
#ifndef SPLASH_H
#define SPLASH_H

#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <SFML/OpenGL.hpp>
#include <iostream>

class Splash : public sf::Drawable
{
   
    private :

    sf::Sprite m_sprite;

        virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
        {
            target.draw(m_sprite, states);
        }

    public:
        Splash();
};

Splash::Splash()
{
    std::cout << "Entered default constructor" << std::endl;
    sf::Texture m_texture;
        m_texture.loadFromFile("resources/Splash.png");
    sf::RectangleShape m_rectangleShape;
        m_rectangleShape.setTexture(&m_texture);
    sf::Sprite m_sprite(m_texture);
        m_sprite.setTextureRect(sf::IntRect(0, 0, 300, 300));
        m_sprite.setPosition(0,0);
}
#endif
 

Code from main.cpp

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <SFML/OpenGL.hpp>
#include <iostream>
#include "splash.h"

int main()
{
    Splash loadSplash;
    sf::ContextSettings contextSettings;
    contextSettings.depthBits = 24;
    int screenX = sf::VideoMode::getDesktopMode().width;
    int screenY = sf::VideoMode::getDesktopMode().height;

    sf::RenderWindow mainWin(sf::VideoMode(screenX/2, screenY), "BusbySoft", sf::Style::Default, contextSettings);
    mainWin.setVerticalSyncEnabled(true);
    mainWin.setPosition(sf::Vector2i(0, 0));
       
    while (mainWin.isOpen())
    {
        sf::Event event;  
 
        while (mainWin.pollEvent(event))
        {

            // Close window: exit
            if (event.type == sf::Event::Closed)
                mainWin.close();

            // Escape key: exit
            if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))
                mainWin.close();
            if(event.type == sf::Event::MouseMoved)
            {
                std::cout << "x=" << event.mouseMove.x << ", y=" << event.mouseMove.y << std::endl;
            }
        }

        // Clear the depth buffer
        glClear(GL_DEPTH_BUFFER_BIT);
       
        //mainWin.clear(sf::Color(35,44,69,255));
        mainWin.draw(loadSplash);

        // Finally, display the rendered frame on screen
        mainWin.display();
    }

    return EXIT_SUCCESS;
}

 
Title: Re: Problem with a Drawable splash to draw to window
Post by: eXpl0it3r on July 03, 2015, 11:49:05 pm
Splash::Splash()
{
    sf::Texture m_texture; // Create texture
    sf::Sprite m_sprite(m_texture); // Create sprite and pass texture by reference
} // Delete texture and sprite

You might want to get your good C++ book (https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) again and read up on how class instances get created, how constructor initialization list works and how member variable are set, because you're create a whole new m_sprite within the constructor, but you never use the member variable which has the same name.
And then you don't keep the texture alive while you use it. So even if you set the texture of the member sprite, by the time the constructor is left, the texture will get destroyed and with it the whole image information is gone. ;)

I can also highly recommend the official tutorials (http://www.sfml-dev.org/tutorials/2.3/) which tackles the texture issue and many other useful things.
Title: Re: Problem with a Drawable splash to draw to window
Post by: ralligood2 on July 04, 2015, 09:06:46 pm
Thank you eXpl0it3r for all the comments about my code. :) They really helped me correct my code and got it working. I'm just getting my hands wet on programming with graphics. I'm still in school and next semester is my first OOP class which will cover most of the items you listed in your comments. Since I'm a nice person and there isn't much resources on the web that gives full code on creating a drawable class in a .h file and the main.cpp file. I'll share the full code in hopes that someone else will find it useful. This code does work and was compiled and tested running Arch Linux.

FILE: splash.h
#ifndef SPLASH_H
#define SPLASH_H

#include <SFML/Graphics.hpp>
#include <SFML/OpenGL.hpp>
#include <iostream>

class Splash : public sf::Drawable
{
   
    private:
        sf::Sprite m_sprite;
        sf::Texture m_texture;
        sf::RectangleShape m_rectangleShape;
        int screenX;
        int screenY;
        float winX;
        float winY;

            virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
            {
                target.draw(m_sprite, states);
            }
    public:
        Splash();
        void loadTexture();
        sf::Sprite setSprite();
};

Splash::Splash()
{
        screenX = sf::VideoMode::getDesktopMode().width;
        screenY = sf::VideoMode::getDesktopMode().height;
        winX = 800;
        winY = 600;
}

void Splash::loadTexture()
{
    if (!m_texture.loadFromFile("resources/Splash.png", sf::IntRect(0, 0, winX, winY)))
    {
        std::cout << "Could not load texture." << std::endl;
    }
}

sf::Sprite Splash::setSprite()
{
    std::cout << "setSprite Member Function was called" << std::endl;
    m_sprite.setTexture(m_texture);
    m_sprite.setPosition(((screenX/2)-winX)/2, (screenY-winY)/2);
return m_sprite;
}

#endif
 

FILE: main.cpp

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <SFML/OpenGL.hpp>
#include <iostream>
#include "splash.h"

int main()
{
    Splash loadSplash;
        loadSplash.loadTexture();
     
        sf::Sprite mySprite;
            mySprite = loadSplash.setSprite();

    sf::ContextSettings contextSettings;
    contextSettings.depthBits = 24;
    int screenX = sf::VideoMode::getDesktopMode().width;
    int screenY = sf::VideoMode::getDesktopMode().height;

    sf::RenderWindow mainWin(sf::VideoMode(screenX/2, screenY), "Main Window", sf::Style::Default, contextSettings);
    mainWin.setVerticalSyncEnabled(true);
    mainWin.setPosition(sf::Vector2i(0, 0));    

    while (mainWin.isOpen())
    {
        sf::Event event;  
 
        while (mainWin.pollEvent(event))
        {

            // Close window: exit
            if (event.type == sf::Event::Closed)
                mainWin.close();

            // Escape key: exit
            if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))
                mainWin.close();
            if(event.type == sf::Event::MouseMoved)
            {
                std::cout << "x=" << event.mouseMove.x << ", y=" << event.mouseMove.y << std::endl;
            }
        }

        // Clear the depth buffer
        glClear(GL_DEPTH_BUFFER_BIT);
       
        mainWin.clear(sf::Color(35,44,69,255));
        mainWin.draw(mySprite);

        // Finally, display the rendered frame on screen
        mainWin.display();
    }

    return 0;
}
 

Title: Re: Problem with a Drawable splash to draw to window
Post by: eXpl0it3r on July 04, 2015, 10:45:44 pm
Since you're in for learning things, here's how I would refactor the posted code:

Splash.hpp
#ifndef SPLASH_HPP
#define SPLASH_HPP

#include <SFML/Graphics.hpp>
#include <iostream>

class Splash : public sf::Drawable
{
public:
    Splash();
    virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const;
   
private:
    sf::Sprite m_sprite;
    sf::Texture m_texture;
    sf::Vector2u m_screenSize;
    sf::Vector2u m_windowSize;
};

#endif // SPLASH_HPP
 

Spalsh.cpp
#include "Splash.hpp"

Splash::Splash()
: m_sprite(m_texture)
, m_screenSize(sf::VideoMode::getDesktopMode().width, sf::VideoMode::getDesktopMode().height)
, m_windowSize(800, 600)
{
    m_sprite.setPosition(((m_screenSize.x / 2.f) - m_windowSize.x) / 2.f, (m_screenSize.y - m_windowSize.y) / 2.f);
   
    if (!m_texture.loadFromFile("resources/Splash.png", sf::IntRect(0, 0, m_windowSize.x, m_windowSize.y)))
    {
        std::cout << "Could not load texture." << std::endl;
    }
}

void Splash::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
    target.draw(m_sprite, states);
}
 

main.cpp

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics.hpp>
#include <SFML/OpenGL.hpp>
#include <SFML/System.hpp>
#include <iostream>
#include "Splash.hpp"

int main()
{
    Splash splash;

    sf::ContextSettings contextSettings;
    contextSettings.depthBits = 24;
    sf::Vector2u screenSize(sf::VideoMode::getDesktopMode().width, sf::VideoMode::getDesktopMode().height);

    sf::RenderWindow mainWin(sf::VideoMode(screenSize.x / 2.f, screenSize.y), "Main Window", sf::Style::Default, contextSettings);
    mainWin.setVerticalSyncEnabled(true);
    mainWin.setPosition(sf::Vector2i(0, 0));    

    while (mainWin.isOpen())
    {
        sf::Event event;  
 
        while (mainWin.pollEvent(event))
        {
            // Close window: exit
            if (event.type == sf::Event::Closed)
                mainWin.close();

            // Escape key: exit
            if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))
                mainWin.close();
               
            if(event.type == sf::Event::MouseMoved)
                std::cout << "x=" << event.mouseMove.x << ", y=" << event.mouseMove.y << std::endl;
        }

        // Clear the depth buffer
        glClear(GL_DEPTH_BUFFER_BIT);
       
        mainWin.clear(sf::Color(35,44,69,255));
        mainWin.draw(splash);

        // Finally, display the rendered frame on screen
        mainWin.display();
    }
}
 

Here a few comments on what I changed:


One thing I don't understand is your OpenGL code to clear the depth buffer. What's that for?
Title: Re: Problem with a Drawable splash to draw to window [SOLVED]
Post by: ralligood2 on July 04, 2015, 11:25:58 pm
That is some old code that I was playing around before all this. I've deleted that code already after posting the last posting. Thanks for the comments, I'll surely take a look at what you changed.
Title: Re: Problem with a Drawable splash to draw to window [SOLVED]
Post by: ralligood2 on July 05, 2015, 05:57:46 am
Ok so I created the files and tried to compile and during linking I got some errors.

main.o: In function `main':
main.cpp:(.text+0xb6): undefined reference to `Splash::Splash()'
main.o: In function `Splash::~Splash()':
main.cpp:(.text._ZN6SplashD2Ev[_ZN6SplashD5Ev]+0xe): undefined reference to `vtable for Splash'
collect2: error: ld returned 1 exit status

Here are the commands that I used:
g++ -c main.cpp
g++ main.o -o Main -lsfml-graphics -lsfml-window -lsfml-system -lglut -lGLU -lGL -lXmu -lX11
Title: AW: Problem with a Drawable splash to draw to window [SOLVED]
Post by: eXpl0it3r on July 05, 2015, 08:00:57 am
You didn't compile the Splash.cpp.
Title: Re: Problem with a Drawable splash to draw to window [SOLVED]
Post by: ralligood2 on July 05, 2015, 05:03:54 pm
Right that would help. Thanks again. The window is working but the spalsh isn't showing. Any idea?
Thanks
Title: Re: Problem with a Drawable splash to draw to window [SOLVED]
Post by: eXpl0it3r on July 05, 2015, 05:14:13 pm
I'd blame your math. I just refactored the code, didn't really check the logic. ;)
Title: Re: Problem with a Drawable splash to draw to window [SOLVED]
Post by: ralligood2 on July 06, 2015, 02:34:54 am
I'll admit that my math isn't the best :), but it wasn't my math this time....LOL When you refactored the code you placed the sprite to set the texture before the block of code to loadfromfile, so the constructor was trying to set the texture that wasn't even loaded yet. Once I placed setTexture after that block of code, it appeared. Thanks for your help.