[SFML] Ruch gracza w grze
Ostatnio zmodyfikowano 2024-05-11 19:55
pekfos |
» 2024-05-10 22:43:57 skoro tak, to dt nie jest deltą. Przynajmniej tak to rozumiem. Nie chodzi o to czy jest, tylko o implementację obliczeń. Precyzja liczby zmiennoprzecinkowej zależy od jej wartości. Dla odpowiednio dużej liczby nie ma w ogóle części ułamkowej. Czas wciąż płynie, ale te floaty będą miały dokładność co do np pół sekundy, albo całej sekundy i wtedy delta będzie wynosić 0.5s albo 1s i zero w pozostałych obiegach pętli. sf::Time wewnętrznie trzyma czas jako liczbę całkowitą w mikrosekundach, więc nie ma tego problemu. Więc jak wtedy aktualizować gracza ? A co z kodem który podałem na to wcześniej? dt = currentTime.asSeconds() - prevTime.asSeconds();
Jak już to dt =( currentTime - prevTime ).asSeconds();
Chcesz mieć sf::Time minus sf::Time, a nie float minus float. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-05-10 23:11:39 Ok, już rozumiem dlaczego należy używać sf::Time. Pozostało mi wyznaczyć aktualną klatkę animacji, ale przez to dt się gubię. sf::Clock clock; sf::Time prevTime = clock.getElapsedTime(); sf::Time currentTime = prevTime; float dt;
while( window->isOpen() ) { prevTime = currentTime; currentTime = clock.getElapsedTime(); dt =( currentTime - prevTime ).asSeconds(); for( auto & go: gameObjects ) go->update( dt ); |
|
pekfos |
» 2024-05-11 13:31:55 No to znowu, co z tym kodem który podałem? Masz tu symulację. Założyłem że animacja ma 12fps, zmienną fps w maine możesz kontrolować ile faktycznie aktualizacji na sekundę wykonujesz. Dla fps mniejszego od 12 będziesz czasem gubić klatki animacji, a dla większego czasem wyświetlać tą samą parę razy pod rząd, ale po 2 sekundach pracy będzie osiągnięte oczekiwane ~24 klatki w obu przypadkach. struct S { int step = 0; float countdown = 0; void update( float dt ) { countdown -= dt; while( countdown <= 0 ) { countdown += 1.f / 12; step++; } } };
#include <cstdio>
int main() { S s; int fps = 10; float dt = 1.f / fps; for( float t = 0; t < 2; t += dt ) { printf( "t=%8.4fs, dt=%.4f, frame=%d\n", t, dt, s.step ); s.update( dt ); } } |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-05-11 18:46:24 dobra, zrozumiałem. Przepisałem kod i wyszło mi coś takiego. Wszystko działa płynnie, dziękuję za pomoc :-) void calculateCurrentFrame( float dt ) { countdown -= dt; while( countdown <= 0.0f ) { countdown += 1.0f / 12.0f; step += 1.0f; } }
void update( float dt ) { float distance = 15.0f * stepSize * dt; if( state == states::fight ) { calculateCurrentFrame( dt ); if( step > 3.0f ) { step -= float( step / 3 ) * 3.0f; state = states::idle; } bodySprite->setTexture( * fightTextures[ direction * 4 + int( step ) ] ); } else if( state == states::run ) { calculateCurrentFrame( dt ); state = states::idle; if( step > 3.0f ) step -= float( step / 3 ) * 3.0f; if( direction == 0 ) y -= distance; if( direction == 1 ) x += distance; if( direction == 2 ) y += distance; if( direction == 3 ) x -= distance; bodySprite->setTexture( * runTextures[ direction * 4 + int( step ) ] ); } else if( state == states::idle ) { calculateCurrentFrame( dt ); if( step > 3.0f ) step -= float( step / 3 ) * 3.0f; bodySprite->setTexture( * idleTextures[ direction * 4 + int( step ) ] ); } mouseOvering(); bodySprite->setPosition( x, y ); collider->setPosition( x, y ); attackRangeArea->setPosition( x, y ); textname->setPosition( x, y - height - 30 ); }
|
|
1 « 2 » |