Draw the entire map to a huge canvas (maybe sf::Texture?)I think you may be looking for sf::RenderTexture (http://www.sfml-dev.org/documentation/2.3.2/classsf_1_1RenderTexture.php).
I think you may be looking for sf::RenderTexture (http://www.sfml-dev.org/documentation/2.3.2/classsf_1_1RenderTexture.php).Thanks! That's exactly it!
It should be fine to draw all the tiles directly to the window as long as the ones that are not in display are culled. Combining the tiles and drawing them as a vertex array would also significantly reduce the number of draw calls from, say, drawing each tile as a separate sf::Sprite.
I can imagine setting up a renderTexture for the GUI and keep track of whether it requires redrawing (as the gui will change less often). But the game world is pretty much in constant change due to hero and monster movement and tile animations.I don't think GUI is the reason to use a render texture. Apart from the fact that it would likely change often, with it giving live feedback, it should be absolutely fine to just draw the entire UI directly to the window each frame.
I don't fully see the advantage yet of a renderTexture as opposed to drawing directly to the renderWindow (for the world tiles).There are a few of reasons why you might do this. One is to help alleviate the slight "tile-edging" error that can occur when tiles are transformed to where this occurs. Another is to apply cropping or effects, with effects probably being applied via a shader.
I'm not familiar with the vertex array. Sounds interesting! I will look into this as well. Thanks!If your map is a regular grid and is stored as an array (or vector etc.) of tile numbers, you may be interested in sw::TileMap (https://github.com/Hapaxia/SelbaWard/wiki/Tile-Map), which should do the majority of the ground-work. It internally uses a render texture for a few reasons - the two above are a couple of them.
These seem to work only for single layer tilemaps. I'd like to work with a multi-layer tilemap though.sw::TileMap is designed to be used for static, single layered tile-maps. It could still be used, however, using a few of them drawn directly on top of each other for the layers and choosing the correct tile depending on the frame of animation but this becomes so manual that it's likely to be better to build a more bespoke tile map.
What i mean is, every wold tile is in fact an array of tiles so i can stack multiple tiles on the same spot.
1. Draw visible tiles to offscreen renderTextureIf you are drawing the render texture directly to the window, there is no point in using the render texture because all of the drawing would be the same as the window and then it's just copied onto the window, so it would be the same as doing points 1-4 directly to the window.
2. Draw PCs, NPCs and objects to offscreen renderTexture
3. Apply effects / mask / lighting / what not to offscreen renderTexture
4. Draw the GUI to offscreen renderTexture
5. draw the renderTexture to the renderWindow
What about an array(vector) of sf::RenderTextures? Each render texture would represent a different layer.This could be useful if each layer needs to be processed individually but that's unlikely and probably rare.
Am i understanding correctly that i'm creating / populating the sf::VertexArray for every frame drawn (so in the draw() function)?The draw() method should (usually) be used to draw the vertices to the target, not prepare the vertices. You could simply have an update() function that updates the vertices, which you would update each frame before drawing.
Secondly, seeing as vertexArrays work with positions of textures in a large tilesheet, I'm considering generating the tilesheet on a renderTexture when loading the level. Reason for this is that i store my tiles separately in their own files. During gameplay however, tiles can be affected causing them to change. A full grassplot can turn into a half grassplot or disappear alltogether. If i'd use a rendered tilesheet, i would need to check whether the changed tile exists in the tilesheet and if not, add it (at the cost of performance).So, you want to create a texture programmatically and then use that for your tile map? Although render texture should work for that, I think a render texture might be overkill as it's not getting rendered to often.
The draw() method should (usually) be used to draw the vertices to the target, not prepare the vertices. You could simply have an update() function that updates the vertices, which you would update each frame before drawing.Check. The highlighted code is very useful. Also, yes - It would make more sense to have a separate update function, keeping the draw() function more straightforward.
Possibly something like this:// windowLoop:The update function might look something like this highlighted code in the update method of sw::TileMap (https://github.com/Hapaxia/SelbaWard/blob/master/src/SelbaWard/TileMap.cpp#L262-L295)
{
handleEvents();
updateGameLogicEtc();
updateGraphicsEtc(); // includes tilemap.update()
window.clear();
window.draw(graphics); // include window.draw(tilemap);
window.display();
}
So, you want to create a texture programmatically and then use that for your tile map? Although render texture should work for that, I think a render texture might be overkill as it's not getting rendered to often.Alright. So what if:
An option is to use a temporary sf::Image (http://www.sfml-dev.org/documentation/2.3.2/classsf_1_1Image.php) to create the image texture that you want (you can copy parts of images around) and then transfer it to the sf::Texture that you use for the tile map.
Remember you can load file as images and only transfer to a texture when you need them. (sf::Texture internally uses an sf::Image to load the file and then transfers it)
Thanks a lot for your patience and detailed replies, Hapax. I really appreciate you taking the time to help me out.You're welcome. I'm glad it's helping.
It would make more sense to have a separate update function, keeping the draw() function more straightforward.I probably shouldn't point this out but it is, in fact, possible to update automatically in the draw method but it can get really messy (the draw method is const so it can't/shouldn't alter anything).
1. i'd use a vector <sf::Image> array (TileIndex), with each image representing a tile collection like the grass example i posted earlier -> [grasstiles image, dirttiles image, forestroad tiles, image, etc...]1) vector of sf::Image for each tileset (as you said)
2. Then use this vector <sf::Image> array as the source from which i copy the relevant tiles to a sf::Texture Tilesheet.
3. The Tilesheet is then used by the VertexArray to draw the sf::RenderTexture Tilemap (the visible part of the world).
...(4. bacon...?)
I probably shouldn't point this out but it is, in fact, possible to update automatically in the draw method but it can get really messy (the draw method is const so it can't/shouldn't alter anything).Will do! I wanted to put it all in one draw() function, but i can appreciate keeping the logic separated in favor of code tidyness. This game is a relatively ambitious project (for me), so that's why i'm aiming for the best / most efficient approach.
I did do that for sw::Sprite3D (https://github.com/Hapaxia/SelbaWard/wiki/Sprite-3D) so that it would work in the same way as a normal sf::Sprite - without needing an extra update method. Feel free to have a look through the code ;D
1) vector of sf::Image for each tileset (as you said)Can't get any clearer than this :-). Awesome!
2) create a temporary sf::Image and use the vector to provide the pieces you want to copy, then update the sf::Texture from that image (http://www.sfml-dev.org/documentation/2.3.2/classsf_1_1Texture.php#a037cdf171af0fb392d07626a44a4ea17).
3) use the sf::Texture to draw the vertex array (no render texture needed?)
I'm not sure why you have a render texture although you can either use an sf::Image or an sf::RenderTexture in the place of the "temporary sf::Image" described above.The render Texture in the third step was more meant as drawing to the render object. It could/should have been RenderWindow, but i wrote renderTexture because it still feels strange to draw tile world directly to the window, instead of drawing it in the background and then display whole thing once.
it still feels strange to draw tile world directly to the window, instead of drawing it in the background and then display whole thing once.When drawing to the window, it actually draws to a buffer - not the actual window. It then swaps this buffer with the window's content in one go when you call window.display() (which is why this is required).
Looking forward to the result. Don't forget that the SFML forum has a dedicated Projects forum (http://en.sfml-dev.org/forums/index.php?board=10.0). ;)Yeah i noticed. Some cool stuff there! At the moment it felt a bit premature as i don't have anything visual to show (obviously lol). But as soon as it's starting to take shape i will deff share my project!
When drawing to the window, it actually draws to a buffer - not the actual window. It then swaps this buffer with the window's content in one go when you call window.display() (which is why this is required).Ah right...That makes sense!