2013-09-01 10 views
6

Attualmente sto usando la libreria SDL2 e C per scrivere un'applicazione per iPhone, e le cose sono andate bene per la maggior parte. Sfortunatamente, la documentazione sembra essere piuttosto sottile in alcune aree, specialmente nelle funzioni specifiche di iOS. Sono nuovo nell'utilizzo di SDL2 e questo rende le cose molto difficili. Finora, tutto ha funzionato, ma sono perplesso su un problema. SDL2 definisce sei tipi di eventi da utilizzare specificamente per le applicazioni mobili. Il file README-ios.txt loro e li utilizzano descrive come tali:Come dovrei usare gli eventi applicativi iOS SDL2?

int HandleAppEvents(void *userdata, SDL_Event *event) 
{ 
    switch (event->type) 
    { 
    case SDL_APP_TERMINATING: 
     /* Terminate the app. 
      Shut everything down before returning from this function. 
     */ 
     return 0; 
    case SDL_APP_LOWMEMORY: 
     /* You will get this when your app is paused and iOS wants more memory. 
      Release as much memory as possible. 
     */ 
     return 0; 
    case SDL_APP_WILLENTERBACKGROUND: 
     /* Prepare your app to go into the background. Stop loops, etc. 
      This gets called when the user hits the home button, or gets a call. 
     */ 
     return 0; 
    case SDL_APP_DIDENTERBACKGROUND: 
     /* This will get called if the user accepted whatever sent your app to the background. 
      If the user got a phone call and canceled it, you'll instead get an SDL_APP_DIDENTERFOREGROUND event and restart your loops. 
      When you get this, you have 5 seconds to save all your state or the app will be terminated. 
      Your app is NOT active at this point. 
     */ 
     return 0; 
    case SDL_APP_WILLENTERFOREGROUND: 
     /* This call happens when your app is coming back to the foreground. 
      Restore all your state here. 
     */ 
     return 0; 
    case SDL_APP_DIDENTERFOREGROUND: 
     /* Restart your loops here. 
      Your app is interactive and getting CPU again. 
     */ 
     return 0; 
    default: 
     /* No special processing, add it to the event queue */ 
     return 1; 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    SDL_SetEventFilter(HandleAppEvents, NULL); 

    //... run your main loop 

    return 0; 
} 

Ho alcune domande su questo codice.

Cosa SDL_SetEventFilter() fare? Ho letto la pagina Wiki di SDL e mi è sembrato particolarmente vago.

In pratica, come fa il HandleAppEvents() lavoro di funzione? Per esempio, se ho il codice come questo:

int main(int argc, char* argv[]) 
{ 
    //Initialize SDL, etc... 
    SDL_SetEventFilter(HandleAppEvents, NULL); 


    //I've got some SDL_Textures and windows and things... 
    SDL_Window* my_window; 
    SDL_Renderer* windowrend; 
    SDL_Texture* tex1, tex2, tex3; 

    //Primitive game loop 
    while(game_is_running){ 
     handle_input(); 
     do_logic(); 
     update_screen(); 
    } 

    destroy_all_my_data(); 
    SDL_Quit(); 
    return 0; 
} 

Che tipo di codice deve essere inserito in HandleAppEvents() o main() di distruggere la memoria o fermare il mio ciclo di gioco quando ricevo uno SDL_APP_WILLENTERBACKGROUND, per esempio?

Diciamo che tex2 è sacrificabile e può essere eliminato se l'applicazione riceve uno SDL_APP_LOWMEMORY. Come cancellerei tex2 da HandleAppEvents() senza fare confusione con altri dati?

Cosa c'è nel puntatore userdata?

Quando la mia app entra in background, dovrei convertire le mie trame in superfici e salvarle nella directory ../tmp/ come bmps, o saranno ancora in memoria quando l'app tornerà in primo piano?

spero le mie domande confuse fare una sorta di senso. Se c'è un posto in cui posso trovare una documentazione approfondita per SDL2, sarebbe bello saperlo.

Grazie per dare un'occhiata!

risposta

5

SDL_SetEventFilter è un modo per "anticipare" la coda degli eventi di SDL. Fondamentalmente ottieni gli eventi appena vengono ricevuti, prima che vengano messi in coda, e nel caso iOS devi reagire immediatamente.

Il motivo tecnico di questo è che per questo tipo di messaggi, iOS utilizza una serie di callback, che SDL riceve e avvolge per rendere l'esperienza cross-platform il più semplice possibile, ma ciò non toglie che iOS si aspetta ancora che tu agisca su di loro prima di tornare dal callback.

Quindi, per esempio, se dovessimo semplicemente inserire il messaggio che il sistema ha poca memoria in coda invece di passarlo direttamente all'app tramite questo meccanismo, e basta fare nulla finché quell'evento non passa attraverso coda, il polling, ecc., iOS può chiudere forzatamente la tua app perché non si comporta come previsto.

Quando l'applicazione va in fondo, non è necessario per salvare le texture. iOS lo fa per te, e se non ha abbastanza memoria per farlo, uccide la tua app (non perdi mai i contesti GL ES/ES2, cosa che può accadere su determinati dispositivi Android).

Il puntatore userdata sta per contenere i dati passati come secondo parametro a SDL_SetEventFilter, quindi se si utilizza SDL_SetEventFilter (HandleAppEvents, NULL), userdata sarà NULL.

Su SDL_APP_WILLENTERBACKGROUND, se non ricordo male, non c'è bisogno di fare nulla.Non ho attivato la mia app iOS per un po ', ma penso che SDL gestisca tutto il suo stato interno (incluso il blocco del ciclo degli eventi e poi il riavvio) da solo. Gli eventi che devi gestire tu sono SDL_APP_LOWMEMORY e SDL_APP_TERMINATING, come gestisci che è specifico di app (cancella trame, memoria libera, ecc, va oltre SDL in particolare)

+0

+1 Per una risposta molto informativa. Mi piacerebbe davvero vedere un po 'di codice che spieghi cosa intendi, se ne hai il tempo! – BrainSteel

+0

Non penso che un esempio di codice si applichi in questo caso, poiché stai chiedendo per lo più domande "filosofiche", e dove il codice sarebbe utile nella parte specifica dell'app (SDL_APP_LOWMEMORY, ecc.) ... ma non ho un esempio per dare lì, probabilmente implica liberare risorse e tenerne traccia per ricrearle quando richiesto. Ma se vuoi chiarimenti sulla risposta, chiedi via! – gabomdq

+0

Ok, capisco cosa intendi. Ho intenzione di aggiornare la domanda con il codice più tardi, e spero di poter capire meglio l'argomento attraverso il tuo feedback. – BrainSteel

1

Come si deve vedere da this thread devi fermare il tuo loop di gioco su SDL_APP_WILLENTERBACKGROUND e riprenderlo su SDL_APP_WILLENTERFOREGROUND per evitare arresti anomali.