Cocos2d处理多层触摸

Kay*_*cas 19 touch ios

我已经忙了几天试图找出如何在我的Cocos2d项目中处理触摸.情况与正常情况有点不同.我有几个不同的游戏图层,上面有我需要通过触摸控制的项目:

  • ControlLayer:保持游戏控制(移动,动作按钮).这一层位于顶部.
  • GameplayLayer:持有游戏对象(CCSprites).该图层位于ControlLayer的正下方.

现在我在ControlLayer中工作得很好,我可以移动我的可玩角色并让他跳跃并做其他愚蠢的事情.然而,我无法掌握如何实现我的一些CCSprites的触摸.

到目前为止我收集的信息让我觉得我需要从控制层获取所有触摸输入.然后我不知何故需要将触摸信息"级联"到GameplayLayer,以便我可以在那里处理输入.另一种选择是让我通过某种方式创建一个指向应该可触摸的对象的指针来从我的精灵中获取CGRect信息.我应该能够在ControlLayer中使用该信息来检查该项目中每个项目是否被触摸.

这样做的最佳选择是什么,我该如何实现?我对使用cocoa和Objective C进行编程有点新意,所以我不确定这个语言的最佳选择是什么,以及如何在另一个类中访问sprite CGRect信息([mySpriteName boundingBox])然后是它的层呈现在.

目前,我确定让它工作的唯一方法是为每个CCSprite位置创建重复的CGRects,因此我可以检查它们,但我知道这不是正确的方法.

我到目前为止(测试)是这样的:ControlLayer.m

- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView: [touch view]];

CGRect rect = CGRectMake(0.0f, 0.0f, 100.0f, 100.0f);

//Tried some stuff here to get see if I could get a sprite by tagname so I could use it's bounding box but that didn't work

// Check for touch with specific location
if (CGRectContainsPoint([tree boundingBox], location)) {
    CCLOG(@"CGRect contains the location, touched!");
}

CCLOG(@"Layer touched at %@", NSStringFromCGPoint(location));
Run Code Online (Sandbox Code Playgroud)

}

在此先感谢您的帮助!

Luk*_*man 27

解决问题的最简单最简单的方法是使用ccTouchBegan/ Moved/ Ended而不是ccTouchesBegan/ Moved/ 来解决问题Ended.这意味着,您在特定时刻处理单个触摸,以避免混淆多个触摸,加上最重要的特征ccTouchBegan是CCLayer可以"消耗"触摸并阻止它传播到下一层.下面的代码示例后的更多解释.

以下是执行此操作的步骤.在应该处理触摸事件的所有CCLayer子类中实现这些方法集:

首先,注册CCTouchDispatcher:

- (void)registerWithTouchDispatcher {
    [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
}
Run Code Online (Sandbox Code Playgroud)

接下来,实现ccTouchBegan,下面的示例来自我创建的游戏(当然省略了一些部分):

- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
    if (scene.state != lvlPlaying) {
        // don't accept touch if not playing
        return NO;
    }
    CGPoint location = [self convertTouchToNodeSpace:touch];
    if (scene.mode == modePlaying && !firstTouch) {
        if (CGRectContainsPoint(snb_putt.sprite.boundingBox, location)) {
            touchOnPutt = touch.timestamp;

            // do stuff

            // return YES to consume the touch
            return YES;
         }
    }
    // default to not consume touch
    return NO;
}
Run Code Online (Sandbox Code Playgroud)

最后像ccTouches*同行一样实现ccTouchMoved和ccTouchEnded,除了它们处理单点触摸而不是触摸.传递给这些方法的触摸仅限于ccTouchBegan中使用的触摸,因此无需在这两种方法中进行验证.

基本上这就是它的工作原理.触摸事件由CCScene基于z排序(即从顶层到底层开始)逐个传递到其每个CCLayer,直到任何层消耗触摸.因此,如果顶部的层(例如控制层)消耗触摸,则触摸将不会传播到下一层(例如,对象层).这样每个层只需要担心自己决定是否消耗触摸.如果它决定不能使用触摸,那么它只需要不消耗触摸(从ccTouchBegan返回NO)并且触摸将自动向下传播到层.

希望这可以帮助.

  • `[CCTouchDispatcher sharedDispatcher]`已弃用.您可以使用`[[CCDirector sharedDirector] touchDispatcher]`. (4认同)