gpt4 book ai didi

cocos2d-iphone - cocos2d中非矩形CCNode的轮廓(描边)

转载 作者:行者123 更新时间:2023-12-03 22:42:43 27 4
gpt4 key购买 nike

我需要动态创建这样的大纲:

Red 2px outline

不是针对一个 CCSprite,而是针对一个 CCNode 中的多个动画 CCSprite。我在想:

  • 将 CCNode 的内容复制到纹理(如 AS3 中的 canvasBitmapData.draw(sourceDisplayObject))
  • 使用生成的纹理创建 CCSprite
  • 给 Sprite 着色以勾勒颜色并放大一点
  • 将 Sprite 放置在节点中其他 Sprite 的后面

  • 我不知道如何执行第 1 步。也许在纹理的不透明像素周围绘制“ true stroke”比第 3 步中的色调比例更快?

    最佳答案

    我完全忘了发布这个问题的答案。这是一个非常平滑的笔划的代码。它并不快,但对于第一代 iPad 上的几个大 Sprite 来说效果很好。

    这个想法是在 Sprite 周围绘制微小的彩色和模糊的球,并将它们放置在自己的纹理上。它可以用于 CCNode 和 CCSprite。该代码还会移动 anchor ,因为生成的 Sprite 将具有更大的宽度和高度。

    得到的轮廓( body 和 2 只手,在 iPad1 上大约 0.3 秒):

    outline

    白球示例:

  • 5f:http://i.stack.imgur.com/e9kos.png
  • 10f:http://i.stack.imgur.com/S5goU.png
  • 20f:http://i.stack.imgur.com/qk7GL.png

  • CCNode 类别,适用于 Cocos2d-iPhone 2.1:
    @implementation CCNode (Outline)

    - (CCSprite*) outline
    {
    return [self outlineRect:CGRectMake(0, 0, self.contentSize.width, self.contentSize.height)];
    }

    - (CCSprite*) outlineRect:(CGRect)rect
    {
    NSInteger gap = dscale(4);
    CGPoint positionShift = ccp(gap - rect.origin.x, gap - rect.origin.y);
    CGSize canvasSize = CGSizeMake(rect.size.width + gap * 2, rect.size.height + gap * 2);

    CCRenderTexture* renderedSpriteTexture = [self renderTextureFrom:self shiftedFor:positionShift onCanvasSized:canvasSize];
    CGSize textureSize = renderedSpriteTexture.sprite.contentSize;
    CGSize textureSizeInPixels = renderedSpriteTexture.sprite.texture.contentSizeInPixels;

    NSInteger bitsPerComponent = 8;
    NSInteger bytesPerPixel = (bitsPerComponent * 4) / 8;
    NSInteger bytesPerRow = bytesPerPixel * textureSizeInPixels.width;
    NSInteger myDataLength = bytesPerRow * textureSizeInPixels.height;

    NSMutableData* buffer = [[NSMutableData alloc] initWithCapacity:myDataLength];
    Byte* bytes = (Byte*)[buffer mutableBytes];

    [renderedSpriteTexture begin];
    glReadPixels(0, 0, textureSizeInPixels.width, textureSizeInPixels.height, GL_RGBA, GL_UNSIGNED_BYTE, bytes);
    [renderedSpriteTexture end];

    //SEE ATTACHMENT TO GET THE FILES
    NSString* spriteFrameName;
    if (IS_IPAD) spriteFrameName = (CC_CONTENT_SCALE_FACTOR() == 1) ? @"10f.png" : @"20f.png";
    else spriteFrameName = (CC_CONTENT_SCALE_FACTOR() == 1) ? @"5f.png" : @"10f.png";

    CCSprite* circle = [CCSprite spriteWithSpriteFrameName:spriteFrameName];
    circle.anchorPoint = ccp(0.48, 0.48);
    float retinaScale = (CC_CONTENT_SCALE_FACTOR() == 1) ? 1.0 : 0.5;

    CCRenderTexture* strokeTexture = [CCRenderTexture renderTextureWithWidth:textureSize.width height:textureSize.height pixelFormat:kCCTexture2DPixelFormat_RGBA8888];
    [strokeTexture beginWithClear:0 g:0 b:0 a:0];
    for (NSInteger x = 0; x < textureSizeInPixels.width; x++)
    {
    for (NSInteger y = 0; y < textureSizeInPixels.height; y++)
    {
    NSInteger idx = y * bytesPerRow + x * bytesPerPixel + 3;
    NSInteger w = 1;
    if (bytes[idx] <= 254)
    {
    BOOL shouldBeStroked = NO;
    for (NSInteger nx = -w; nx <= w; nx++)
    {
    for (NSInteger ny = -w; ny <= w; ny++)
    {
    if (x + nx < 0 || y + ny < 0 || x + nx >= textureSizeInPixels.width || y + ny >= textureSizeInPixels.height)
    continue;

    if (bytes[idx + nx * bytesPerPixel + ny * bytesPerRow] == 255)
    {
    shouldBeStroked = YES;
    break;
    }
    }
    }

    if (shouldBeStroked == YES)
    {
    circle.position = ccp(x * retinaScale, y * retinaScale);
    [circle visit];
    }
    }
    }
    }
    [strokeTexture end];

    CCSprite* resultSprite = [CCSprite spriteWithTexture:strokeTexture.sprite.texture];
    [resultSprite.texture setAntiAliasTexParameters];
    resultSprite.flipY = YES;

    if ([self isKindOfClass:[CCSprite class]]) {
    CGPoint oldAnchorInPixels = ccp(roundf(self.contentSize.width * self.anchorPoint.x), roundf(self.contentSize.height * self.anchorPoint.y));
    resultSprite.anchorPoint = ccp((oldAnchorInPixels.x + gap) / resultSprite.contentSize.width, (oldAnchorInPixels.y + gap) / resultSprite.contentSize.height);
    resultSprite.position = self.position;
    } else { //CCNode
    resultSprite.anchorPoint = CGPointZero;
    resultSprite.position = ccpAdd(self.position, ccp(rect.origin.x - gap, rect.origin.y - gap));
    }
    return resultSprite;
    }

    - (CCRenderTexture*) renderTextureFrom:(CCNode*)node shiftedFor:(CGPoint)posShift onCanvasSized:(CGSize)size
    {
    SoftAssertion(!CGSizeEqualToSize(size, CGSizeZero), @"node has zero size");

    BOOL isSprite = [node isMemberOfClass:[CCSprite class]];
    CGPoint apSave = node.anchorPoint;
    CGPoint posSave = node.position;
    BOOL wasVisible = node.visible;

    CCRenderTexture* rtx = [CCRenderTexture renderTextureWithWidth:size.width
    height:size.height
    pixelFormat:kCCTexture2DPixelFormat_RGBA8888];
    [rtx beginWithClear:0 g:0 b:0 a:0];

    node.anchorPoint = CGPointZero;
    node.position = posShift;
    node.visible = YES;

    if (isSprite) [node visit];
    else [[self cloneCCNode:node] visit];

    node.anchorPoint = apSave;
    node.position = posSave;
    node.visible = wasVisible;

    [rtx end];
    return rtx;
    }

    - (CCNode*) cloneCCNode:(CCNode*)source
    {
    CCNode* clone = [CCNode node];

    void (^copyCCNodeProperties)(CCNode*, CCNode*) = ^(CCNode* source, CCNode* clone)
    {
    clone.visible = source.visible;
    clone.rotation = source.rotation;
    clone.position = source.position;
    clone.anchorPoint = source.anchorPoint;
    clone.zOrder = source.zOrder;
    clone.tag = source.tag;
    };

    for (CCNode* srcSubnode in source.children) {

    CCNode* subNode;

    if ([srcSubnode isMemberOfClass:[CCSprite class]]) {
    CCSprite* srcSprite = (CCSprite*)srcSubnode;
    subNode = [CCSprite spriteWithTexture:srcSprite.texture];
    CCSprite* subSprite = (CCSprite*)subNode;
    subSprite.flipX = srcSprite.flipX;
    subSprite.flipY = srcSprite.flipY;
    subSprite.displayFrame = srcSprite.displayFrame;
    subSprite.opacity = srcSprite.opacity;
    }
    else if ([srcSubnode isMemberOfClass:[CCLabelTTF class]]) {
    CCLabelTTF* srcLabel = (CCLabelTTF*)srcSubnode;
    subNode = [CCLabelTTF labelWithString:srcLabel.string fontName:srcLabel.fontName fontSize:srcLabel.fontSize dimensions:srcLabel.dimensions hAlignment:srcLabel.horizontalAlignment vAlignment:srcLabel.verticalAlignment];
    CCSprite* subLabel = (CCSprite*)subNode;
    subLabel.flipX = srcLabel.flipX;
    subLabel.flipY = srcLabel.flipY;
    subLabel.color = srcLabel.color;
    }
    else {
    subNode = [self cloneCCNode:srcSubnode];
    }

    copyCCNodeProperties(srcSubnode, subNode);
    [clone addChild:subNode];
    }
    copyCCNodeProperties(source, clone);

    return clone;
    }

    关于cocos2d-iphone - cocos2d中非矩形CCNode的轮廓(描边),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13492951/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com