gpt4 book ai didi

iphone - UITableView 和 UIScrollview 停止 cocos2d 动画

转载 作者:可可西里 更新时间:2023-11-01 06:23:30 33 4
gpt4 key购买 nike

我有 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);
}
}

最佳答案

原因是因为 UIKit View 没有设计为与其他 View 协作。它们用于用户交互,因此滚动是否停止更新其他 View 通常并不重要。在用户界面驱动的应用程序中,这很有意义,因为您希望对具有用户焦点并且需要大量资源来制作动画(即滚动)的 View 提供最佳响应和感觉。

正确解决此问题的唯一方法是使用信号量改进 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);
}
}

此代码将 cocos2d drawscene 方法放入其自己的调度队列中。我曾经明白它做了什么,但我不记得了,所以与其错误地解释它的作用或它为什么起作用,我希望有人能在评论中补充这一点。 :)

注意:可能不需要每次都调用最后一个分派(dispatch)信号量,但我这样做是因为切换 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

在 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);
}

并在dealloc中释放:

-(void) dealloc
{
dispatch_release(frameRenderingDispatchQueue);
dispatch_release(frameRenderingSemaphore);
[displayLink release];
[super dealloc];
}

这样可以防止 ScrollView 遮挡cocos2d框架绘制。我添加了 cocoaFriendlyRendering BOOL(我假设您知道如何添加 BOOL 属性)所以我可以只为使用 ScrollView 的场景打开此行为。我认为这可能会更好地提高性能并防止游戏过程中出现任何奇怪的问题,但这可能没有必要。

此代码适用于 cocos2d 1.0.1,可能需要稍作调整以适用于 cocos2d 2.x,例如 EAGLView -> CCGLView、EAGLContext -> CCGLContext。

Other solutions revolve around timers和/或降低帧速率(animationInterval)和/或更改显示链接对象的运行循环模式。它们并不能很好地工作,滚动可能不流畅或滚动可能突然停止。我尝试了所有这些解决方案,因为我不想弄乱 cocos2d 的渲染循环 - 但信号量是唯一可以使 UIKit 滚动与 cocos2d 协作(反之亦然)的完美工作解决方案。

更新:

我忘了说,我做了一个处理 cocoaFriendlyRendering 的 UIScrollView 的子类(在 init 上是 YES,在 dealloc 上不是)更重要的是,它覆盖了触摸事件,以便根据需要将它们转发到 cocos2d(每当 ScrollView 不存在时) t 滚动)。

这些是重写的触摸方法:

-(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];
}

关于iphone - UITableView 和 UIScrollview 停止 cocos2d 动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15185720/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com