0
votes

I'm writing a function that will rotate all the sprites contained in an object reletive to their position from the center of that object (If I move a sprite off to the right, when I rotate the container object, I want the sprite to keep it's position relative to the newly rotated object).

How i've done this is as follows (I run this code for each of the sprites contained in the object)

        std::pair<float,float> childPos = child->get_pos(); // This returns a pair with the x and y values of the child sprite

        float radius   = std::sqrt( (xPos - childPos.first)*(xPos - childPos.first) + (yPos - childPos.second)*(yPos - childPos.second)); // xPos and yPos are the container's x and y position
        angle = atan2(yPos - childPos.second, xPos - childPos.first); 

        angle = angle + (cAngle /180*3.14); // cAngle is the container's angle


        float newX = radius * std::cos(angle);
        float newY = radius * std::sin(angle);


        child->set_pos(newX, newY); // this sets the sprite's x and y coordinates
        child->set_angle(drawables[i].second->angleOffset + cAngle); // this sets the spries rotation around it's local axis. it only affects the sprite's orientation, not position

I've experimented, and the angle and radius always match my own calculations. (when it's 90 degrees different than the sprite, and I have it print out the angle the program gives me, it's 90. Then it stays properly adjusted each time the container sprite is rotated) However, the cos and sin functions give seemingly random results. All the contained sprites spin out of control and end up in random locations on the screen. (this function gets run every frame that the container is rotating, adjusting the children to the sprite's current angle.)

Have I missed something obvious? I'm not quite sure what the problem with my code is. Any help you could offer would be great x.x

-edit, I've been told I should provide an example to demonstrate exactly what's wrong, so I had the console output the data for one of the child sprites.

The results are as follows

> ----------------------
> --> Container X: 50
> --> Container Y: 200
> --> Container Angle (in raidans): 0
> --> Container Angle (in degrees): 0
> -
> --> Sprite X: 50
> --> Sprite Y: 180
> --> Sprite Radius from container's center: 20
> --> Sprite Angle from container's center (in radians): 1.5708(note, this will st ay the same, as I can't properly adjust it each time
> because cos and sin provide  weird output)
> --> Sprite Angle from container's center (in degrees): 90.0457(note, this will s tay the same, as I can't properly adjust it each time
> because cos and sin provid e weird output)
> --> Sprite's angle adjusted for the container's rotation (in radians): 1.5708
> --> Sprite's angle adjusted for the container's rotation (in degrees): 90.0457
> -
> --> result of using cos with the adjusted angle in radians: -8.74228e-007
> --> result of using sin with the adjusted angle in radians: 20
> ----------------------
> 
> ----------------------
> --> Container X: 50
> --> Container Y: 200
> --> Container Angle (in raidans): 14489.8
> --> Container Angle (in degrees): 252.766
> -
> --> Sprite X: 50
> --> Sprite Y: 180
> --> Sprite Radius from container's center: 20
> --> Sprite Angle from container's center (in radians): 1.5708(note, this will st ay the same, as I can't properly adjust it each time
> because cos and sin provide  weird output)
> --> Sprite Angle from container's center (in degrees): 90.0457(note, this will s tay the same, as I can't properly adjust it each time
> because cos and sin provid e weird output)
> --> Sprite's angle adjusted for the container's rotation (in radians): 5.98016
> --> Sprite's angle adjusted for the container's rotation (in degrees): 342.812
> -
> --> result of using cos with the adjusted angle in radians: 19.0887
> --> result of using sin with the adjusted angle in radians: -5.96822
> ----------------------
> 
> ----------------------
> --> Container X: 50
> --> Container Y: 200
> --> Container Angle (in raidans): 20505.2
> --> Container Angle (in degrees): 357.702
> -
> --> Sprite X: 50
> --> Sprite Y: 180
> --> Sprite Radius from container's center: 20
> --> Sprite Angle from container's center (in radians): 1.5708(note, this will st ay the same, as I can't properly adjust it each time
> because cos and sin provide  weird output)
> --> Sprite Angle from container's center (in degrees): 90.0457(note, this will s tay the same, as I can't properly adjust it each time
> because cos and sin provid e weird output)
> --> Sprite's angle adjusted for the container's rotation (in radians): 7.81071
> --> Sprite's angle adjusted for the container's rotation (in degrees): 447.748
> -
> --> result of using cos with the adjusted angle in radians: 0.865144
> --> result of using sin with the adjusted angle in radians: 19.9813
> ----------------------
> 
> ----------------------
> --> Container X: 50
> --> Container Y: 200
> --> Container Angle (in raidans): 20636.9
> --> Container Angle (in degrees): 360
> -
> --> Sprite X: 50
> --> Sprite Y: 180
> --> Sprite Radius from container's center: 20
> --> Sprite Angle from container's center (in radians): 1.5708(note, this will st ay the same, as I can't properly adjust it each time
> because cos and sin provide  weird output)
> --> Sprite Angle from container's center (in degrees): 90.0457(note, this will s tay the same, as I can't properly adjust it each time
> because cos and sin provid e weird output)
> --> Sprite's angle adjusted for the container's rotation (in radians): 7.8508
> --> Sprite's angle adjusted for the container's rotation (in degrees): 450.046
> -
> --> result of using cos with the adjusted angle in radians: 0.0637081
> --> result of using sin with the adjusted angle in radians: 19.9999
> ----------------------

Not quite sure why it provides strange results like that.

2
If you are saying that sin and cos are giving incorrect results, it should be trivial to come up with an SSCCE (sscce.org), right? Please add it to your question. - NPE
If cAngle = 10, and you call this multiple times, then each time the object will rotate another 10 degrees. Is that what you want? (My guess is that you want the child to rotate only by the amount that the container rotation has changed) - Russell Zahniser
@NPE, I added an example of the output. That's about as self contained as I can make my example, as the code I'm using requires a library to run, and demonstrating it in it's current state would take a lot of extra code unrelated to the error itself. (I already tested all those to make sure it was THIS function giving me problems) - Legacyblade
@Legacyblade: No, you can make a testcase. - Lightness Races in Orbit

2 Answers

2
votes

I think you want:

float newX = childPos.first + radius * std::cos(angle);
float newY = childPos.second + radius * std::sin(angle);

(Assuming that the container angle is the amount you want the child to rotate by each time that this is called, as noted in the comment above)

1
votes

I can see two potential issues that can cause problems:

  1. If cAngle is an integer type, then the cAngle / 180 will be a truncating division. You will want to change that to cAngle / 180.0 instead.
  2. You should use M_PI instead of 3.14; it's much more precise.