Welcome, Guest. Please login or register.

Author Topic: Rotate a sprite around its center using a Transform  (Read 2167 times)

0 Members and 1 Guest are viewing this topic.

tetra

  • Newbie
  • *
  • Posts: 16
    • View Profile
Rotate a sprite around its center using a Transform
« on: May 04, 2015, 08:31:32 pm »
I have an object that needs to be able to be rotated around its center, but keeping the same origin (for setting position, etc). So, I figured I needed to use a Transform.

I have a class, DoorTile, that extends Tile, that extends Drawable (just for context, not really relevant):

    private Transform t;

    public DoorTile() {
        super();
        t = new Transform();
        setPassable(false);
        sprite.setTexture(TileTextures.DOORTEXTURE);
    }
   
    public void rotateAroundCenter(float degrees) {
        Vector2f center = SpriteUtils.getTextureCenter(TileTextures.DOORTEXTURE);
        t = Transform.rotate(t, degrees, center.x, center.y);
    }
   
    public void draw(RenderTarget rt, RenderStates states) {
        RenderStates newStates = new RenderStates(
                states.blendMode,
                Transform.combine(states.transform, t),
                sprite.getTexture(),
                states.shader);
       
        sprite.draw(rt, newStates);
    }

getTextureCenter(Texture t) returns the center coordinates of t, and sprite is the sprite of the Tile.

Now, when I apply this rotation, my sprites have a weird behavior. At first, using 45 degrees as a test, they completely disappeared from the screen. So then I tried 1 degree. The sprites affected seemed to have pieces "cut off" and translated downward. Here's a picture, using 1 degree as an argument:



Keep in mind, that I'm applying this rotation before setting their position on the map.

For context, I'm trying to rotate those white sprites (will be 'doors') so they fit properly in the corridor. E.g. horizontal on vertical cooridors, vertical on horizontal corridors. (The white part of the sprite is a placeholder for transparency, that's just there for debugging purposes.)

What should I do to be able to make this work properly? That is, how can I:

- Rotate a sprite around its center
- Keep the original origin (top left corner) for drawing

Thanks!
« Last Edit: May 04, 2015, 09:10:11 pm by tetra »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6130
  • Thor Developer
    • View Profile
    • Bromeon
Re: Rotate a sprite around its center using a Transform
« Reply #1 on: May 04, 2015, 08:57:25 pm »
I assume Transform.rotate in Java follows the Immutable pattern and doesn't modify the argument. But you should double-check the documentation in any case. Same for the Transform default constructor, make sure it's the identity. Also check if you're not mixing coordinate systems (for example, the center is in local coordinates)...

Same for Transform.combine(t, states.transform), might it be that it applies the transforms in the wrong order? Because in C++, the states transform is multiplied with the current object's, see here for example.

Furthermore, you're throwing away the whole render states except for the transform. Even if it may not be relevant here, you should preserve the other attributes (texture, shader, blend mode).
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development: first SFML book

tetra

  • Newbie
  • *
  • Posts: 16
    • View Profile
Re: Rotate a sprite around its center using a Transform
« Reply #2 on: May 04, 2015, 09:05:44 pm »
I assume Transform.rotate in Java follows the Immutable pattern and doesn't modify the argument. But you should double-check the documentation in any case. Same for the Transform default constructor, make sure it's the identity. Also check if you're not mixing coordinate systems (for example, the center is in local coordinates)...

Same for Transform.combine(t, states.transform), might it be that it applies the transforms in the wrong order? Because in C++, the states transform is multiplied with the current object's, see here for example.

Furthermore, you're throwing away the whole render states except for the transform. Even if it may not be relevant here, you should preserve the other attributes (texture, shader, blend mode).

In the JSFML documentation, Transform has many static methods that return a new Transform, using another Transform as an argument (see my code: t = Transform.rotate(...))

A new Transform is initialized to the identity, yes.

How would I get the center of the texture in global coordinates?

I'll try to make a proper constructor to preserve other rendering characteristics, then I'll get back to you.

Thanks so much for your help!

Edit:

Changed code in the OP to reflect current state.
« Last Edit: May 04, 2015, 09:09:03 pm by tetra »