CCScrollLayer (cocos2d中实现的滚动层)
http://labs.ywlx.net/?p=2035
以往在cocos2d中实现此效果都是结合UIScrollView和UIButton来实现, cocos2d与UIView结合需要经过多个步骤,过程繁琐。还有一个缺点就是当选中一个UIButton之后再拖拽,是拖不动的。
所以在此我们使用 自定义CCLayer和CCSprite来实现,脱离和UIView的结合。
*实现思路:
初始化多个CCLayer,把需要的数据添加到每个CCLayer里。把这些CCLayer添加到自己自定义的一个CCLayer里,然后在这个自定义的CCLayer里通过重写方法(void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event来改变自定义CCLayer的position从而实现滚动效果。
*主要代码:MainScene
//初始化一系列CCLayer后 添加到自定义的CCLayer,并设定翻页之后 改变下方小点状态函数的delegate
- (void)initScrollLayer
{
NSMutableArray *arrLevel=[NSMutableArray arrayWithCapacity:0];
for(int i=0;i<iPageCount;i++){
CCLayer *tempLayer=[CCLayer node];
tempLayer.tag=TAG_LEVEL_LAYER_START+i;
for(int j=0;j<LEVEL_COL*LEVEL_ROW;j++){
if(i*LEVEL_COL*LEVEL_ROW+j<iLevelCount){
//在此添加内容
}
}
[arrLevel addObject:tempLayer];
}
CCScrollLayer *scroller = [[CCScrollLayer alloc] initWithLayers:arrLevel
widthOffset: 0];
// finally add the scroller to your scene
[self addChild:scroller];
// page moved delegate
{
NSMethodSignature* signature =
[[self class] instanceMethodSignatureForSelector:@selector(onPageMoved:)];
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setTarget:self];
[invocation setSelector:@selector(onPageMoved:)];
scroller.onPageMoved = invocation;
}
}
//初始化下放的小点
- (void)initPageIndex:(int)defaultPage
maxPage:(int)maxPage
{
CGPoint indexPos = ccp(200, 20);
CGPoint offsetPos = ccp(30, 0);
for (int i = 0; i < maxPage; ++i)
{
CCSprite *sprite=[CCSprite spriteWithFile:@"dot1.png"];
sprite.position= ccpAdd(indexPos, ccpMult(offsetPos, i));
CCLabelTTF *lab = [CCLabelTTF labelWithString:[NSString stringWithFormat:@"%i",i+1]
fontName:@”Arial”
fontSize:12];
lab.tag=1;
[sprite addChild:lab];
[self addChild:sprite];
[pageIndexArray addObject:sprite];
}
[self setPageIndex:defaultPage];
}
//翻页之后修改下方小点的状态
- (void)setPageIndex:(int)pageIndex
{
if ([pageIndexArray objectAtIndex:pageIndex] == nil)
{
return;
}
for(CCSprite *sprite in pageIndexArray){
CCLabelTTF *lab=(CCLabelTTF *)[sprite getChildByTag:1];
lab.string=@”";
CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:@”dot1.png”];
[sprite setTextureRect:CGRectMake(0, 0, texture.contentSize.width, texture.contentSize.height)];
id frame = [CCSpriteFrame frameWithTexture:texture rect:CGRectMake(0, 0, texture.contentSize.width, texture.contentSize.height)];
[sprite setDisplayFrame:frame];
}
CCSprite *sprite=(CCSprite *)[pageIndexArray objectAtIndex:pageIndex];
CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:@”dot2.png”];
[sprite setTextureRect:CGRectMake(0, 0, texture.contentSize.width, texture.contentSize.height)];
id frame = [CCSpriteFrame frameWithTexture:texture rect:CGRectMake(0, 0, texture.contentSize.width, texture.contentSize.height)];
[sprite setDisplayFrame:frame];
CCLabelTTF *lab=(CCLabelTTF *)[sprite getChildByTag:1];
lab.string=[NSString stringWithFormat:@"%i",pageIndex+1];
lab.position =ccp(sprite.textureRect.size.width/2,sprite.textureRect.size.height/2);
}
*主要代码 :CCScrollLayer
//初始化
-(id) initWithLayers:(NSMutableArray *)layers widthOffset: (int) widthOffset
{
if ( (self = [super init]) )
{
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
if(!widthOffset){
widthOffset = 0;
}
currentScreen = 1;
scrollWidth = [[CCDirector sharedDirector] winSize].width – widthOffset;
scrollHeight = [[CCDirector sharedDirector] winSize].height;
startWidth = scrollWidth;
startHeight = scrollHeight;
int i = 0;
for (CCLayer *l in layers)
{
l.anchorPoint = ccp(0,0);
l.position = ccp((i*scrollWidth),0);
[self addChild:l];
i=i+1;
}
totalScreens = i;
}
return self;
}
//delegate
- (void)onPageMoved:(id)sender
{
if (self.onPageMoved != nil)
{
[self.onPageMoved setArgument:&self atIndex:2];
[self.onPageMoved invoke];
}
}
//翻到page页
-(void) moveToPage:(int)page
{
id changePage = [CCEaseBounce actionWithAction:[CCMoveTo actionWithDuration:0.3 position:ccp(-((page-1)*scrollWidth),0)]];
id actions = [CCSequence actions:
changePage,
[CCCallFunc actionWithTarget:self selector:@selector(onPageMoved:)],
nil];
[self runAction:actions];
currentScreen = page;
}
//下一页
-(void) moveToNextPage
{
id changePage = [CCEaseBounce actionWithAction:[CCMoveTo actionWithDuration:0.3 position:ccp(-(((currentScreen+1)-1)*scrollWidth),0)]];
id actions = [CCSequence actions:changePage,
[CCCallFunc actionWithTarget:self selector:@selector(onPageMoved:)],nil];
[self runAction:actions];
currentScreen = currentScreen+1;
}
//上一页
-(void) moveToPreviousPage
{
id changePage = [CCEaseBounce actionWithAction:[CCMoveTo actionWithDuration:0.3 position:ccp(-(((currentScreen-1)-1)*scrollWidth),0)]];
id actions = [CCSequence actions:changePage,
[CCCallFunc actionWithTarget:self selector:@selector(onPageMoved:)],
nil];
[self runAction:actions];
currentScreen = currentScreen-1;
}
//触摸开始
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchPoint = [touch locationInView:[touch view]];
startSwipe = touchPoint.x;
for(int i=0;i<LEVEL_COL*LEVEL_ROW;i++){
NSInteger x=i%LEVEL_COL;
NSInteger y=i/LEVEL_COL;
CGRect iRect=CGRectMake(LEVEL_POS_X+x*(LEVEL_ROW_WIDTH+LEVEL_COL_MARGIN),
LEVEL_POS_Y+y*(LEVEL_ROW_HIGHT+LEVEL_ROW_MARGIN),
LEVEL_ROW_WIDTH,
LEVEL_ROW_HIGHT);
//在次实现点击的后的效果
if(CGRectContainsPoint(iRect, touchPoint)){
iLevel=i;
NSInteger iTag=(currentScreen-1)*LEVEL_COL*LEVEL_ROW+iLevel;
CCLayer *layer=(CCLayer *)[self getChildByTag:TAG_LEVEL_LAYER_START+currentScreen-1];
CCSprite *downSprite=(CCSprite *)[layer getChildByTag:iTag];
downSprite.anchorPoint=ccp(0.5, 0.5);
CGPoint posi=ccp(LEVEL_POS_X+x*(LEVEL_ROW_WIDTH+LEVEL_COL_MARGIN)+LEVEL_ROW_WIDTH/2,
LEVEL_POS_Y+y*(LEVEL_ROW_HIGHT+LEVEL_ROW_MARGIN)+LEVEL_ROW_HIGHT/2);
posi= [[CCDirector sharedDirector] convertToGL:posi];
downSprite.position=posi;
CCScaleTo *scaleAction=[CCScaleTo actionWithDuration:0.2 scale:1.2f];
[downSprite runAction:scaleAction];
return YES;
}
}
return YES;
}
//通过修改本Layer的position来实现滚动
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchPoint = [touch locationInView:[touch view]];
self.position = ccp((-(currentScreen-1)*scrollWidth)+(touchPoint.x-startSwipe),0);
}
//触摸结束
- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchPoint = [touch locationInView:[touch view]];
//取消点击产生的效果
if(iLevel>=0){
NSInteger iTag=(currentScreen-1)*LEVEL_COL*LEVEL_ROW+iLevel;
CCLayer *layer=(CCLayer *)[self getChildByTag:TAG_LEVEL_LAYER_START+currentScreen-1];
CCSprite *downSprite=(CCSprite *)[layer getChildByTag:iTag];
[downSprite stopAllActions];
downSprite.scale=1.0;
NSInteger x=iLevel%LEVEL_COL;
NSInteger y=iLevel/LEVEL_COL;
CGRect iRect=CGRectMake(LEVEL_POS_X+x*(LEVEL_ROW_WIDTH+LEVEL_COL_MARGIN),
LEVEL_POS_Y+y*(LEVEL_ROW_HIGHT+LEVEL_ROW_MARGIN),
LEVEL_ROW_WIDTH,
LEVEL_ROW_HIGHT);
//如果触摸结束时touchPoint所在的rect和触摸开始时touchPoint所在的rect相等,那么就认为点击了此rect对应的sprite
if(CGRectContainsPoint(iRect, touchPoint)){
iapp.iCurLvl=(currentScreen-1)*LEVEL_COL*LEVEL_ROW+iLevel+1+(iapp.iCurScene-1)*SCENE_LEVEL_COUNT;
[[CCDirector sharedDirector] replaceScene:[GameScene scene]];
return;
}
iLevel=-1;
}
int newX = touchPoint.x;
if ( (newX – startSwipe) < -100 && (currentScreen+1) <= totalScreens )
{
[self moveToNextPage];
}
else if ( (newX – startSwipe) > 100 && (currentScreen-1) > 0 )
{
[self moveToPreviousPage];
}
else{
[self moveToPage:currentScreen];
}
}

浙公网安备 33010602011771号