本来想着用ScrollView+Menu可以很容易实现类似Angry Bird,滑动菜单选择关卡的效果。结果悲剧了,cocos2D没有CCScrollView,没办法。。。自己实现了一个。
成员变量:
1 startPos_触摸开始时候的触摸点位置,在touchBegan中初始化。
2 endPos_触摸结束时候的触摸点位置,在touchEnd中初始化。
3 menu1_,menu2_, menu3_三个菜单对象
4 beginTouchedItem_ 记录触摸开始时候触摸到的CCMenuItem对象,如果开始没触摸到任何一个Item则不处理
- 将本层Layer的触摸优先级设置的比CCMenu的高,并且不吞掉touch事件,使其可以传递到CCMenu层(CCMenu为-128),因为CCMenu继承自CCLayer,它默认会吞掉touch事件。
-
- (void)registerWithTouchDispatcher { [[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self priority:-129 swallowsTouches:NO]; }
- touchBegan的处理:注意触摸点要转换到Menu的坐标系中才能和CCMenuItem的方框比较位置
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event { CGPoint location = [self convertTouchToNodeSpace:touch]; CGPoint locationInMenu1 = [menu1_ convertToNodeSpace:location]; CGPoint locationInMenu2 = [menu2_ convertToNodeSpace:location]; CGPoint locationInMenu3 = [menu3_ convertToNodeSpace:location]; startPos_ = location; [menu1_ stopAllActions]; [menu2_ stopAllActions]; [menu3_ stopAllActions]; for (CCMenuItem *item in menu1_.children) { if (CGRectContainsPoint([self getMenuCGRect:item], locationInMenu1)) { [item setIsEnabled:NO]; BeginTouchedItem_ = item; return YES; } } for (CCMenuItem *item in menu2_.children) { if (CGRectContainsPoint([self getMenuCGRect:item], locationInMenu2)) { [item setIsEnabled:NO]; BeginTouchedItem_ = item; return YES; } } for (CCMenuItem *item in menu3_.children) { if (CGRectContainsPoint([self getMenuCGRect:item], locationInMenu3)) { [item setIsEnabled:NO]; BeginTouchedItem_ = item; return YES; } } return YES; }
- touchEnd的处理
- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event { CGSize winSize = [[CCDirector sharedDirector] winSize]; CGPoint centerPoint = CGPointMake(winSize.width/2, winSize.height/2); centerPoint = [self convertToNodeSpace:centerPoint]; endPos_ = [self convertTouchToNodeSpace:touch]; if (startPos_.x == endPos_.x && startPos_.y == endPos_.y) { [BeginTouchedItem_ setIsEnabled:YES]; [BeginTouchedItem_ activate]; return; } CGRect menu1Rect = [self getMenuCGRect:menu1_]; CGRect menu2Rect = [self getMenuCGRect:menu2_]; CGRect menu3Rect = [self getMenuCGRect:menu3_]; if (CGRectContainsPoint(menu1Rect, centerPoint)) { [menu1_ runAction:[CCMoveTo actionWithDuration:0.5 position:ccp(winSize.width/2, winSize.height/2)]]; [menu2_ runAction:[CCMoveTo actionWithDuration:0.5 position:ccp(winSize.width/2+winSize.width, winSize.height/2)]]; [menu3_ runAction:[CCMoveTo actionWithDuration:0.5 position:ccp(winSize.width/2+winSize.width*2, winSize.height/2 )]]; } else if (CGRectContainsPoint(menu2Rect, centerPoint)) { [menu1_ runAction:[CCMoveTo actionWithDuration:0.5 position:ccp(-winSize.width/2, winSize.height/2)]]; [menu2_ runAction:[CCMoveTo actionWithDuration:0.5 position:ccp(winSize.width/2, winSize.height/2)]]; [menu3_ runAction:[CCMoveTo actionWithDuration:0.5 position:ccp(winSize.width/2+winSize.width, winSize.height/2 )]]; } else if (CGRectContainsPoint(menu3Rect, centerPoint)) { [menu1_ runAction:[CCMoveTo actionWithDuration:0.5 position:ccp(-winSize.width/2-winSize.width, winSize.height/2)]]; [menu2_ runAction:[CCMoveTo actionWithDuration:0.5 position:ccp(-winSize.width/2, winSize.height/2)]]; [menu3_ runAction:[CCMoveTo actionWithDuration:0.5 position:ccp(winSize.width/2, winSize.height/2 )]]; } else if (centerPoint.x <= menu1_.position.x - menu1_.contentSize.width/2) { [menu1_ runAction:[CCMoveTo actionWithDuration:0.5 position:ccp(winSize.width/2, winSize.height/2)]]; [menu2_ runAction:[CCMoveTo actionWithDuration:0.5 position:ccp(winSize.width/2+winSize.width, winSize.height/2)]]; [menu3_ runAction:[CCMoveTo actionWithDuration:0.5 position:ccp(winSize.width/2+winSize.width*2, winSize.height/2 )]]; } else if (centerPoint.x - menu3_.position.x >= menu3_.contentSize.width/2) { [menu1_ runAction:[CCMoveTo actionWithDuration:0.5 position:ccp(-winSize.width/2-winSize.width, winSize.height/2)]]; [menu2_ runAction:[CCMoveTo actionWithDuration:0.5 position:ccp(-winSize.width/2, winSize.height/2)]]; [menu3_ runAction:[CCMoveTo actionWithDuration:0.5 position:ccp(winSize.width/2, winSize.height/2 )]]; } }
- touchMove的处理
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event { CGPoint curLocation = [self convertTouchToNodeSpace:touch]; CGPoint oldLocation = [touch previousLocationInView:touch.view]; oldLocation = [[CCDirector sharedDirector] convertToGL:oldLocation]; oldLocation = [self convertToNodeSpace:oldLocation]; CGPoint translation = ccpSub(curLocation, oldLocation); [self panForTranslation:ccp(translation.x, 0)]; }
- 用到的辅助方法:panForTranslation用来在touchMove的时候移动Menu
- (void) panForTranslation: (CGPoint)translation { menu1_.position = ccpAdd(menu1_.position, translation); menu2_.position = ccpAdd(menu2_.position, translation); menu3_.position = ccpAdd(menu3_.position, translation); } - (CGRect) getMenuCGRect: (CCNode *)node { CGRect menuRect = CGRectMake(node.position.x - node.contentSize.width/2, node.position.y - node.contentSize.height/2, node.contentSize.width, node.contentSize.height); return menuRect; }