2015-12-09 25 views
5

Ho un'app cocos2d v2.x che ha una scena che ha molti sprite, nodi, configurazione, dati , ecc. È piuttosto costoso da caricare, tanto che quando si aggiunge la scena al regista, c'è una pausa da 1/2 a 1 secondo, causando il congelamento delle animazioni correnti fino a quando la scena non viene caricata. Ho profilato i metodi più lenti e sto cercando di eseguirli in modo asincrono in un thread in background e visualizzare una finestra di avanzamento mentre carica.Cercando di caricare/impostare la scena in thread in background risulta "Errore OpenGL 0x0502 in - [CCSprite draw] 530"

mia implementazione è qualcosa di simile:

-(void)performAsyncLoad { 
    self.progressSpinner.visible = YES; 
    self.containerForLoadedStuff.visible = NO; 
    self.mainContext = [EAGLContext currentContext]; 

    NSOperationQueue *queue = [NSOperationQueue new]; 
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self 
                      selector:@selector(loadDependencies) 
                       object:nil]; 
    [queue addOperation:operation]; 
} 

-(void)loadDependencies { 
    @autoreleasepool { 
     glFlush(); 
     EAGLSharegroup *shareGroup = [[(CCGLView*)[[CCDirector sharedDirector] view] context] sharegroup]; 
     EAGLContext *context = [[EAGLContext alloc] initWithAPI:[[EAGLContext currentContext] API] sharegroup:shareGroup]; 
     [EAGLContext setCurrentContext:context]; 

     // ... expensive stuff here 
     // [self.containerForLoadedStuff addChild:sprites, etc...] 

     [self performSelectorOnMainThread:@selector(done) withObject:nil waitUntilDone:NO]; 
    } 
} 

-(void)done { 
    glFlush(); 
    [EAGLContext setCurrentContext:self.mainContext]; 
    self.progressSpinner.visible = NO; 
    self.containerForLoadedStuff.visible = YES; 
} 

Purtroppo questo non funziona, una volta che l'operazione viene richiamata, si blocca con EXC_BAD_ACCESS on line 523 di CCTextureAtlas su

glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(_indices[0]))); 

e la console log mostra miliardi di:

Errore OpenGL 0x0502 in - [disegno CCSprite] 530

cosa sto facendo di sbagliato?

UPDATE

ho cambiato il mio codice di fare:

dispatch_queue_t queue = dispatch_queue_create("myqueue", NULL); 
CCGLView *view = (CCGLView*)[[Director sharedDirector] view]; 
EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup:[[view context] sharegroup]]; 

dispatch_async(queue, ^{ 
    [EAGLContext setCurrentContext:context]; 

    // expensive calls 

    glFlush(); 
    [self performSelector:@selector(done) onThread:[[CCDirector sharedDirector] runningThread] withObject:nil waitUntilDone:NO]; 
    [EAGLContext setCurrentContext:nil]; 
}); 

e si è fermato il crash, e tutto funziona, ma ho ancora ottenere un miliardo:

OpenGL error 0x0502 in -[CCSprite draw] 530 
OpenGL error 0x0502 in -[CCSprite draw] 530 
OpenGL error 0x0502 in -[CCSprite draw] 530 
OpenGL error 0x0502 in -[CCSprite draw] 530 
OpenGL error 0x0502 in -[CCSprite draw] 530 
OpenGL error 0x0502 in -[CCSprite draw] 530 
OpenGL error 0x0502 in -[CCSprite draw] 530 
OpenGL error 0x0502 in -[CCSprite draw] 530 
OpenGL error 0x0502 in -[CCSprite draw] 530 
OpenGL error 0x0502 in -[CCSprite draw] 530 
OpenGL error 0x0502 in -[CCSprite draw] 530 
OpenGL error 0x0502 in -[CCSprite draw] 530 
OpenGL error 0x0502 in -[CCSprite draw] 530 
OpenGL error 0x0502 in -[CCSprite draw] 530 

Qualche idea sul perché questi errori stanno accadendo e su come posso fermarli?

ANCORA un altro aggiornamento

Questo non ha senso ... a quanto pare questi errori provengono da aggiungere sprite a un CCSpriteBatchNode. Se li metto su un normale CCNode, allora tutto funziona correttamente. CHE DIAVOLO!?!?!?!?!

ED UN ULTIMO AGGIORNAMENTO FINALE *

Sembra che non v'è solo un sacco di sciocchezze che io proprio non capisco. Sono riuscito a eliminare questi errori al 98%, ma sembra che si verifichino casualmente in modo estremamente intermittente. Ho fatto un sacco di debugger e processo & test errori, e ho trovato che questo codice:

-(void)loadDependencies { 
    dispatch_queue_t queue = dispatch_queue_create("myqueue", NULL); 
    CCGLView *view = (CCGLView*)[[Director sharedDirector] view]; 
    EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup:[[view context] sharegroup]]; 

    dispatch_async(queue, ^{ 
     [EAGLContext setCurrentContext:context]; 

     [self.myObject doExpensiveStuff]; 

     glFlush(); 
     [self performSelector:@selector(done) onThread:[[CCDirector sharedDirector] runningThread] withObject:nil waitUntilDone:NO]; 
     [EAGLContext setCurrentContext:nil]; 
    }); 
} 

-(void)done { 
    [self.delegate completedAsyncStuff]; 
} 

causato crashes-- casuale removeFromParent solito cocos cercando di rimuovere un quad a un indice non valido ... Allora ho provato facendo una pausa l'oggetto prima di fare il lavoro su di esso ..

//... background thread stuff: 
[self.myObject pauseSchedulerAndActions]; 
[self.myObject doExpensiveStuff]; 
[self.myObject resumeSchedulerAndActions]; 

Poi si è schiantato non è più, ma mettere gazillions di quelle OpenGL 0x0502 errore nel - [CCSprite pareggio] 530 nel registro ......

Così ho fatto un po 'di registrazione estrema per cercare di trovare dove accadevano questi errori ...

... // previous code above... etc 
     NSLog(@"gl flush..."); 
     glFlush(); 
     NSLog(@"after gl flush..."); 
     [self performSelector:@selector(done) onThread:[[CCDirector sharedDirector] runningThread] withObject:nil waitUntilDone:NO]; 
     [EAGLContext setCurrentContext:nil]; 
    }); 
} 

-(void)done { 
    NSLog(@"done scheduling notify delegate"); 
    [self scheduleOnce:@selector(notifyDelegate) delay:1]; 
} 

-(void)notifyDelegate { 
    NSLog(@"about to notify delegate"); 
    [self.delegate completedAsyncStuff]; 
} 

Nel mio registro vedo:

gl flush 
after gl flush 
done scheduling notify delegate 
OpenGL error 0x0502 in -[CCSprite draw] 530 
OpenGL error 0x0502 in -[CCSprite draw] 530 
OpenGL error 0x0502 in -[CCSprite draw] 530 
OpenGL error 0x0502 in -[CCSprite draw] 530 
OpenGL error 0x0502 in -[CCSprite draw] 530 
OpenGL error 0x0502 in -[CCSprite draw] 530 
OpenGL error 0x0502 in -[CCSprite draw] 530 
about to notify delegate 

Così questi errori accadono quando cocos è in attesa di fuoco di un selettore di programma ???? Che diavolo!? Non lo sopporto più e nessuno è stato in grado di aiutarmi, quindi è tempo di una ricompensa.

+0

http://stackoverflow.com/questions/15632690/opengl-error-0x0502-in-ccsprite-draw-530 – PWiggin

+0

@PWiggin mi dispiace, non capisco ... Non sto usando GLBegin(), GLLineWidth (), o glDrawArrays() ... Sto semplicemente aggiornando i miei ccsprites/ccno des e aggiungendoli come bambini. Stai dicendo che CCSpriteBatchNodes sta usando la modalità immediata? – patrick

+0

Questi sono solo esempi. L'importante è attenersi all'API Opengl 2.0. – PWiggin

risposta

5

Ecco come lo faccio:

LoadingScene

-(void) onEnterTransitionDidFinish { 
    [super onEnterTransitionDidFinish]; 
    [NSThread detachNewThreadSelector:@selector(loadGameSceneInAnotherThread) toTarget:self withObject:nil]; 
} 

- (void) loadGameSceneInAnotherThread { 
    NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; 
    CCGLView *view = (CCGLView*)[[CCDirector sharedDirector] view]; 
    EAGLContext *auxGLcontext = [[EAGLContext alloc] 
           initWithAPI:kEAGLRenderingAPIOpenGLES2 
           sharegroup:[[view context] sharegroup]]; 

    if([EAGLContext setCurrentContext:auxGLcontext]) { 
     self.gameScene = [GameScene sceneWithLevelName:levelName]; 
     self.gameLoadingDone = YES; 
     glFlush(); 
     [EAGLContext setCurrentContext:nil]; 
    } 
    [auxGLcontext release]; 
    [autoreleasepool release]; 
} 


//this method ticks every 0.5sec 
-(void) checkIfGameSceneLoaded { 
    if (self.gameLoadingDone) { 
     [self unschedule:@selector(checkIfGameSceneLoaded)]; 
     [[CCDirector sharedDirector] replaceScene:[CCTransitionFade transitionWithDuration:0.75 scene:self.gameScene]]; 
    } 
} 

Tuttavia, non mi consiglia di caricamento in background per le scene .. perchè cocos2d non realmente progettato per fare in modo ...

+0

Grazie! Stavo facendo affidamento sul figlio per eseguire performSelectorOnMainThread per informare il genitore (tramite la delega) che era pronto per essere aggiunto come un bambino e che ha provocato errori intermittenti. Avere il polling del genitore se il bambino è caricato e pronto per essere aggiunto sembra risolvere il problema (usando l'idea "checkIfGameSceneLoaded") e non vedo più quegli odiosi livelli OpenGL. Grazie!!! – patrick

+0

argh .. ho parlato troppo presto. ancora ottenere gli errori in modo casuale e intermittente. arrrrrrrgh. – patrick

+0

Forse questi errori perché il tuo sprite non ha dimensioni? Nessuna cornice?Ricordo tali errori nel mio vecchio gioco, solo perché ho aggiunto ai nodi batchnode e sprite senza immagine ([[CCSprite alloc] init], forse è per quello. Cerca di trovare esattamente cosa sprite causa questo problema. – KAMIKAZE

4

Puoi dirmi perché fai quello che vuoi così forte?

Se fossi in te, farei quanto segue, per caricare la scena asincrona.

  1. Caricare una scena intermedia con indicatore di caricamento o aggiungerla a quella corrente. + Crea un nuovo oggetto scena.
  2. Invio asincronicamente metodo costoso per quella nuova scena.
  3. Dopo aver fatto sostituire la scena con il CCDirector, tihs spedizione funzionamento sincrono

Usa GCD come si fa adesso. Non vuoi davvero disegnare la scena mentre la carichi, credimi.

+0

Ho una schermata di selezione del livello con una finestra di anteprima, e la selezione di un livello rivela uno spinner nella finestra di anteprima, ovvero quando il livello carica asincrona e la finestra di anteprima mostra il livello dopo il suo caricamento. Il problema è che non capisco da dove vengono questi errori. Se creo il mio nuovo nodo e carico tutto asyc, e dopo aver restituito il thread principale, aggiungo quel nuovo nodo come figlio, non ci dovrebbe essere "disegno" fino a quando il nodo non viene aggiunto come figlio. Eppure quegli errori OpelGL [CCSprite draw] accadono ancora. Proverò il tuo suggerimento e vedrò cosa succede. – patrick