Saving the generated SKTexture to a file

Now I filed an error for the question below. Anyone with a good workaround?

I am trying to save a file SKTextureto a file and load it again, but I failed. The following code snippet can be copied to GameScene.m in the Xcode launch project.

I use textureFromNodein generateTexture, and this, apparently, is the main cause of my problem. If I use a sprite texture, the code works and two spaceships are visible.

This code worked in iOS 8, but it stopped working in Xcode7 and iOS 9. I just want to check that this is a bug before I write a bug report. My concern is that I am doing something wrong with NSKeyedArchiver.

This happens both in the simulator and on the device.

#import "GameScene.h"

@implementation GameScene

// Generates a texture
- (SKTexture *)generateTexture
{
    SKScene *scene = [[SKScene alloc] initWithSize:CGSizeMake(100, 100)];

    SKShapeNode *shapeNode = [SKShapeNode shapeNodeWithRectOfSize:CGSizeMake(50, 50)];
    shapeNode.position = CGPointMake(50, 50);
    shapeNode.strokeColor = SKColor.redColor;
    shapeNode.lineWidth = 10;
    [scene addChild:shapeNode];

    SKTexture *texture = [self.view textureFromNode:scene];
    //SKTexture *texture = [SKSpriteNode spriteNodeWithImageNamed:@"Spaceship"].texture; // This works!

    return texture;
}

// Just generate a path
- (NSString *)fullDocumentsPath
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *yourFileName = [documentsDirectory stringByAppendingPathComponent:@"fileName"];

    return yourFileName;
}

- (void)didMoveToView:(SKView *)view
{    
    self.scaleMode = SKSceneScaleModeResizeFill;

    // Verify that the generateTexture method indeed produces a valid texture.
    SKSpriteNode *s1 = [SKSpriteNode spriteNodeWithTexture:[self generateTexture]];
    s1.position = CGPointMake(100, 100);
    [self addChild:s1];

    // Start with saving the texture.
    NSString *fullName = [self fullDocumentsPath];
    NSError *error;
    NSFileManager *fileMgr = [NSFileManager defaultManager];
    if ([fileMgr fileExistsAtPath:fullName])
    {
        [fileMgr removeItemAtPath:fullName error:&error];
        assert(error == nil);
    }
    NSDictionary *dict1 = [NSDictionary dictionaryWithObject:[self generateTexture] forKey:@"object"];
    bool ok = [NSKeyedArchiver archiveRootObject:dict1 toFile:fullName];
    assert(ok);

    // Read back the texture and place it in a sprite. This sprite is not shown. Why?
    NSData *data = [NSData dataWithContentsOfFile:fullName];
    NSDictionary *dict2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    SKTexture *loadedTexture = [dict2 objectForKey:@"object"];
    SKSpriteNode *s2= [SKSpriteNode spriteNodeWithTexture:loadedTexture];
    NSLog(@"t(%f, %f)", loadedTexture.size.width, loadedTexture.size.height); // Size of sprite & texture is zero. Why?
    s2.position = CGPointMake(200, 100);
    [self addChild:s2];
}

@end

Update for Yudong:

, , 4 , . , . . . , .

-(SKTexture*)generateTexture
{
  SKScene *scene = [[SKScene alloc] initWithSize:CGSizeMake(100, 100)];

  SKSpriteNode *ship = [SKSpriteNode spriteNodeWithImageNamed:@"Spaceship"];
  ship.position = CGPointMake(50, 50);
  [scene addChild:ship];

  SKTexture *texture = [self.view textureFromNode:scene];

  NSLog(@"texture: %@", texture);

  return texture;
}

/ :

, . !

CGImageRef  cgImg = texture.CGImage;
SKTexture *newText = [SKTexture textureWithCGImage:cgImg];
+4
2

/ SKTextures. SKTextures. . , textureFromNode textureFromNode: crop: SKPhysicsBodies . ios 8, Apple , ios 9.0. ios 9.0 . nil- SKPhysicsBodies .

/ SKTextures.

/, , :

.

, , SKSpriteNode, .

(. .)

, :

, , node, . "

... , CGImage():

        // ios 9.2 workaround for white boxes on serialization
        let img = texture!.CGImage()
        let uimg = UIImage(CGImage: img)
        let ntex = SKTexture(image: uimg)
        let sprite = SKSpriteNode(texture: ntex, size: texture!.size())

, SKSpriteNodes, , /. , size() SKSpriteNode , , , .

  1. textureFromNode: crop: , : ios 8 ( , , UIScreen.mainScreen()). ios 9.0 ( nil). ios 9.2 ( - ), . , /, , № 3 .

, . , SKTextures, .

+4

Xcode 7 , texture, generateTexture, null. , - , .

NSLog . . generateTexture:

NSLog(@"texture: %@", texture);

:

texture: '(null)' (300 x 300)

s1 dict1 :

s1: name: '(null)' texture: ['(null)' (300 x 300)]: {100, 100}: {1.00, 1.00} : {100, 100} : {0.5, 0.5} : 0.00

dict1: {     object = "'(null)' (300 x 300)"; }

iOS 8, iOS 9, , , .

, SKShapeNode scene, scene. SKShapeNode, .

shapeNode.fillTexture = [SKTexture textureWithImageNamed:@"Spaceship"];
SKTexture *texture = shapeNode.fillTexture;
return texture;

Update:

, textureFromNode , , iOS 9. , , , . , , . , , , .

, SKLabelNode SKSpriteNode didMoveToView. , , snapshot, . .

- (UIImage *)snapshot
{
    UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0.5);
    [self.view drawViewHierarchyInRect:self.view.bounds afterScreenUpdates:YES];
    UIImage *snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return snapshotImage;
}

UIImage, . iOS 8, 9.

+2

Source: https://habr.com/ru/post/1608357/


All Articles