Question

In my effort to save a ScrollingBackground object I've subclassed the CCSprites to conform to NSCoding. The ScrollingBackground doesn't display. Please see the relevant code below. I'm not really sure whats wrong. Please help.

ScrollingBackground.h: (CCBackgroundSprite's interface)

@interface CCBackgroundSprite: NSObject <NSCoding>

@property (nonatomic, assign) float xValue;
@property (nonatomic, assign) float yValue;
@property (nonatomic, retain) NSString* backgroundStringName;

@end

ScrollingBackground.m: (CCBackgroundSprite's implementation)

@implementation CCBackgroundSprite

-(id)init
{
    if((self = [super init])){
    }

   return self;
}

-(id) initWithCoder:(NSCoder *) aDecoder {

self = [super init];
if(self != nil) {
    self.xValue = [aDecoder decodeFloatForKey:@"xValue"];
    self.yValue = [aDecoder decodeFloatForKey:@"yValue"];
    self.backgroundStringName = [aDecoder decodeObjectForKey:@"backgroundStringName"];
  }
  return self;
}

-(void) encodeWithCoder:(NSCoder *)aCoder {

   [aCoder encodeFloat:self.xValue forKey:@"xValue"];
   [aCoder encodeFloat:self.yValue forKey:@"yValue"];
   [aCoder encodeObject:self.backgroundStringName forKey:@"backgroundStringName"];
}

@end

Setting CCBackgroundSprite's instances for the CCSprite properties:

-(void)spriteProperties {
   background1 = [[CCBackgroundSprite alloc] init];
   [background1 setXValue:bg.position.x];
   [background1 setYValue:bg.position.y];
   [background1 setBackgroundStringName:@"bg"];

   background2 = [[CCBackgroundSprite alloc] init];
   [background2 setXValue:bgSwap.position.x];
   [background2 setYValue:bgSwap.position.y];
   [background2 setBackgroundStringName:@"bgSwap"];

   background3 = [[CCBackgroundSprite alloc] init];
   [background3 setXValue:bgSwap2.position.x];
   [background3 setYValue:bgSwap2.position.y];
   [background3 setBackgroundStringName:@"bgSwap2"];
}

encoding/decoding of other non-Sprite related properties of the ScrollingBackground:

-(void) encodeWithCoder:(NSCoder *)aCoder {
   [aCoder encodeInt:self.backgroundCount forKey:@"backgroundCount"];
   [aCoder encodeInt:self.backgroundRepeatCount forKey:@"backgroundRepeatCount"];
   [aCoder encodeFloat:self.scrollSpeed forKey:@"scrollSpeed"];
   [aCoder encodeObject:self.backgroundArray forKey:@"backgroundArray"];
   [aCoder encodeObject:self.changeArray forKey:@"changeArray"];
              .
              .
              .
} 

-(id) initWithCoder:(NSCoder *) aDecoder {

self = [super init];
if(self != nil) {
        self.backgroundCount = [aDecoder decodeIntForKey:@"backgroundCount"];
        self.backgroundRepeatCount = [aDecoder decodeIntForKey:@"backgroundRepeatCount"];
        self.scrollSpeed = [aDecoder decodeFloatForKey:@"scrollSpeed"];
        self.backgroundArray = [aDecoder decodeObjectForKey:@"backgroundArray"];
        self.changeArray = [aDecoder decodeObjectForKey:@"changeArray"];
           .
           .
           .
     }
 }

Saving and loading of ScrollingBackground object:

- (void)saveBackgroundObject:(ScrollingBackground *)object key:(NSString *)key {
   [self spriteProperties];
   NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:object];
   NSString *dataToString = [NSString stringWithFormat:@"%@", encodedObject];
   CCLOG(@"encodedObject = %@ \n", dataToString);

   NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
   [defaults setObject:encodedObject forKey:key];
   [defaults synchronize];
}

-(ScrollingBackground *)loadBackgroundWithKey:(NSString *)key {
   NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
   NSData *encodedObject = [defaults objectForKey:key];
   NSString *dataToString = [NSString stringWithFormat:@"%@", encodedObject];
   CCLOG(@"encodedObject = %@ \n", dataToString);
   ScrollingBackground *object = [NSKeyedUnarchiver unarchiveObjectWithData:encodedObject];
   return object;
 }

UPDATED:

I have made the following changes the spriteProperties method:

-(void)spriteProperties {
  background1 = [[CCBackgroundSprite alloc] init];
  [background1 setXValue:bg.position.x];
  [background1 setYValue:bg.position.y];
  [background1 setBackgroundImageName:bg.displayFrame.textureFilename];
  [self addChild:background1];

  background2 = [[CCBackgroundSprite alloc] init];
  [background2 setXValue:bgSwap.position.x];
  [background2 setYValue:bgSwap.position.y];
  [background2 setBackgroundImageName:bgSwap.displayFrame.textureFilename];
  [self addChild:background2];

  background3 = [[CCBackgroundSprite alloc] init];
  [background3 setXValue:bgSwap2.position.x];
  [background3 setYValue:bgSwap2.position.y];
  [background3 setBackgroundImageName:bgSwap2.displayFrame.textureFilename];
  [self addChild:background3];
  }

The main reason I am using displayFrame.textureFilename above is because I'm reusing the sprites along the way. Also to setup of the background images I did:

-(void)startingSprites  //change later to setupInitialBackground
{

    CGSize s = [[CCDirector sharedDirector] winSize];
    bg = [CCSprite spriteWithSpriteFrameName:@"bgImage1.png"];
    bg.position = ccp(s.width/2, s.height/2);
    [currentBackgroundBatchNode addChild:bg];


    swapbg = [CCSprite spriteWithSpriteFrameName:@"bgImage2.png"];
    swapbg.position = ccp(s.width/2, 3*s.height/2 -1.0);
    [currentBackgroundBatchNode addChild: swapbg];

    swapbg2 = [CCSprite spriteWithSpriteFrameName:@"bgImage3.png"];
    swapbg2.position = ccp(s.width/2, 5*s.height/2 - 2.0);
    [currentBackgroundBatchNode addChild: swapbg2];

    CCLOG(@"bg background is %@", bg.displayFrame.textureFilename);
    CCLOG(@"bgSwap background is %@", swapbg.displayFrame.textureFilename);
    CCLOG(@"bgSwap2 background is %@", swapbg2.displayFrame.textureFilename);
}

I've just realized a few things:

  1. the CCLOG's in startingSprites are null
  2. I reuse the currentBackgroundBatchNode (which is a CCSpriteBatchNode) along the way, meaning that I have to encode/decode it. How do I subclass it and with what properties? Not too sure how it'll work out.
Was it helpful?

Solution

I have read a number of your posts, also related to this. I would recommend that instead of trying to subclass several cocos2d classes to conform to NSCoding you should use a simpler work around. I believe your background has it's own layer, so why don't you rather save various background parameters and create another init for your background to handle cases for reloading the background state.

OTHER TIPS

You say you've subclassed CCSprite, but you actually subclassed NSObject. Try:

@interface CCBackgroundSprite: CCSprite <NSCoding>
...
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top