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

Author Topic: Delayed rotation  (Read 4360 times)

0 Members and 1 Guest are viewing this topic.

Inflammatory Nugget

  • Newbie
  • *
  • Posts: 21
    • View Profile
Delayed rotation
« on: January 19, 2014, 07:46:47 pm »
Good day,

let's cut to the chase, shall we?

https://www.dropbox.com/s/f4w3ydjm2f8tu4m/Release.rar

This is a small test program in which a green square turns without delay towards the mouse pointer. The red square underneath does the same, but at a lower speed. When the user moves his mouse over the white line, the red square turns the opposite direction of which it is supposed to turn. This means that when the mouse pointer moves over the white line by going up, the red square turns clockwise while it should be turning counterclockwise.

This is the full code of the program:
#include <SFML\Graphics.hpp>
#include <cmath>
#include <thread>
#include <chrono>
// define PI
#define PI 3.14159265
// main
int main(){
        sf::Vector2i mouse;
        sf::Vector2f player;
        sf::RectangleShape shape[3];
        shape[0].setPosition(400, 300);
        shape[0].setSize(sf::Vector2f(200, 200));
        shape[0].setOrigin(100, 100);
        shape[0].setFillColor(sf::Color::Red);
        shape[1].setPosition(400, 300);
        shape[1].setSize(sf::Vector2f(100, 100));
        shape[1].setOrigin(50, 50);
        shape[1].setFillColor(sf::Color::Green);
        shape[2].setPosition(400, 300);
        shape[2].setSize(sf::Vector2f(400, 1));
        shape[2].setFillColor(sf::Color::White);
        player = shape[0].getPosition();
        sf::RenderWindow window(sf::VideoMode(800, 600), "test", sf::Style::Close);
        sf::Event event;
        while (window.isOpen()){
                // check events
                while (window.pollEvent(event)){
                        switch (event.type){
                        case sf::Event::KeyPressed:
                                if (event.key.code == sf::Keyboard::Escape)
                                        window.close();
                                break;
                        case sf::Event::Closed:
                                window.close();
                                break;
                        case sf::Event::MouseMoved:
                                mouse = sf::Mouse::getPosition(window);
                                break;
                        default:
                                break;
                        }
                }
                // logic
                std::this_thread::sleep_for(std::chrono::milliseconds(10));
                shape[1].setRotation(atan2(mouse.y - player.y, mouse.x - player.x) * 180 / PI);
                if (shape[0].getRotation() < shape[1].getRotation() - 1)
                        shape[0].rotate(1);
                else if (shape[0].getRotation() > shape[1].getRotation() + 1)
                        shape[0].rotate(-1);
                else
                        shape[0].setRotation(shape[1].getRotation());
                // draw
                window.clear(sf::Color::Black);
                window.draw(shape[2]);
                window.draw(shape[0]);
                window.draw(shape[1]);
                window.display();
        }
}
I hope you understand the issue.
« Last Edit: January 19, 2014, 09:09:12 pm by Inflammatory Nugget »

panithadrum

  • Sr. Member
  • ****
  • Posts: 304
    • View Profile
    • Skyrpex@Github
    • Email
Re: Delayed rotation
« Reply #1 on: January 19, 2014, 08:38:44 pm »
I haven't actually look at your code but I think you need this http://www.gmlscripts.com/script/angle_difference

panithadrum

  • Sr. Member
  • ****
  • Posts: 304
    • View Profile
    • Skyrpex@Github
    • Email
Re: Delayed rotation
« Reply #2 on: January 19, 2014, 08:48:00 pm »
It computes the shortest angle difference. Is a game maker script but it's easily convertible to C++.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Delayed rotation
« Reply #3 on: January 19, 2014, 08:53:07 pm »
If you don't want to reinvent the wheel, you might also be interested in Thor's Vector functions.

They are header-only, and thus can be used without building Thor.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Inflammatory Nugget

  • Newbie
  • *
  • Posts: 21
    • View Profile
Re: Delayed rotation
« Reply #4 on: January 19, 2014, 09:34:33 pm »
Hello again,

I implemented the code in your link into my program like this:
...
shape[1].setRotation(atan2(mouse.y - player.y, mouse.x - player.x) * 180 / PI);
                short temp = angle_difference(shape[1].getRotation(), shape[0].getRotation());
                if (temp > 1)
                        shape[0].rotate(1);
                else if (temp < -1)
                        shape[0].rotate(-1);
                else
                        shape[0].setRotation(shape[1].getRotation());
...
short angle_difference(float angle1, float angle2){
        return ((((static_cast<short>(angle1 - angle2)) % 360) + 540) % 360) - 180;
}
Thank you very much, panithadrum. My program is now running as I wanted  ;D

panithadrum

  • Sr. Member
  • ****
  • Posts: 304
    • View Profile
    • Skyrpex@Github
    • Email
Re: Delayed rotation
« Reply #5 on: January 20, 2014, 10:00:46 am »
Glad to hear that!

Sorry Nexus, I didn't know Thor also supported this. Is it the signed angle function?

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Delayed rotation
« Reply #6 on: January 20, 2014, 10:15:21 am »
No problem ;)

It depends on what you exactly want. If you need the rotation of a vector, then polarAngle() is the function of your choice:
sf::Vector2f v(...);
float angle = thor::polarAngle(v);

To compute the (signed) difference between two vectors, i.e. the angle by which you have to turn the first until it overlaps with the second, signedAngle() can be used:
sf::Vector2f v(...), w(...);
float angle = thor::signedAngle(v, w);

As far as I see, the second one does the same as in your example (but it works directly on the vectors), however it's implemented differently (atan2 + cross + dot product vs. twice atan2 + twice modulo + add/subtract). Furthermore, by casting to short, precision is lost; one could use std::fmod() instead.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development: