Scaling CCMenuItemSprite items in a CCMenu

2.4k Views Asked by At

I'm having problems using CCMenu with scaled CCMenuItemSprite menu items. I'm trying to scale the menu item sprites differently based on which device the game is being played on (the iPad needs to scale it to about 1.5x, whereas on the iPhone it's about 0.75x)

From what I've read, we can't scale the CCSprite directly, or the CCMenuItemSprite, because when it's added to the CCMenu the touch rectangles aren't updated correctly. I believe that I have to scale the CCMenu to scale the Menu Items.

Whenever I do this my sprites appear to be scaled to the correct sizes, however it also seems to scale the CCMenu position coordinates, but in the opposite direction as what I'd expect. Also once I go over a certain threshold the menu seems to disappear altogether.

Does anyone have any suggestions on how I should be scaling Sprites in a CCMenu?

Thanks in advance. Buzzrick

3

There are 3 best solutions below

1
On BEST ANSWER

Try this Code........

CCMenuItemImage  *Btn1 = [CCMenuItemImage itemWithNormalImage:@"button1.png" selectedImage:@"button1_active.png" target:self selector:@selector(button1_click:)];

CCMenuItemImage  *Btn2 = [CCMenuItemImage itemWithNormalImage:@"button2.png" selectedImage:@"button2_active.png" target:self selector:@selector(button2_click:)];

CCMenu *Action_menu = [CCMenu menuWithItems:Btn1,Btn2, nil];

[Action_menu setPosition:ccp( 79, 288)];

float delayTime = 0.3f;

for (CCMenuItemFont *each in [Action_menu children]) 
    {
        each.scaleX = 0.0f;
        each.scaleY = 0.0f;
        CCAction *action = [CCSequence actions:
                            [CCDelayTime actionWithDuration: delayTime],
                            [CCScaleTo actionWithDuration:0.5F scale:1.0],
                            nil];
        delayTime += 0.2f;
        [each runAction: action];
    }

[self addChild:Action_menu];
2
On

My suggestion? Don't!

Internally CCMenu scaled the menu items whenever you touch them. You'll notice this if you tap and hold an item, it's scaled up (zoomed in). So whatever scaling you apply to menu items is lost at the latest when the menu item gets touched.

And then, as you noticed, scaling affects the touch area of an item. It can lead to items responding to touches outside the item, or not responding to touches depending on zoom level. I also wouldn't scale the CCMenu for the same reasons.

Long story short, if you have to apply scaling to your menu items, write your own menu item code. Possibly by basing it on the CCMenu code and stripping out what you don't need and making your desired changes.

But really the easiest way is to supply the menu item images using the file suffixes -hd, -ipad and -ipadhd and scaled correspondingly. Trying to get this right with the scale property is just painful.

1
On

Here's how I resolved it in the end: Basically I created the menu elements first, THEN I sorted out the positioning/scaling/rotation. This seems to work much better. This code sample below is where i'm using a single sprite to create two opposing left/right arrow buttons

    [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"ButtonSprites.plist"];
    CCSpriteBatchNode *buttonSprites = [CCSpriteBatchNode batchNodeWithFile:@"ButtonSprites.png"];
    [self addChild:buttonSprites];

    CCSprite *arrowLeftSprite = [CCSprite spriteWithSpriteFrameNameOrFile:@"PageArrow"];
    CCSprite *arrowLeftSpriteSelected = [CCSprite spriteWithSpriteFrameNameOrFile:@"PageArrow"];
    arrowLeftSpriteSelected.opacity = 128;
    CCSprite *arrowRightSprite = [CCSprite spriteWithSpriteFrameNameOrFile:@"PageArrow"];
    CCSprite *arrowRightSpriteSelected = [CCSprite spriteWithSpriteFrameNameOrFile:@"PageArrow"];
    arrowRightSpriteSelected.opacity = 128;

    float buttonWidth = screenSize.width * ButtonWidthPercent;
    int contentPixelWidth = arrowLeftSprite.contentSize.width;
    float scale = buttonWidth / contentPixelWidth;

    CCMenuItemSprite *pageLeftMenu = [CCMenuItemSprite itemFromNormalSprite:arrowLeftSprite selectedSprite:arrowLeftSpriteSelected target:self selector:@selector(buttonPageLeft:)];
    CCMenuItemSprite *pageRightMenu = [CCMenuItemSprite itemFromNormalSprite:arrowRightSprite selectedSprite:arrowRightSpriteSelected target:self selector:@selector(buttonPageRight:)];

    //  First perform the creation
    CCMenu *menu = [CCMenu menuWithItems: mainMenu, pageLeftMenu, pageRightMenu, nil];
    menu.position = ccp(0, 0);

    //  THEN deal with layout,rotation, and scaling
    pageLeftMenu.scale = scale;
    pageLeftMenu.rotation = 180;
    pageRightMenu.scale = scale;

    float arrowHeight = screenSize.height * 0.2;
    pageLeftMenu.position = ccp(screenSize.width * 0.1, arrowHeight);
    pageRightMenu.position = ccp(screenSize.width * 0.9, arrowHeight);

    [self addChild:menu z:2];