Search code examples
multithreadingcocos2d-iphoneloadinggrand-central-dispatchccsprite

Loading sprites in cocos2d using grand central dispatch


In my game I'm using such method for loading sprites asynchronously:

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
 [physicsSprite loadSprite];
dispatch_async(dispatch_get_main_queue(), ^{
                                    [physicsSprite createAnimation];
                                    [physicsSprite createBodyInWorld:world;
                                });
                            });

physicsSprite it's just node that holds CCSprite child. In method loadSprite - I do just self creating sprite by

physicsSprite.sprite = [CCSprite spriteWithSpriteFrameName:@"bla.png"];

And the method

[physicsSprite createAnimation];

using for adding loaded sprite to mainLayer node.

All this logic works well. However I'm thinking if I'm doing something wrong, because I'm NOT creating OpenGL context

So, I've tried my code with context:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
                            CCGLView *view = (CCGLView*)[[CCDirector sharedDirector] view];
                            EAGLContext *auxGLcontext = [[[EAGLContext alloc]
                                                          initWithAPI:kEAGLRenderingAPIOpenGLES2
                                                          sharegroup:[[view context] sharegroup]] autorelease];
                            if( [EAGLContext setCurrentContext:auxGLcontext] ) {

                                [physicsSprite loadSprite];
                                glFlush();
                                [EAGLContext setCurrentContext:nil];
                            }
                            dispatch_async(dispatch_get_main_queue(), ^{
                                [physicsSprite createAnimation];
                                [physicsSprite createBodyInWorld:world];
                            });
                        });

And as result I don't see any difference in gameplay.

But as I know, I need to create context for any sprite that loaded in another thread. So, is what I'm doing wrong? Without creating context...


Solution

  • FRom CCTextureCache:addImageAsync:

    if( [EAGLContext setCurrentContext:_auxGLcontext] ) {
    
        // load / create the texture
        texture = [self addImage:path];
    
        glFlush();
    
        // callback should be executed in cocos2d thread
        [target performSelector:selector onThread:[[CCDirector sharedDirector] runningThread] withObject:texture waitUntilDone:NO];
    
        [EAGLContext setCurrentContext:nil];
    }
    

    So, If take code as example: and I need to use code with context. Just checked this. When texture unload from memory and I try to load it using just loadSprite method - it first loads texture file pvr.ccz(because it's not loaded to memory) and then creates sprite from texture, but without context it will be just black square instead of image. And the reason why I didn't get such problem - I've tested on iPad 4 :p, it has enough memory. Checking this of iPad 3 or iPhone4\4s give immediately results.

    p.s.: funny to answer own questions.