B.S*_*.S. 3 iphone objective-c uitableview cocos2d-iphone ios
我有UITableView,它显示在我的图层`[[CCDirector sharedDirector] .view addSubview:myTableView]前面并占据了屏幕的某些部分.
一切正常:它检测到触摸.但是在tableView的滚动动画期间,所有cocos2d冻结,直到tableView结束此滚动.(在冻结下我的意思是所有节点的动作暂停).
问题是:这种冻结的原因是什么,我该如何避免?
-(void) mainLoop:(id)sender
{
if (dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_NOW) != 0)
{
return;
}
if (self.useCocoaFriendlyRendering)
{
dispatch_sync(frameRenderingDispatchQueue, ^{ // HERE dispatch_async make black screen, i shows everything but still bad performance.
CCGLView *openGLview = (CCGLView*)[self view];
[EAGLContext setCurrentContext:openGLview.context];
[self drawScene];
dispatch_semaphore_signal(frameRenderingSemaphore);
});
}
else
{
CCGLView *openGLview = (CCGLView*)[self view];
[EAGLContext setCurrentContext:openGLview.context];
[self drawScene];
dispatch_semaphore_signal(frameRenderingSemaphore);
}
}
Run Code Online (Sandbox Code Playgroud)
原因是因为UIKit视图不是为了与其他视图合作而设计的.它们用于用户交互,因此滚动停止更新其他视图通常无关紧要.在用户界面驱动的应用程序中,它非常有意义,因为您希望为具有用户关注点的视图提供最佳响应和感觉,并且需要大量资源来进行动画处理(即滚动).
解决这个问题的唯一方法是CCDirectorDisplayLink使用信号量改进cocos2d渲染循环:
-(void) mainLoop:(id)sender
{
if (dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_NOW) != 0)
{
return;
}
if (useCocoaFriendlyRendering)
{
dispatch_async(frameRenderingDispatchQueue, ^{
[EAGLContext setCurrentContext:openGLView_.context];
[self drawScene];
dispatch_semaphore_signal(frameRenderingSemaphore);
});
}
else
{
[EAGLContext setCurrentContext:openGLView_.context];
[self drawScene];
dispatch_semaphore_signal(frameRenderingSemaphore);
}
}
Run Code Online (Sandbox Code Playgroud)
此代码将cocos2d drawcene方法放在其自己的调度队列中.我曾经理解它做了什么,但我不记得了,所以不要错误地解释它的作用或原因,我希望有人可以在评论中填写.:)
注意:最后一次调度信号量可能不需要每次调用,但我这样做是因为切换cocoaFriendlyRendering标志可能会导致semaphore_wait无限期地等待(冻结渲染).所以我每次都发出信号.
我更新了我的CCDirectorDisplayLink如下(CCDirectorIOS有cocoaFriendlyRendering BOOL):
@interface CCDirectorDisplayLink : CCDirectorIOS
{
id displayLink;
dispatch_semaphore_t frameRenderingSemaphore;
dispatch_queue_t frameRenderingDispatchQueue;
}
-(void) mainLoop:(id)sender;
@end
Run Code Online (Sandbox Code Playgroud)
在startAnimation中,创建信号量和调度队列:
- (void) startAnimation
{
...
displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(mainLoop:)];
[displayLink setFrameInterval:frameInterval];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
frameRenderingSemaphore = dispatch_semaphore_create(1);
frameRenderingDispatchQueue = dispatch_queue_create("render", DISPATCH_QUEUE_SERIAL);
}
Run Code Online (Sandbox Code Playgroud)
并在dealloc中发布:
-(void) dealloc
{
dispatch_release(frameRenderingDispatchQueue);
dispatch_release(frameRenderingSemaphore);
[displayLink release];
[super dealloc];
}
Run Code Online (Sandbox Code Playgroud)
这可以防止滚动视图阻止cocos2d框架绘制.我添加了cocoaFriendlyRenderingBOOL(我假设您知道如何添加BOOL属性)所以我可以仅对使用滚动视图的场景启用此行为.我认为这可能对性能更好,并防止在游戏过程中出现任何奇怪的问题,但可能没有必要.
此代码适用于cocos2d 1.0.1,可能需要稍微调整以适应cocos2d 2.x,例如EAGLView - > CCGLView,EAGLContext - > CCGLContext.
其他解决方案围绕定时器和/或降低帧速率(animationInterval)和/或改变显示链接对象的运行循环模式.它们并没有真正起作用,滚动可能不顺畅或滚动可能会突然停止.我尝试了所有这些解决方案,因为我不想弄乱cocos2d的渲染循环 - 但是信号量是使UIKit滚动与cocos2d合作的唯一完美工作解决方案(反之亦然).
更新:
我忘了提一下,我创建了一个UIScrollView的子类来处理cocoaFriendlyRendering(init上的YES,dealloc上的NO),更重要的是,它会覆盖触摸事件,以便根据需要将它们转发到cocos2d(只要滚动视图不滚动) .
这些是被覆盖的触摸方法:
-(void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
if (self.dragging)
[super touchesBegan:touches withEvent:event];
else
[[CCDirector sharedDirector].openGLView touchesBegan:touches withEvent:event];
}
-(void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
if (self.dragging)
[super touchesMoved:touches withEvent:event];
else
[[CCDirector sharedDirector].openGLView touchesMoved:touches withEvent:event];
}
-(void) touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event
{
[super touchesCancelled:touches withEvent:event];
[[CCDirector sharedDirector].openGLView touchesCancelled:touches withEvent:event];
}
-(void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
[super touchesEnded:touches withEvent:event];
[[CCDirector sharedDirector].openGLView touchesEnded:touches withEvent:event];
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2044 次 |
| 最近记录: |