0

子として2つのスプライトを含むレイヤーベースのクラスがあります。それらを背景とツリーと呼びましょう。

このクラスの中には、そのレイヤーのスクリーンショットをキャプチャするメソッドがあります。メソッドは正常に機能しています。そのレイヤーのスクリーンショットを撮るたびに、背景の上の木の構成を取得します。罰金。ある時点で、ツリーなしでそのレイヤーのスクリーンショットを取得したいと思います。だから私がやっていることは、ツリーを非表示にするために、スクリーンショットを撮り、ツリーをもう一度表示することです...このように:

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

驚いたことに、この方法で作成されたスクリーンショットには常にツリーが含まれています。

これはhideTreeと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フォーラムからのスクリーンショットにこの方法を使用しています:

-(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;
}

私は何が欠けていますか?なぜ木が常に表示されているのですか?

4

2 に答える 2

2

ゲームループの更新プロセス中にコードが実行されています。

スクリーンショットは、UIImageの作成に使用する現在のピクセルを取得しています。

ツリーを表示しない、または不透明度をゼロにするように指示すると、次の描画サイクルまで有効になりません。

問題を解決するには、ツリーを非表示にし、描画サイクルを実行してから、次の更新でツリーが表示されていないフレームをキャプチャする必要があります。

わかる?

于 2012-08-02T00:31:08.313 に答える
1

ツリーの不透明度を変更すると、次に画面が更新されたときにのみ有効になります。

一度この問題が発生し、いくつかのスケジュールを実行しました。それ以外の

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

行う

[myLayer hideTree];
[self schedule:@selector(takeScreenshot)interval:0.05];

そして、次のメソッドをシーンに追加します。

-(void)takeScreenshot {
    [self unschedule:@selector(takeScreenshot)];
    UIImage *screenshot = [myLayer screenshot];
    [myLayer showTree];
}

基本的に、画面を更新できるように0.05秒のギャップを設けています。それはうまくいくはずです。

[self visit]上記の方法は私にはうまくいきましたが、木を隠してから呼び出す場合にもうまくいくと思います。しかし、私はテストしたことがありません。

于 2012-08-02T00:37:43.093 に答える