The implementation was done to gain better control over the order in which the sprites are drawn on the screen (which sprites that will appear on top of the others) and to simplify changing the view (the portion of the game world that is displayed on the screen) of certain sprites in the game but ignore other sprites like GUIs and HUDs.
In SFML there is a data type called RenderTexture, that works very similar to RenderWindow. The major difference between the two is that RenderWindow creates a graphical window presented on the computer screen whereas RenderTexture can not be viewed, only drawn as sprites on other surfaces.
I use RenderTextures as the data type for my layers. The layers are stored in a list, in the order they are supposed to be drawn out. All sprites are now associated with a layer variable, which is just an integer that the drawing function uses to determine which layer it should be drawn on.
When all sprites are drawn the view is changed on the specified layers by using the inbuilt functionality renderTexture.setView();
A thing to remember when using RenderTexture as a layer is that the RenderTexture.clear() function has by default to fill the screen with a non transparent black color. To make the layer transparent in the clear function you need to specify the clear color like this .clear(sf::color(0x00,0x00,0x00,0x00)) So that the alpha channel (the fourth value) is set to be fully transparent.
Since entities in this game can have more than one sprite I also implemented a sprite list in each entity. The sprite list consists of a std::vector containing std::pair where the first value of that pair is a pointer to a sprite and the second value of the pair is the layer specifying int for that sprite. To reach the sprite, for example when changing the position of it one needs to write like this inside the entity class: m_sprites[index].first->SetPosition(x,y);.
Implementing layers was a high risk move, since I did not know if it was going to work as I wanted and it required rewriting a lot of code in many classes before I could see a result. It took more time than I thought it would because of all the code needed to be rewriten to work with the layer code. I could have reached similar results without the layers by adjusting the position of all sprites according to the game view in the window before every time the sprites are drawn to the window. I choose the layer approach over the moving sprites approach because it made more sense for me to think in terms of layers and I thought it would generate code that was easier to understand and read. In terms of performance I have no idea what approach is more suitable. In the end I got the result I wanted.
Hello Emil, thank you for writing this post. It ‘s always interesting for me to see how other programmers think, while learning a thing or two and indeed i did.
ReplyDeleteI’d like to start with, pointing out the areas the in my opinion needs a little adjustments, keep in mind that these are just personal opinions that could serve as tips to let the non-programmers understand your development process better. You did explain most of the terms that was foreign to non-programmers, which were excellent explanations that helped me as a programer as well. But sometimes you mentioned some programing terms without explanations, which could confuse the reader, especially if they have not programmed before.
Now let’s start the fun part, you did explain what you were doing very well along side with how you did and why. I want to focus more on the how as it could be sued as a tutorial for others which is extremely good when you don't have a lot of code. Exploring the connect from the start and then expanding on why you did and explain you the reasons behind your approach was a superb move that would make others relate more to your work when working on similar subjects. Well done!
I’m looking forward to see your work in action in beta, best of luck!
Marwan