Autor Wątek: Algorytm na stałą prędkość gry  (Przeczytany 3873 razy)

Offline BrunonDEV

  • Użytkownik
    • Construgia -- RPG

# Lipiec 07, 2015, 23:34:07
Witam. Otóż najpierw zacznę od przedstawienia zmiennych jakimi się posługuję.

A więc każdy obiekt w mojej grze porusza się na podstawie:

obiekt.x += ( 1 - world.speed);
world.speed ma wartość 3.

FPS w grze są wymuszane (timery) na 100.

I teraz tak:

Oczywiście nie na wszystkich komputerach owe 100 FPS zostanie wyciągnięte.

Na komputerach na których gra wyciąga np. jedynie 50 FPS (musi być to naprawdę słaby komputer, ale takie też są) wszystkie postacie chodzą wolniej i w ogóle wszystko dzieje się wolniej.

Pomyślałem więc, że muszę napisać algorytm, który będzie co klatkę sprawdzał FPS i:

  • im mniej FPS, tym większy będzie "bonus" do world.speed,
  • im więcej FPS, tym większy będzie "anty-bonus" do world.speed.

I napisałem coś takiego:

void Update(){
//[..]

world.speed -= ( (100 - fps) * 0.001 );

//[..]
}

Wydaje mi się, że ten algorytm działa, pewności jednak nie mam.

Czy jest jednak prostszy, mniej obciążający sposób?

Czy podany wyżej algorytm działa?


Pozdrawiam. ;)
« Ostatnia zmiana: Lipiec 07, 2015, 23:36:14 wysłana przez BrunonDEV »

Offline Mr. Spam

  • Miłośnik przetworów mięsnych


Offline BrunonDEV

  • Użytkownik
    • Construgia -- RPG

# Lipiec 08, 2015, 00:26:26
Hm.. Czyli mam rozumieć, że mój genialny algorytm nie działa?

Używam czegoś.. podobnego.

Cały kod (tzn. "cały potrzebny" :P):

void Update(){
if(drawToScreen){
ConCity::Update();
FOTT::Update();

player.Update(playerG1, playerG2, playerG3, playerG4, optG);

App::drawText("(C) Construgia v.0.1.4 (DEV)", 110, 0);

eq::logic();

world.speed -= ( (100 - fps) * 0.001 ); // WORLD SPEED ALGHORITM !!!

draw_sprite(bufor, popupBufor, 0, 0);
draw_trans_sprite(bufor, mask, 0, 0);

Quest_System.update();

Options();

App::drawVariableText("FPS: ", 740, 0, fps, -1);

App::drawBufor();
}

if(key[KEY_ESC] && world.speed == -3 && runTimer <= 0) run = false;

if(runTimer >= 0)
runTimer--;

if(saveTimer > 0)
saveTimer--;
else
{
eq::save();
player.save();
Quest_System.save();
ConCity_Zbrojownia::save();
saveTimer = 3000;
}

if(key[KEY_F2] && runTimer <= 0){
std::string a1, a2, a3, a4;

a1 = std::rand() * 1;
a2 = std::rand() * 3;
a3 = std::rand() * 5;
a4 = std::rand() * 9;

std::string ciag;

ciag = a1 + a2 + a3 + a4;
ciag = "Screenshots/" + ciag + ".bmp";

save_bitmap(ciag.c_str(), bufor, default_palette);
runTimer = 25;
}
}

//////////////////////

void game(){
install_timer();
install_int(increment_speed, 10);
install_int_ex( increment_speed, BPS_TO_TIMER( speedXX ) );
install_int_ex(game_time_ticker, BPS_TO_TIMER(10));
srand( time( NULL ) );

Start();

int frames_done = 0;
int old_time = 0;

while(run){
while(speed == 0 && run)
{
rest(1);

if(key[KEY_ESC])
run = false;
}
while( speed > 0 && run)
{
int old_speed = speed;

Update();

speed--;

if(old_speed <= speed)
break;
}
// FPS->
if(game_time - old_time >= 10 && run)
{
fps = frames_done;

frames_done = 0;
old_time = game_time;

if(key[KEY_ESC])
run = false;
}
frames_done++;
// <-FPS
}

eq::save();
player.save();
Quest_System.save();
ConCity_Zbrojownia::save();

stop_sample( music );
destroy_sample( music );
allegro_exit();
}

Offline Adam27

  • Użytkownik

  • +1
# Lipiec 08, 2015, 00:51:13
Zazwyczaj prędkość wystarczy pomnożyć przez dt*c, gdzie dt do różnica czasu pomiędzy tą i poprzednio renderowaną klatką w sekundach, a c to jakiś współczynnik który w tym przypadku może wynosić 100 (albo odpowiednio w milisekundach i 0.1). Nie rozumiem tylko czym jest to world.speed, bo wzór na prędkość 1-world.speed wydaje się trochę dziwny.

Offline BrunonDEV

  • Użytkownik
    • Construgia -- RPG

# Lipiec 08, 2015, 00:57:50
Cytuj
Nie rozumiem tylko czym jest to world.speed, bo wzór na prędkość 1-world.speed wydaje się trochę dziwny.

Chodzi o to żeby prędkość była "globalna", i żebym mógł w każdym momencie zapauzować wszystkie obiekty w grze ustawiając world.speed = 1;. ;) Taki mój wymysł...

Dzięki za wskazówki. :)

Offline JasonVoorhees

  • Użytkownik
    • The Immortal Life of the Son of Jay

  • +2
# Lipiec 08, 2015, 11:41:24
Rozumiem, że piszesz swój silnik. Jednakże zalecam, żebyś najpierw zrobił coś w istniejącym silniku. Robiąc coś zgodnie z zasadami przyjętymi w silniku może Cię wiele nauczyć. Np. w unity to co chcesz osiągnąć, to przemnożenie przemieszczenia obiektu przez Time.deltaTime * Time.timeScale;

Jak chcesz zapauzować wszystkie obiekty, to piszesz: Time.timeScale = 0.0f;

No i jakbyś zdecydował się na Unity, to od razu mógłbyś łatwo wspierać więcej platform, no i miałbyś już jakieś doświadczenie, które można wykorzystać współcześnie w pracy.
« Ostatnia zmiana: Lipiec 08, 2015, 11:46:35 wysłana przez JasonVoorhees »

Offline Xion

  • Redaktor
    • xion.log

  • +3
# Lipiec 08, 2015, 12:29:07
Cytuj
Zazwyczaj prędkość wystarczy pomnożyć przez dt*c, gdzie dt do różnica czasu pomiędzy tą i poprzednio renderowaną klatką w sekundach, a c to jakiś współczynnik
Nie "jakiś", tylko przyspieszenie :P

Cytuj
Chodzi o to żeby prędkość była "globalna", i żebym mógł w każdym momencie zapauzować wszystkie obiekty w grze ustawiając world.speed = 1;. ;) Taki mój wymysł...
Twój `world.speed` to prostu mnożnik delty czasu; ustawiając go na 0, osiągniesz ową "pauzę". Tyle że w praktyce pauza jest po prostu osobnym stanem gry, a nie hackiem na pętli głównej.

Cytuj
Rozumiem, że piszesz swój silnik.
Nah, z tego pamiętam on pisze jakąś małą skomplikowaną grę typu point&click. Cokolwiek siedzi w jej środku, nazywanie tego "silnikiem" byłoby trochę na wyrost ;)

Cytuj
Jednakże zalecam, żebyś najpierw zrobił coś w istniejącym silniku.
Zwykle bym się zgodził, ale akurat tutaj wydaje mi się, że dłubanie we własnym kodzie będzie dla OP bardziej pożyteczne -- nauczy się, czego nie należy robić ;-)

Co do oryginalnego pytania, to wydaje mi się, że głównym problemem jest tutaj niezrozumienie istoty pętli czasu rzeczywistego i tego, jak należy uzależnić mechanikę od upływającego czasu (a nie jakichś wielkości pochodnych, jak FPS). Pozwolę więc sobie bezwstydnie wtrącić mój artykuł, który koncept ten powinien odpowiednio wyjaśnić :)

(Ten zalinkowany przez MaxGarden polecam przeczytać w drugiej kolejności, bo o ile opisuje on ważną kwestię stabilności symulacji fizycznych, to podejrzewam że dla OP nie będzie ona miała na razie wielkiego znaczenia, jeśli nie używa on niczego bardziej skomplikowanego niż ruch ze stałym przyspieszeniem, który da się dokładnie scałkować Eulerem ze zmiennym krokiem).

Offline BrunonDEV

  • Użytkownik
    • Construgia -- RPG

# Lipiec 08, 2015, 18:07:19
Wielkie dzięki Xion, to bardzo pomoże. :)

Cytuj
Nah, z tego pamiętam on pisze jakąś małą skomplikowaną grę typu point&click. Cokolwiek siedzi w jej środku, nazywanie tego "silnikiem" byłoby trochę na wyrost ;)

Tak, piszę małą gierkę, ale nie point'n'click tylko strzałka'n'naciśnięcie. :D

I rzeczywiście silnikiem tego nie mogę nazwać, chodź by łatwiej opisywać to w filmikach podzieliłem kod gry na części "silnik" i "gra", gdzie w "silniku" są metody i klasy, których używam w "grze". ;)

Jeszcze raz dzięki wszystkim za odpowiedzi. :)

Pozdrawiam!