SFML community forums

Help => Graphics => Topic started by: wh1t3crayon on December 08, 2014, 02:31:03 pm

Title: SFML Texture only showing up as a black box?
Post by: wh1t3crayon on December 08, 2014, 02:31:03 pm
I've heard of the white box issue, but why is only a black box rendering where my sprite is? My code was working fine until I gave the sprite its own class, then it stopped responding to all setPositions()'s and is only showing a 10*10 black box (the texture is 10*10 as well). Here is the new code I tried to implement
Flashlight::Flashlight(){
        light.setOrigin(light.getGlobalBounds().width / 4, light.getGlobalBounds().height / 2);
        light.setPosition(250, 250);
        light.setTexture(imgr.GetImage("images/light.png"));
}
light light is a class sprite. I set their velocites like this:
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){
                flashlight.AddVelocity(sf::Vector2f(-1, 0));
        }

//and

void Flashlight::AddVelocity(sf::Vector2f increment){
        velocityX += increment.x;
        velocityY += increment.y;
}

//return functions
sf::Vector2f &Flashlight::GetVelocity(){
        if(velocityX >= MAX_FLASHLIGHT_VELOCITY.x){
                velocityX = MAX_FLASHLIGHT_VELOCITY.x;
        }
        if(velocityY >= MAX_FLASHLIGHT_VELOCITY.y){
                velocityY = MAX_FLASHLIGHT_VELOCITY.y;
        }
        return sf::Vector2f(velocityX, velocityY);
}

sf::Sprite Flashlight::GetLight(){
        return light;
}

//and move the sprite, which is also not working
void Engine::Update(float interpolation){
        if(CollisionTest() == false){
                flashlight.GetLight().move(flashlight.GetVelocity().x * interpolation * .8, flashlight.GetVelocity().y * interpolation * .8);
                flashlight.GetShader().setPosition(flashlight.GetLight().getPosition());
        }
}
 
Where flashlight is an object of my new class I created.
That's everything related to my new code. I'm not sure why the sprite is now unresponsive, but any help would be appreciated.
Title: Re: SFML Texture only showing up as a black box?
Post by: Raincode on December 08, 2014, 04:28:28 pm
instead of
sf::Sprite Flashlight::GetLight(){
    return light;
}
you should have a function
Flashlight::move(dt)
 
Title: Re: SFML Texture only showing up as a black box?
Post by: wh1t3crayon on December 08, 2014, 06:02:59 pm
Ok, but what about the texture not rendering properly?
Title: Re: SFML Texture only showing up as a black box?
Post by: eXpl0it3r on December 08, 2014, 07:06:45 pm
You should by now know what the rules are (http://en.sfml-dev.org/forums/index.php?topic=5559.0). Provide a minimal and complete example. Describe what you're doing - give context. Add your OS, compiler, etc. etc.
Title: Re: SFML Texture only showing up as a black box?
Post by: wh1t3crayon on December 08, 2014, 07:25:48 pm
vs c++11, windows 8, and the code was honestly as minimal as I was able to make it because I wanted to show that the sprite is in a seperate class from where it is being accessed. The context I thought was fairly given in the OP? If not, I'm trying to draw a sprite stored in a different class, but upon drawing it I cannot set its position and a same-sized black box appears where the sprite's initial position is.
Title: Re: SFML Texture only showing up as a black box?
Post by: smguyk on December 08, 2014, 07:29:53 pm
I think it's because you return a copy in this function

sf::Sprite Flashlight::GetLight(){
    return light;
}

instead of a reference or pointer to the sprite.
Title: Re: SFML Texture only showing up as a black box?
Post by: G. on December 08, 2014, 07:31:16 pm
GetLight returns a copy of your sprite.
That's far from complete and minimal, have you read the link given by expl0iter? ???
Title: Re: SFML Texture only showing up as a black box?
Post by: eXpl0it3r on December 08, 2014, 07:32:49 pm
It does say minimal and complete. While you have everything in your head and know what gets drawn where and when and how, we've no idea. ;)

For example: What does imgr.GetImage() return? If we couldn't deduce from the functions called, we wouldn't be able to know that light is a sprite. How are light and flashlight connected? How do you draw things? Do you copy that "different class" around? etc. etc.

I think it's because you return a copy in this function

sf::Sprite Flashlight::GetLight(){
    return light;
}

instead of a reference or pointer to the sprite.
That doesn't have to be an issue. The texture reference will get copied as well.
Title: Re: SFML Texture only showing up as a black box?
Post by: wh1t3crayon on December 08, 2014, 08:07:23 pm
Actually, that was half the issue. Returning a reference gave me control of the sprite's position. So about the code I provided, how would I change it any while still keeping the original functions? It seems to give the complete idea, mostly.
Quote
What does imgr.GetImage() return?
That function returns a sf::texture which is mapped to the given filename.
And I did create just a sprite without the Flashlight class and it rendered fine, so I know it's not an issue with the .png file.
Title: Re: SFML Texture only showing up as a black box?
Post by: eXpl0it3r on December 08, 2014, 08:10:23 pm
The goal is not to keep all the functions, but it's to keep all the code that generates the issue.
Create new stub classes with just one function or don't use classes at all. Start from scratch with a plain old main function and build up your scenario, etc.
It's not about throwing the code out there and hoping someone spots the issue, but it's about cutting out everything that has nothing to do with the issue, thus isolating the issue itself and making it more obvious where the issue is. THIS is what a programmers main skill should be: Isolating and solving problems. ;)

If it returns a plain sf::Texture, that is not a reference or pointer to said object, then the texture of which you give the reference to the sprite, will be deleted after setTexture() has been executed.
Title: Re: SFML Texture only showing up as a black box?
Post by: wh1t3crayon on December 08, 2014, 08:12:48 pm
Sorry, you're right, it does return a reference. It's just something from a tutorial I found, but it has worked before so I knew that wasn't the issue either.
Title: Re: SFML Texture only showing up as a black box?
Post by: eXpl0it3r on December 08, 2014, 08:14:20 pm
You knew, we didn't and that's exactly the reason why a complete example is so important. ;)

Anyways maybe someone else understands your setup just from that vague description and these random bits of code. Unfortunately I don't.
Title: Re: SFML Texture only showing up as a black box?
Post by: wh1t3crayon on December 08, 2014, 08:25:35 pm
Fair enough, but hopefully that's not to be confused with a "case closed." The situation is exactly like the infamous "white square problem" except with a black square. Has anybody even heard of this?
Title: Re: SFML Texture only showing up as a black box?
Post by: eXpl0it3r on December 08, 2014, 08:34:17 pm
I can go on a bit with wild guesses, but at some point I'll stop bothering. ;)

The "white square" problem only is white, because the default color of the sprite is white. If you change the sprite color to black, it will be black. Or if the alpha channel is fully transparent and you render it with some blend modes, it will let through what ever lies behind it, which might be black.
Title: Re: SFML Texture only showing up as a black box?
Post by: Raincode on December 08, 2014, 10:23:30 pm
How is one supposed to tell, why you are seeing a black square, without you even showing the code where your sprite is drawn? I can only say what has been said. Create a minimal example, that compiles, which illustrates your problem. Who knows, you might solve it yourself trying to do so. At least show more code. Maybe someone can find the error without making a program from it.

Nobody can guess what the error might be. Or maybe one could, but it wold most likely lead to nothing

One more thing: I checked the docs and couldn't find a ´setPosition()´ member function for shaders. This makes
flashlight.GetShader().setPosition(...
rather confusing
Title: Re: SFML Texture only showing up as a black box?
Post by: wh1t3crayon on December 09, 2014, 01:13:43 am
Ok, so here is a compile-able piece of code. The movement is glitchy, but whatever, the image draws on screen just fine. The black box issue comes in whenever I give the sprite flashlight its own class, which is why I had all the random bits of code.
#include "stdafx.h"
#include "SFML\Graphics.hpp"


int _tmain(int argc, _TCHAR* argv[])
{
        sf::RenderWindow window;
        window.create(sf::VideoMode(500, 500, 32), "Test");
        sf::Sprite flashlight;
        sf::Texture texture;
        texture.loadFromFile("images/light.png");
        flashlight.setTexture(texture);

        const sf::Vector2i MAX_FLASHLIGHT_VELOCITY = sf::Vector2i(5, 5);
        sf::Vector2f flashlightVelocity(0, 0);

        while(window.isOpen()){
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){
                        flashlightVelocity.x -= 1;
                }
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
                        flashlightVelocity.x += 1;
                }
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down)){
                        flashlightVelocity.y += 1;
                }
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up)){
                        flashlightVelocity.y -= 1;
                }
                if(flashlightVelocity.x > MAX_FLASHLIGHT_VELOCITY.x){
                        flashlightVelocity.x = MAX_FLASHLIGHT_VELOCITY.x;
                }
                if(flashlightVelocity.x < MAX_FLASHLIGHT_VELOCITY.x * -1){
                        flashlightVelocity.x = MAX_FLASHLIGHT_VELOCITY.x * -1;
                }
                if(flashlightVelocity.y > MAX_FLASHLIGHT_VELOCITY.y){
                        flashlightVelocity.y = MAX_FLASHLIGHT_VELOCITY.y;
                }
                if(flashlightVelocity.y < MAX_FLASHLIGHT_VELOCITY.y * -1){
                        flashlightVelocity.y = MAX_FLASHLIGHT_VELOCITY.y * -1;
                }
                flashlight.move(flashlightVelocity);
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
                        window.close();

                window.clear();
                window.draw(flashlight);
                window.display();
        }

        return 0;
}

Like I said, that works. This will be long, but here is the full code of the flashlight class just so you guys can see what I am working with:
flashlight.h
#include "stdafx.h"
#include "SFML\Graphics.hpp"
        #pragma once
#include "stdafx.h"
#include "ImageManager.h"

class Flashlight{
public:
        Flashlight();
        ~Flashlight();

        //individual functions for independent collision movement, set both x and y for regular movement
        void AddVelocityX(float increment);
        void AddVelocityY(float increment);
        void AddVelocity(sf::Vector2f increment);
        void SetVelocityX(float velocity);
        void SetVelocityY(float velocity);
        void SetVelocity(sf::Vector2f velocity);
        sf::Vector2f &GetVelocity();

        sf::Sprite &GetLight();
        sf::Sprite &GetShader();
private:
        void CheckVelocities();
        //class objects
        ImageManager imgr;

        float velocityX, velocityY;

        sf::Sprite light;
        sf::Sprite shader;
};
flashlight.cpp
#include "stdafx.h"
#include "Flashlight.h"

const int SCREEN_WIDTH = 500;
const int SCREEN_HEIGHT = 500;

const sf::Vector2i MAX_FLASHLIGHT_VELOCITY = sf::Vector2i(5, 5);

Flashlight::Flashlight(){
        //light.setOrigin(light.getGlobalBounds().width / 2, light.getGlobalBounds().height / 2);
        light.setPosition(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
        light.setTexture(imgr.GetImage("images/light.png"));

        shader.setOrigin(SCREEN_WIDTH, SCREEN_HEIGHT);
        shader.setPosition(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
        light.setTexture(imgr.GetImage("images/shader.png"));

        velocityX = 0;
        velocityY = 0;
}

Flashlight::~Flashlight(){

}

void Flashlight::AddVelocityX(float increment){
        velocityX += increment;
}

void Flashlight::AddVelocityY(float increment){
        velocityY += increment;
}

void Flashlight::AddVelocity(sf::Vector2f increment){
        velocityX += increment.x;
        velocityY += increment.y;
}

void Flashlight::SetVelocityX(float velocity){
        velocityX = velocity;
}

void Flashlight::SetVelocityY(float velocity){
        velocityY = velocity;
}

void Flashlight::SetVelocity(sf::Vector2f velocity){
        velocityX = velocity.x;
        velocityY = velocity.y;
}

sf::Vector2f &Flashlight::GetVelocity(){
        if(velocityX > MAX_FLASHLIGHT_VELOCITY.x){
                velocityX = MAX_FLASHLIGHT_VELOCITY.x;
        }
        if(velocityX < MAX_FLASHLIGHT_VELOCITY.x * -1){
                velocityX = MAX_FLASHLIGHT_VELOCITY.x * -1;
        }
        if(velocityY > MAX_FLASHLIGHT_VELOCITY.y){
                velocityY = MAX_FLASHLIGHT_VELOCITY.y;
        }
        if(velocityY < MAX_FLASHLIGHT_VELOCITY.y * -1){
                velocityY = MAX_FLASHLIGHT_VELOCITY.y * -1;
        }
        return sf::Vector2f(velocityX, velocityY);
}

void Flashlight::CheckVelocities(){
        if(velocityX >= MAX_FLASHLIGHT_VELOCITY.x){
                velocityX = MAX_FLASHLIGHT_VELOCITY.x;
        }
        if(velocityY >= MAX_FLASHLIGHT_VELOCITY.y){
                velocityY = MAX_FLASHLIGHT_VELOCITY.y;
        }
}

sf::Sprite &Flashlight::GetLight(){
        return light;
}

sf::Sprite &Flashlight::GetShader(){
        return shader;
}
 

I draw these sprites the exact same way as I did in the compile-able code:
window.clear(sf::Color::Black);
window.draw(flashlight.GetLight());
        window.draw(flashlight.GetShader());
window.display();
These functions can be seen in the flashlight.cpp code. Sorry that's a little long, it's just hard to find a balance between too much code and incomplete code. Please continute to bear with me.
Title: Re: SFML Texture only showing up as a black box?
Post by: Hapax on December 09, 2014, 09:59:32 am
Have you tried the class without using your ImageManager?
We can only assume that the fault is with ImageManager since we cannot see any of its code (especially since it's supposed to be doing the thing that is failing).
Title: Re: SFML Texture only showing up as a black box?
Post by: eXpl0it3r on December 09, 2014, 10:26:17 am
Is your ImageManager a global? What does the shader thing do? What happens if you disable it?
Title: Re: SFML Texture only showing up as a black box?
Post by: Hapax on December 09, 2014, 10:55:38 am
Is your ImageManager a global?
I initially thought this too but I found it; it's a private member of the Flashlight class.
Title: Re: SFML Texture only showing up as a black box?
Post by: eXpl0it3r on December 09, 2014, 11:03:36 am
Ah I see. Well if a flashlight instance gets copied somewhere, the whole thing would make sense, of course we don't know, since nothing has been provided.

Anyways my last few tries for the "Guess My Code" game are upcoming, if you know what I mean.
Title: Re: SFML Texture only showing up as a black box?
Post by: wh1t3crayon on December 09, 2014, 02:34:05 pm
Wow, ok I found out the soultion while trying to provide a better code sample  ;D So can anybody explain this to me? The solution was that I had to create the sf::Texture on a lower base class than the flashlight class. I'll demonstrate:
class Flashlight{
//...
sf::Sprite flashlight;
//sf::Texture texture; this doesn't work here, it must "go down" a class
};

class BaseClass{
//...
//this class holds both the instance of the Flashlight object and the sf::Texture I was trying to use
Flashlight flashlight;
sf::Texture texture; //I moved the sf::Texture declaration to the class which holds the Flashlight object
//^^why is this necessary
}
 

My question: why does the sf::Texture need to be in the same class as the instance of the Flashlight object? Why can't a texture be in the same class as its sprite is? And I know this code is just pseudo-code, but that's because I'm just looking for a more abstract answer now as my problem seems to be solved.
Title: Re: SFML Texture only showing up as a black box?
Post by: eXpl0it3r on December 09, 2014, 02:46:27 pm
You don't derive from the Flashlight class.
Also if you do wonky stuff - which of course we still have no idea about - things can go wrong. Guess you want to read up on polymorphism etc. ;)
Title: Re: SFML Texture only showing up as a black box?
Post by: wh1t3crayon on December 09, 2014, 02:52:32 pm
So it is possible to have the sf::Texture and sf::Sprite in the same class/object? Is there an example of this you can point to?
Title: Re: SFML Texture only showing up as a black box?
Post by: eXpl0it3r on December 09, 2014, 03:02:23 pm
Yes it's possible and yet I wouldn't recommend it, instead texture should be managed independently from the drawing objects, because they are heavy resources, which shouldn't get copied around.

https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list