Tôi đang di chuyển tất cả trò chơi của mình sang cocos2d 3.0. Tôi đã sử dụng SlidingMenuGrid.m với sửa đổi nhỏ.cocos2d 3.0 lưới menu trượt
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
Mã nguồn là từ Brandon Reynolds và tôi đã sửa đổi nó một chút để phù hợp hơn với lối chơi của mình. Tôi sử dụng này 5 phương pháp để dễ dàng xây dựng các menu cho gói (hàng duy nhất, cột đa) và cấp (multi hàng, cột đa)
-(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;
Nhưng mã gl mở không hoạt động nữa cho cocos2d 3,0 (ví dụ ccGLBlendFunc
vv). Làm thế nào tôi có thể cập nhật lớp này cho cocos2d 3.x? Hoặc bất kỳ triển khai mới nào cho lưới menu tương tự?