2014-06-25 8 views
5

Sto migrando tutti i miei giochi a cocos2d 3.0. Ho usato SlidingMenuGrid.m con una leggera modifica.griglia menu cocos2d 3.0

SlidingMenuGrid.h:

// 
// SlidingMenuGrid 
// 
// Created by Brandon Reynolds on 1/9/11. 

#import "cocos2d.h" 

@interface SlidingMenuGrid : CCLayer 
{ 
    tCCMenuState state; // State of our menu grid. (Eg. waiting, tracking touch, cancelled, etc) 
    CCMenuItem *selectedItem; // Menu item that was selected/active. 

    CGPoint padding; // Padding in between menu items. 
    CGPoint menuOrigin; // Origin position of the entire menu grid. 
    CGPoint touchOrigin; // Where the touch action began. 
    CGPoint touchStop; // Where the touch action stopped. 

    int iPageCount; // Number of pages in this grid. 
    int iCurrentPage; // Current page of menu items being viewed. 

    bool bMoving; // Is the grid currently moving? 
    bool bSwipeOnlyOnMenu; // Causes swiping functionality to only work when siping on top of the menu items instead of entire screen. 
    bool bVerticalPaging; // Disabled by default. Allows for pages to be scrolled vertically instead of horizontal. 

    float fMoveDelta; // Distance from origin of touch and current frame. 
    float fMoveDeadZone; // Amount they need to slide the grid in order to move to a new page. 
    float fAnimSpeed; // 0.0-1.0 value determining how slow/fast to animate the paging. 



    CGPoint pageIndicatorPosition; 

} 


//use this 5: 
-(int) getTotalPage; 
-(int) getCurrentPage; 
-(void) moveToPage: (int) page animated: (BOOL) animated; 
+(id) packWithArray: (NSMutableArray*) items posY: (int) posY indicatorPosY: (int) indiPosY; 
+(id) levelWithArray: (NSMutableArray*) items cols: (int) cols rows: (int) rows leftEdge: (int) leftEdge upperEdge: (int) upperEdge lowerEdge: (int) lowerEdge indicatorPosY: (int) indiPosY; 




+(id) menuWithArray:(NSMutableArray*)items cols:(int)cols rows:(int)rows position:(CGPoint)pos padding:(CGPoint)pad pageIndicatorPosition:(CGPoint)pip; 

-(id) initWithArray:(NSMutableArray*)items cols:(int)cols rows:(int)rows position:(CGPoint)pos padding:(CGPoint)pad verticalPaging:(bool)vertical pageIndicatorPosition:(CGPoint)pip; 

-(void) buildGrid:(int)cols rows:(int)rows; 
-(void) buildGridVertical:(int)cols rows:(int)rows; 
-(CCMenuItem*) GetItemWithinTouch:(UITouch*)touch; 
- (CGPoint) GetPositionOfCurrentPageWithOffset:(float)offset; 
- (CGPoint) GetPositionOfCurrentPage; 

- (bool) IsSwipingOnMenuOnlyEnabled; 
- (void) SetSwipingOnMenuOnly:(bool)bValue; 

- (float) GetSwipeDeadZone; 
- (void) SetSwipeDeadZone:(float)fValue; 

- (bool) IsVerticallyPaged; 
- (void) SetVerticalPaging:(bool)bValue; 

@property (nonatomic, readwrite) CGPoint padding; 
@property (nonatomic, readwrite) CGPoint menuOrigin; 
@property (nonatomic, readwrite) CGPoint touchOrigin; 
@property (nonatomic, readwrite) CGPoint touchStop; 
@property (nonatomic, readwrite) int iPageCount; 
@property (nonatomic, readwrite) int iCurrentPage; 
@property (nonatomic, readwrite) bool bMoving; 
@property (nonatomic, readwrite) bool bSwipeOnlyOnMenu; 
@property (nonatomic, readwrite) bool bVerticalPaging; 
@property (nonatomic, readwrite) float fMoveDelta; 
@property (nonatomic, readwrite) float fMoveDeadZone; 
@property (nonatomic, readwrite) float fAnimSpeed; 

@end 

SlidingMenuGrid.m

#import "SlidingMenuGrid.h" 

#import "Constants.h" 

@implementation SlidingMenuGrid 

@synthesize padding; 
@synthesize menuOrigin; 
@synthesize touchOrigin; 
@synthesize touchStop; 
@synthesize bMoving; 
@synthesize bSwipeOnlyOnMenu; 
@synthesize fMoveDelta; 
@synthesize fMoveDeadZone; 
@synthesize iPageCount; 
@synthesize iCurrentPage; 
@synthesize bVerticalPaging; 
@synthesize fAnimSpeed; 


-(int) getTotalPage { 
    return iPageCount; 
} 
-(int) getCurrentPage { 
    return iCurrentPage; 
} 

+(id) packWithArray: (NSMutableArray*) items posY: (int) posY indicatorPosY: (int) indiPosY { 


    CGSize size = [CCDirector sharedDirector].winSize; 
    BOOL vertical = NO; 
    //pos, padding, pageindicatorpos 
    CGPoint pos = ccp(size.width/2, posY); 
    CGPoint posIndicator = ccp(size.width/2, indiPosY); 
    //padding no matter 

    return [SlidingMenuGrid menuWithArray:items cols:1 rows:1 position:pos padding:ccp(0, 0) verticalPaging:vertical pageIndicatorPosition:posIndicator]; 

} 
+(id) levelWithArray: (NSMutableArray*) items cols: (int) cols rows: (int) rows leftEdge: (int) leftEdge upperEdge: (int) upperEdge lowerEdge: (int) lowerEdge indicatorPosY: (int) indiPosY { 

    CGSize screen = [CCDirector sharedDirector].winSize; 
    BOOL vertical = NO; 

    CGSize itemSize = [[items objectAtIndex:0] boundingBox].size; 
    //pos, padding, pageindipos 
    CGPoint posIndicator = ccp(screen.width/2, indiPosY); 

    int posx = leftEdge + itemSize.width/2; 
    int posy = screen.height - (upperEdge + itemSize.height/2); 
    int padx = (screen.width - itemSize.width - 2 * leftEdge)/(cols - 1); 
    int pady = (screen.height - upperEdge - lowerEdge - itemSize.height)/(rows - 1); 

    return [SlidingMenuGrid menuWithArray:items cols:cols rows:rows position:ccp(posx, posy) padding:ccp(padx, pady) verticalPaging:vertical pageIndicatorPosition:posIndicator]; 
} 



+(id) menuWithArray:(NSMutableArray*)items cols:(int)cols rows:(int)rows position:(CGPoint)pos padding:(CGPoint)pad pageIndicatorPosition:(CGPoint)pip 
{ 
    return [[[self alloc] initWithArray:items cols:cols rows:rows position:pos padding:pad verticalPaging:false pageIndicatorPosition:pip] autorelease]; 
} 

+(id) menuWithArray:(NSMutableArray*)items cols:(int)cols rows:(int)rows position:(CGPoint)pos padding:(CGPoint)pad verticalPaging:(bool)vertical pageIndicatorPosition: (CGPoint) pip 
{ 
    return [[[self alloc] initWithArray:items cols:cols rows:rows position:pos padding:pad verticalPaging:vertical pageIndicatorPosition:pip] autorelease]; 
} 

-(id) initWithArray:(NSMutableArray*)items cols:(int)cols rows:(int)rows position:(CGPoint)pos padding:(CGPoint)pad verticalPaging:(bool)vertical pageIndicatorPosition:(CGPoint)pip 
{ 
    if ((self = [super init])) 
    { 
     self.isTouchEnabled = YES; 

     int z = 1; 
     for (id item in items) 
     { 
      [self addChild:item z:z tag:z]; 
      ++z; 
     } 

     padding = pad; 
     iCurrentPage = 0; 
     bMoving = false; 
     bSwipeOnlyOnMenu = false; 
     menuOrigin = pos; 
     fMoveDeadZone = 10; 
     bVerticalPaging = vertical; 
     fAnimSpeed = 0.6f; 
     (bVerticalPaging) ? [self buildGridVertical:cols rows:rows] : [self buildGrid:cols rows:rows]; 
     self.position = menuOrigin; 


     pageIndicatorPosition = pip; 
    } 

    return self; 
} 

-(void) dealloc 
{ 
    [super dealloc]; 
} 

-(void) buildGrid:(int)cols rows:(int)rows 
{ 
    CGSize winSize = [[CCDirector sharedDirector] winSize]; 

    int col = 0, row = 0; 
    for (CCMenuItem* item in self.children) 
    { 
     // Calculate the position of our menu item. 
     item.position = CGPointMake(self.position.x + col * padding.x + (iPageCount * winSize.width), self.position.y - row * padding.y); 

     // Increment our positions for the next item(s). 
     ++col; 
     if (col == cols) 
     { 
      col = 0; 
      ++row; 

      if(row == rows) 
      { 
       iPageCount++; 
       col = 0; 
       row = 0; 
      } 
     } 
    } 

    if([self children].count > rows * cols * iPageCount) iPageCount++; 

} 



-(void) buildGridVertical:(int)cols rows:(int)rows 
{ 
    CGSize winSize = [[CCDirector sharedDirector] winSize]; 

    int col = 0, row = 0; 
    for (CCMenuItem* item in self.children) 
    { 
     // Calculate the position of our menu item. 
     item.position = CGPointMake(self.position.x + col * padding.x , self.position.y - row * padding.y + (iPageCount * winSize.height)); 

     // Increment our positions for the next item(s). 
     ++col; 
     if (col == cols) 
     { 
      col = 0; 
      ++row; 

      if(row == rows) 
      { 
       iPageCount++; 
       col = 0; 
       row = 0; 
      } 
     } 
    } 


    if([self children].count > rows * cols * iPageCount) iPageCount++; 



} 

-(void) addChild:(CCMenuItem*)child z:(int)z tag:(int)aTag 
{ 
    return [super addChild:child z:z tag:aTag]; 
} 

-(CCMenuItem*) GetItemWithinTouch:(UITouch*)touch 
{ 
    // Get the location of touch. 
    CGPoint touchLocation = [[CCDirector sharedDirector] convertToGL: [touch locationInView: [touch view]]]; 

    // Parse our menu items and see if our touch exists within one. 
    for (CCMenuItem* item in [self children]) 
    { 
     //only deal with the item 
     if ([item isKindOfClass:[CCMenuItem class]]) { 
      CGPoint local = [item convertToNodeSpace:touchLocation]; 

      CGRect r = [item rect]; 
      r.origin = CGPointZero; 

      // If the touch was within this item. Return the item. 
      if (CGRectContainsPoint(r, local)) 
      { 
       return item; 
      } 
     } 
    } 

    // Didn't touch an item. 
    return nil; 
} 

-(void) registerWithTouchDispatcher 
{ 
    [[CCDirector sharedDirector].touchDispatcher addTargetedDelegate:self priority:kCCMenuHandlerPriority swallowsTouches:NO]; 
} 

-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
    // Convert and store the location the touch began at. 
    touchOrigin = [[CCDirector sharedDirector] convertToGL:[touch locationInView:[touch view]]]; 

    // If we weren't in "waiting" state bail out. 
    if (state != kCCMenuStateWaiting) 
    { 
     return NO; 
    } 

    // Activate the menu item if we are touching one. 
    selectedItem = [self GetItemWithinTouch:touch]; 
    [selectedItem selected]; 

    // Only track touch if we are either in our menu system or dont care if they are outside of the menu grid. 
    if (!bSwipeOnlyOnMenu || (bSwipeOnlyOnMenu && selectedItem)) 
    { 
     state = kCCMenuStateTrackingTouch; 
     return YES; 
    } 

    return NO; 
} 

// Touch has ended. Process sliding of menu or press of menu item. 
-(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
    // User has been sliding the menu. 
    if(bMoving) 
    { 
     bMoving = false; 

     // Do we have multiple pages? 
     if(iPageCount > 1 && (fMoveDeadZone < abs(fMoveDelta))) 
     { 
      // Are we going forward or backward? 
      bool bForward = (fMoveDelta < 0) ? true : false; 

      // Do we have a page available? 
      if(bForward && (iPageCount>iCurrentPage+1)) 
      { 
       // Increment currently active page. 
       iCurrentPage++; 
      } 
      else if(!bForward && (iCurrentPage > 0)) 
      { 
       // Decrement currently active page. 
       iCurrentPage--; 
      } 
     } 

     // Start sliding towards the current page. 
     [self moveToCurrentPage];   

    } 
    // User wasn't sliding menu and simply tapped the screen. Activate the menu item. 
    else 
    { 
     [selectedItem unselected]; 
     [selectedItem activate]; 
    } 

    // Back to waiting state. 
    state = kCCMenuStateWaiting; 
} 

-(void) moveToPage: (int) page animated:(BOOL)animated { 
    float interval = 0; 
    if (animated) { 
     interval = 0.3f * abs(iCurrentPage - page); 
    } 

    iCurrentPage = page; 

    // Perform the action 
    CGPoint position = [self GetPositionOfCurrentPage]; 
    CCMoveTo* action = [CCMoveTo actionWithDuration:interval position:position]; 
    [self runAction:action]; 

} 

// Run the action necessary to slide the menu grid to the current page. 
- (void) moveToCurrentPage 
{ 
    CGSize winSize = [[CCDirector sharedDirector] winSize]; 

    // Perform the action 
    CGPoint position = [self GetPositionOfCurrentPage]; 
    CCMoveTo* action = [CCMoveTo actionWithDuration:fAnimSpeed * 0.3f position:position]; 
    [self runAction:action]; 

} 

-(void) ccTouchCancelled:(UITouch *)touch withEvent:(UIEvent *)event 
{ 
    [selectedItem unselected]; 

    state = kCCMenuStateWaiting; 
} 

-(void) ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event 
{ 


    // Calculate the current touch point during the move. 
    touchStop = [[CCDirector sharedDirector] convertToGL:[touch locationInView:[touch view]]]; 

    // Distance between the origin of the touch and current touch point. 
    fMoveDelta = (bVerticalPaging) ? (touchStop.y - touchOrigin.y) : (touchStop.x - touchOrigin.x); 

    // Set our position. 
    [self setPosition:[self GetPositionOfCurrentPageWithOffset:fMoveDelta]]; 
    bMoving = true; 

    if (selectedItem) { 
     [selectedItem unselected]; 
     selectedItem = nil; 
    } 

} 

- (CGPoint) GetPositionOfCurrentPage 
{ 
    CGSize winSize = [[CCDirector sharedDirector] winSize]; 

    return (bVerticalPaging) ? 
    CGPointMake(menuOrigin.x,menuOrigin.y-(iCurrentPage*winSize.height)) 
    : CGPointMake((menuOrigin.x-(iCurrentPage*winSize.width)),menuOrigin.y); 
} 

- (CGPoint) GetPositionOfCurrentPageWithOffset:(float)offset 
{ 
    CGSize winSize = [[CCDirector sharedDirector] winSize]; 

    return (bVerticalPaging) ? 
    CGPointMake(menuOrigin.x,menuOrigin.y-(iCurrentPage*winSize.height)+offset) 
    : CGPointMake((menuOrigin.x-(iCurrentPage*winSize.width)+offset),menuOrigin.y); 
} 



// Returns whether or not we should only allow swiping on the actual grid. 
- (bool) IsSwipingOnMenuOnlyEnabled 
{ 
    return bSwipeOnlyOnMenu; 
} 

// Sets the ability to swipe only on the menu or utilize entire screen for swiping. 
- (void) SetSwipingOnMenuOnly:(bool)bValue 
{ 
    bSwipeOnlyOnMenu = bValue; 
} 

// Returns the swiping dead zone. 
- (float) GetSwipeDeadZone 
{ 
    return fMoveDeadZone; 
} 

- (void) SetSwipeDeadZone:(float)fValue 
{ 
    fMoveDeadZone = fValue; 
} 

// Returns wheather or not vertical paging is enabled. 
- (bool) IsVerticallyPaged 
{ 
    return bVerticalPaging; 
} 

// Sets the vertical paging flag. 
- (void) SetVerticalPaging:(bool)bValue 
{ 
    bVerticalPaging = bValue; 
    [self buildGridVertical]; 
} 










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

    BOOL showPagesIndicator = YES; 


    ccColor4B pagesIndicatorNormalColor_ = ccc4(180, 180, 180, 255); 
    ccColor4B pagesIndicatorSelectedColor_ = ccc4(255, 255, 255, 255); 
    if (showPagesIndicator) 
    { 
     int totalScreens = iPageCount; 

     // Prepare Points Array 
     CGFloat n = (CGFloat)totalScreens; //< Total points count in CGFloat. 
     CGFloat pY = pageIndicatorPosition.y; //< Points y-coord in parent coord sys. 
     CGFloat d = ph_pad(16.0f, 16.0f * 2); //< Distance between points. 
     CGPoint points[totalScreens]; 
     for (int i=0; i < totalScreens; ++i) 
     { 
      CGFloat pX = pageIndicatorPosition.x + d * ((CGFloat)i - 0.5f*(n-1.0f)); 
      points[i] = ccp (pX, pY); 
     } 

     // Set GL Values 
#if COCOS2D_VERSION >= 0x00020000 
//  ccGLEnable(CC_GL_BLEND); 
     ccPointSize(ph_pad(5.0 * CC_CONTENT_SCALE_FACTOR(), 5.0 * CC_CONTENT_SCALE_FACTOR() * 2)); 
#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(ph_pad(5.0 * CC_CONTENT_SCALE_FACTOR(), 5.0 * CC_CONTENT_SCALE_FACTOR() * 2)); 

#define DRAW_4B_FUNC glColor4ub 

#endif 
     ccGLBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
//  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[iCurrentPage]); 

     // 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 
     ccGLBlendFunc(blend_src, blend_dst); 
//  glBlendFunc(blend_src, blend_dst); 
#endif 
    } 
} 




@end 

Il codice sorgente è da Brandon Reynolds e ho modificato un po 'per soddisfare meglio il mio gioco. Uso questo 5 metodi per creare facilmente menu per confezioni (ad una corona, multi colonne) e livelli (multi file, multi colonne)

-(int) getTotalPage; 
-(int) getCurrentPage; 
-(void) moveToPage: (int) page animated: (BOOL) animated; 
+(id) packWithArray: (NSMutableArray*) items posY: (int) posY indicatorPosY: (int) indiPosY; 
+(id) levelWithArray: (NSMutableArray*) items cols: (int) cols rows: (int) rows leftEdge: (int) leftEdge upperEdge: (int) upperEdge lowerEdge: (int) lowerEdge indicatorPosY: (int) indiPosY; 

Ma il codice gl aperta non funziona più per cocos2d 3.0 (es ccGLBlendFunc ecc). Come posso aggiornare questo corso per cocos2d 3.x? O qualsiasi nuova implementazione per griglia di menu simile?

risposta

0

Ora è preferibile utilizzare CCScrollView.

Supporta l'impaginazione ed è possibile creare facilmente la griglia di livello semplicemente pre-creando come nodo di contenuto.