1
\$\begingroup\$

I currently have a Renderer class, which as in the example code, looks like this:

Class Renderer()
{
private:
    std::vector<sf::Sprite*> sprites;

public:
    
    void pushSprite(sf::Sprite& sprite)
    {
        sprites.push_back(&sprite);
    }

    void update()
    {
        std::sort(sprites.begin(), sprites.end(), sort_y);
    }

    void render(sf::RenderWindow window)
    {
        for (/**/)
        {
            window.draw(*sprites[i])
        }
    }
}

The problem is the following, I have classes like Projectile which holds it's own sprite, and I have vectors in my Game class, to hold instances of classes like this, but as these vectors increase in size, they may change their position in memory, therefore making all the pointers in the Renderer invalid.

I have a few questions:

Having a Renderer class structured like that is the usual? If not, how should I do it? If yes, how would I solve the problem?

\$\endgroup\$
5
  • \$\begingroup\$ IMHO, if you have your entities in std::vectors, I think it's simpler just to traverse those vectors and draw the sprites, like: window.draw(projectile.sprite). No pointers involved (not yours, at least). As for the renderer class, I think it justs adds another layer of indirection: sf::Sprite* -> sf::Sprite -> sf::Texture which complicates things. \$\endgroup\$
    – Alex CB
    Commented Aug 17, 2023 at 11:55
  • \$\begingroup\$ I understand, but the problem is that I also have layers, and the renderer class deals with them, how would I draw stuff based on their layer just down like you said? \$\endgroup\$
    – BOOM
    Commented Aug 17, 2023 at 15:41
  • \$\begingroup\$ Supposing that by layers you mean a way to draw things on top of other things, you can std::sort the entities' std::vector by layer before rendering, so things on lower layers get drawn first. If you can edit your post so we can see how Render class deals with layers will be of help ;) \$\endgroup\$
    – Alex CB
    Commented Aug 17, 2023 at 16:17
  • \$\begingroup\$ Also note that probably you should be passing window by reference: void render(sf::RenderWindow& window). Or even have the window as a member of the class. \$\endgroup\$
    – Alex CB
    Commented Aug 17, 2023 at 16:20
  • \$\begingroup\$ @AlexCB Edited, I basically do what you said, but inside the sprites vector, my concern is that in game class I will have more than just one vector storing things that hold a sprite, I know how to sort one vector, but how would I iterate through all of them and decide which to draw before the other? \$\endgroup\$
    – BOOM
    Commented Aug 17, 2023 at 16:41

1 Answer 1

0
\$\begingroup\$

About the rendering class, I don't know if it's the usual.

About the pointers. The most raw solution to your problem with the pointers, without having to change design, I think it would be to implement some kind of pool.

  • Define the maximum of entities of each class that could be in a certain time. ie: 5000000 projectiles for a Vampire Survivors clone.
  • Create some std::vector (or even std::array) of fixed size for each class of entity you have.
  • Reuse the entities when they are disabled. Don't allocate them with new, use the body(memory) of a killed one. Have a check with the health or another flag to decide if the entity can be used to "create" a new one, and just replenish health and position it in the correct place. This way, the memory positions would be the same for the runtime. For more advanced solutions, look for object pool, or the good ol' gameprogrammingpatterns.
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .