UIScrollView和Cocos2D [英] UIScrollView and Cocos2D

查看:175
本文介绍了UIScrollView和Cocos2D的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在cocos2d应用程序中创建了一个UIScrollView。我动态添加sprites超过3页。在第一页上,触摸在sprite上完美地工作,然而,如果我使用滚动视图并导航到第二页,触摸不工作不正确...当我触摸屏幕时,sprite将响应触摸,大约金额我已经滚动到左边。如果我回滚到第一页,触摸工作完美的精灵。有任何想法吗?我正在使用以下教程: http://getsetgames.com/2009/ 08/21 / cocos2d-and-uiscrollview / :)






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



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



CocosOverlayScrollView CocosOverlayViewController



我在我的图层中创建CocosOverlayViewController: -

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

我在我的场景中创建图层: -


$ b b

  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函数,我可以触摸一个sprite,它会响应,所以我知道它的工作原理,当我使用UIScrollView 。



我希望您了解我的问题,并且能够帮助您:)



Carl

解决方案

我最后得到实现滚动一个CCLayer通过使用UIScrollView派生类,按照这个问题中提到的教程:





是一个很好的阅读,强烈建议更深入地了解如何UIScrollViews(和一般的UIViews)可以处理触摸与Cocos2D合作。



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



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

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

(请注意,调用此前一行足以将非滚动和非滚动触摸从UIScrollView传播到Cocos2D,你不需要像前面提到的博客帖子那样调用nextResponder:)



这个解决方案对两个Cocos2D源有一个小的修改:



CCNode.m

   - (CGPoint)convertTouchToNodeSpace: *)当与其他覆盖视图(例如UIScrollView)一起使用时,触摸{
// cocos2d 1.0 rc错误。
// 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错误与额外的覆盖视图(如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
$ b - (CCMenuItem *)itemForTouch:(UITouch *)touch {
// cocos2d 1.0 rc错误,与其他叠加视图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。


I have created a UIScrollView in a cocos2d application. I am adding sprites dynamically, over 3 pages. On the first page, touch works perfectly on a sprite, however if I use the scroll view and navigate to the second page, touch does not work quite right... the sprite will respond to the touch when I touch the screen, approximately the amount I have scrolled to the left. If I scroll back to the first page, touch works perfectly for a sprite. Any ideas? I am using the following tutorial: http://getsetgames.com/2009/08/21/cocos2d-and-uiscrollview/ :)


I think some code might be useful:-

I am using the exact code from your demo...

CocosOverlayScrollView and CocosOverlayViewController

I am creating the CocosOverlayViewController in my layer:-

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

I am creating the layer in my scene:-

Scene *scene = [Scene node];
GridLayer *layer = [GridLayer node];
[scene addChild: layer z:-1];
[scene setTag:12];

I am creating the sprites in my layer:-

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

The sprite is using the TouchesDispatcher and the touches are resolved in the class.

If I use the cocos2d moveto function on the layer I can touch a sprite and it responds so I know it works, things just get a little odd when I use the UIScrollView.

I hope you understand my problem and can help, all the best :)

Carl

解决方案

I finally got to implementing scrolling of a CCLayer by using a UIScrollView derived class, following the tutorials mentioned in this question:

Both of them are an excellent read, and highly recommended to get a deeper understanding about how UIScrollViews (and UIViews in general) can be made to handle touches in cooperation with Cocos2D.

However, upon implementing these solutions, I also experienced the bug described in the question: if you don't scroll, touches are propagated from the UIScrollView to the CCLayer correctly. If you scroll, the layer scrolls beautifully but non-scrolling touches on the UIScrollView propagate to the CCLayer with an offset that grows the more you scroll, which makes the CCLayer (and/or accompanying CCMenus) unusable.

I have found the cause of this problem to be a bug in how Cocos2D translates touches sent to the OpenGLView to the local CCNode or CCMenu coordinate systems. This bug is present in 1.0 rc, and only affects touches that are generated on a OpenGLView's subview (like our UIScrollView) and get propagated to the Cocos2D main touching area (namely the OpenGLView) by calling the following line inside the UIScrollView's -touchesBegan: method

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

(Note that calling this previous line is enough for propagating nonscrolling and nonzooming touches from the UIScrollView to Cocos2D, you do not need to call nextResponder: as the aforementioned blog posts do.)

The solution comes with a small modification on two Cocos2D sources:

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];
    ...

The key here is UITouch's locationInView: method. The argument for this method should be the UIView that you want to translate the touches coordinates into. Most Cocos2D project only have one UIView: the OpenGLView, so touches get generated in the OpenGLView (= touch view) and get translated to the same view. However, if you add overlaying subviews to receive touches, such as a UIScrollView, 'touch view' will have this value, which no longer corresponds to the desired OpenGLView.

这篇关于UIScrollView和Cocos2D的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆