Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Zwiększenie prędkości animacji w SFML przy użyciu Clock

Ostatnio zmodyfikowano 2017-12-23 11:28
Autor Wiadomość
Kyubix
Temat założony przez niniejszego użytkownika
Zwiększenie prędkości animacji w SFML przy użyciu Clock
» 2017-12-23 00:17:35
Piszę w SFMLu własnego Arkanoida. Zmagam się z problemem dotyczącym animacji. Konkretnie ustawiam ruch mojej paletki przy użyciu zegara. W klasie mam zainicjowane atrybuty czas oraz mnoznikPredkosci. Czas odpowiada za taktowanie zegara, a mnoznikPredkosci ma na celu zwiększanie lub zmniejszanie szybkości taktowania. W tym miejscu pojawia się problem z zegarem. Gdy mój mnoznik jest duży (10) to paletka porusza się bardzo wolno i w miarę jego zmniejszania przyspiesza. Problem pojawia się gdy zejdę już do wartości ok. 1. Wtedy paletka już nie przyspiesza, i dla wartości 1 oraz np. 0.001 jej prędkość jest taka sama. Wiem, że mógłbym po prostu zwiększyć ruch paletki na więcej niż jeden pixel, jednak trochę to komplikuje mi to dalsze tworzenie gry. Dodatkowo, gdy ruch paletki tworzę w głównej pętli programu już bez zegara to nie ma żadnych ograniczeń i paletka bardzo szybko się porusza.
Klasa:
C/C++
class Paletka
{
protected:
    Sprite paletka;
    Texture teksturaPaletki;
    Clock zegarPaletki;
    float czas; //czas jednej klatki
    float mnoznikPredkosci; //im mniejszy tym szybciej leci piłka
public:
    Paletka( float = 1.0, float = 5.0 );
    ~Paletka();
    void Wczytaj();
    Sprite PaletkaZwroc();
    void Sterowanie( Tlo t );
};
Konstruktor i metoda Sterowanie:
C/C++
Paletka::Paletka( float mnPredkosci, float t )
{
    this->mnoznikPredkosci = mnPredkosci;
    this->czas = t;
    Wczytaj();
}

void Paletka::Sterowanie( Tlo background )
{
    float time = this->czas * this->mnoznikPredkosci;
    if( this->zegarPaletki.getElapsedTime().asMilliseconds() > time )
    {
        if( paletka.getPosition().x > 8 )
        if( Keyboard::isKeyPressed( Keyboard::Left ) )
             paletka.move( - 1, 0 );
       
        if( paletka.getPosition().x + teksturaPaletki.getSize().x < background.TloZwroc().getGlobalBounds().width - 8 )
        if( Keyboard::isKeyPressed( Keyboard::Right ) )
             paletka.move( 1, 0 );
       
        this->zegarPaletki.restart();
    }
}
Metodę Sterowanie wywołuję w pętli głównej programu.
Sprawdzałem w debuggerze i zmienna time przyjmuje dobre wartości.
Wiem, że może mój kod nie wygląda zbyt profesjonalnie, ale niedawno zacząłem przygodę z obiektowym programowaniem, więc proszę o wyrozumiałość :)
P-168072
pekfos
» 2017-12-23 00:41:39
C/C++
int time = this->czas * this->mnoznikPredkosci;
Tracisz precyzję rzutując to na int. Poza tym takie podejście jest błędne. Jak chcesz precyzyjnie określać prędkość, to zrób prędkość. Podstawowy wzór z fizyki, s = v * t.
P-168073
Kyubix
Temat założony przez niniejszego użytkownika
» 2017-12-23 00:53:36
Tam rzeczywiście ma być float, dużo razy kombinowałem z typem danych i przeoczyłem tą zamianę. Jednak to nadal nie naprawia problemu. Może tłumacząc to w prostszy sposób: tworzę zmienną czas, która jest czasem, po którym paletka się przesunie. Dla 10 ms paletka się porusza wolno, dla 5 już przyspiesza jednak dalsze zmniejszanie zmiennej czas nie wpływa na jej szybszy ruch. Czy to może być spowodowane? Fizykę mogę zrobić w każdej chwili, jednak nie to jest moim problemem.
C/C++
void Paletka::Sterowanie( Tlo background )
{
    float czas = 10.0; //przy 5.0 paletka przestaje przyspieszac
    if( this->zegarPaletki.getElapsedTime().asMilliseconds() > czas )
    ...
   
         }
P-168074
pekfos
» 2017-12-23 00:57:58
Nie przesuwasz nigdy paletki częściej niż raz na klatkę. Czasy poniżej pewnego progu już nic nie robią w twoim kodzie. Powinieneś raczej robić akumulator typu float do którego dodajesz czas i dopóki ten czas jest większy od progu, to wykonujesz akcję i odejmujesz wartość progu od akumulatora. W ten sposób nie będziesz tracić czasu, jak teraz, gdzie sprawdzasz raz, czy upłynęło dość czasu by się ruszyć i resetujesz zegar.
P-168075
Kyubix
Temat założony przez niniejszego użytkownika
» 2017-12-23 01:16:38
Mógłbyś pokazać jak to w kodzie by wyglądało lub jakoś bardziej naprowadzić? Nie do końca rozumiem jak to zrobić.
P-168076
pekfos
» 2017-12-23 01:23:20
C/C++
float m_time; // w klasie

// w aktualizacji:
constexpr float TimeStep = 0.5f; // Co pół sekundy
m_time += m_clock.reset().asSeconds();

for(; m_time >= TimeStep; m_time -= TimeStep )
{
    // Tu rzecz która ma się dziać co TimeStep sekund
}
P-168077
Kyubix
Temat założony przez niniejszego użytkownika
» 2017-12-23 11:28:48
Super, teraz wszystko ładnie śmiga. Trzeba tylko jeszcze atrybutowi m_czas przypisać w konstruktorze wartość początkową 0.0f. Dzięki za pomoc.
P-168079
« 1 »
  Strona 1 z 1