Изображение, которое я загружал в ветку, не появилось - PullRequest
3 голосов
/ 01 ноября 2011

Я использую CCScrollLayer и хочу подготовить изображения, когда игрок выбирает этапы. Это просто, но когда я прокручиваю этапы, это требует времени (задержка загрузки изображений).

поэтому я решил использовать NSThread. и я получил сообщение "cocos2d: CCSpriteFrameCache: Попытка использовать файл 'Level3.png' в качестве текстуры" от cocos2d. тогда это должно появиться. но эти изображения, загруженные в нить, не отображаются так, как я хочу. просто ничего.

-(void) moveToStagePage:(int)page
{   
    ... 
    [NSThread detachNewThreadSelector:@selector(prepareTexture:) toTarget:self withObject:[NSNumber numberWithInt:page]];
    ...
}

ниже исходного кода находится код, который готовит изображения. (Тема)

-(void) prepareTexture:(NSNumber*)number
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    int _page = [number intValue];
    NSLog(@"%d Thread start", _page);

    if(loadingTexNum != 0 && (_page + 1) != loadingTexNum)
    {
        [[CCSpriteFrameCache sharedSpriteFrameCache] removeSpriteFramesFromFile:[NSString stringWithFormat:@"Level%d.plist", loadingTexNum]];
        loadingTexNum = _page + 1;
        [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:[NSString stringWithFormat:@"Level%d.plist", loadingTexNum]];
    }

    if(loadingTexNum == 0 && (_page + 1) != loadingTexNum)
    {
        loadingTexNum = _page + 1;
        [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:[NSString stringWithFormat:@"Level%d.plist", loadingTexNum]];
    }

    [NSThread sleepForTimeInterval:10.0];
    NSLog(@"%d Thread release", _page);
    [pool release];
}

Ответы [ 3 ]

1 голос
/ 01 ноября 2011

OpenGL не поддерживает загрузку в нескольких потоках, если вы не передаете контекст openGL.

Каждый поток в процессе Mac OS X имеет один текущий контекст рендеринга OpenGL. Каждый раз, когда ваше приложение вызывает функцию OpenGL, OpenGL неявно ищет контекст, связанный с текущим потоком, и изменяет состояние или объекты, связанные с этим контекстом.

OpenGL не реентерабелен. Если вы изменяете один и тот же контекст из нескольких потоков одновременно, результаты непредсказуемы. Ваше приложение может аварийно завершить работу или работать неправильно. Если по какой-то причине вы решили установить более одного потока для одного контекста, то вы должны синхронизировать потоки, поместив мьютекс вокруг всех вызовов OpenGL в контексте, таких как gl * и CGL *. Команды OpenGL, которые блокируют, например команды забора, не синхронизируют потоки.

Источник

Вы можете использовать - (void) addImageAsync:(NSString *)filename target:(id) target selector:(SEL)selector; в CCTextureCache классе, вызывая это в вашем основном потоке.

Или вы можете реализовать свой собственный, фактически такой же, как addImageAsync.

Для справки, вот как CCTextureCache выполняет загрузку изображений:

 NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];

        // textures will be created on the main OpenGL context
        // it seems that in SDK 2.2.x there can't be 2 threads creating textures at the same time
        // the lock is used for this purpose: issue #472
        [contextLock lock];
        if( auxEAGLcontext == nil ) {
                auxEAGLcontext = [[EAGLContext alloc]
                                                           initWithAPI:kEAGLRenderingAPIOpenGLES1
                                                           sharegroup:[[[[CCDirector sharedDirector] openGLView] context] sharegroup]];

                if( ! auxEAGLcontext )
                        CCLOG(@"cocos2d: TextureCache: Could not create EAGL context");
        }

        if( [EAGLContext setCurrentContext:auxEAGLcontext] ) {

                // load / create the texture
                CCTexture2D *tex = [self addImage:async.data];

                // The callback will be executed on the main thread
                [async.target performSelectorOnMainThread:async.selector withObject:tex waitUntilDone:NO];

                [EAGLContext setCurrentContext:nil];
        } else {
                CCLOG(@"cocos2d: TetureCache: EAGLContext error");
        }
        [contextLock unlock];

        [autoreleasepool release];
0 голосов
/ 01 ноября 2011

При загрузке текстур в отдельном потоке вам нужно использовать [[CCTextureCache sharedTextureCache] addImageAsync:texture target:target selector:@selector(onTextureLoaded)]; (иначе `GLContext испортится).

0 голосов
/ 01 ноября 2011

Я верю, что основной поток пытается использовать изображения до того, как у потока prepareTexture появится возможность загрузить текстуры.

Если вы немедленно попытаетесь создать спрайты с новыми текстурами, например, прямо в методе moveToStagePage, то это не получится. Ваш метод загрузки текстур должен будет пометить другой поток, который завершил загрузку текстур. Самый простой способ - просто переключить переменную BOOL. Только когда поток загрузки текстуры сигнализирует о загрузке текстур, вы должны пытаться создавать спрайты и т. Д., Используя эти текстуры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...