我正在将所有游戏迁移到cocos2d 3.0。我稍微修改了SlidingMenuGrid.m。
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
源代码来自Brandon Reynolds,我对其进行了一些修改以更好地适应我的游戏。我使用这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;
但是对于cocos2d 3.0(例如ccGLBlendFunc
等),open gl代码不再起作用了。如何为cocos2d 3.x更新此类?或类似菜单网格的任何新实现?
答案 0 :(得分:0)
现在最好使用CCScrollView。
它支持分页,您只需将其预创建为内容节点,即可轻松创建关卡网格。