Tworzenie gry 2D - kłopot z przycięciami

0

Witam. Mam pewien problem przy wyświetlaniu w grze. Otóż w momencie, kiedy ustawiam blokadę klatek (np. na 60) - obraz w pewnych momentach zaczyna się przycinać. Kompletnie nie mam pomysłu, czego to może być wina, pewnie ja coś robię źle, albo nie robię czegoś, co powinienem. Korzystam z biblioteki graficznej SFML i kompiluję na Code::Blocks, ale próbowałem również na Visual Studio 2015. Próba przerzucenia się na openFrameworks-a nie pomogła - problem został ten sam mimo, iż tam kod wyglądał nieco inaczej. Próbowałem interpolacji, ale to też nic nie dało (pewnie dlatego, że w przykładzie, który podam poniżej ruch gracza wykonuje się częściej bądź z tą samą częstotliwością, co wyświetlanie). Próbowałem zamienić float-a na int-a i operować przy pozycji gracza na dużych wartościach (dla większej dokładności, bo float może źle zaokrąglać), ale bez skutku. Poniżej kod przykładowego programu:

#include <SFML/Graphics.hpp>

#define FRAMERATE       60
#define ENGINE_TICKS    600

#define SCREEN_WIDTH    1280
#define SCREEN_HEIGHT   720

using namespace std;
using namespace sf;

float PosX = 0;
float PosY = 0;
float Speed;

void Move( Int64 Time )
{
    Speed = 0.0005 * Time;

    if( Keyboard::isKeyPressed( Keyboard::A ) )
        PosX -= Speed;

    if( Keyboard::isKeyPressed( Keyboard::W ) )
        PosY -= Speed;

    if( Keyboard::isKeyPressed( Keyboard::D ) )
        PosX += Speed;

    if( Keyboard::isKeyPressed( Keyboard::S ) )
        PosY += Speed;


    if( PosX < 0 )
        PosX = SCREEN_WIDTH;
    else if( PosX > SCREEN_WIDTH )
        PosX = 0;

    if( PosY < 0 )
        PosY = SCREEN_HEIGHT;
    else if( PosY > SCREEN_HEIGHT )
        PosY = 0;
}

int main()
{
    RenderWindow window( VideoMode( SCREEN_WIDTH, SCREEN_HEIGHT ), "Lag Test" );
    window.setFramerateLimit( ENGINE_TICKS ); // Blokada predkosci silnika

    Texture texture;
    texture.loadFromFile( "player.png" );

    Sprite sprite;
    sprite.setTexture( texture );

    Clock GameClock;
    Time GameTime;

    Clock FramerateClock;
    Time FramerateTime;

    // Glowna petla gry
    while ( window.isOpen())
    {
        Event event;
        while ( window.pollEvent( event ) )
        {
            if ( event.type == Event::Closed )
                window.close();
        }

        // Czas w grze
        GameTime = GameClock.getElapsedTime();
        GameClock.restart();

        // Ruch
        Move( GameTime.asMicroseconds() );

        // Blokada klatek
        static int Frame = 0;
        FramerateTime = FramerateClock.getElapsedTime();

        if( FramerateTime.asMicroseconds() >= ( float( 1000000 / FRAMERATE ) * Frame ) )
        {
            if( FramerateTime.asMicroseconds() >= 1000000 )
            {
                FramerateClock.restart();
                Frame = 0;
            }
            Frame++;

            //Wyswietlanie
            window.clear( Color( 0, 255, 255 ) );
            sprite.setPosition( PosX, PosY );
            window.draw( sprite );
            window.display();
        }
    }

    return 0;
}

To jest przykład napisany przeze mnie na podstawie kodu ze strony SFML-a: http://www.sfml-dev.org/tutorials/2.3/start-cb.php. U znajomego w grze problem przycinania również się pojawiał (zupełnie niezależny projekt od mojego). Próbowałem już różnych modeli pętli głównej gry, ale przy tym efekt był najmniej widoczny.

Myślę, że to najważniejsze informacje dotyczące problemu. Ewentualnie, jeszcze jeżeli chodzi o moje obserwacje to np. jeśli w if-ie, gdzie wyświetlam obraz wstawiłem cout-a, który wyświetla w konsoli cokolwiek (np. pozycję gracza), to w momentach przycinania tekst w konsoli również poddany był temu efektowi, gdy zaś próbowałem blokady do 80 FPS-ów, to przycinki były regularne (nieco słabsze od tych przy 40 klatkach), a problem oczywiście przestaje być widoczny przy odpowiednio wysokim limicie klatek. Mam wrażenie, jakby niektóre klatki były generowane z opóźnieniem i stąd to wrażenie "przeskakiwania" gracza.

Dodam jeszcze, że szukałem różnych poradników i przeszukiwałem to forum, ale nie znalazłem podobnego tematu, ani żadnej pomocnej informacji.
Z góry dziękuję za pomoc i wyrozumiałość :)

0

ja bym zrobil serwer rysujący na jednym wątku. Przerysowywać w zależności od potrzeb powinien całość lub fragmenty.

0
kaczus napisał(a):

ja bym zrobil serwer rysujący na jednym wątku. Przerysowywać w zależności od potrzeb powinien całość lub fragmenty.

Nie wiem, czy dobrze Cię zrozumiałem, ale zrobiłem osobny wątek, w którym mam pętlę wyświetlającą "scenę" z gry i o ile rzeczywiście wydajność bez blokady jest wyższa (ok. 15 %), to przy blokadzie 60 FPS problem zostaje.

Jeśli źle Cię zrozumiałem, chodzi o coś bardziej skomplikowanego, czy związanego z samym OpenGL-em to byłbym wdzięczny za jakieś wyjaśnienie/tutorial itp.

0

Jeśli chcesz przystopować, to sygnał do przerysowywania wysyłaj z timera, bo do końca nie wiem co chcesz teraz uzyskać.

0
kaczus napisał(a):

Jeśli chcesz przystopować, to sygnał do przerysowywania wysyłaj z timera, bo do końca nie wiem co chcesz teraz uzyskać.

Nie wiem, czy próbowałeś skompilować mój kod, bo technicznie rzecz biorąc działa jak by się tego oczekiwało - ogranicza wyświetlanie klatek do pożądanej wartości (w tym przypadku do 60), ale niepożądanym efektem są przycięcia, których nie potrafię wyeliminować. Ale jeśli się tego nie włączy i nie przetestuje, to oczywiste, że się nie zobaczy co mi w zasadzie nie pasuje.

Moje pytanie dokładnie brzmi tak: jak mam skonstruować pętlę główną gry (albo co mam w ogóle zrobić), aby przy 60 klatkach na sekundę obraz był płynny (co nawet udało mi się osiągnąć) i się nie przycinać w losowych momentach (czego nie potrafię osiągnąć).

Na wszelki wypadek, w załączniku przesyłam skompilowany program, żeby można było sobie zobaczyć ten efekt bez potrzeby kompilacji/instalowania biblioteki SFML.

0

Może dodam jeszcze załącznik z wersją dla 80 FPS. Teoretycznie powinno być lepiej, bo jest wyższy framerate, ale płynności tutaj już nie ma żadnej.

0

Cokolwiek ma to robić u mnie nie działa... Pokazuje się okno, ale w srodku nic....

0
kaczus napisał(a):

Cokolwiek ma to robić u mnie nie działa... Pokazuje się okno, ale w srodku nic....

Ten program na pewno działa (nie tylko u mnie, ale u moich kolegów także, a przynajmniej na Windows 10), więc nie wiem, co u Ciebie jest nie tak, ale powinno się wyświetlić okno z tłem w kolorze turkusowym z postacią (człowiekiem w zbroi) w lewym górnym rogu ekranu, którym się porusza standardowo na klawiszach W, S, A i D, ale tych rzeczy powinienem nie musieć Ci tłumaczyć, bo powinieneś to wywnioskować z kodu, a zaczynam się zastanawiać, czy w ogóle do niego zajrzałeś (nie mówiąc o próbie kompilacji). Dzięki za chęci, ale nie musisz się kłopotać, najwyżej poczekam, może ktoś jeszcze się wypowie.

0

Wyświetla się okno bez zawartości, a dokładniej zawartością staje się podkład wyświetlany podczas startu. Windowsa 10 nie mam i nie zamierzam specjalnie dla tego programu instalować

0
kaczus napisał(a):

Wyświetla się okno bez zawartości, a dokładniej zawartością staje się podkład wyświetlany podczas startu. Windowsa 10 nie mam i nie zamierzam specjalnie dla tego programu instalować

Nie oczekuję tego od Ciebie, już napisałem, nie musisz się kłopotać, chyba, że bardzo Ci zależy, to możesz skompilować kod samodzielnie. Jeśli nie potrafisz mi pomóc, to trudno, może komuś innemu się uda.

0

Skompilowałem, u mnie problem nie występuje.

0
Proxima napisał(a):

Skompilowałem, u mnie problem nie występuje.

A jak długo testowałeś? Czasem jest tak, że długo trzeba czekać, zanim się to pojawi, czasem od razu to jest widoczne. I jeśli można spytać, to na jakim systemie to sprawdzałeś?

0

Ciekawe, spróbuję zainstalować jakiegoś linuxa i skompilować to tam. A próbowałeś może na 80 FPS-ach, bo tam to przycinanie jest przez cały czas?

0

Przetestowałem to na Linuxie i problem jest ten sam, co prawda rzadziej się to pojawia (dłużej, niż na Windowsie trwa okres bez przycinania), ale jednak występuje. Ma ktoś jakieś pomysły? Może istnieje jakiś model pętli, który to zniweluje, a może tego problemu nie da się wyeliminować i tak musi być?

0

Niee, na stówe ty coś masz skopane w tej pętli, w każdym razie da się to wyeliminować na stówe, proponuje ci abyś zapytał się na forum SFMLa, gdyż znają oni tam internalsy tej biblioteki pewno lepiej niż tu.

0

Poczekam jeszcze trochę, a jak rzeczywiście tutaj nikt nic nie wymyśli, to napiszę gdzie indziej.

Proxima napisał(a):

... proponuje ci abyś zapytał się na forum SFMLa, gdyż znają oni tam internalsy tej biblioteki pewno lepiej niż tu.

Moim zdaniem to nie powinna być wina SFML-a, bo próbowałem na openFrameworks-ie (jak już wspomniałem w pierwszym poście) i problem był dokładnie ten sam, a testowy program napisałem w nim zupełnie inaczej.

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