Professional Documents
Culture Documents
entities
Transforming SFML entities
All SFML classes (sprites, text, shapes) use the same interface for
transformations: sf::Transformable. This base class provides a simple API to
move, rotate and scale your entities. It doesn't provide maximum flexibility, but
instead defines an interface which is easy to understand and to use, and
which covers 99% of all use cases -- for the remaining 1%, see the last
chapters.
Position
The position is the... position of the entity in the 2D world. I don't think it needs
more explanation :).
transformable class
1
sf::Vector2f position = entity.getPosition(); // = (15, 55)
By default, entities are positioned relative to their top-left corner. We'll see
how to change that with the 'origin' property later.
Rotation
The rotation is the orientation of the entity in the 2D world. It is defined
in degrees, in clockwise order (because the Y axis is pointing down in SFML).
transformable class
entity.setRotation( 45.f);
entity.rotate( 10.f);
2
Note that SFML always returns an angle in range [0, 360) when you
call getRotation.
As with the position, the rotation is performed around the top-left corner by
default, but this can be changed by setting the origin.
Scale
The scale factor allows the entity to be resized. The default scale is 1. Setting
it to a value less than 1 makes the entity smaller, greater than 1 makes it
bigger. Negative scale values are also allowed, so that you can mirror the
entity.
transformable class
3
Origin
The origin is the center point of the three other transformations. The entity's
position is the position of its origin, its rotation is performed around the origin,
and the scale is applied relative to the origin as well. By default, it is the top-
left corner of the entity (point (0, 0)), but you can set it to the center of the
entity, or any other corner of the entity for example.
To keep things simple, there's only a single origin for all three transformation
components. This means that you can't position an entity relative to its top-left
corner while rotating it around its center for example. If you need to do such
things, have a look at the next chapters.
transformable class
Note that changing the origin also changes where the entity is drawn on
screen, even though its position property hasn't changed. If you don't
understand why, read this tutorial one more time!
4
Transforming your own classes
sf::Transformable is
not only made for SFML classes, it can also be a base (or
member) of your own classes.
// ...
};
MyGraphicalEntity entity;
entity.setRotation( 110.f);
To retrieve the final transform of the entity (commonly needed when drawing
it), call the getTransform function. This function returns a sf::Transform object.
See below for an explanation about it, and how to use it to transform an SFML
entity.
Custom transforms
The sf::Transformable class is easy to use, but it is also limited. Some users
might need more flexibility. They might need to specify a final transformation
as a custom combination of individual transformations. For these users, a
lower-level class is available: sf::Transform. It is nothing more than a 3x3
matrix, so it can represent any transformation in 2D space.
5
o by using the predefined functions for the most common transformations
(translation, rotation, scale)
o by combining two transforms
o by specifying its 9 elements directly
sf::Transform t1 = sf::Transform::Identity;
// a rotation transform
sf::Transform t2;
t2.rotate( 45.f);
// a custom matrix
// a combined transform
sf::Transform t4 = t1 * t2 * t3;
sf::Transform t;
t.rotate( 90.f);
6
Back to the point: How can a custom transform be applied to a graphical
entity? Simple: Pass it to the draw function.
window.draw(entity, transform);
sf::RenderStates states;
states.transform = transform;
window.draw(entity, states);
Bounding boxes
After transforming entities and drawing them, you might want to perform some
computations using them e.g. checking for collisions.
SFML entities can give you their bounding box. The bounding box is the
minimal rectangle that contains all points belonging to the entity, with sides
aligned to the X and Y axes.
7
quickly, and its area is close enough to that of the real entity to provide a good
approximation.
if (boundingBox.contains(point))
// collision!
// check collision with another box (like the bounding box of another entity)
if (boundingBox.intersects(otherBox))
// collision!
There's another function that returns the bounding box of the entity in
its local coordinate system (before its transformations are
applied): getLocalBounds. This function can be used to get the initial size of an
entity, for example, or to perform more specific calculations.
class Node
public :
const
onDraw(target, combinedTransform);
m_children[i]->draw(target, combinedTransform);
private :
transform) const = 0;
9
sf::Transform m_transform;
std::vector<Node*> m_children;
};
public :
private :
transform) const
target.draw(m_sprite, transform);
sf::Sprite m_sprite;
};
10