I can't figure this out for the life of me – my project was 100% fine until after installing the new templates (w/ clang). My project wouldn't build after the Xcode 5.1 update released a few weeks ago – through research I found that I had to recreate my project and through frustration I simply did that by recreating the files and pasting the code into a command line template project. Now I am having an issue with (some) sprites displaying.
Example: My player fires a bullet. Sometimes the texture is loaded to the bullet, sometimes it is not (white square), sometimes it is a gray line (?).
Here is a gif to show you exactly what I'm referring to:
(https://dl.dropboxusercontent.com/u/82139804/bad_bullets.gif)
the blinking spike is the texture that should be loaded ... as you can see, the texture is sometimes failing to load. I have other sprites, such as the player and enemy which don't fail at all:
(https://dl.dropboxusercontent.com/u/82139804/enemies.gif)
I'm using a Textures class which holds a container for all the sprites to retrieve as reference:
Textures.h
namespace Textures
{
struct TextureObject
{
std::string t_name;
sf::Texture t_texture;
};
class TextureContainer
{
public:
void AddTexture(std::string textureFile);
void TextureList();
TextureContainer();
sf::Texture& SetTexture(std::string temp_name);
std::vector<TextureObject*> textureVector;
};
typedef std::vector<TextureObject*> ::iterator textureIter;
}
Textures.cpp
#include "Textures.h"
#include "ResourcePath.hpp"
namespace Textures{
void TextureContainer::AddTexture(std::string textureFile)
{
TextureObject* newTexture;
newTexture = new TextureObject;
newTexture->t_texture.loadFromFile("/Users/darionmccoy/Desktop/Dooberry/Platformer/Platformer/" + (textureFile));
newTexture->t_texture.setSmooth(false);
newTexture->t_name = textureFile;
textureVector.push_back(newTexture);
}
void TextureContainer::TextureList()
{
std::cout << "Loaded textures ..." << std::endl;
for (textureIter it = textureVector.begin(); it != textureVector.end(); it++)
{
std::cout << (*it)->t_name << std::endl;
}
}
TextureContainer::TextureContainer()
{
AddTexture("block.png");
AddTexture("spike.png");
AddTexture("icon.png");
AddTexture("blip.png");
AddTexture("blip_2.png");
AddTexture("blip_3.png");
AddTexture("bomb.png");
AddTexture("bomb_2.png");
AddTexture("smoke.png");
AddTexture("Pplayer.png");
AddTexture("cluster.png");
AddTexture("polygon.png");
AddTexture("circle.png");
AddTexture("grunt.png");
TextureList();
}
sf::Texture& TextureContainer::SetTexture(std::string temp_name)
{
for (textureIter it = textureVector.begin(); it != textureVector.end(); it++)
{
if((*it)->t_name == temp_name)
{
return (*it)->t_texture;
}
else if(it == textureVector.end() && (*it)->t_name != temp_name)
{
std::cout << "Texture not found" << std::endl;
}
}
}
}
Example of how the texture is set (the bullet):
Projectile::Projectile(Textures::TextureContainer& t_container) : Object (t_container)
{
Object::objectSprite.setTexture((t_container.SetTexture("spike.png")));
Object::objectSprite.setTextureRect(sf::IntRect(0, 0, 25, 8));
}
And the enemy:
Grunt::Grunt(Textures::TextureContainer& t_container) : Object (t_container)
{
objectSprite.setTexture((t_container.SetTexture("grunt.png")));
objectSprite.setTextureRect(sf::IntRect (0,0,20,30));
objectSprite.setPosition((rand() % 300 + 100),0);
}
I would think it is a constructor issue, but I am at a loss what to change since they are all initialized the same way (polymorphism).
I have 0 errors or warnings. Also, I'm on Osx 10.9.2 and Xcode 5.1. Thanks in advanced guys ... in the meantime, I'll try to get some clues.
Just so happened to comment out the code which animates the bullets and the texture doesn't fail as long as it doesn't change frame? This is sort of weird since the player and enemy are animated the same way ... Here is the projectile update() function which animates the bullet (all objects are in a container, which calls their update function to move, animate, etc). I blocked out the animation portion:
void Projectile::Update(Level::LevelContainer& Lvl, Textures::TextureContainer& tbox, Container& PC)
{
sf::Time time = clock.getElapsedTime();
sf::Time frameChange = sf::milliseconds(30);
Animating------------------------
if(time >= frameChange)
{
Object::objectSprite.setTextureRect(sf::IntRect(frame * 25, 0, 25, 8));
frame++;
time = clock.restart();
if(frame == 3)
{
frame = 0;
}
}
------------------------
if(velX < 0)
{
objectSprite.setTextureRect(sf::IntRect(25, 0, -25, 8));
}
objectSprite.move(velX,0);
if(objectSprite.getPosition().x >= 400 || objectSprite.getPosition().x <= 100)
{
for(int i = 0; i < 15; i++)
{
itemQueue particles;
particles.iposX = objectSprite.getPosition().x;
particles.iposY = objectSprite.getPosition().y;
particles.itemType = "Particle";
PC.Queue.push_back(particles);
}
itemQueue bomb;
bomb.iposX = objectSprite.getPosition().x;
bomb.iposY = objectSprite.getPosition().y;
bomb.itemType = "Cluster";
PC.Queue.push_back(bomb);
Object::misDestroyed = true;
}
}
I assumed it was automatically initialized to '0' when declaring without initializing.
That's only true for static and global variables.
In general, you should initialize variables in C++ immediately. Code such as
int i;
i = 7;
or even worse
int i = 0;
... // do something without using i
i = 7;
should be avoided at all costs.