UIScrollView和Cocos2D

5
我在一个cocos2d应用程序中创建了一个UIScrollView。我在3个页面上动态添加精灵。在第一页上,触摸在精灵上工作得非常好,但是如果我使用滚动视图并导航到第二页,触摸就不那么正确了......当我触摸屏幕时,精灵将响应触摸,大约与我向左滚动的量相同。如果我滚动回第一页,触摸对于精灵的操作非常完美。有什么想法吗?我正在使用以下教程:http://getsetgames.com/2009/08/21/cocos2d-and-uiscrollview/ :)

我认为一些代码可能会有用:

我正在使用您的演示中的确切代码......

CocosOverlayScrollViewCocosOverlayViewController

我在我的图层中创建CocosOverlayViewController:

CocosOverlayViewController *scrollView = [CocosOverlayViewController alloc];
[[[Director sharedDirector] openGLView] addSubview:scrollView.view];

我正在创建场景中的图层:-
Scene *scene = [Scene node];
GridLayer *layer = [GridLayer node];
[scene addChild: layer z:-1];
[scene setTag:12];

我正在创建我的图层中的精灵:-
    myImage.position = ccp(53 * (coordinate.x  + 0.52), 57 * (coordinate.y + 1.45));
   [myImage runAction:[FadeIn actionWithDuration:0.3]];
    myImage.relativeAnchorPoint = YES;
   [self addChild:myImage z:-1];

精灵正在使用TouchesDispatcher,触摸事件在类中解决。
如果我在层上使用cocos2d的moveto函数,我可以触摸精灵并得到响应,所以我知道它是有效的,但当我使用UIScrollView时事情就有点奇怪了。
希望您能理解我的问题并提供帮助,祝一切顺利 :)
卡尔

嘿,Carl,你正在和那篇文章的作者交谈!很高兴你找到了它,希望它能让你开始顺利。至于你的问题,听起来像是你正在使用一个分页滚动视图实例,是这样吗?我没有考虑到那种情况写这篇文章,但我相信我们可以想出一些解决办法。 - Rob Segal
我正在使用页面滚动视图,但我的应用程序并不依赖它,所以我可以将其删除。我之前没有很好地解释清楚,触摸事件在第一个“页面”上完美地工作,但是当我滚动(即使是最轻微的)时,精灵会移动,但触摸事件仍然响应于精灵的先前位置。有什么想法吗? - Carl
1
我使用Cocos2d和UIScrollView创建了一个示例项目,并在cocos2d论坛上发布了链接:http://www.cocos2d-iphone.org/forum/topic/9417 - Nate Murray
这个问题与我的兴趣相关。Carl,Rob:你们找到解决方案了吗?如果有的话,能否发布答案? - Ricardo Sanchez-Saez
我已经阅读了教程,准备尝试实现它,但是我有一些问题:它是否适用于Cocos2D iPhone 1.0rc?如何在Cocos2D项目中使用CocosOverlayViewController?它应该替换默认的RootViewController吗? - Ricardo Sanchez-Saez
Nate,我刚刚看了你的解决方案,它看起来太棒了(艺术也很棒!),我认为你应该将链接发布为答案,并尝试将其标记为正确答案。干杯。 - Ricardo Sanchez-Saez
1个回答

10
我终于通过使用一个派生自UIScrollView的类来实现CCLayer的滚动,按照这个问题中提到的教程进行操作。 两者都是非常好的阅读材料,强烈推荐阅读,以深入了解如何让UIScrollViews(以及一般的UIView)与Cocos2D协作处理触摸事件。
然而,在实现这些解决方案时,我也遇到了问题:如果您不滚动,则UIScrollView到CCLayer的触摸事件传递正确。如果您滚动,图层会滚动得很好,但UIScrollView上的非滚动触摸会带有一个偏移量传递给CCLayer,随着您滚动的越来越多,这使得CCLayer(和/或相应的CCMenus)无法使用。
我已经找到了这个问题的原因,这是Cocos2D在将发送到OpenGLView的触摸事件转换为本地CCNode或CCMenu坐标系时存在的错误。此错误存在于1.0 rc中,并且仅影响在OpenGLView的子视图(例如我们的UIScrollView)上生成并通过调用以下行将其传播到Cocos2D主触摸区域(即OpenGLView)的触摸事件。-touchesBegan:方法
 [[[CCDirector sharedDirector] openGLView] touchesBegan:touches withEvent:event];

请注意,仅调用此前一行即足以将UIScrollView中的非滚动和非缩放触摸传播到Cocos2D,您无需像上述博客文章所示那样调用nextResponder:。
解决方案需要对两个Cocos2D源进行小修改:

CCNode.m

- (CGPoint)convertTouchToNodeSpace:(UITouch *)touch {
    // cocos2d 1.0 rc bug when using with additional overlayed views (such as UIScrollView).
    // CGPoint point = [touch locationInView: [touch view]];
    CGPoint point = [touch locationInView: [[CCDirector sharedDirector] openGLView]];
    point = [[CCDirector sharedDirector] convertToGL: point];
    return [self convertToNodeSpace:point];
}

- (CGPoint)convertTouchToNodeSpaceAR:(UITouch *)touch {
    // cocos2d 1.0 rc bug when using with additional overlayed views (such as UIScrollView).
    // CGPoint point = [touch locationInView: [touch view]];
    CGPoint point = [touch locationInView: [[CCDirector sharedDirector] openGLView]];
    point = [[CCDirector sharedDirector] convertToGL: point];
    return [self convertToNodeSpaceAR:point];
}

CCMenu.m

-(CCMenuItem *) itemForTouch: (UITouch *) touch {
    // cocos2d 1.0 rc bug when using with additional overlayed views (such as UIScrollView).
    // CGPoint touchLocation = [touch locationInView: [touch view]];
    CGPoint touchLocation = [touch locationInView: [[CCDirector sharedDirector] openGLView]];
    touchLocation = [[CCDirector sharedDirector] convertToGL: touchLocation];
    ...

这里的关键是UITouch的locationInView:方法。该方法的参数应该是您想要将触摸坐标转换为其内部坐标系的UIView。大多数Cocos2D项目只有一个UIView:OpenGLView,因此触摸事件在OpenGLView(=触摸视图)中生成并被转换到相同的视图中。但是,如果您添加了叠加的子视图以接收触摸事件,例如UIScrollView,则“触摸视图”将具有不同的值,不再对应所需的OpenGLView。

1
只是想指出需要编辑的第二个文件是CCMenu.m而不是CCLayer.m;-) - fedmest
我认为我刚刚独立完成了这个修复,因为我也在使用UIScrollView以及EAGLView。 - David Dunham

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接