SFML - Limit ruchu myszki wokół okienka....

Odpowiedz Nowy wątek
2014-04-11 21:52
0

Witam, przez ostatni czas zgryzam zęby ze względu na problem który mi doskwiera. Muszę zastanowić się nad algorytmem do swojej gry, który będzie odpowiedzialny o blokowanie myszki, gdyby ta chciała wyjść poza ekran (Chcę, by myszką można było poruszać tylko i wyłącznie wokół okienka). Problem niby prosty, więc się zabrałem za to w taki sposób: Jeżeli dana pozycja X lub Y myszki jest poza ekranem (x < 0 || x > 1280, oraz y < 0 || y > 800) to resetuje mi pozycje myszki. Algorytm "jakoś" działa, i wygląda w moim kodzie tak:

    if (sf::Mouse::getPosition(window).x < 0 )
       sf::Mouse::setPosition(sf::Vector2i(0,sf::Mouse::getPosition(window).y),window);
    if (sf::Mouse::getPosition(window).x > 1024)
       sf::Mouse::setPosition(sf::Vector2i(1024,sf::Mouse::getPosition(window).y),window);
    if (sf::Mouse::getPosition(window).y < 0)
       sf::Mouse::setPosition(sf::Vector2i(sf::Mouse::getPosition(window).x,0),window);
    if (sf::Mouse::getPosition(window).y > 800)
       sf::Mouse::setPosition(sf::Vector2i(sf::Mouse::getPosition(window).x,800),window);

Dla ułatwienia, w pseudokodzie można było by to zapisać w takiej postaci:

if (MouseX < 0)
MouseSetPosition(0, MouseY);
if (MouseX > 1280) // 1280 to szerokość okienka
MouseSetPosition(1280, MouseY);
if (MouseY < 0)
MouseSetPosition(MouseX,0);
if (MouseY < 800) // 800 to wysokość okienka
MouseSetPosition(MouseX, 800);

Niestety, w taki sposób nie mogę doskonale zablokować myszki, bo w rzeczywistości można nią wyjść poza ekran, jeżeli w ciągu jednej klatki szybko machniemy myszką.
W przypadku innych gier, takie coś nie ma miejsca - przykładowo w grze Dota 2, która idealnie blokuje myszkę. (Oczywiście w okienkowym modzie, bo o takim mówimy)

Moje pytanie brzmi, czy jest w SFML 2.0 coś, co umożliwi mi ustanowienie limitu poruszania myszki tylko i wyłącznie w obrębie ekranu. Lub czy istnieje jakaś uniwersalna metoda, o której nie mam zielonego pojęcia.

Pozdrawiam.

edytowany 3x, ostatnio: Dawid90dd, 2014-04-11 22:00
W której pętli sprawdzasz pozycje myszki? pętli zdarzeń, czy pętli głównej ? - Proxima 2014-04-12 09:44

Pozostało 580 znaków

2014-04-12 10:08
0

Jak robiłem arkanoida to rozwiązałem to mniej więcej tak, sprawdzałem czy myszka nie jest krytycznie blisko boków, jeśli tak to cofałem myszkę.
Ten kod sprawdza boki, ale nie rogi okna, tzn musisz dopisać sobie jescze ify na przypadki gdy
X == 1; Y == 1;
X == maxX - 1; Y == 1;
oraz gdy:
X == 1: Y == maxY-1;
x == maxX - 1; Y == maxY-1;


#include <SFML/Graphics.hpp>
int main()
{
    const short int s_X = 600;
    const short int s_Y = 600;
    sf::RenderWindow window(sf::VideoMode(s_X, s_Y), "Przyklad");  
    sf::Vector2i pozycja; // Pozycja gryzonia;
    while (window.isOpen())
    {
        sf::Event event;
        sf::Mouse mysza;
        while (window.pollEvent(event))
        {
            /* 
             * Jeśli user bedzie miał ZAMIAR (a nie już to zrobił) 
             * wyjść poza ekran to zmień pozycje myszy 
             * w pętli sprawdzamy pozycje myszy tylko jak została poruszona */
            if(event.MouseMoved)
            {                                
                pozycja = sf::Mouse::getPosition(window);           
                    if(pozycja.x < 1)        sf::Mouse::setPosition(sf::Vector2i(1,pozycja.y),window);
                    if(pozycja.x > s_X - 1)  sf::Mouse::setPosition(sf::Vector2i(s_X-3,pozycja.y),window);          
                    if(pozycja.y < 1)        sf::Mouse::setPosition(sf::Vector2i(pozycja.x,1),window);
                    if(pozycja.y > s_Y - 1)  sf::Mouse::setPosition(sf::Vector2i(pozycja.x,s_Y-3),window);  
            }   
        }
        window.display();
    }
    return 0;
}
edytowany 1x, ostatnio: Proxima, 2014-04-12 10:14

Pozostało 580 znaków

2014-04-12 11:27
0

Odniosę się do Twojego komentarza: robiłem to w pętli głównej.
Hmm. Szczerze mówiąc byłem ciekawy czy to u mnie zadziała. Spróbowałem napisać to w swojej grze z wykorzystaniem eventu, ale to właściwie ma podobny, jak nie identyczny efekt jak w przypadku tego mojego sposobu... Jeżeli nie zrobiłem niczego źle, to oznacza, że za pomocą eventów raczej tego się nie da zrobić. Event jest dopiero po najechaniu myszki, a to oznacza że można wyjechać nią poza ekran.

Pokaż pozostałe 2 komentarze
Nie jestem specjalistą od SFML 2.0, może to gdzieś u mnie błąd... wysłałbym cały kod, ale to jest od kupy i jeszcze więcej. Może zaraz spróbuje zrobić nowy pusty program SFML 2.0, i tam spróbuje na czysto na funkcji main. - Dawid90dd 2014-04-12 11:35
Napisałem wyżej, że jako zamiar rozumiem to że mysza jest już bardzo blisko (kilka pixeli) od krawędzi okna. Jeśli jest już prawie przy skraju okna, to jest bardzo duże prawdopodobieństwo że za ułamek sekundy znajdzie się już poza nim(a tego SFML raczej nie kontroluje) (Sprawdź w nowym pliku czy ten mój kod Ci chodzi i wszystko będzie jasne) - Proxima 2014-04-12 11:41
No i właśnie zatoczyliśmy koło, bo to mój problem. Ostatnio mój przyjaciel stwierdził, że to co chce zrobić nie jest możliwe na SFML 2.0 w tradycyjny sposób - Refresh systemu a aplikacji nie są ==, z tego pętla główna z app SFML nie potrafi nadążyć. Zakładając jeżeli to jest źródło problemu, to nawet event nie nadąża idealnie za myszką. Zaraz sprawdzę czy zadziała to na czystym pliku. - Dawid90dd 2014-04-12 11:49
Bingo! Tak jak pisałem. Refresh systemu większy od refresh app. Zrobiłem to na nowej aplikacji, i rzeczywiście tak jest. Przy unlimited FPS, jakoś to działa. (chociaż generalnie nadal można wyjść poza ekran) Przy limicie fps do... np 20... no to nie wygląda za ciekawie.A w mojej aplikacji FPS jest ustawiony na 120, i właściwie nadal można wyjść myszką poza ekran. - Dawid90dd 2014-04-12 11:56
Tylko, że to nie rozwiązuje mojego problemu. Moja aplikacja nie bedzie miała idealnego refresh rate, a może nawet będzie miała limit do... nie wiem, 60? Nie wiem właściwie co teraz mogę zrobić... - Dawid90dd 2014-04-12 12:01

Pozostało 580 znaków

2014-04-12 12:14
0

Jeśli interesuje cię rozwiązanie z winapi to możesz użyć tego
http://msdn.microsoft.com/en-[...]op/ms648383%28v=vs.85%29.aspx
Nie wiem tylko czy nie będzie to sprawiać innych problemów.

Może to jeszcze się przyda
http://msdn.microsoft.com/en-[...]op/ms648380%28v=vs.85%29.aspx

edytowany 2x, ostatnio: Sopelek, 2014-04-12 12:20

Pozostało 580 znaków

2014-04-12 12:42
0

Jestem tylko ciekawy czy mógłbym połączyć winapi z SFML 2.0 (tak jak np sfml z opengl jeżeli się nie myle). W każdym razie dzięki za referencje, bo właśnie ich potrzebowałem - w mojej obecnej sytuacji bardzo mi pomogliście. Spróbuję poszukać więcej informacji w internecie, i być może właśnie rozwiązanie pokroju winapi. jak uda mi się to zrobić w krótkim czasie to na pewno dam znać! :-)

edytowany 3x, ostatnio: Dawid90dd, 2014-04-12 12:43

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0