UIScrollView和Cocos2D

时间:2010-03-16 19:18:25

标签: iphone uiviewcontroller uiscrollview cocos2d-iphone

我在cocos2d应用程序中创建了一个UIScrollView。我正在动态添加精灵,超过3页。在第一页上,触摸在精灵上完美运行,但是如果我使用滚动视图并导航到第二页,则触摸不能正常工作...当我触摸屏幕时,精灵会响应触摸,大约是金额我向左滚动。如果我滚动回到第一页,触摸可以完美地用于精灵。有任何想法吗?我使用以下教程:http://getsetgames.com/2009/08/21/cocos2d-and-uiscrollview/ :)


我认为某些代码可能有用: -

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

CocosOverlayScrollView CocosOverlayViewController

我在我的图层中创建了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时,事情变得有些奇怪。

我希望你能理解我的问题并且可以提供最好的帮助:)。

卡尔

1 个答案:

答案 0 :(得分:10)

我终于通过使用UIScrollView派生类实现了对CCLayer的滚动,遵循此问题中提到的教程:

它们都是一本优秀的读物,强烈建议您更深入地了解UIScrollViews(以及一般的UIViews)如何与Cocos2D合作处理触摸。

然而,在实现这些解决方案时,我也遇到了问题中描述的错误:如果不滚动,则触摸会从UIScrollView正确传播到CCLayer。如果滚动,图层会滚动得很漂亮,但UIScrollView上的非滚动触摸会传播到CCLayer,偏移越多,滚动越多,这会使CCLayer(和/或伴随CCMenus)无法使用。

我发现这个问题的原因是Cocos2D如何将发送到OpenGLView的触摸转换为本地CCNode或CCMenu坐标系的错误。此错误出现在1.0 rc中,并且只影响在OpenGLView的子视图(如我们的UIScrollView)上生成的触摸,并通过调用UIScrollView的-touchesBegan:方法中的以下行传播到Cocos2D主触摸区域(即OpenGLView)。

 [[[CCDirector sharedDirector] openGLView] touchesBegan:touches withEvent:event];

(请注意,调用此前一行足以将UonscrollView中的非滚动和非索引触摸传播到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。