Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Need help with sf::Texture, sf::Sprite and design choices  (Read 5400 times)

0 Members and 2 Guests are viewing this topic.

MrPlow442

  • Newbie
  • *
  • Posts: 14
    • View Profile
Need help with sf::Texture, sf::Sprite and design choices
« on: February 22, 2013, 06:24:33 pm »
I'm not sure whether this is the appropriate forum section so I apologize if I messed up.

Basically I'm trying to make a Tic-Tac-Toe game for my first project while also trying to write classes to possibly be reusable in other future projects with little to no changes.

Right now the biggest question for me is how should i handle textures and sprites.
I'm making a Texture cache similar to this sprite cache code, and creating a tile class which will contain certain info such as states(like locked or interactable) and owner( cross or circle in this case, although I'm thinking of replacing this with some sort of a player reference or something ) and a board class which will basically contain an std::array of tiles to manipulate them.

First question would be:
Regarding the texture cache being made similar to the sprite cache code above: since the sf::Sprite takes a reference to a sf::Texture then there should be no problem with my cache since the texture will be alive for as long as there are sprites referencing it? Or am I thinking it wrongly?

And my second question would be:
What would be a better overall design choice:
a) to have the board class load the texture and for each tile to have it's own sf::Sprite?
b) to have the board and tile classes only contain "logic" parts, and have a separate manager class to take care of creating sprites and drawing and then somehow unify all that in the main game class?
c) neither?




Haze

  • Full Member
  • ***
  • Posts: 201
    • View Profile
    • Github Profile
Re: Need help with sf::Texture, sf::Sprite and design choices
« Reply #1 on: February 22, 2013, 07:07:25 pm »
since the sf::Sprite takes a reference to a sf::Texture then there should be no problem with my cache since the texture will be alive for as long as there are sprites referencing it? Or am I thinking it wrongly?

The sf::Sprite class doesn't own a copy of the texture, only a pointer. So when you call sf::Sprite::setTexture, you have to make sure the texture object is stored somewhere else during the sprite lifetime.
That's why almost all applications use a resource manager :
- textures being heavy resources, it ensures each resource is loaded once and only once.
- it also ensures the textures will remain available during all the program execution

What would be a better overall design choice:
a) to have the board class load the texture and for each tile to have it's own sf::Sprite?
b) to have the board and tile classes only contain "logic" parts, and have a separate manager class to take care of creating sprites and drawing and then somehow unify all that in the main game class?
c) neither?
I would say the Board class acts as the tile manager, and I would either make Tile inherit from sf::Sprite, or Tile having a sf::Sprite attribute. (You're not supposed to inherit SMFL classes because it's not a framework, but I confess it can be convenient sometimes).
A resource manager class will store the textures, and you can set the tile's texture either from the Board class, of from the Tile class itself.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Need help with sf::Texture, sf::Sprite and design choices
« Reply #2 on: February 22, 2013, 08:24:18 pm »
Something I also had to teach myself: Don't make things more complicated than necessary. Manager classes, shared and weak pointers are rarely necessary -- mainly if you have true shared ownership and can't determine a class to have responsibilities about resources. For such cases, I have also written thor::ResourceCache, so you wouldn't need to reinvent the wheel.

But often, a simple STL container (std::map if you have some sort of ID) is enough to store textures. You can then distribute raw pointers, given that you guarantee the lifetime of the resources.

Concerning your board, you can try to have only logic in the tiles. In my game Zloxx II, each tile contains only a few attributes like type or animation step. I even create a new sf::Sprite in each frame for each visible tile, and I have not had any performance problems. In such a case, you could still take sf::VertexArray or try other optimizations.

You can also have a sf::Sprite as a member (not base class!) of your tile class, however tiles become more heavyweight as a result. Copies are more expensive, and you need to keep data like the position or texture rect always synchronous and sometimes even duplicate information.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

MrPlow442

  • Newbie
  • *
  • Posts: 14
    • View Profile
Re: Need help with sf::Texture, sf::Sprite and design choices
« Reply #3 on: February 22, 2013, 10:29:30 pm »
Something I also had to teach myself: Don't make things more complicated than necessary. Manager classes, shared and weak pointers are rarely necessary -- mainly if you have true shared ownership and can't determine a class to have responsibilities about resources. For such cases, I have also written thor::ResourceCache, so you wouldn't need to reinvent the wheel.

But often, a simple STL container (std::map if you have some sort of ID) is enough to store textures. You can then distribute raw pointers, given that you guarantee the lifetime of the resources.

Wow the Thor library seems pretty sweet. Anything that makes me write less code to achieve a goal is nice.
One question though. For Thor 2.0(the newest eXpl0it3r VS2010 nightly), will it work with SFML 2.0 RC or do i have to download the newest SFML build? I'm kind of unwilling to build things myself since I'm awfully inexperienced in CMake( i really ought to learn how to build things properly ).

Also is there anything wrong with how I've made the sprite cache? Cause i was planning on making the texture cache almost identical. The sprite cache started out from my misunderstanding of sprites( it should've been a texture cache all along ). At first it was just raw pointers but then someone told me and pointed me to resources which said that i should never use raw pointers in C++ if i have the option of using smart pointers. So i made it with weak_ptr/shared_ptr. I spent quite a lot of time on it(learning about smart pointers mostly) so even though I don't plan on using it I still want to know what i did wrong. 

Concerning your board, you can try to have only logic in the tiles. In my game Zloxx II, each tile contains only a few attributes like type or animation step. I even create a new sf::Sprite in each frame for each visible tile, and I have not had any performance problems. In such a case, you could still take sf::VertexArray or try other optimizations.

You can also have a sf::Sprite as a member (not base class!) of your tile class, however tiles become more heavyweight as a result. Copies are more expensive, and you need to keep data like the position or texture rect always synchronous and sometimes even duplicate information.
I still have a lot of planning to do so I'll see how everything goes. What I'd like the most is to have either a specialized class(a functor maybe?) or just a function which would be used to unify(synchronize?) the logic elements with sprites. Like have the main Game class with update() and render() methods.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11016
    • View Profile
    • development blog
    • Email
AW: Re: Need help with sf::Texture, sf::Sprite and design choices
« Reply #4 on: February 22, 2013, 11:18:07 pm »
One question though. For Thor 2.0(the newest eXpl0it3r VS2010 nightly), will it work with SFML 2.0 RC or do i have to download the newest SFML build? I'm kind of unwilling to build things myself since I'm awfully inexperienced in CMake( i really ought to learn how to build things properly ).
The Thor Nigthly builds match the SFML Nightly builds, so they'll most likely fail with SFML 2 RC. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

MrPlow442

  • Newbie
  • *
  • Posts: 14
    • View Profile
Re: AW: Re: Need help with sf::Texture, sf::Sprite and design choices
« Reply #5 on: February 22, 2013, 11:25:07 pm »
The Thor Nigthly builds match the SFML Nightly builds, so they'll most likely fail with SFML 2 RC. ;)

Oh, well i guess I'll just have to download the newest SFML nightly then. :P
Are there any changelogs i could look at to see what has changed between the RC and the newest nightly aside from reading the Commit history?

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11016
    • View Profile
    • development blog
    • Email
AW: Need help with sf::Texture, sf::Sprite and design choices
« Reply #6 on: February 22, 2013, 11:50:12 pm »
No ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Need help with sf::Texture, sf::Sprite and design choices
« Reply #7 on: February 23, 2013, 12:15:23 am »
At first it was just raw pointers but then someone told me and pointed me to resources which said that i should never use raw pointers in C++ if i have the option of using smart pointers. So i made it with weak_ptr/shared_ptr. I spent quite a lot of time on it(learning about smart pointers mostly) so even though I don't plan on using it I still want to know what i did wrong.
You should not use raw pointers with ownership - i.e. don't manage memory manually using new and delete. Here, std::unique_ptr is the alternative. Raw pointers are no problem as long as they don't own resources.

std::shared_ptr is a complex and expensive smart pointer, it should never be the default approach. It can be taken when ownership has to be shared among multiple owners, and it's not clear which owner is responsible of destruction. std::weak_ptr is always used together with std::shared_ptr; it allows to have weak references (i.e. smart pointers that don't keep the resource alive).


Also is there anything wrong with how I've made the sprite cache?
I don't see why you have a sprite manager and shared pointers to sprites. sf::Sprite is a very lightweight class, don't be afraid of copying it. So, simply have a std::vector<sf::Sprite> without any managers, custom sprite classes and smart pointers. These indirections make code very complicated, but don't really add an advantage. Your class ActualSprite is broken anyway, since it doesn't consider the Rule Of Three.


What I'd like the most is to have either a specialized class(a functor maybe?) or just a function which would be used to unify(synchronize?) the logic elements with sprites.
You could simply have a function that draws a tile.
void Renderer::draw(const Tile& tile, int x, int y)
{
    sf::Sprite sprite;
    sprite.setTexture(getTileTexture(tile));
    sprite.setTextureRect(getTileTextureRect(tile));
    sprite.setPosition(Tile::Size * x, Tile::Size * y);
    ...
   
    mWindow.draw(sprite);
}
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

MrPlow442

  • Newbie
  • *
  • Posts: 14
    • View Profile
Re: Need help with sf::Texture, sf::Sprite and design choices
« Reply #8 on: February 23, 2013, 03:17:19 pm »
std::shared_ptr is a complex and expensive smart pointer, it should never be the default approach. It can be taken when ownership has to be shared among multiple owners, and it's not clear which owner is responsible of destruction. std::weak_ptr is always used together with std::shared_ptr; it allows to have weak references (i.e. smart pointers that don't keep the resource alive).
That makes sense. std::shared_ptr also creates a structure of reference counters so i guess it is expensive to use. I just thought it fit the purpose of a cache since I'd have multiple objects share the same resource and I didn't want it to be released prematurely.


I don't see why you have a sprite manager and shared pointers to sprites. sf::Sprite is a very lightweight class, don't be afraid of copying it. So, simply have a std::vector<sf::Sprite> without any managers, custom sprite classes and smart pointers. These indirections make code very complicated, but don't really add an advantage. Your class ActualSprite is broken anyway, since it doesn't consider the Rule Of Three.

Yeah, I basically misunderstood sf::Sprites. I didn't notice that they take a reference to a texture so I thought that each sprite contains a copy of their own texture. That's why i made a sprite cache, instead what I really should have made was a texture cache.  But I don't have to now.
« Last Edit: February 23, 2013, 03:29:56 pm by MrPlow442 »