Multithreading 使用grand central dispatch在cocos2d中加载精灵
在我的游戏中,我使用这样的方法异步加载精灵:Multithreading 使用grand central dispatch在cocos2d中加载精灵,multithreading,cocos2d-iphone,loading,grand-central-dispatch,ccsprite,Multithreading,Cocos2d Iphone,Loading,Grand Central Dispatch,Ccsprite,在我的游戏中,我使用这样的方法异步加载精灵: dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ [physicsSprite loadSprite]; dispatch_async(dispatch_get_main_queue(), ^{ [physicsSprite createAnimation];
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它只是保存CCSprite子节点的节点。
在方法loadSprite中,我只是通过
physicsSprite.sprite = [CCSprite spriteWithSpriteFrameName:@"bla.png"];
方法呢
[physicsSprite createAnimation];
用于将加载的精灵添加到mainLayer节点
所有这些逻辑都运作良好。然而,我在想如果我做错了什么,因为我没有创建OpenGL上下文
因此,我尝试了使用上下文的代码:
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];
});
});
结果我看不出游戏性有什么不同
但正如我所知,我需要为加载到另一个线程中的任何精灵创建上下文。那么,我做错了什么?如果不创建上下文…Cocos2d不是线程安全的,任何更改OpenGL状态或使用OpenGL上下文的代码都必须在主线程上运行(与OpenGL上下文相同的线程)。尝试使用
dispatch\u async
加载纹理(精灵)将是徒劳的
最明确的是,您不应该创建自己的EAGLContext,也不应该在调度块中创建cocos2d视图。此由cocos2d内部处理
但是,CCTextureCache和其他类具有异步加载纹理和精灵帧的方法,例如:
CCTextureCache* texCache = [CCTextureCache sharedTextureCache];
[texCache addImageAsync:image target:self selector:@selector(didLoadTexture:)];
然后在纹理可用时调用选择器:
-(void) didLoadTexture:(CCTexture2D*)texture
{
}
可以使用选择器使用纹理初始化精灵。因为如果您更早这样做,cocos2d将尝试使用正常的同步方法立即加载纹理。如果这与异步加载同时发生,它甚至可能崩溃。来自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];
}
所以,如果以代码为例:我需要使用带有上下文的代码。刚刚检查过这个。当纹理从内存卸载时,我尝试使用justloadSprite方法加载它-它首先加载纹理文件pvr.ccz(因为它没有加载到内存),然后从纹理创建sprite,但如果没有上下文,它将只是黑色方形,而不是图像。我没有遇到这样的问题的原因是——我在iPad4:p上测试过,它有足够的内存。检查iPad 3或iPhone4\4s的这一点,立即给出结果
p、 回答自己的问题很有趣。我在加载屏幕上使用addImageAsync。因此,纹理已经加载到内存中。然而,有时会卸载一些纹理,因为游戏会收到内存警告。我有3个非常大的纹理,大约3500x4000px,可能还有2个更小的纹理1000x1500px。当游戏运行时,它会在加载屏幕上加载所有这些文件,但稍后,在内存警告后,它会卸载其中的一些文件。无论如何,即使在这种情况下,我也能很好地工作。。所以,我不明白我的代码中是否需要上下文。您是否知道,大于2048x2048的纹理大小会使您的应用程序无法在iPad 1、iPhone 4及更早版本上运行?您的3500x4000(每像素32位的倍数)每台电脑消耗大约53兆字节?您最好的选择是将颜色深度减少到16位到内存使用量的一半,或者使用.pvr.ccz使其加载速度超快,并使用更少的内存。TexturePacker可以创建.pvr.ccz纹理。是的,使用这么大的纹理是疯狂的(而且基本上毫无意义)。是的,可以肯定,min iOS 7,所以只有iPhone 4在这里。。。是的,53mb,但我能做的是,我的游戏需要如此漂亮的图形:)当然我使用的是pvr.ccz。但不管怎样,有时我的比赛会落后。。比如小挂起..我已经检查了一些其他格式,5551看起来适合大多数图像。。也许我需要试试。。