Hey, what's up,
I've recently started with SFML, and I've run into the infamous "white square problem". The documentation explains the problem, but doesn't give any hints at solutions. I get that under the hood, it uses a pointer to a texture, but that doesn't explain what "breaks" this pointer or what can be done to keep it "intact" (lol).
So I'm writing this simple 2D shooter, and I have a player class and a laser class. The player class has a vector of lasers, and draws them all in its "update" method. The objects are created and added to the vector, but this is where I'm hitting the white square bug. Here's some code:
// Player class
#include <vector>
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include "PlayerLaser.h"
class Player
{
public:
/**
* Constructor - initialize instance variables
*/
Player();
/**
* Updates the player's position based on keyboard input
* @param[in] Pointer to the keyboard event
*/
void HandleEvents(sf::Event * event);
/**
* Update and draw the object to the screen
* @param[in] Pointer to the window to draw to
* @param[in] The player's speed
*/
void Update(sf::RenderWindow * window, float speed);
private:
sf::Texture texture;
sf::Sprite sprite;
bool MovingLeft, MovingRight, MovingUp, MovingDown;
int index;
std::vector<PlayerLaser> Lasers;
};
Player::Player()
{
// Set up the sprite
if (!texture.loadFromFile("bin\\debug\\graphics\\player.png"))
throw "Failed to load player texture.";
sprite.setTexture(texture);
sprite.setTextureRect(sf::IntRect(0, 0, 64, 32));
sprite.setPosition(320, 320);
// Init other variables
MovingUp = false;
MovingDown = false;
MovingLeft = false;
MovingRight = false;
index = 0;
}
void Player::HandleEvents(sf::Event * event)
{
if (event->type == sf::Event::KeyPressed)
{
if (event->key.code == sf::Keyboard::Left)
MovingLeft = true;
else if (event->key.code == sf::Keyboard::Right)
MovingRight = true;
else if (event->key.code == sf::Keyboard::Up)
MovingUp = true;
else if (event->key.code == sf::Keyboard::Down)
MovingDown = true;
else if (event->key.code == sf::Keyboard::Space)
{
PlayerLaser pl(sprite.getPosition().x, sprite.getPosition().y);
Lasers.push_back(pl);
}
}
else if (event->type == sf::Event::KeyReleased)
{
if (event->key.code == sf::Keyboard::Left)
MovingLeft = false;
else if (event->key.code == sf::Keyboard::Right)
MovingRight = false;
else if (event->key.code == sf::Keyboard::Up)
MovingUp = false;
else if (event->key.code == sf::Keyboard::Down)
MovingDown = false;
}
}
void Player::Update(sf::RenderWindow * window, float speed)
{
// Update the player's animation
index++;
if (index == 1000)
sprite.setTextureRect(sf::IntRect(0, 32, 64, 32));
if (index == 2000)
{
sprite.setTextureRect(sf::IntRect(0, 0, 64, 32));
index = 0;
}
// Update the player's position
if (MovingLeft && sprite.getPosition().x > 0)
sprite.move(speed * -1, 0);
else if (MovingRight && sprite.getPosition().x < 640 - 64)
sprite.move(speed, 0);
if (MovingUp && sprite.getPosition().y > 0)
sprite.move(0, speed * -1);
if (MovingDown && sprite.getPosition().y < 480 - 32)
sprite.move(0, speed);
// Draw the player
window->draw(sprite);
// Draw the lasers
for (PlayerLaser pl : Lasers)
pl.Update(window, speed + (speed / 2));
}
// Main
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include "Background.h"
#include "Player.h"
#include "PlayerLaser.h"
int main()
{
// Create the main window
sf::RenderWindow window(sf::VideoMode(640, 480), "3017");
// Create the background and player objects
Background background;
Player player;
// Test
PlayerLaser pl(32, 32);
/*
// Create a graphical text to display
sf::Font font;
if (!font.loadFromFile("arial.ttf"))
return EXIT_FAILURE;
sf::Text text("Hello SFML", font, 50);
// Load music to play
sf::Music music;
if (!music.openFromFile("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();
else if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape)
window.close();
else
player.HandleEvents(&event);
}
// Clear screen
window.clear();
// Draw the background
background.Update(&window, 0.025);
player.Update(&window, 0.1);
// test - no white square for this instance
pl.Update(&window, 0.2);
// Update the window
window.display();
}
return EXIT_SUCCESS;
}
So the laser object works, if it's created at compile time, before the while loop. But if it's created by the player object pressing space, it gets whitesquared. So are objects not allowed to be created at runtime or something? I suppose if I create every single instance at compile time it'll avoid the problem, but I'd really like to know if there's an actual solution available. Unfortunately my knowledge of SFML's internals, vector's internals and whatever else the heck could be causing this to even come up with a logical theory; so for now I'm left Googling and guessing. (hair--;) lol
Any clues would be greatly appreciated.