Cocos2DXNA / cocos2d-xna

XNA Port of Cocos2d-X
www.cocos2dxna.com
226 stars 123 forks source link

CCMenuItem and CCMenuItemToggle differing positions #433

Open Arkiliknam opened 10 years ago

Arkiliknam commented 10 years ago

This may well be down to my own usage, but it seems odd if it is.

I have a method which create a CCMenuItem for me. It is a common way of creating my specially designed buttons complete with background sprites, label and label stroke.

In my menus, I sometimes use CCMenuItemToggles and sometimes use just the CCMenuItem alone.

The odd thing is that the positioning and anchoring seems to be different depending on whether I add the to a CCMenu directly or as part of a CCMenuItemToggle. When added directly to the CCMenu, it appears on the left and its anchor point is no longer in the middle (easy to tell as there is CCRotateBy actions running on them).

Here's a sample of my code in case it is due to my implementation:

    public static CCMenuItem CreateScaledMenuItemLabel(CCSize buttonSize, int labelPadding, float strokeSize, CCColor3B textColor, CCColor3B strokeColor, CCColor3B backColor, string labelText, Action action)
    {
        var menuItem = action != null ? new CCMenuItem(o => action()) : new CCMenuItem();

        var labelSize = new CCSize(buttonSize.Width - labelPadding, buttonSize.Height - labelPadding);

        // Add background
        var blockSprite = new CCSprite("images/Block_Back");
        blockSprite.ScaleTo(buttonSize);
        blockSprite.Color = backColor;

        menuItem.AddChild(blockSprite);
        menuItem.ContentSize = buttonSize;

        // Add label
        var labelTtf = new CCLabelTTF(labelText, "Hansen-48", 10);
        labelTtf.Color = textColor;

        // Add Stroke to label
        if (strokeSize > 0) labelTtf.AddStroke(strokeSize, strokeColor);

        if (labelTtf.ContentSize.Width > labelSize.Width)
        {
            labelTtf.ScaleTo(labelSize);
        }

        menuItem.AddChild(labelTtf);

        return menuItem;
    }

    public static void AddJiggle(this CCNode targetSprite)
    {
        var swingTime = CCRandom.Next(10, 31) / 100f;

        var rotateLeftAction = new CCRotateBy(swingTime, 1);
        var rotateRightAction = new CCRotateBy(swingTime * 2, -2);
        var rotateBackAction = new CCRotateBy(swingTime, 1);

        var rotateSequence = new CCSequence(rotateLeftAction, rotateRightAction, rotateBackAction);
        var repeatAction = new CCRepeatForever(rotateSequence);

        targetSprite.RunAction(repeatAction);
    }

This is used here to see the different behaviours:

    var randomFilterMenuItem = CocosExtensions.CreateScaledMenuItemLabel(_targetButtonSize, 20, 4, GameLibrary.SharedGameLibrary.RandomTextColor(), new CCColor3B(Microsoft.Xna.Framework.Color.Black), new CCColor3B(Microsoft.Xna.Framework.Color.White), "Random Surprise!", RandomFilterAction);
        randomFilterMenuItem.AddJiggle();

        var backMenuItem = CocosExtensions.CreateScaledMenuItemLabel(_targetButtonSize, 20, 4, GameLibrary.SharedGameLibrary.RandomTextColor(), new CCColor3B(Microsoft.Xna.Framework.Color.Black), new CCColor3B(Microsoft.Xna.Framework.Color.White), "Back", null);
        var backMenuItemToggle = new CCMenuItemToggle(BackAction, new[]{backMenuItem});
        backMenuItemToggle.AddJiggle();

        var menu = new CCMenu(new[]
        {
            randomFilterMenuItem, 
            backMenuItemToggle, 
        });
totallyeviljake commented 10 years ago

What does this do:

labelTtf.AddStroke

Arkiliknam commented 10 years ago

FYI:

    public static void AddStroke(this CCSprite targetSprite, float size, CCColor3B color)
    {
        var rt = new CCRenderTexture((int)(targetSprite.ContentSize.Width + size * 2), (int)(targetSprite.ContentSize.Height + size * 2));

        var originalPos = targetSprite.Position;
        var originalColor = targetSprite.Color;
        var originalVisibility = targetSprite.Visible;

        targetSprite.Color = color;
        targetSprite.Visible = true;

        var bottomLeft = new CCPoint(targetSprite.ContentSize.Width * targetSprite.AnchorPoint.X + size, targetSprite.ContentSize.Height * targetSprite.AnchorPoint.Y + size);
        var positionOffset = new CCPoint(-targetSprite.ContentSize.Width / 2, -targetSprite.ContentSize.Height / 2);

        var position = originalPos.Sub(ref positionOffset);

        rt.Begin();

        for (var i = 0; i < 360; i += 60)
        {
            targetSprite.Position = new CCPoint((float)(bottomLeft.X + Math.Sin(CCMacros.CCDegreesToRadians(i)) * size), (float)(bottomLeft.Y + Math.Cos(CCMacros.CCDegreesToRadians(i)) * size));
            targetSprite.Visit();
        }
        rt.End();

        rt.Sprite.Texture.IsAntialiased = true;
        targetSprite.Position = originalPos;

        targetSprite.Color = originalColor;
        targetSprite.Visible = originalVisibility;

        rt.Position = position;

        targetSprite.AddChild(rt, -1);
    }
totallyeviljake commented 10 years ago

Can we put this into the framework?

Arkiliknam commented 10 years ago

Absolutely!

Arkiliknam commented 10 years ago

If you were going to add it, you might want to pass that 60 constant I use in as an argument instead of being hardcoded. It really equates to number of strokes made in a circle, so the closer to 360, the higher the quality of stroke.

Arkiliknam commented 10 years ago

Oops, I mean the smaller the number, the higher the quality!

totallyeviljake commented 10 years ago

The fix I provided does not work. The touch location of the toggle menu is incorrect with the change I made.