-
Hello!
First: Sry for my bad english :P
I wrote a class to load a map from my map1.txt.
Every value in the maparray is correct.
But i cant see anything in my window except my playercharacter and a black screen behind him, not one single tile.
#include <iostream>
#include <fstream>
#include <vector>
#include <SFML/Graphics.hpp>
using namespace std;
class Map
{
public:
int map_x, map_y;
static int tile;
int map[100][100];
sf::Image image;
sf::Texture textur;
vector<sf::Sprite> tiles;
sf::RenderTexture rMap;
sf::Sprite sMap;
public:
Map()
{
map_x = 0;
map_y = 0;
image.loadFromFile("graphics/boden.png");
if(!image.loadFromFile("graphics/boden.png"))
{
std::cout << "boden.png konnte nicht geladen werden!\n";
}
textur.loadFromImage(image);
};
~Map(){};
void loadMap(const char *filename)
{
int loadCounterX = 0, loadCounterY = 0;
std::ifstream file(filename);
if(file.is_open())
{
file >> map_x >> map_y;
while(!file.eof())
{
file >> map[loadCounterX][loadCounterY];
loadCounterX++;
if(loadCounterX >= map_x)
{
loadCounterX = 0;
loadCounterY++;
}
}
}
for(int x = 0; x < map_x; x++)
{
for(int y = 0;y < map_y; y++)
{
int tileId = map[x][y];
sf::Sprite tile;
tile.setTexture(textur);
tile.setTextureRect(sf::IntRect(map[y][x]*32, 0, 32, 32));
tile.setPosition(x*32, y*32);
tiles.push_back(tile);
}
}
for(int x = 0; x < tiles.size(); x++)
{
rMap.draw(tiles.at(x));
cout << "x";
}
}
sf::Sprite drawMap()
{
rMap.display();
sMap.setTexture(rMap.getTexture());
return sMap;
}
};
first i called this out of the mainloop:
Map map1;
map1.loadMap("map1.txt");
And in my mainloop i call:
Spiel.draw(map1.drawMap());
Hope you can help me.
Greetings!
-
I though I knew that problem from somewhere (spieleprogrammierer)... ;D
The problem I think lies in the call sMap.setTexture(rMap.getTexture());, because you set a new texture but you don't change the size of the texture rectangle, so you actually don't cut out anything from the render texture. (I think Schorsch already tried to point you in that direction).
Try changing it to: sMap.setTexture(rMap.getTexture(), true);
Also you shouldn't return a copy of the sprite when calling drawMap() but instead use a const reference. ;)
-
I though I knew that problem from somewhere (spieleprogrammierer)... ;D
The problem I think lies in the call sMap.setTexture(rMap.getTexture());, because you set a new texture but you don't change the size of the texture rectangle, so you actually don't cut out anything from the render texture. (I think Schorsch already tried to point you in that direction).
Try changing it to: sMap.setTexture(rMap.getTexture(), true);
Also you shouldn't return a copy of the sprite when calling drawMap() but instead use a const reference. ;)
:P
sMap.setTexture(rMap.getTexture(), true);
Still everything black. :/
const sf::Sprite sMap
Error at sMap.setTexture(rMap.getTexture(), true);
Error: The object has type qualifiers that are not compatible with the member function
(German error: Error: Das Objekt weist Typqualifizierer auf, die nicht mit der Memberfunktion kompatibel sind)
-
He means that:
const sf::Sprite& drawMap()
(you probably won't notice the difference on the performances though...)
Displaying and assigning the render-texture should only be done once, after drawing. This way, your getter can be const. And it should really have a different name. Calling "draw" something that only returns an object is misleading.
void loadMap(const char *filename)
{
...
rMap.display();
sMap.setTexture(rMap.getTexture());
}
const sf::Sprite& getSprite() const
{
return sMap;
}
Additionnaly, an even better design would be to let the map draw itself, this way it can hide completely all the drawing details and provide a cleaner API to the caller:
void draw(sf::RenderTarget& target) const
{
target.draw(sMap);
}
And... please fix your indentation, some parts of your code are hardly readable.
-
#include <iostream>
#include <fstream>
#include <vector>
#include <SFML/Graphics.hpp>
using namespace std;
class Map
{
public:
int map_x, map_y; // width, height
int map[100][100]; // Maparray
sf::Image image; // Image Tilemap
sf::Texture textur; // Texture from Image Tilemap
vector<sf::Sprite> tiles; // Tilevector
sf::RenderTexture rMap; // Texture sMap
sf::Sprite sMap; // Mapsprite
public:
Map()
{
map_x = 0;
map_y = 0;
// Loading Texture
image.loadFromFile("graphics/boden.png");
if(!image.loadFromFile("graphics/boden.png"))
{
std::cout << "boden.png konnte nicht geladen werden!\n";
}
textur.loadFromImage(image);
};
~Map(){};
// Just tilesize
static int getTile()
{
return 32; // 1 Tile = 32 Pixel
}
void loadMap(const char *filename)
{
// Load map from filename, first line width and height, other lines: id of tile
int loadCounterX = 0, loadCounterY = 0;
std::ifstream file(filename);
if(file.is_open())
{
file >> map_x >> map_y;
while(!file.eof())
{
file >> map[loadCounterX][loadCounterY];
loadCounterX++;
if(loadCounterX >= map_x)
{
loadCounterX = 0;
loadCounterY++;
}
}
}
// Create tiles
for(int x = 0; x < map_x; x++)
{
for(int y = 0;y < map_y; y++)
{
int tileId = map[x][y];
sf::Sprite tile;
tile.setTexture(textur);
tile.setTextureRect(sf::IntRect(map[y][x]*32, 0, 32, 32));
tile.setPosition(x*32, y*32);
tiles.push_back(tile);
}
}
// Draw tiles on rMap
for(int x = 0; x < tiles.size(); x++)
{
rMap.draw(tiles.at(x));
}
rMap.display();
sMap.setTexture(rMap.getTexture(), true);
}
// get Mapsprite
const sf::Sprite& getSprite() const
{
return sMap;
}
//draw Mapsprite on target
void draw(sf::RenderTarget& target) const
{
target.draw(sMap);
}
};
Still everything black. :/
Indentation is changed a bit by the forum, sorry for this.
-
You should provide a minimal and complete example and include a map file, so we could test everything... ;)
-
map1.txt is like:
3 3
0 2 1
2 0 1
main.cpp (copied important lines from mine):
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include "map.cpp"
sf::RenderWindow window(sf::VideoMode(800, 608, 32), "Spiel", sf::Style::Close);
Spiel.setVerticalSyncEnabled(true);
Map map1;
map1.loadMap("map1.txt");
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
switch(event.type)
{
case sf::Event::Closed:
window.close();
break;
default:
break;
}
}
window.clear();
map1.draw(window);
window.display();
}
}
return EXIT_SUCCESS;
}
map.cpp:
see above
EDIT:
You should fix the code-tag, everytime it ruins my indentation :P
-
You should fix the code-tag, everytime it ruins my indentation
The code tag is not broken, it shows exactly what you type.
-
The whole problem was that you never created the render texture, thus it had a size of (0,0) and obviously nothing gets displayed...
Here's a fully working code. I cleaned up your strange indentation (now uses tabs) and removed the useless vector thingy. I mean there's no sense in reading it into one vector if you're going to draw it once to a render texture and then use that texture. You don't need the sprites objects later. I also fixed the possibility that the program crashes if the map file doesn't exists and a few other minor things...
You should really stop just trying to 'solve' things by programming and rather sit down and think about what you're doing. ;)
Edit: Hmm the indentation doesn't look that nice now either...
@Laurent: Is it really necessary that one tab gets translated to 8 spaces? :O
#include <iostream>
#include <fstream>
#include <SFML/Graphics.hpp>
class Map
{
public:
int map_x, map_y; // width, height
int map[100][100]; // Maparray
sf::Texture textur; // Texture from Image Tilemap
sf::RenderTexture rMap; // Texture sMap
sf::Sprite sMap; // Mapsprite
public:
Map() :
map_x(0),
map_y(0)
{
// Loading Texture
if(!textur.loadFromFile("boden.png"))
{
std::cout << "boden.png konnte nicht geladen werden!\n";
}
};
// Just tilesize
static int getTile()
{
return 32; // 1 Tile = 32 Pixel
}
void loadMap(const char *filename)
{
// Load map from filename, first line width and height, other lines: id of tile
int loadCounterX = 0, loadCounterY = 0;
std::ifstream file(filename);
// Exit if file doesn't exist
if(!file.is_open())
{
std::cout << "Couldn't open '" << filename << "'. Aborting." << std::endl;
return;
}
file >> map_x >> map_y;
while(!file.eof())
{
file >> map[loadCounterX][loadCounterY];
loadCounterX++;
if(loadCounterX >= map_x)
{
loadCounterX = 0;
loadCounterY++;
}
}
// Create the off screen texture
rMap.create(map_x*32, map_y*32);
rMap.clear();
// Create tiles
for(unsigned int y = 0; y < map_y; ++y)
for(unsigned int x = 0; x < map_x; ++x)
{
sf::IntRect ir(map[y][x]*32, 0, 32, 32);
sf::Sprite sprite(textur, sf::IntRect(map[y][x]*32, 0, 32, 32));
sprite.setPosition(x*32, y*32);
rMap.draw(sprite);
}
rMap.display();
rMap.getTexture().copyToImage().saveToFile("test.png");
sMap.setTexture(rMap.getTexture(), true);
}
// get Mapsprite
const sf::Sprite& getSprite() const
{
return sMap;
}
//draw Mapsprite on target
void draw(sf::RenderTarget& target) const
{
target.draw(sMap);
}
};
int main()
{
// Create window
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML");
// Limit framerate
window.setFramerateLimit(60);
Map mm;
mm.loadMap("map1.txt");
while(window.isOpen())
{
// Event handling
sf::Event event;
while(window.pollEvent(event))
{
if(event.type == sf::Event::Closed)
window.close();
}
// Render
window.clear();
mm.draw(window);
window.display();
}
}
-
@Laurent: Is it really necessary that one tab gets translated to 8 spaces? :O
The mod doesn't allow to change the tab width through the admin panel. I have to add a line of code to the mod sources.
And if I change the mod settings so that tabs are not translated to spaces, I lose line breaks :(
-
The mod doesn't allow to change the tab width through the admin panel. I have to add a line of code to the mod sources.
I guess/hope shouldn't be that hard...
I'd suggest a 1 tab = 4 spaces translation, which is what you mostly get as default setting in many editors.
And if I change the mod settings so that tabs are not translated to spaces, I lose line breaks :(
Bad mod! :P
-
I guess/hope shouldn't be that hard...
Yep, I'll try that as soon as I can.
-
Thanks eXpl0it3r, everything works fine now.
@Laurent:
My indentation in VC++ is made with tabs, not spaces. After copy it into the codefunction, everything was messy so i had to clean it with spaces. That's why it looks so bad here.
Problem is fixed and thread can be closed now.
Thank you!
-
My indentation in VC++ is made with tabs, not spaces. After copy it into the codefunction, everything was messy so i had to clean it with spaces. That's why it looks so bad here.
I was not talking about the indentation length, but about things that were not properly aligned although they belong to the same level of indentation (the texture loading in your first post, the event loop in your last post, etc.).
-
I'd suggest a 1 tab = 4 spaces translation
Done :)
-
I'd suggest a 1 tab = 4 spaces translation
Done :)
You're awesome! :)
Btw would it be possible to install the tapatalk mod, so one could read the forum easily on the phone?
-
Btw would it be possible to install the tapatalk mod, so one could read the forum easily on the phone?
Ha! This is working great, thanks a lot! :-)
-
You're faster than light ;D
I'll open a new topic so that we can stop polluting this one.