[SFML] Przetwarzanie czasu w grze
Ostatnio zmodyfikowano 2024-02-12 17:06
tBane Temat założony przez niniejszego użytkownika |
[SFML] Przetwarzanie czasu w grze » 2024-02-12 15:50:15 Załóżmy, że mam obiekt Unit, który posiada zmienną timeOfPrevAction przechowującą informację o tym kiedy została wykonana poprzednia akcja. Jak aktualizować ten obiekt co 0.1s ?? class Unit { public: float x, y; int timeOfPrevAction; Unit(); ~Unit(); void update(); };
|
|
DejaVu |
» 2024-02-12 15:56:22 Jednostki nie powinny zawierać informacji 'kiedy' ostatni raz była wykonana akcja. W grach stosuje się zazwyczaj 'stałą' deltę przyrostu czasu. Oznacza to, że poza jednostkami kontrolujesz czas i dbasz o to, aby np. 30x na sekundę w równych odstępach czasu była wywoływana metoda update(). Zamiast czasu możesz stosować 'ticki'. Tick to taka sztuczna jednostka, gdzie np. zakładasz, że logika gry aktualizuje się 30x na sekundę, czyli w ciągu 1 sekundy masz 30 ticków. Wówczas jeżeli jakieś zdarzenie trwa 45 ticków to wiesz, że po 45 wywołaniach metody Update ma np. skończyć się budować broń/jednostka lub np. ma się przeładować broń i być gotowa do kolejnego strzału. Mając ticki, wszystko kontrolujesz w liczbach całkowitych.
Jeżeli nie chcesz robić ticków, możesz przekazywać 'delta czasu' do metody 'update' ile upłynęło czasu w sekundach (typ double), ale obliczenia na double-ach to pchanie się w kłopoty, bo gdzieś będzie Ci uciekała precyzja obliczeń i prędzej czy później będziesz miał z tego powodu 'artefakty'.
Gdy zatrzymujesz czas, to po prostu przestajesz wywoływać metodę update() dla każdej jednostki, ale nadal logika 'pauzy' odbywa się poza jednostkami, tylko w klasie, która steruje czasem, a dokładniej 'kontroluje' w jakich odstępach czasu rzeczywistego należy wywołać metodę update, aby uzyskać mniej więcej 30 ticków/sek. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-02-12 16:58:48 czyli zamiast stosować timeOfPrevAction lepiej zastosować "liczniki akcji" ? np. dla ataku: attackAction = 0.0f; attackActionEndValue = 50.0f;
if( attackActions < attackActionEndValue ) { attackAction += 1.0f; } else { attackAction = 0.0f; attack(); }
|
|
DejaVu |
» 2024-02-12 17:03:35 Nie używaj double. Użyj int-a lub ewentualnie uint64_t jeżeli uważasz, że int może być 'za mały'. Double jest podatny na błędy. Czyli: void Unit::update() { if( m_waitForWeaponRecharge > 0 ) --m_waitForWeaponRecharge; }
bool Unit::attack( Unit * target ) { if( m_waitForWeaponRecharge > 0 ) return false; if( target == nullptr ) return false; if( !target->canBeAttacked() ) return false; target->dealDamage( 50 ); m_waitForWeaponRecharge = 10; return true; }
|
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-02-12 17:06:31 dzięki za pomoc! :-) |
|
« 1 » |