1

我正在尝试使用 cocos2d 2.0 在我的应用程序中创建一个可滚动的画廊,类似于 ios6 中的集合视图,但这是我尝试弄清楚如何垂直滚动任何内容的第三天。我从 CCScrollLayer 开始,并将其用作水平滚动菜单。我花了一些时间试图找到与 cocos2d 2.0 兼容的版本,因为原始 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
4

1 回答 1

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
于 2012-11-13T14:41:00.783 回答