Domanda

Sto costruendo un gioco 3d da zero in C ++ usando OpenGL e SDL su Linux come hobby e per saperne di più su questa area di programmazione.

Mi chiedo quale sia il modo migliore per simulare il tempo mentre il gioco è in esecuzione. Ovviamente ho un loop simile a:

void main_loop()
{
    while(!quit)
    {
         handle_events();
         DrawScene();
         ...
         SDL_Delay(time_left());
    }
}

Sto usando SDL_Delay e time_left () per mantenere un framerate di circa 33 fps.

Avevo pensato di aver solo bisogno di alcune variabili globali come

int current_hour = 0;
int current_min = 0;
int num_days = 0;
Uint32 prev_ticks = 0;

Quindi una funzione come:

void handle_time()
{
    Uint32 current_ticks;
    Uint32 dticks;
    current_ticks = SDL_GetTicks();
    dticks = current_ticks - prev_ticks; // get difference since last time

    // if difference is greater than 30000 (half minute) increment game mins
    if(dticks >= 30000) {
         prev_ticks = current_ticks;
         current_mins++;
         if(current_mins >= 60) {
            current_mins = 0;
            current_hour++;
         }
         if(current_hour > 23) {
            current_hour = 0;
            num_days++;
         }
    }
 }

e quindi chiama la funzione handle_time () nel ciclo principale.

Compila ed esegue (usando printf per scrivere l'ora sulla console al momento) ma mi chiedo se questo è il modo migliore per farlo. Esistono modi più semplici o modi più efficienti?

È stato utile?

Soluzione

Ne ho già parlato in altri thread relativi al gioco. Come sempre, segui i suggerimenti di Glenn Fiedler nelle sue serie di giochi fisici

Quello che vuoi fare è usare un timestep costante che ottieni accumulando delta di tempo. Se vuoi 33 aggiornamenti al secondo, il tuo timestep costante dovrebbe essere 1/33. Puoi anche chiamarla frequenza di aggiornamento . Dovresti anche separare la logica di gioco dal rendering in quanto non si uniscono. Volete essere in grado di utilizzare una bassa frequenza di aggiornamento mentre il rendering è veloce quanto la macchina lo consente. Ecco un po 'di codice di esempio:

running = true;
unsigned int t_accum=0,lt=0,ct=0;
while(running){
    while(SDL_PollEvent(&event)){
        switch(event.type){
            ...
        }
    }
    ct = SDL_GetTicks();
    t_accum += ct - lt;
    lt = ct;
    while(t_accum >= timestep){
        t += timestep; /* this is our actual time, in milliseconds. */
        t_accum -= timestep;
        for(std::vector<Entity>::iterator en = entities.begin(); en != entities.end(); ++en){
            integrate(en, (float)t * 0.001f, timestep);
        }
    }
    /* This should really be in a separate thread, synchronized with a mutex */
    std::vector<Entity> tmpEntities(entities.size());
    for(int i=0; i<entities.size(); ++i){
        float alpha = (float)t_accum / (float)timestep;
        tmpEntities[i] = interpolateState(entities[i].lastState, alpha, entities[i].currentState, 1.0f - alpha);
    }
    Render(tmpEntities);
}

Gestisce il sottocampionamento e il sovracampionamento. Se usi l'aritmetica intera come fatto qui, la tua fisica di gioco dovrebbe essere prossima al 100% deterministico, non importa quanto sia lenta o veloce la macchina. Questo è il vantaggio di aumentare il tempo a intervalli di tempo fissi. Lo stato utilizzato per il rendering viene calcolato mediante interpolazione tra lo stato precedente e quello corrente, in cui il valore residuo all'interno dell'accumulatore temporale viene utilizzato come fattore di interpolazione. Ciò garantisce che il rendering sia fluido, indipendentemente dalla dimensione del timestep.

Altri suggerimenti

Oltre ai problemi già indicati (dovresti usare una struttura per i tempi e passarla a handle_time () e il tuo minuto verrà incrementato ogni mezzo minuto) la tua soluzione va bene per tenere traccia del tempo in esecuzione nel gioco.

Tuttavia, per la maggior parte degli eventi di gioco che devono accadere ogni tanto, probabilmente dovresti basarli sul loop di gioco principale invece che su un tempo reale, in modo che accadranno nelle stesse proporzioni con un fps diverso.

Uno dei post di Glenn che vorresti davvero leggere è Fix Your Timestep! . Dopo aver cercato questo link ho notato che Mads ti ha indirizzato allo stesso posto generale nel suo risposta

Non sono uno sviluppatore Linux, ma potresti voler dare un'occhiata all'utilizzo dei timer anziché al polling per le zecche.

http://linux.die.net/man/2/timer_create

EDIT:
SDL sembra supportare i timer: SDL_SetTimer

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top