-
I'm creating a 2D tile engine with C++ and SFML 2.0. I have no errors yet when I build and run the code I just get a black render window. I'm probably doing something really stupid but help is really appreciated. I'm also not getting the "can't find file" error that should apparently pop up. I'll post code if needed/asked.
http://imgur.com/WQLQ1,XGXsL,XWWsQ
Those are 3 pictures. 1 of my project folder showing the texture, 2 showing the code where I try to get the image and 3 showing the black render window.
I thank you in advance for any help.
-
How are we supposed to know why your texture doesn't work by looking at screen of files.. especially if you don't get can't find file.. :o
-
Copying code must be eeextremly complex... ::)
From the small snippet I can't determine anything. Might be that the texture gets invalid on copying, might be that you don't adjust the texture rect, might be that you accidentally change the view so it doesn't show anymore, etc etc.
You need to shrink your code until you get a minimal and complete example that reproduces the problem and if you do it right, you'll most probably find the problem on your own...
-
I didn't copy any code. I read an outdated tutorial about it, wrote everything and then updated it with SFML 2.0. I didn't copy and paste anything. Once again, I said I will provide any code that's asked for.
-
Once again, I said I will provide any code that's asked for.
YES,PLEASE. Provide the code...
-
There's quite a lot so I'll add it in different replies.
TextureManager.cpp and TextureManager.h
#include "TextureManager.h"
#include <vector>
#include <SFML\Graphics.hpp>
TextureManager::TextureManager()
{
}
TextureManager::~TextureManager()
{
}
void TextureManager::AddTexture(sf::Texture& texture)
{
// Adds the image to the end of the vector
textureList.push_back(texture);
}
sf::Texture& TextureManager::GetTexture(int index)
{
// Return the index of the image being retrived
return textureList[index];
}
#ifndef _TEXTUREMANAGER_H
#define _TEXTUREMANAGER_H
#include <vector>
#include <SFML\Graphics.hpp>
using namespace std;
class TextureManager
{
private:
// Creting vector to hold images
vector<sf::Texture> textureList;
public:
//Constructor
TextureManager();
//Destructer
~TextureManager();
// Adding an image
void AddTexture(sf::Texture& texture);
// Retrieving an image
sf::Texture& GetTexture(int index);
};
#endif
-
Tile.h and Tile.cpp
#ifndef _TILE_H
#define _TILE_H
#include <SFML\Graphics.hpp>
class Tile
{
private:
// Initializing the sprite
sf::Sprite baseSprite;
public:
// Constructor
Tile(sf::Texture& texture);
// Destructor
~Tile();
// Draws tile to the specifix co-ordinates and window
void Draw(float x, float y, sf::RenderWindow* rw);
};
#endif
#include "Tile.h"
#include <SFML\Graphics.hpp>
Tile::Tile(sf::Texture& texture)
{
// Setting the image of baseSprite
baseSprite.setTexture(texture);
}
Tile::~Tile()
{
}
void Tile::Draw(float x, float y, sf::RenderWindow* rw)
{
// Setting the position off the sprite
baseSprite.setPosition(x, y);
// The render window draws on the sprite
rw->draw(baseSprite);
}
-
Engine.cpp and Engine.h
#include "Engine.h"
#include <SFML\Graphics.hpp>
#include "TextureManager.h"
Engine::Engine()
{
}
Engine::~Engine()
{
{
delete window;
//this is so that the 'window = new sf::RenderWindow' is removed from memory when the engine stops)
delete textureManager;
//this is so that the texturemanager is also deleted once the engine is stopped
}
}
bool Engine::Init()
{
// Setting up the window
window = new sf::RenderWindow(sf::VideoMode(800, 600, 32), "Vanity Engine V0.1");
textureManager = new TextureManager();
// If the window is already open, don't make a new one
if(!window)
return false;
LoadTextures();
return true;
}
void Engine::LoadTextures()
{
sf::Texture texture;
// Load tile textue
texture.loadFromFile("grassTile.png");
// Add the image to imageManager
textureManager->AddTexture(texture);
// Initialize grassTile as a new tile and set it's texture
grassTile = new Tile(textureManager->GetTexture(0));
}
void Engine::RenderFrame()
{
// Clear the window
window->clear();
// Draw the tile to X = 0, Y = 0 on the render window
grassTile->Draw(0,0, window);
// Render window displays the tile
window->display();
}
void Engine::ProcessInput()
{
// Initiate an event
sf::Event evt;
// Loop through all the window events
while(window->pollEvent(evt))
{
// If the user closes the program the window closes
if(evt.type == sf::Event::Closed)
window->close();
}
}
void Engine::Update()
{
}
void Engine::MainLoop()
{
//Loop until the window is closed
while(window->isOpen())
{
ProcessInput();
Update();
RenderFrame();
}
}
void Engine::Go()
{
if(!Init())
throw "Could not intialize Engine";
MainLoop();
}
#ifndef _ENGINE_H
#define _ENGINE_H
#include <SFML\Graphics.hpp>
#include "TextureManager.h"
#include "Tile.h"
class Engine
{
private:
// The window where everything is rendered
sf::RenderWindow* window;
// Adding instance of ImageManager
TextureManager* textureManager;
// Loads the images
void LoadTextures();
// Set up the tile
Tile* grassTile;
//Initialising the engine
bool Init();
//The main loop of the game
void MainLoop();
//Renders one frame
void RenderFrame();
//Processes any user input
void ProcessInput();
//Updates the internal processes of the Engine
void Update();
public:
//Constructer
Engine();
//Destructer
~Engine();
//Starts the engine
void Go();
};
#endif
-
Main.cpp
#include <Windows.h>
#include "Engine.h"
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
Engine* engine = new Engine();
try
{
engine->Go();
}
catch(char* e)
{
MessageBoxA(NULL, e, "Exception Occured", MB_OK | MB_ICONERROR);
}
}
-
Vector is a container that keeps reallocating itself so your texture references may become invalid.
Try changing it to something less insane for this task (ie. std::list) and see if that's that.
-
Could you post an example? It keeps giving me errors.
-
Since you're only adding one item to the vector in your code, I don't believe that's a problem, but it certainly could be in the future.
So, for future reference: When you add an item to a vector, it may not have enough memory initially to store it. If it doesn't it allocates more memory, copies/moves what was in the old memory to the new memory, and releases the old memory. This means that any pointers or references to those objects would no longer be referencing valid objects. If those references or pointers are then used/dereferenced the result is undefined behavior which will hopefully just crash the program instead of appearing to work correctly while silently formatting your hard drive.
To avoid that, make sure all textures are loaded before you attach any sprites to them, or use a container like std::deque for which it isn't an issue.
Change your implementation of Engine::LoadTextures to:
void Engine::LoadTextures()
{
sf::Texture texture;
// Load tile textue
if ( !texture.loadFromFile("grassTile.png"))
throw "Unable to open file: grassTile.png" ;
// Add the image to imageManager
textureManager->AddTexture(texture);
// Initialize grassTile as a new tile and set it's texture
grassTile = new Tile(textureManager->GetTexture(0));
}
Run, report, and remember to check return values from functions.
-
Yeah so apparently it can't find the file. I'm starting to think either I'm doing something slightly wrong or it's my laptop. I tried it on Visual C# 2010 by copying and pasting a random tile engine tutorial, yet I still can't manage to get the texture on that either. Is there something I have to specifically do except for writing that find file code to get it to work?
-
Is there something I have to specifically do except for writing that find file code to get it to work?
You could put the file where the program expects to find it.
If you're using Visual Studio and running from the IDE, the default location is the same place it places your source files. So just open a file in the IDE, right click on the tab and click "Open Containing Folder." Paste your file into that folder and it should work. Of course, if you've messed with the default settings that may not be the case.
Then you may need to check under project settings -> configuration properties -> debugging -> working directory. You can choose edit from the pulldown box and click the macros button to see what the macro expands to if it happens to be a macro.
At least, that's how it works for C++. You mentioned C#, and I don't know if that's handled the same way.
-
I'll try that out, thanks!