Elikkä minä teen erästä peliä, ja se kaipaisi nyt jotain kunnon framerate systeemiä, tähän mennessä olen vain tehnyt neekerinkengät eli laittanut kisaloopin loppuun SDL_Delay(15); Tämä ei liene kuitenkaan tehokas tapa, eikä varsinkaan vakaa ja järjestelmäriippumaton. Joten kuinkas tämä tehdään ammattimaisesti?
SDL:llä on muuten kiva funktio fsp:n rajoittamiseen, FPSmanager. Tässähän tämä:
// Rajoita framea: // Alusta framin hallintafunkkari: FPSmanager fpsm; SDL_initFramerate(&fpsm); SDL_setFramerate(&fpsm, 60); // 60 framea sekunnissa // Kutsutaan FrameLimitteri: SDL_framerateDelay(&fpsm);
"Ammattimaisesti" homma kuitenkin tehdään niin, että katsotaan, kauanko aikaa on mennyt edellisen framen piirtämisestä ja sitten lasketaan kaikki pelin fysiikka yms sen ajan mukaan. FPS voi olla mikä vaan, mutta kaikki tapahtuu yhtä nopeasti koneesta riippumatta.
Ja mitä sitten tehdään, kun peli ei pyöri tuolla 60:llä framella? Eli ei mitään FPS:n purkkasäätöä, vaan tuo Deewiantin mainitsema tapa.
Mahdollisimman tarkalla tavalla:
for (i = 0; i < KulunutAika; ++i) { Nopeus += Kiihtyvyys; Sijainti += Nopeus; }
Tai nopeammin:
Nopeus += Kiihtyvyys * KulunutAika; Sijainti += Nopeus * KulunutAika;
Tai sitten jollakin hienommalla tavalla. Konstit on monet.
Miten tuo for
-looppi on tarkempi kuin kertolasku? Ainahan tuosta tulee sama tulos, ellei sitten tule jotain overflowta, jolloin kummankin tavan tuottama tulos on pielessä.
Metabolix kirjoitti:
Ja mitä sitten tehdään, kun peli ei pyöri tuolla 60:llä framella? Eli ei mitään FPS:n purkkasäätöä, vaan tuo Deewiantin mainitsema tapa.
Mahdollisimman tarkalla tavalla:
for (i = 0; i < KulunutAika; ++i) { Nopeus += Kiihtyvyys; Sijainti += Nopeus; }Tai nopeammin:
Nopeus += Kiihtyvyys * KulunutAika; Sijainti += Nopeus * KulunutAika;Tai sitten jollakin hienommalla tavalla. Konstit on monet.
Nyt en täysin ymmärtänyt... Mikä tuossa on tuo KulunutAika?
Tumpelo kirjoitti:
Mikä tuossa on tuo KulunutAika?
Tämäntyylisesti:
int main() { while (pelataan) loop(); } void loop() { int aikaNyt = katoKellosta(); int kulunutAika = edellinenAika - aikaNyt; ynnääNopeusJaSijainti(kulunutAika); edellinenAika = aikaNyt; }
No kuinkas tuo aika sitten katsotaan?
Hakua saa käyttää.
Uint32 KulunutAika, VanhaAika; // Aika aluksi (Vai lupasikohan SDL, että se on nolla? Anyway...) VanhaAika = SDL_GetTicks(); // Pääsilmukkasi, mikä lie onkaan while (1) { KulunutAika = SDL_GetTicks() - VanhaAika; VanhaAika += KulunutAika; // Kaikki muu koodi tänne }
Ah, nyt selkeni. Vaikuttaa kätevälle, pitää viikonloppuna soveltaa koodissa kun aivot juoksevat sitten paremmin...
Metabolix kirjoitti:
// Aika aluksi (Vai lupasikohan SDL, että se on nolla? Anyway...)
SDL_GetTicks()
palauttaa SDL:n alustuksesta (vai ohjelman käynnistyksestä?) kuluneen ajan millisekunteina. Todennäköisesti se siis ei ole nolla.
Ja koska se on 32-bittinen etumerkitön kokonaisluku, se overflowaa vajaan 50 päivän päästä, eli softan käyttötarkoituksesta riippuen kannattaa olla tarkkana.
Ah, mutta overflowlla ei ole tässä tapauksessa mitään merkitystä, koska framen pituus tulee laskettua oikein siitä huolimatta. Ongelmia tulee vasta, jos yhden framen pituus venyy sinne 49,7 vuorokauden yli.
Nollalla tarkoitin juuri sitä, että onko tuo mahdollisesti SDL_n alustuksen jälkeen nolla. Mutta toki tuo kuuluu joka tapauksessa poimia juuri ennen pääsilmukkaa, koska sitä ennen on kuitenkin jo latailtu tiedostoista jotakin. Minusta on myös hyvä asettaa se kohdalleen aina, kun jotakin mahdollisesti pitkäkestoista tapahtuu (esimerkiksi tason lataaminen tiedostosta).
Aihe on jo aika vanha, joten et voi enää vastata siihen.