Domanda

I am trying to get a screen grab of a view that has a SKScene in it. The technique I am using is:

UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, scale);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

This works great with normal UIViews, but for whatever reason it is ignoring all the sprites in the SKScene.

I'm not sure if this is a bug, or if Sprite Kit's rendering is separate from UIGraphics.

Question: How do I get a screen grab of an SKScene when the way that worked for UIViews seems to not work with Sprite Kit, or has anyone had success using UIGraphics context with Sprite Kit?

È stato utile?

Soluzione

You almost have it, but the problem is as explained in the comment above. If you want to capture SKScene contents, try something like this instead:

UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, scale);
[self.view drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

The solution is to basically use the new method drawViewHierarchyInRect:afterScreenUpdates instead, which is the best we have for now; note, it's not exactly speedy, so doing this in realtime will not be pretty.

Altri suggerimenti

As a faster alternative, you can use the textureFromNode method on SKView, which returns an image of the view as an SKTexture. Simply pass the SKScene as the argument:

let texture = skView.textureFromNode(scene)

Or to capture part of the scene:

let texture = skView.textureFromNode(scene, crop: cropRect)

//1: get texture from "someNode"

let texture = skView.textureFromNode(someNode)

//2: get UIImage from the node texture

let image = UIImage(cgImage: texture!.cgImage())

A solution for Swift:

func getScreenshot(scene: SKScene, duration:TimeInterval = 0.0001, completion:((_ txt:SKTexture) -> Void)?) {
    let action = SKAction.run {
        let bounds = scene.view?.bounds
        var image = UIImage()
        UIGraphicsBeginImageContextWithOptions(bounds!.size, true, UIScreen.main.scale)
        scene.view?.drawHierarchy(in: bounds!, afterScreenUpdates: true)
        if let screenshot = UIGraphicsGetImageFromCurrentImageContext() {
            UIGraphicsEndImageContext()
            image = screenshot
        } else {
            assertionFailure("Unable to make a screenshot for the scene \(type(of:scene))")
        }
        completion!(SKTexture(image: image))
    }
    let wait = SKAction.wait(forDuration: duration)
    let seq = SKAction.sequence([wait,action])
    scene.run(seq,withKey:"getScreenshot")
}

Usage:

getScreenshot(scene: self, completion:{ (txt) -> Void in
            let thumbNode = SKSpriteNode(texture: txt, size:CGSize(width:300,height:224))
            // do whatever you want with your screenshot..
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top