SFML community forums

Help => Graphics => Topic started by: wh1t3crayon on October 02, 2014, 05:56:14 pm

Title: Rotating a sprite is causing some really weird bugs
Post by: wh1t3crayon on October 02, 2014, 05:56:14 pm
I'm trying to implement rotation into my tetris clone and it is going terribly. Basically, when I try and set the tetrimino's sprite's origin to its center so I can rotate it without changing the position any, the sprite moves a lot farther on the screen that it should. Like it moves by tens of pixels each time. Here is the rotate function:
void GamePiece::RotateLeft(){
        if(originCount != 10){
                bool rotate = true;
                int newx, newy;
                sf::Vector2f origin(pieceRectangles_[0].getPosition().x + originCount, pieceRectangles_[0].getPosition().y + originCount);
                for(int i = 0; i < 4; i++){
                        newx = (origin.x + origin.y - pieceRectangles_[i].getPosition().y - 10);
                        newy = (pieceRectangles_[i].getPosition().x + origin.y - origin.x);

                        sf::RectangleShape temp = pieceRectangles_[i];
                        temp.setPosition(newx, newy);
                        sf::FloatRect fr = temp.getGlobalBounds();

                        for(int j = 0; j < levelCollisions.size(); j++){
                                if(fr.intersects(levelCollisions[j])){
                                        rotate = false;
                                }
                        }
                }
                if(rotate == true){
                        for(int i = 0; i < 4; i++){
                                newx = (origin.x + origin.y - pieceRectangles_[i].getPosition().y - 10);
                                newy = (pieceRectangles_[i].getPosition().x + origin.y - origin.x);
                                pieceRectangles_[i].setPosition(newx, newy);
                        }
                        pieceShape.setOrigin(pieceShape.getPosition().x + pieceShape.getGlobalBounds().width / 2, pieceShape.getPosition().y + pieceShape.getGlobalBounds                                                       ().height / 2);
                        pieceShape.rotate(90);
                        pieceShape.setOrigin(pieceShape.getPosition());
                }
        }
}

The first half with the for loops and such is the part that rotates all the individual squares which I use for collision detection. This part works perfectly (I have their color set to blue so I can see where they are moving versus the new position of the actual sprite). The problem starts at pieceShape.setOrigin(). I'm trying to set the sprite's origin to its center so I can rotate it smoothly, but the sprite spirals out from where it should have been, with increasing distance everytime.
Title: Re: Rotating a sprite is causing some really weird bugs
Post by: zsbzsb on October 02, 2014, 06:06:06 pm
Position/Rotation/Scale all happen around the origin when the sprite is drawn, not when rotate(...) is called.
Title: Re: Rotating a sprite is causing some really weird bugs
Post by: wh1t3crayon on October 02, 2014, 06:08:24 pm
Right I read that in the documentation... So, do I have to go through and change all of my other transforming functions to accomodate a new origin?
Title: Re: Rotating a sprite is causing some really weird bugs
Post by: wh1t3crayon on October 02, 2014, 06:11:32 pm
 pieceShape.setOrigin(pieceShape.getPosition().x + pieceShape.getGlobalBounds().width / 2, pieceShape.getPosition().y + pieceShape.getGlobalBounds().height / 2);
            pieceShape.rotate(90);
            pieceShape.setOrigin(pieceShape.getPosition());
Update, if I comment out the last two lines and only set the origin, the sprite is placed back at (0,0). Why?

Update update:: That was a stupid question. But, if I do set the origin to the sprite's center in the constructor, it's still not rotating around its center. This function does set the origin to the center, right:
pieceShape.setOrigin(pieceShape.getPosition().x + pieceShape.getGlobalBounds().width / 2, pieceShape.getPosition().y + pieceShape.getGlobalBounds().height / 2);
?
Title: Re: Rotating a sprite is causing some really weird bugs
Post by: zsbzsb on October 02, 2014, 06:45:35 pm
That is another thing I didn't see in your original code, but origin is relative to the sprite/transformable - not to the world (position is relative to the world).
Title: Re: Rotating a sprite is causing some really weird bugs
Post by: Hapax on October 02, 2014, 06:48:31 pm
This function does set the origin to the center, right:
pieceShape.setOrigin(pieceShape.getPosition().x + pieceShape.getGlobalBounds().width / 2, pieceShape.getPosition().y + pieceShape.getGlobalBounds().height / 2);
?

Does this work instead:
pieceShape.setOrigin(pieceShape.getLocalBounds().x / 2, pieceShape.getLocalBounds().y / 2);

p.s. Why do I keep just giving the answer to people...
Title: Re: Rotating a sprite is causing some really weird bugs
Post by: zsbzsb on October 02, 2014, 07:06:22 pm
p.s. Why do I keep just giving the answer to people...

Because you believe people can't figure out things on their own and they must C&P code to get anywhere.  ;)
Title: Re: Rotating a sprite is causing some really weird bugs
Post by: Hapax on October 02, 2014, 07:13:59 pm
you believe people can't figure out things on their own and they must C&P code to get anywhere.
Not fully true; I guess I'm just 'saving them the trouble'. Unfortunately, this can often have the adverse effect of getting into the habit of having answers spoon-fed. Sometimes, I'm just too nice  :(
Title: Re: Rotating a sprite is causing some really weird bugs
Post by: wh1t3crayon on October 03, 2014, 02:29:23 pm
Quote
Does this work instead:
pieceShape.setOrigin(pieceShape.getLocalBounds().x / 2, pieceShape.getLocalBounds().y / 2);

p.s. Why do I keep just giving the answer to people...

It does not work, it actually throws an error because getLocalBounds() does not have a member 'x' or 'y'. I believe you meant
pieceShape.setOrigin(pieceShape.getLocalBounds().width / 2, pieceShape.getLocalBounds().height / 2);
However, this doesn't work. The piece is still not rotating around its center, but it's not rotating around 0,0 either.

The image below shows the four orientations of my sprite. The blue line is where the piece is supposed to be rotating, and the red line is where is actually ends up. So it's rotating close to its center, but not exactly.
Title: Re: Rotating a sprite is causing some really weird bugs
Post by: dabbertorres on October 03, 2014, 06:25:08 pm
Try using floating point division rather than integer division.
ie:
pieceShape.setOrigin(pieceShape.getLocalBounds().width / 2.f, pieceShape.getLocalBounds().height / 2.f);
Title: Re: Rotating a sprite is causing some really weird bugs
Post by: Hapax on October 03, 2014, 06:54:19 pm
It does not work...I believe you mean.
I see that I'm subconciously still getting people to help themselves  ;)

Title: Re: Rotating a sprite is causing some really weird bugs
Post by: wh1t3crayon on October 03, 2014, 07:18:44 pm
Try using floating point division rather than integer division.
ie:
pieceShape.setOrigin(pieceShape.getLocalBounds().width / 2.f, pieceShape.getLocalBounds().height / 2.f);
That produced no change at all. I discovered that if I just comment out the line where I set the origin, then there is also no change in the rotation. In other words, no matter what I set the origin to the piece rotates around the same point.
//pieceShape.setOrigin(pieceShape.getLocalBounds().width / 2.f, pieceShape.getLocalBounds().height / 2.f);
So, this function essentially does nothing, commented out or not
Title: Re: Rotating a sprite is causing some really weird bugs
Post by: Hapax on October 03, 2014, 07:43:05 pm
Does this work?
pieceShape.setOrigin(static_cast<float>(pieceShape.getLocalBounds().width) / 2.f, static_cast<float>(pieceShape.getLocalBounds().height) / 2.f);
Title: Re: Rotating a sprite is causing some really weird bugs
Post by: didii on October 05, 2014, 12:27:36 pm
Are you sure you read the tutorial about transformables (http://sfml-dev.org/tutorials/2.1/graphics-transform.php)? I think you are forgetting that changing the origin also relatively changes the position of the sprite.

Just draw a sprite at (0,0) with it's origin at (0,0) and then with it's origin changed. See what changes. Hapax last suggestion should not change anything because of how casts work is C++, but it's safer anyway how he writes it.
Title: Re: Rotating a sprite is causing some really weird bugs
Post by: Laurent on October 05, 2014, 02:19:50 pm
Both operands are floats, the static_cast is totally useless.
Title: Re: Rotating a sprite is causing some really weird bugs
Post by: Hapax on October 05, 2014, 02:48:56 pm
I did think the casts was more than I usually use. My earlier suggestion (using width instead of x though etc.) will be setting the origin to the centre of the pieceShape.
I suppose the next question is:
Is pieceShape the entire shape or just one of the squares?
Title: Re: Rotating a sprite is causing some really weird bugs
Post by: wh1t3crayon on October 06, 2014, 04:24:04 am
I did think the casts was more than I usually use. My earlier suggestion (using width instead of x though etc.) will be setting the origin to the centre of the pieceShape.
I suppose the next question is:
Is pieceShape the entire shape or just one of the squares?

pieceShape is the entire shape. Each shape has one sprite to draw, and four invisible sf::RectangleShapes for collision detection. The blue shapes in the images I posted are the rectangle shapes, and are where the sprite (red) should be turning. But what has me so confused is whenever I print the values of the sprite's origin after explicitly changing the origin, the output is still 0,0
Title: Re: Rotating a sprite is causing some really weird bugs
Post by: Hapax on October 09, 2014, 12:56:02 am
Did you output the origin immediately after changing it?
If not, then it's being changed back somewhere else, but if so, there is something wrong.
First, try placing the output immediately after to confirm it's actually getting changed as expected then, either move that output further away and find out when it changes, or try to use your debugger to step through it.

Is pieceShape a sprite, rectangle, or a container class with those things in it?
If it's a container class, you might have to get the local bounds of its internal element for the origin.