2012-11-11 72 views
1

我试图让我的应用程序可滚动画廊使用cocos2d的2.0,像在iOS6的集合视图,但它是我试图弄清楚如何滚动什么第三天垂直。我从CCScrollLayer开始,并将其用作水平滚动菜单。我花了一些时间,试图找到一个版本与cocos2d的2.0兼容,因为原来的CCScrollLayer有一些过时的方法和未声明的标识符。CCScrollLayer或其他方法,使图库视图垂直滚动

大家说的只是改变X到Y,它会垂直滚动,但我不能做到这一点。然后我开始看CCMenuAdvanced,但对我来说太困难了,我根本无法完成它。我想只是添加CCMenuItemImage元素层,因为菜单元素不需要额外的触摸检测功能是代码,我可以放置一些代码为每个元素块,它已经显示图片。

我还发现一个修改CCScrollLayer具有水平和垂直滚动的选项,我不能让它工作,因为它不是用cocos2d的兼容。能比我更聪明的人对这段代码做出正确的修改吗?我很抱歉,但我找不到原始链接,不记得作者的名字/尼克。

// 
// CCScrollLayer.h 
// 
// Copyright 2010 DK101 
// http://dk101.net/2010/11/30/implementing-page-scrolling-in-cocos2d/ 
// 
// Copyright 2010 Giv Parvaneh. 
// http://www.givp.org/blog/2010/12/30/scrolling-menus-in-cocos2d/ 
// 
// Copyright 2011 Stepan Generalov 
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy 
// of this software and associated documentation files (the "Software"), to deal 
// in the Software without restriction, including without limitation the rights 
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
// copies of the Software, and to permit persons to whom the Software is 
// furnished to do so, subject to the following conditions: 
// The above copyright notice and this permission notice shall be included in 
// all copies or substantial portions of the Software. 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
// THE SOFTWARE. 

#import <Foundation/Foundation.h> 
#import "cocos2d.h" 

#ifndef __MAC_OS_X_VERSION_MAX_ALLOWED 

/* 
It is a very clean and elegant subclass of CCLayer that lets you pass-in an array 
of layers and it will then create a smooth scroller. 
Complete with the "snapping" effect. You can create screens with anything that can be added to a CCLayer. 
Additions since Giv Parvaneh version: 
1. Added ability to swipe above targetedTouchDelegates. 
2. Added touches lengths & screens properties. 
3. Added factory class method. 
4. Code cleanup. 
5. Added current page number indicator (iOS Style Dots). 
Limitations: 
1. Mac OS X not supported. (Note #ifndef wrappers ;)) 
2. Standard Touch Delegates will still receive touch events after layer starts sliding. 
*/ 
@interface CCScrollLayer : CCLayer { 

// Holds the current distance of the screen substracting offset. 
CGFloat scrollDistance_; 

// Holds the current page being displayed. 
int currentScreen_; 

// A count of the total screens available. 
int totalScreens_; 

// The x coord of initial point the user starts their swipe. 
CGFloat startSwipe_; 

// For what distance user must slide finger to start scrolling menu. 
CGFloat minimumTouchLengthToSlide_; 

// For what distance user must slide finger to change the page. 
CGFloat minimumTouchLengthToChangePage_; 

// Whenever show or not gray/white dots under scrolling content. 
BOOL showPagesIndicator_; 

// Internal state of scrollLayer (scrolling or idle). 
int state_; 

// is horizontal, else is vertical. 
BOOL isHorizontal_; 

} 
@property(readwrite, assign) CGFloat minimumTouchLengthToSlide; 
@property(readwrite, assign) CGFloat minimumTouchLengthToChangePage; 
@property(readwrite, assign) BOOL showPagesIndicator; 
@property(readonly) int totalScreens; 
@property(readonly) int currentScreen; 
@property(readonly) BOOL isHorizontal; 

// Horizontal scrolling 
+(id) nodeWithLayers:(NSArray *)layers widthOffset: (int) offset; 
-(id) initWithLayers:(NSArray *)layers widthOffset: (int) offset; 

// Vertical scrolling 
+(id) nodeWithLayers:(NSArray *)layers heightOffset: (int) offset; 
-(id) initWithLayers:(NSArray *)layers heightOffset: (int) offset; 

@end 

#endif 

// 
// CCScrollLayer.m 
// 
// Copyright 2010 DK101 
// http://dk101.net/2010/11/30/implementing-page-scrolling-in-cocos2d/ 
// 
// Copyright 2010 Giv Parvaneh. 
// http://www.givp.org/blog/2010/12/30/scrolling-menus-in-cocos2d/ 
// 
// Copyright 2011 Stepan Generalov 
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy 
// of this software and associated documentation files (the "Software"), to deal 
// in the Software without restriction, including without limitation the rights 
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
// copies of the Software, and to permit persons to whom the Software is 
// furnished to do so, subject to the following conditions: 
// 
// The above copyright notice and this permission notice shall be included in 
// all copies or substantial portions of the Software. 
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
// THE SOFTWARE. 

#ifndef __MAC_OS_X_VERSION_MAX_ALLOWED 

#import "CCScrollLayer.h" 
#import "CCGL.h" 

enum 
{ 
kCCScrollLayerStateIdle, 
kCCScrollLayerStateSliding, 
}; 

@interface CCTouchDispatcher (targetedHandlersGetter) 
- (NSMutableArray *) targetedHandlers; 

@end 

@implementation CCTouchDispatcher (targetedHandlersGetter) 

- (NSMutableArray *) targetedHandlers 
{ 
return targetedHandlers; 
} 

@end 

@implementation CCScrollLayer 

@synthesize minimumTouchLengthToSlide = minimumTouchLengthToSlide_; 
@synthesize minimumTouchLengthToChangePage = minimumTouchLengthToChangePage_; 
@synthesize totalScreens = totalScreens_; 
@synthesize currentScreen = currentScreen_; 
@synthesize showPagesIndicator = showPagesIndicator_; 
@synthesize isHorizontal = isHorizontal_; 

+(id) nodeWithLayers:(NSArray *)layers widthOffset: (int) offset 
{ 
return [[[self alloc] initWithLayers: layers widthOffset:offset] autorelease]; 
} 

-(id) initWithLayers:(NSArray *)layers widthOffset: (int) offset 
{ 
if ((self = [super init])) 
{ 
    NSAssert([layers count], @"CCScrollLayer#initWithLayers:widthOffset: you must provide at least one layer!"); 

    // Enable touches. 
    self.isTouchEnabled = YES; 

    // Set default minimum touch length to scroll. 
    self.minimumTouchLengthToSlide = 30.0f; 
    self.minimumTouchLengthToChangePage = 100.0f; 

    // Show indicator by default. 
    self.showPagesIndicator = YES; 

    // Set up the starting variables 
    currentScreen_ = 1; 

    // offset added to show preview of next/previous screens 
    scrollDistance_ = [[CCDirector sharedDirector] winSize].width - offset; 

    // Loop through the array and add the screens 
    int i = 0; 
    for (CCLayer *l in layers) 
    { 
     l.anchorPoint = ccp(0,0); 
     l.position = ccp((i*scrollDistance_),0); 
     [self addChild:l]; 
     i++; 
    } 

    // Setup a count of the available screens 
    totalScreens_ = [layers count]; 

} 
return self; 
} 

+(id) nodeWithLayers:(NSArray *)layers heightOffset: (int) offset 
{ 
return [[[self alloc] initWithLayers: layers heightOffset:offset] autorelease]; 
} 

-(id) initWithLayers:(NSArray *)layers heightOffset: (int) offset 
{ 
if ((self = [super init])) 
{ 
    NSAssert([layers count], @"CCScrollLayer#initWithLayers:heightOffset: you must provide at least one layer!"); 

    // Enable touches. 
    self.isTouchEnabled = YES; 

    // Set default minimum touch length to scroll. 
    self.minimumTouchLengthToSlide = 30.0f; 
    self.minimumTouchLengthToChangePage = 100.0f; 

    // Show indicator by default. 
    self.showPagesIndicator = YES; 

    // Set up the starting variables 
    currentScreen_ = 1; 

    // offset added to show preview of next/previous screens 
    scrollDistance_ = [[CCDirector sharedDirector] winSize].height - offset; 

    // Loop through the array and add the screens 
    int i = 0; 
    for (CCLayer *l in layers) 
    { 
     l.anchorPoint = ccp(0,0); 
     l.position = ccp(0,-(i*scrollDistance_)); 
     [self addChild:l]; 
     i++; 
    } 

    // Setup a count of the available screens 
    totalScreens_ = [layers count]; 

} 
return self; 
} 

#pragma mark CCLayer Methods ReImpl 

// Register with more priority than CCMenu's but don't swallow touches 
-(void) registerWithTouchDispatcher 
{ 
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:kCCMenuTouchPriority - 1 swallowsTouches:NO]; 
} 

- (void) visit 
{ 
[super visit];//< Will draw after glPopScene. 

if (self.showPagesIndicator) 
{ 
    // Prepare Points Array 
    CGFloat n = (CGFloat)totalScreens_; //< Total points count in CGFloat. 
    CGFloat d = 16.0f; //< Distance between points. 
    CGPoint points[totalScreens_]; 

    if (isHorizontal_ == YES) { 
     CGFloat pY = ceilf (self.contentSize.height/8.0f); //< Points y-coord in parent coord sys. 
     for (int i=0; i < totalScreens_; ++i) 
     { 
      CGFloat pX = 0.5f * self.contentSize.width + d * ((CGFloat)i - 0.5f*(n-1.0f)); 
      points[i] = ccp (pX, pY); 
     } 
    } else { 
     CGFloat pX = self.contentSize.width - ceilf (self.contentSize.width/8.0f); //< Points x-coord in parent coord sys. 
     for (int i=0; i < totalScreens_; ++i) 
     { 
      CGFloat pY = 0.5f * self.contentSize.height - d * ((CGFloat)i - 0.5f*(n-1.0f)); 
      points[i] = ccp (pX, pY); 
     } 
    } 

    // Set GL Values 
    glEnable(GL_POINT_SMOOTH); 
    GLboolean blendWasEnabled = glIsEnabled(GL_BLEND); 
    glEnable(GL_BLEND); 
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
    glPointSize(6.0 * CC_CONTENT_SCALE_FACTOR()); 

    // Draw Gray Points 
    glColor4ub(0x96,0x96,0x96,0xFF); 
    ccDrawPoints(points, totalScreens_); 

    // Draw White Point for Selected Page 
    glColor4ub(0xFF,0xFF,0xFF,0xFF); 
    ccDrawPoint(points[currentScreen_ - 1]); 

    // Restore GL Values 
    glPointSize(1.0f); 
    glDisable(GL_POINT_SMOOTH); 
    if (! blendWasEnabled) 
     glDisable(GL_BLEND); 
} 
} 

#pragma mark Pages Control 

-(void) moveToPage:(int)page 
{ 
int changeX = 0; 
int changeY = 0; 

if (isHorizontal_ == YES) { 
    changeX = -((page-1)*scrollDistance_); 
} else { 
    changeY = ((page-1)*scrollDistance_); 
} 

id changePage = [CCMoveTo actionWithDuration:0.3 position:ccp(changeX,changeY)]; 
[self runAction:changePage]; 
currentScreen_ = page; 
} 

#pragma mark Hackish Stuff 

- (void) claimTouch: (UITouch *) aTouch 
{ 
// Enumerate through all targeted handlers. 
for (CCTargetedTouchHandler *handler in [[CCTouchDispatcher sharedDispatcher] targetedHandlers]) 
{ 
    // Only our handler should claim the touch. 
    if (handler.delegate == self) 
    { 
     if (![handler.claimedTouches containsObject: aTouch]) 
     { 
      [handler.claimedTouches addObject: aTouch]; 
     } 
     else 
     { 
      CCLOGERROR(@"CCScrollLayer#claimTouch: %@ is already claimed!", aTouch); 
     } 
     return; 
    } 
} 
} 

- (void) cancelAndStoleTouch:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
// Throw Cancel message for everybody in TouchDispatcher. 
[[CCTouchDispatcher sharedDispatcher] touchesCancelled: [NSSet setWithObject: touch] withEvent:event]; 

//< after doing this touch is already removed from all targeted handlers 

// Squirrel away the touch 
[self claimTouch: touch]; 
} 

#pragma mark Touches 

-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
CGPoint touchPoint = [touch locationInView:[touch view]]; 
touchPoint = [[CCDirector sharedDirector] convertToGL:touchPoint]; 

if (isHorizontal_ == YES) { 
    startSwipe_ = touchPoint.x; 
} else { 
    startSwipe_ = touchPoint.y; 
} 

state_ = kCCScrollLayerStateIdle; 
return YES; 
} 

- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
CGPoint touchPoint = [touch locationInView:[touch view]]; 
touchPoint = [[CCDirector sharedDirector] convertToGL:touchPoint]; 

int moveDistance = 0; 
if (isHorizontal_ == YES) { 
    moveDistance = touchPoint.x-startSwipe_; 
} else { 
    moveDistance = touchPoint.y-startSwipe_; 
} 

// If finger is dragged for more distance then minimum - start sliding and cancel pressed buttons. 
// Of course only if we not already in sliding mode 
if ((state_ != kCCScrollLayerStateSliding) 
    && (fabsf(moveDistance) >= self.minimumTouchLengthToSlide)) 
{ 
    state_ = kCCScrollLayerStateSliding; 

    // Avoid jerk after state change. 
    if (isHorizontal_ == YES) { 
     startSwipe_ = touchPoint.x; 
    } else { 
     startSwipe_ = touchPoint.y; 
    } 

    [self cancelAndStoleTouch: touch withEvent: event]; 
} 

if (state_ == kCCScrollLayerStateSliding) { 
    int pointX = 0; 
    int pointY = 0; 
    if (isHorizontal_ == YES) { 
     pointX = (-(currentScreen_-1)*scrollDistance_)+(touchPoint.x-startSwipe_); 
    } else { 
     pointY = ((currentScreen_-1)*scrollDistance_)+(touchPoint.y-startSwipe_); 
    } 
    self.position = ccp(pointX,pointY); 
} 

} 

- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
CGPoint touchPoint = [touch locationInView:[touch view]]; 
touchPoint = [[CCDirector sharedDirector] convertToGL:touchPoint]; 

int offsetLoc = 0; 
if (isHorizontal_ == YES) { 
    offsetLoc = (touchPoint.x - startSwipe_); 
} else { 
    offsetLoc = -(touchPoint.y - startSwipe_); 
} 

if (offsetLoc < -self.minimumTouchLengthToChangePage && (currentScreen_+1) <= totalScreens_) 
{ 
    [self moveToPage: currentScreen_+1]; 
} 
else if (offsetLoc > self.minimumTouchLengthToChangePage && (currentScreen_-1) > 0) 
{ 
    [self moveToPage: currentScreen_-1]; 
} 
else 
{ 
    [self moveToPage:currentScreen_]; 
} 
} 

@end 

#endif 

回答

0

编辑:我终于设法使其与cocos2d的2.x协同工作。这是代码,水平和垂直方向都很棒,可能你需要它。

// 
// CCScrollLayer.h 
// 
// Copyright 2010 DK101 
// http://dk101.net/2010/11/30/implementing-page-scrolling-in-cocos2d/ 
// 
// Copyright 2010 Giv Parvaneh. 
// http://www.givp.org/blog/2010/12/30/scrolling-menus-in-cocos2d/ 
// 
// Copyright 2011 Stepan Generalov 
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy 
// of this software and associated documentation files (the "Software"), to deal 
// in the Software without restriction, including without limitation the rights 
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
// copies of the Software, and to permit persons to whom the Software is 
// furnished to do so, subject to the following conditions: 
// 
// The above copyright notice and this permission notice shall be included in 
// all copies or substantial portions of the Software. 
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
// THE SOFTWARE. 
#import <Foundation/Foundation.h> 
#import "cocos2d.h" 

#ifndef __MAC_OS_X_VERSION_MAX_ALLOWED 
@interface CCScrollLayerVerticalHorizontal : CCLayer { 

    // Holds the current distance of the screen substracting offset. 
    CGFloat scrollDistance_; 

    // Holds the current page being displayed. 
    int currentScreen_; 

    // A count of the total screens available. 
    int totalScreens_; 

    // The x coord of initial point the user starts their swipe. 
    CGFloat startSwipe_; 

    // For what distance user must slide finger to start scrolling menu. 
    CGFloat minimumTouchLengthToSlide_; 

    // For what distance user must slide finger to change the page. 
    CGFloat minimumTouchLengthToChangePage_; 

    // Whenever show or not gray/white dots under scrolling content. 
    BOOL showPagesIndicator_; 
    ccColor4B pagesIndicatorSelectedColor_; 
    ccColor4B pagesIndicatorNormalColor_; 
    // Internal state of scrollLayer (scrolling or idle). 
    int state_; 

    // is horizontal, else is vertical. 
    BOOL isHorizontal_; 

} 
@property(readwrite, assign) CGFloat minimumTouchLengthToSlide; 
@property(readwrite, assign) CGFloat minimumTouchLengthToChangePage; 
@property(readwrite, assign) BOOL showPagesIndicator; 
@property(readonly) int totalScreens; 
@property(readonly) int currentScreen; 
@property(readonly) BOOL isHorizontal; 

// Horizontal scrolling 
+(id) nodeWithLayers:(NSArray *)layers widthOffset: (int) offset; 
-(id) initWithLayers:(NSArray *)layers widthOffset: (int) offset; 

// Vertical scrolling 
+(id) nodeWithLayers:(NSArray *)layers heightOffset: (int) offset; 
-(id) initWithLayers:(NSArray *)layers heightOffset: (int) offset; 

@end 

#endif 


// 
// CCScrollLayer.m 
// 
// Copyright 2010 DK101 
// http://dk101.net/2010/11/30/implementing-page-scrolling-in-cocos2d/ 
// 
// Copyright 2010 Giv Parvaneh. 
// http://www.givp.org/blog/2010/12/30/scrolling-menus-in-cocos2d/ 
// 
// Copyright 2011 Stepan Generalov 
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy 
// of this software and associated documentation files (the "Software"), to deal 
// in the Software without restriction, including without limitation the rights 
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
// copies of the Software, and to permit persons to whom the Software is 
// furnished to do so, subject to the following conditions: 
// 
// The above copyright notice and this permission notice shall be included in 
// all copies or substantial portions of the Software. 
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
// THE SOFTWARE. 

#ifndef __MAC_OS_X_VERSION_MAX_ALLOWED 

#import "CCScrollLayerVerticalHorizontal.h" 
#import "CCGL.h" 

enum 
{ 
    kCCScrollLayerStateIdle, 
    kCCScrollLayerStateSliding, 
}; 

@interface CCTouchDispatcher (targetedHandlersGetter) 
- (NSMutableArray *) targetedHandlers; 

@end 

@implementation CCTouchDispatcher (targetedHandlersGetter) 

- (NSMutableArray *) targetedHandlers 
{ 
    return targetedHandlers; 
} 

@end 

@implementation CCScrollLayerVerticalHorizontal 

@synthesize minimumTouchLengthToSlide = minimumTouchLengthToSlide_; 
@synthesize minimumTouchLengthToChangePage = minimumTouchLengthToChangePage_; 
@synthesize totalScreens = totalScreens_; 
@synthesize currentScreen = currentScreen_; 
@synthesize showPagesIndicator = showPagesIndicator_; 
@synthesize isHorizontal = isHorizontal_; 

+(id) nodeWithLayers:(NSArray *)layers widthOffset: (int) offset 
{ 
    return [[[self alloc] initWithLayers: layers widthOffset:offset] autorelease]; 
} 

-(id) initWithLayers:(NSArray *)layers widthOffset: (int) offset 
{ 
    if ((self = [super init])) 
    { 
     NSAssert([layers count], @"CCScrollLayer#initWithLayers:widthOffset: you must provide at least one layer!"); 
     // Horizontal 
     isHorizontal_ = YES; 
     // Enable touches. 
     self.isTouchEnabled = YES; 

     // Set default minimum touch length to scroll. 
     self.minimumTouchLengthToSlide = 30.0f; 
     self.minimumTouchLengthToChangePage = 100.0f; 

     // Show indicator by default. 
     self.showPagesIndicator = YES; 

     // Set up the starting variables 
     currentScreen_ = 1; 

     // offset added to show preview of next/previous screens 
     scrollDistance_ = [[CCDirector sharedDirector] winSize].width - offset; 

     // Loop through the array and add the screens 
     int i = 0; 
     for (CCLayer *l in layers) 
     { 
      l.anchorPoint = ccp(0,0); 
      l.position = ccp((i*scrollDistance_),0); 
      [self addChild:l]; 
      i++; 
     } 

     // Setup a count of the available screens 
     totalScreens_ = [layers count]; 

    } 
    return self; 
} 

+(id) nodeWithLayers:(NSArray *)layers heightOffset: (int) offset 
{ 
    return [[[self alloc] initWithLayers: layers heightOffset:offset] autorelease]; 
} 

-(id) initWithLayers:(NSArray *)layers heightOffset: (int) offset 
{ 
    if ((self = [super init])) 
    { 
     NSAssert([layers count], @"CCScrollLayer#initWithLayers:heightOffset: you must provide at least one layer!"); 
     // Horizontal 
     isHorizontal_ = NO; 
     // Enable touches. 
     self.isTouchEnabled = YES; 

     // Set default minimum touch length to scroll. 
     self.minimumTouchLengthToSlide = 30.0f; 
     self.minimumTouchLengthToChangePage = 100.0f; 

     // Show indicator by default. 
     self.showPagesIndicator = YES; 

     // Set up the starting variables 
     currentScreen_ = 1; 

     // offset added to show preview of next/previous screens 
     scrollDistance_ = [[CCDirector sharedDirector] winSize].height - offset; 

     // Loop through the array and add the screens 
     int i = 0; 
     for (CCLayer *l in layers) 
     { 
      l.anchorPoint = ccp(0,0); 
      l.position = ccp(0,-(i*scrollDistance_)); 
      [self addChild:l]; 
      i++; 
     } 

     // Setup a count of the available screens 
     totalScreens_ = [layers count]; 

    } 
    return self; 
} 

#pragma mark CCLayer Methods ReImpl 

// Register with more priority than CCMenu's but don't swallow touches 
-(void) registerWithTouchDispatcher 
{ 
    [[[CCDirector sharedDirector]touchDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:NO]; 
} 

- (void) visit 
{ 
    [super visit];//< Will draw after glPopScene. 

    if (self.showPagesIndicator) 
    { 
     // Prepare Points Array 
     CGFloat n = (CGFloat)totalScreens_; //< Total points count in CGFloat. 
     CGFloat d = 16.0f; //< Distance between points. 
     CGPoint points[totalScreens_]; 

     if (isHorizontal_ == YES) { 
      CGFloat pY = ceilf (self.contentSize.height/8.0f); //< Points y-coord in parent coord sys. 
      for (int i=0; i < totalScreens_; ++i) 
      { 
       CGFloat pX = 0.5f * self.contentSize.width + d * ((CGFloat)i - 0.5f*(n-1.0f)); 
       points[i] = ccp (pX, pY); 
      } 
     } else { 
      CGFloat pX = self.contentSize.width - ceilf (self.contentSize.width/8.0f); //< Points x-coord in parent coord sys. 
      for (int i=0; i < totalScreens_; ++i) 
      { 
       CGFloat pY = 0.5f * self.contentSize.height - d * ((CGFloat)i - 0.5f*(n-1.0f)); 
       points[i] = ccp (pX, pY); 
      } 
     } 

     // Set GL Values 
#if COCOS2D_VERSION >= 0x00020000 
     // ccGLEnable(CC_GL_BLEND); //Guru 
     ccPointSize(6.0 * CC_CONTENT_SCALE_FACTOR()); 
#define DRAW_4B_FUNC ccDrawColor4B 

#else 
     glEnable(GL_POINT_SMOOTH); 
     GLboolean blendWasEnabled = glIsEnabled(GL_BLEND); 
     glEnable(GL_BLEND); 

     // save the old blending functions 
     int blend_src = 0; 
     int blend_dst = 0; 
     glGetIntegerv(GL_BLEND_SRC, &blend_src); 
     glGetIntegerv(GL_BLEND_DST, &blend_dst); 
     glPointSize(6.0 * CC_CONTENT_SCALE_FACTOR()); 

#define DRAW_4B_FUNC glColor4ub 

#endif 
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

     // Draw Gray Points 
     DRAW_4B_FUNC(pagesIndicatorNormalColor_.r, 
        pagesIndicatorNormalColor_.g, 
        pagesIndicatorNormalColor_.b, 
        pagesIndicatorNormalColor_.a); 

     ccDrawPoints(points, totalScreens_); 

     // Draw White Point for Selected Page 
     DRAW_4B_FUNC(pagesIndicatorSelectedColor_.r, 
        pagesIndicatorSelectedColor_.g, 
        pagesIndicatorSelectedColor_.b, 
        pagesIndicatorSelectedColor_.a); 
     ccDrawPoint(points[currentScreen_]); 

     // Restore GL Values 
#if COCOS2D_VERSION >= 0x00020000 
     ccPointSize(1.0f); 
#else 
     glPointSize(1.0f); 
     glDisable(GL_POINT_SMOOTH); 
     if (! blendWasEnabled) 
      glDisable(GL_BLEND); 

     // always restore the blending functions too 
     glBlendFunc(blend_src, blend_dst); 
#endif 

    } 
} 

#pragma mark Pages Control 

-(void) moveToPage:(int)page 
{ 
    int changeX = 0; 
    int changeY = 0; 

    if (isHorizontal_ == YES) { 
     changeX = -((page-1)*scrollDistance_); 
    } else { 
     changeY = ((page-1)*scrollDistance_); 
    } 

    id changePage = [CCMoveTo actionWithDuration:0.3 position:ccp(changeX,changeY)]; 
    [self runAction:changePage]; 
    currentScreen_ = page; 
} 

#pragma mark Hackish Stuff 

- (void) claimTouch: (UITouch *) aTouch 
{ 
#if COCOS2D_VERSION >= 0x00020000 
    CCTouchDispatcher *dispatcher = [[CCDirector sharedDirector] touchDispatcher]; 
#else 
    CCTouchDispatcher *dispatcher = [CCTouchDispatcher sharedDispatcher]; 
#endif 

    // Enumerate through all targeted handlers. 
    for (CCTargetedTouchHandler *handler in [dispatcher targetedHandlers]) 
    { 
     // Only our handler should claim the touch. 
     if (handler.delegate == self) 
     { 
      if (![handler.claimedTouches containsObject: aTouch]) 
      { 
       [handler.claimedTouches addObject: aTouch]; 
      } 
     } 
     else 
     { 
      // Steal touch from other targeted delegates, if they claimed it. 
      if ([handler.claimedTouches containsObject: aTouch]) 
      { 
       if ([handler.delegate respondsToSelector:@selector(ccTouchCancelled:withEvent:)]) 
       { 
        [handler.delegate ccTouchCancelled: aTouch withEvent: nil]; 
       } 
       [handler.claimedTouches removeObject: aTouch]; 
      } 
     } 
    } 
} 
- (void) cancelAndStoleTouch:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
    // Throw Cancel message for everybody in TouchDispatcher. 
    [[CCDirector sharedDirector] touchesCancelled: [NSSet setWithObject: touch] withEvent:event]; 

    //< after doing this touch is already removed from all targeted handlers 

    // Squirrel away the touch 
    [self claimTouch: touch]; 
} 

#pragma mark Touches 

-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
    CGPoint touchPoint = [touch locationInView:[touch view]]; 
    touchPoint = [[CCDirector sharedDirector] convertToGL:touchPoint]; 

    if (isHorizontal_ == YES) { 
     startSwipe_ = touchPoint.x; 
    } else { 
     startSwipe_ = touchPoint.y; 
    } 

    state_ = kCCScrollLayerStateIdle; 
    return YES; 
} 

- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
    CGPoint touchPoint = [touch locationInView:[touch view]]; 
    touchPoint = [[CCDirector sharedDirector] convertToGL:touchPoint]; 

    int moveDistance = 0; 
    if (isHorizontal_ == YES) { 
     moveDistance = touchPoint.x-startSwipe_; 
    } else { 
     moveDistance = touchPoint.y-startSwipe_; 
    } 

    // If finger is dragged for more distance then minimum - start sliding and cancel pressed buttons. 
    // Of course only if we not already in sliding mode 
    if ((state_ != kCCScrollLayerStateSliding) 
     && (fabsf(moveDistance) >= self.minimumTouchLengthToSlide)) 
    { 
     state_ = kCCScrollLayerStateSliding; 

     // Avoid jerk after state change. 
     if (isHorizontal_ == YES) { 
      startSwipe_ = touchPoint.x; 
     } else { 
      startSwipe_ = touchPoint.y; 
     } 

     [self cancelAndStoleTouch: touch withEvent: event]; 
    } 

    if (state_ == kCCScrollLayerStateSliding) { 
     int pointX = 0; 
     int pointY = 0; 
     if (isHorizontal_ == YES) { 
      pointX = (-(currentScreen_-1)*scrollDistance_)+(touchPoint.x-startSwipe_); 
     } else { 
      pointY = ((currentScreen_-1)*scrollDistance_)+(touchPoint.y-startSwipe_); 
     } 
     self.position = ccp(pointX,pointY); 
    } 

} 

- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
    CGPoint touchPoint = [touch locationInView:[touch view]]; 
    touchPoint = [[CCDirector sharedDirector] convertToGL:touchPoint]; 

    int offsetLoc = 0; 
    if (isHorizontal_ == YES) { 
     offsetLoc = (touchPoint.x - startSwipe_); 
    } else { 
     offsetLoc = -(touchPoint.y - startSwipe_); 
    } 

    if (offsetLoc < -self.minimumTouchLengthToChangePage && (currentScreen_+1) <= totalScreens_) 
    { 
     [self moveToPage: currentScreen_+1]; 
    } 
    else if (offsetLoc > self.minimumTouchLengthToChangePage && (currentScreen_-1) > 0) 
    { 
     [self moveToPage: currentScreen_-1]; 
    } 
    else 
    { 
     [self moveToPage:currentScreen_]; 
    } 
} 

@end 

#endif 
+0

人,非常感谢你! – user1351086