我正在使用CCScrollLayer,我想在玩家选择阶段时准备图像。这很简单但是当我滚动阶段时,它会占用时间(延迟加载图像)。
所以我决定使用NSThread。我收到一条消息“cocos2d:CCSpriteFrameCache:尝试使用来自cocos2d的文件'Level3.png'作为纹理”。那应该出现了。但我在线程上加载的这些图像并不像我想的那样出现。什么都没有。
-(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];
}
答案 0 :(得分:1)
除非你传递openGL上下文,否则OpenGL不支持在多个线程上加载。
Mac OS X进程中的每个线程都有一个当前的OpenGL渲染上下文。每次应用程序调用OpenGL函数时,OpenGL都会隐式查找与当前线程关联的上下文,并修改与该上下文关联的状态。
OpenGL不可重入。如果同时从多个线程修改相同的上下文,则结果是不可预测的。您的应用程序可能会崩溃或可能呈现不正确。如果由于某种原因你决定设置多个线程来定位相同的上下文,那么你必须通过在所有OpenGL调用周围放置一个互斥来同步线程,例如gl *和CGL *。阻止的OpenGL命令(例如fence命令)不会同步线程。
你可以在CCTextureCache类中使用- (void) addImageAsync:(NSString *)filename target:(id) target selector:(SEL)selector;
,在主线程上调用它。
或者您可以实现自己的,实际上与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];
答案 1 :(得分:0)
我相信发生的事情是主线程尝试在prepareTexture线程有机会加载纹理之前使用图像。
如果您立即尝试使用新纹理创建精灵,例如在moveToStagePage方法中,那么这将失败。您的线程纹理加载方法将需要标记到已完成加载纹理的其他线程。最简单的方法是简单地切换BOOL变量。只有当纹理加载线程表示已加载纹理时,才应尝试使用这些纹理创建精灵等。
答案 2 :(得分:0)
在单独的线程上加载纹理时,需要使用[[CCTextureCache sharedTextureCache] addImageAsync:texture target:target selector:@selector(onTextureLoaded)];
(否则`GLContext会搞乱)。