Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Rotation Formula  (Read 3770 times)

0 Members and 1 Guest are viewing this topic.

Voroz

  • Full Member
  • ***
  • Posts: 128
    • View Profile
Rotation Formula
« on: August 07, 2011, 07:30:00 pm »
Hi. I have been trying for many hours to get this to work.
I want to rotate a door together with a room, so it stays on the same wall when the room rotates. I did try to set center of the door on the same location as setcenter of the room is (middle), and that worked. But then the doors x and y will be missplaced.

I would like to know of a formula that can rotate the door around a point based on what angle the room has. I have only done Math A and B so i'm no math proffessor, maybe someone else is and can help me by explaining it well? :).
Thx

SCPM

  • Newbie
  • *
  • Posts: 11
    • View Profile
Rotation Formula
« Reply #1 on: August 07, 2011, 08:11:01 pm »
Hello:
I believe the formula you are looking for goes something like this:
Code: [Select]
satellite.x = body.x + (body.width/2) + Math.cos(angleofBodyInDegrees) * DistanceFromBodyCenter;
satellite.y = body.y + (body.height/2) + Math.sin(angleofBodyInDegrees) * DistanceFromBodyCenter;

It's from an old formula I was using in Flixel, I hope it's still relevant.  I believe what I was trying to do with the body.x + (body.width/2), body.y + (body.height/2) parts of the code was get the center of the body?  I forget.  I hope this helps!

Edit:  Whoops, I think the angle of the body ought to be in radians, not degrees.

Edit 2: Okay, it's sloppy, but here's a simple program that should demonstrate everything:

Code: [Select]
#include <SFML/Graphics.hpp>
#include <cmath>

const double PI = 3.14159265;

int main()
{
    // Create the main window
    sf::RenderWindow App(sf::VideoMode(400, 300, 32), "SFML Events");

    sf::Shape Rect = sf::Shape::Rectangle(0, 0, 50, 50, sf::Color::Green);
    Rect.SetCenter(25, 25);
    Rect.SetX(200);
    Rect.SetY(150);

    sf::Shape Rect2 = sf::Shape::Rectangle(0, 0, 24, 24, sf::Color::Blue);
    Rect2.SetCenter(12, 12);

    // Start main loop
    while (App.IsOpened())
    {
        // Process events
        sf::Event Event;
        while (App.GetEvent(Event))
        {
            // Close window : exit
            if (Event.Type == sf::Event::Closed)
                App.Close();

            // Escape key : exit
            if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape))
                App.Close();
        }

        // Get elapsed time
        float ElapsedTime = App.GetFrameTime();

        if (App.GetInput().IsKeyDown(sf::Key::Up))    Rect.Move(0, -80 * ElapsedTime);
        if (App.GetInput().IsKeyDown(sf::Key::Down))  Rect.Move(0,  80 * ElapsedTime);

        if (App.GetInput().IsKeyDown(sf::Key::Left))
        {
            Rect.SetRotation(Rect.GetRotation() - 1 * ElapsedTime * 100);
        }
        if (App.GetInput().IsKeyDown(sf::Key::Right))
        {
            Rect.SetRotation(Rect.GetRotation() + 1 * ElapsedTime * 100);
        }
        float BodyAngle = Rect.GetRotation() * PI / 180;
        Rect2.SetX(Rect.TransformToGlobal(Rect.GetCenter()).x + (sin(BodyAngle) * 80));
        Rect2.SetY(Rect.TransformToGlobal(Rect.GetCenter()).y + (cos(BodyAngle) * 80));

        // Clear the screen (fill it with white color)
        App.Clear(sf::Color(255, 255, 255));

        // Draw player
        App.Draw(Rect);
        App.Draw(Rect2);

        // Display window on screen
        App.Display();
    }

    return EXIT_SUCCESS;
}

Voroz

  • Full Member
  • ***
  • Posts: 128
    • View Profile
Rotation Formula
« Reply #2 on: August 07, 2011, 11:39:46 pm »
Thx for taking the time to make that example. I tried it and it worked fine, i have not tried yet to implement it into my code but i will soon. I just have a question first.

Code: [Select]
float BodyAngle = Rect.GetRotation() * PI / 180;
        Rect2.SetX(Rect.TransformToGlobal(Rect.GetCenter()).x + (sin(BodyAngle) * 80));
        Rect2.SetY(Rect.TransformToGlobal(Rect.GetCenter()).y + (cos(BodyAngle) * 80));


That part, what are you doing there? I haven't learned about sin, cos yet but i will try to now. I understand that you are converting the rotation degrees to something else. Would you mind trying to explain to me what's happening here exactly? thx again for the help :).

SCPM

  • Newbie
  • *
  • Posts: 11
    • View Profile
Rotation Formula
« Reply #3 on: August 08, 2011, 12:02:07 am »
Hi,
The line:
Code: [Select]
float BodyAngle = Rect.GetRotation() * PI / 180;
converts the angle of the body from degrees to radians.  We will need the radian values to work with the sin and cos trigonometric functions.  Once we have the angle in radians, we can set the x position of the satellite by first getting the x value of the center of the main body rectangle (which we need to convert to global coordinates in this case), and add the sine of the angle in radians multiplied by the distance we want the satellite to be positioned from the body.  We do the same for the y position of the satellite, this time getting the cosine (if we switched the sine and cosine, the satellite will orbit in the opposite direction when we change the angle, so this is really a matter of how you intend to implement it).  That's all there is to it!  For some additional reading, here's a couple good articles:
http://www.helixsoft.nl/articles.php
 :)

Voroz

  • Full Member
  • ***
  • Posts: 128
    • View Profile
Rotation Formula
« Reply #4 on: August 08, 2011, 02:12:39 am »
thx again for a quick reply. I checked out that link and now know better how it works. cos and sin is to take the length and angle (which we know), and add the position in x and y. Anyway i made it work in my code, but not the way i wanted. I noticed that the "satellite" which is my "door" in my example wants to spawn at the center of the x and at the top / bottom of y. That means i can't put the door at the right or left. My other object is rectangular so the door can only go on the long sides. I will try to think for myself if i can correct this.

Another thing that was weird was that the position of the door would only update 7 times on a full lap around the circle independant of speed. The rotation of the door and the room would update on every frame though.

Voroz

  • Full Member
  • ***
  • Posts: 128
    • View Profile
Rotation Formula
« Reply #5 on: August 08, 2011, 04:53:18 am »
Ok i managed to change the start position to either left / right / top / bottom by switching the sin, cos and the minus and plus. Now the only problem is that it doesn't update position when it should.

This is the code of the setposition.

Code: [Select]
Door.SetPosition(Room.GetPosition().x + cos(bodyAngle)*Room.GetSize().x/2, Room.GetPosition().y - sin(bodyAngle)*Room.GetSize().x/2);

Edit: My bad. Was using int for the bodyAngle :oops:. Also i was able to change the starting position of the door by adding for example -90 here:
Code: [Select]
double bodyAngle = (Room.GetRotation() - 90) * PI / 180; Thanks alot for your help, i learned something new now that will certainly help alot.