-
Notifications
You must be signed in to change notification settings - Fork 0
Tutorial: Drawable Group
This page lacks examples and images.
This tutorial has been written because of this thread.
Drawable's children cover a wide range of uses: Shapes, Sprites, Texts, etc. but the "family" lacks one member: Group, so we'll create it there. Indeed, the class exists in well-known libraries such as Pygame.
Why are Groups useful? Basically, you can store your game objects in them so that they don't "swim" in a big "pool", and apply precise calculations on a specified part of them easily.
- You can make a "backgrounds" Group, followed by a "Level" one, and then a "Foreground" One, for example. This, way, backgrounds will always be drawn before the level tiles which will also be drawn before the foreground elements, even if you had backgrounds, tiles, or foregrounds, which would have otherwise been on the top. Imagine you add a background without using Groups: it covers everything and you can't see behind it!
- You can make a traditionnal 2D game with depth, where there are two parallels level. The character must only be on one of the layers, and change by jumping. Each "layer" can be implemented as a Group, and the one where the player stands is used for collisions, while the other can be tinted in grey (
Group.SetColor(sf::Color(100, 100, 100))
) to show that the player is standing on the other side. - You'll find many others.
Group would behave like a simple std::vector, but would also be drawable itself. There are two main reasons for this:
- simplicity: it's easier to type
Group.Draw()
thanfor(int i = 0; ...) { Group[i].Draw() }
. It also makes Groups storable in other Groups, like other Drawables, which ables to process the whole very easily ; - sharing of properties for the membres of a Group. For example, if you want all the Sprites stored in a Group to move at the same time, you can just update the coordinates of the Group. This is very useful if you make an articulated body made of sprites. You can also separate objects around a single point: the origin of the Group, just by using
Group.SetCenter(..., ...)
!
Here's what I use. The SFML doesn't implement a Group class for ownership reasons: should the Group destroy its elements when it is destroyed? etc.
#ifndef GROUP_INCLUDED_HPP
#define GROUP_INCLUDED_HPP
#include <SFML/Graphics.hpp>
class Group : public sf::Drawable, public std::vector<sf::Drawable*> {
public:
Group();
~Group();
void render(sf::RenderTarget&) const;
};
#endif
#include "group.hpp"
Group::Group() :
sf::Drawable(),
std::vector<sf::Drawable*>() {
}
Group::~Group() {
for(std::vector<sf::Drawable*>::iterator i = begin(); i != end(); ++i) {
delete *i;
}
}
// This is what ables you to do Group.Draw() to draw all the Drawable inside of a Group,
// and to apply common settings such as position, color, ... to its elements.
void Group::render(sf::RenderTarget& Tar) const {
for(std::vector<sf::Drawable*>::iterator i = begin(); i != end(); ++i) {
Tar.draw(*i);
}
}
You can even add namespace sf { ... }
if you think that Group should belong to the SFML ;).
It would be a good idea to use the "reasons" said above and make code snippets out of them