Nie moge sobie poradzić z problemem (jak w temacie). Sprawa wygląda tak:
Mam prostokąt (RectangleShape). Origin ma ustawiony na punkt (x0, y0), połowa długości krótszej ściany - jeśli ktoś się nie orientuje, origin to punkt na obiekcie względem którego jest wykonywany obrót. Chciałbym go obracać "przeciągajac go". Póki co dąże do tego, żeby obracał się w strone miejsca w które klikne myszką. Jeśli w chwili kliknięcia jest poziomo (stan początkowy) i kąt obrotu nie będzie powyżej ~30*, to całkiem nieźle działa. Jeśli nie jest już poziomo - dzieją się różne rzeczy. Jęsli kąt jest większy niż te ~30* - zwiększa się błąd i obraca się troche za bardzo.
A więc wygląda to tak:
Klikam myszką, obliczana jest różnica, załóżmy delta = Yp - (wsp. Y puntu kliknięcia myszką). Kąt jest obliczny z arc-tangensa, w c++ atanf(delta / R). R - jak na rysunku - szerokość prostokąta.
Wzór na punkt (Xp, Yp) policzyłem z równań prostej przechodzącej przez (x0, y0) i (Xp, Yp) oraz okręgu po którym obraca się prostokąt (środek (x0, y0) , promień R). Wyszło: Xp = R / sqrt(1 + tg^2(alfa) ) + x0 i
Yp = Xp * tg(alfa) + y0 - x0 * tg(alfa). Kat alfa to oczywiście aktualne obrócenie naszego prostokąta względem poziomu. Tego wzoru jestem niemal pewien.
W założeniu ma to wyglądać tak, że klikam myszką na prostokąt i trzymając myszke przeciagam i obracam tyle ile chce. Dodam, że raczej nie potzrebny mi maksymalny obrót większy niż 90*.
W każdym razie - nie wiem co tu nie działa, możliwe, że jest już byt skomplikowane i nie ogarniam. A może da się to rozwiązać w zupełnie inny, prostszy sposób?
Tutaj rysunek do którego przez cały czas się odnosiłem:
I kod:
sf::Vector2f pos(sf::RectangleShape& rect){
const float x0 = rect.getPosition().x;
const float y0 = rect.getPosition().y;
const float R = rect.getSize().y;
const float arc = rect.getRotation();
const float tg = tan(arc);
float X = R / sqrtf(pow(tg, 2) + 1) + x0;
float Y = X * tg + y0 - (x0 * tg);
return sf::Vector2f(X, Y);
}
int main(){
sf::RenderWindow window(sf::VideoMode(500, 500), "okno");
window.setFramerateLimit(60);
sf::RectangleShape shape(sf::Vector2f(200.f, 80.f));
shape.setFillColor(sf::Color::Green);
shape.setOrigin(200.f, 40.f);
shape.setPosition(250.f, 250.f);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed){
window.close();
return 0;
}
if ( sf::Mouse::isButtonPressed(sf::Mouse::Left)){
float a = pos(shape).y - sf::Mouse::getPosition(window).y;
std::cout<<"shape posY: "<<pos(shape).y<<std::endl;
std::cout<<"mouse posY: "<<sf::Mouse::getPosition(window).y<<std::endl;
std::cout<<"a: "<<a<<std::endl;
float b = shape.getSize().x;
std::cout<<"b: "<<b<<std::endl;
float arc = atanf(a/b) * 180.f / 3.14;
shape.rotate(arc);
std::cout<<arc<<std::endl;
}
}
window.clear(sf::Color::White);
window.draw(shape);
window.display();
}
}