Cocos2D 2.0 - 截屏期间的奇怪行为奇怪、行为、Cocos2D

2023-09-06 10:24:28 作者:孤魂伴野鬼

我有一个基于图层的类,其中包含两个子精灵.让我们称它们为:背景和树.

I have a layer based class that contains two sprites as children. Lets call them: background and tree.

在这个类中,我有一个方法来捕获该层的屏幕截图.该方法工作正常.每次我对该图层进行截图时,我都会获得背景上树的构成.美好的.在某一点上,我想获得没有树的那层的屏幕截图.所以我要做的是,隐藏树,截取屏幕截图并再次显示树......就像这样:

Inside this class I have a method to capture a screenshot of that layer. The method is working fine. Every time I take a screenshot of that layer, I obtain the composition of the tree over the background. Fine. At a certain point, I want to get the screenshot of that layer without the tree. So what I do is, to hide the tree, take the screenshot and show the tree again... like this:

[myLayer hideTree];
UIImage *screenshot = [myLayer screenshot];
[myLayer showTree];

令我惊讶的是,以这种方式生成的屏幕截图总是包含树.

To my surprise, the screenshots produced this way always contain the tree.

这是 hideTree 和 showTree:

this is hideTree and showTree:

- (void) hideTree {
    [treeLayer setOpacity:0];
    // I have also tried [treelayer setVisible:NO];
}

- (void) showTree {
    [treeLayer setOpacity:255];
    // I have also tried [treelayer setVisible:YES];
}

我用这个方法截图,来自cocos2d论坛:

I am using this method for screenshots, from cocos2d forums:

-(UIImage*) screenshot
{
    CGSize displaySize  = [[CCDirector sharedDirector] winSize];
    CGSize winSize      = [self winSize];

    //Create buffer for pixels
    GLuint bufferLength = displaySize.width * displaySize.height * 4;
    GLubyte* buffer = (GLubyte*)malloc(bufferLength);

    //Read Pixels from OpenGL
    glReadPixels(0, 0, displaySize.width, displaySize.height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
    //Make data provider with data.
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer, bufferLength, NULL);

    //Configure image
    int bitsPerComponent = 8;
    int bitsPerPixel = 32;
    int bytesPerRow = 4 * displaySize.width;
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
    CGImageRef iref = CGImageCreate(displaySize.width, displaySize.height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);

    uint32_t* pixels = (uint32_t*)malloc(bufferLength);
    CGContextRef context = CGBitmapContextCreate(pixels, winSize.width, winSize.height, 8, winSize.width * 4, CGImageGetColorSpace(iref), kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

    CGContextTranslateCTM(context, 0, displaySize.height);
    CGContextScaleCTM(context, 1.0f, -1.0f);

    UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
    switch (orientation)
    {
        case UIDeviceOrientationPortrait: break;
        case UIDeviceOrientationPortraitUpsideDown:
            CGContextRotateCTM(context, CC_DEGREES_TO_RADIANS(180));
            CGContextTranslateCTM(context, -displaySize.width, -displaySize.height);
            break;
        case UIDeviceOrientationLandscapeLeft:
            CGContextRotateCTM(context, CC_DEGREES_TO_RADIANS(-90));
            CGContextTranslateCTM(context, -displaySize.height, 0);
            break;
        case UIDeviceOrientationLandscapeRight:
            CGContextRotateCTM(context, CC_DEGREES_TO_RADIANS(90));
            CGContextTranslateCTM(context, displaySize.width * 0.5f, -displaySize.height);
            break;
        case UIDeviceOrientationUnknown:
            break;
        case UIDeviceOrientationFaceUp:
            break;
        case UIDeviceOrientationFaceDown:
            break;
    }

    CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, displaySize.width, displaySize.height), iref);
    CGImageRef imageRef = CGBitmapContextCreateImage(context);
    UIImage *outputImage = [UIImage imageWithCGImage:imageRef];

    //Dealloc
    CGImageRelease(imageRef);
    CGDataProviderRelease(provider);
    CGImageRelease(iref);
    CGColorSpaceRelease(colorSpaceRef);
    CGContextRelease(context);
    free(buffer);
    free(pixels);

    return outputImage;
}

我错过了什么?为什么树总是显示?

what am I missing? Why is the tree always showing?

推荐答案

你的代码在游戏循环的更新过程中运行.

Your code is running during the update process of the game loop.

屏幕截图正在获取用于创建 UIImage 的当前像素.

The screenshot is getting the current pixels to use to create the UIImage.

当您告诉树不可见或不透明度为零时,直到下一个绘制周期才会生效.

When you tell the tree to not be visible or have zero opacity, that will not take effect until the next draw cycle.

要解决您的问题,您需要隐藏树,执行绘制循环,然后在下一次更新中捕获未显示树的帧.

To fix your problem, you need to hide the tree, do a draw cycle, and then in the next update capture the frame with the tree not showing.

有意义吗?