0

そのため、現在、Cocos2d ゲームの設定を保存する機能的な方法があり、使用している方法は XML パーサーです。

まず、このような場合は NSUserDefaults を使用した方がよいでしょうか?

編集:XMLパーサーがどのように機能するかをすでに知っている場合は、最後までスキップしてください。

ここに私の GlobalSettings.h があります:

#import <Foundation/Foundation.h>

@interface GlobalSettings : NSObject {

// Declare variables with an underscore in front, for example:
int _currency;
BOOL _BankerBossDefeated;
BOOL _BabyBossDefeated;
BOOL _DuckBossDefeated;
BOOL _BaseBallBossDefeated;
BOOL _NewtonBossDefeated;

BOOL _CatchExtender;
BOOL _CatchExtenderEnabled;
BOOL _SpeedBoost;
BOOL _SpeedBoostEnabled;
}

// Declare your variable properties without an underscore, for example:
@property (nonatomic, assign) int currency;
@property (nonatomic, assign) BOOL BankerBossDefeated;
@property (nonatomic, assign) BOOL BabyBossDefeated;
@property (nonatomic, assign) BOOL DuckBossDefeated;
@property (nonatomic, assign) BOOL BaseBallBossDefeated;
@property (nonatomic, assign) BOOL NewtonBossDefeated;
@property (nonatomic, assign) BOOL SpeedBoost;
@property (nonatomic, assign) BOOL CatchExtender;
@property (nonatomic, assign) BOOL SpeedBoostEnabled;
@property (nonatomic, assign) BOOL CatchExtenderEnabled;

// Put your custom init method interface here:
-(id)initWithcurrency:(int)currency 
BankerBossDefeated:(BOOL)BankerBossDefeated
BabyBossDefeated:(BOOL)BabyBossDefeated
DuckBossDefeated:(BOOL)DuckBossDefeated
BaseBallBossDefeated:(BOOL)BaseBallBossDefeated
NewtonBossDefeated:(BOOL)NewtonBossDefeated
CatchExtender:(BOOL)CatchExtender
       SpeedBoost:(BOOL)SpeedBoost
 CatchExtenderEnabled:(BOOL)CatchExtenderEnabled
       SpeedBoostEnabled:(BOOL)SpeedBoostEnabled;

@end

私の GlobalSettings.m は次のとおりです。

#import "GlobalSettings.h"

@implementation GlobalSettings

// Synthesize your variables here, for example: 
@synthesize currency = _currency;
@synthesize BankerBossDefeated = _BankerBossDefeated;
@synthesize BabyBossDefeated = _BabyBossDefeated;
@synthesize DuckBossDefeated = _DuckBossDefeated;
@synthesize BaseBallBossDefeated = _BaseBallBossDefeated;
@synthesize NewtonBossDefeated = _NewtonBossDefeated;
@synthesize SpeedBoost = _SpeedBoost;
@synthesize CatchExtender = _CatchExtender;
@synthesize SpeedBoostEnabled = _SpeedBoostEnabled;
@synthesize CatchExtenderEnabled = _CatchExtenderEnabled;

// put your custom init method here which takes a variable 
// for each class instance variable
-(id)initWithcurrency:(int)currency
BankerBossDefeated:(BOOL)BankerBossDefeated
 BabyBossDefeated:(BOOL)BabyBossDefeated
 DuckBossDefeated:(BOOL)DuckBossDefeated
 BaseBallBossDefeated:(BOOL)BaseBallBossDefeated
NewtonBossDefeated:(BOOL)NewtonBossDefeated
    CatchExtender:(BOOL)CatchExtender
       SpeedBoost:(BOOL)SpeedBoost
    CatchExtenderEnabled:(BOOL)CatchExtenderEnabled
       SpeedBoostEnabled:(BOOL)SpeedBoostEnabled;{

if ((self = [super init])) {

    // Set class instance variables based on values 
    // given to this method
    self.currency = currency; 
    self.BankerBossDefeated = BankerBossDefeated;  
    self.BabyBossDefeated = BabyBossDefeated;
    self.DuckBossDefeated = DuckBossDefeated;
    self.BaseBallBossDefeated = BaseBallBossDefeated;
    self.NewtonBossDefeated = NewtonBossDefeated;
    self.CatchExtender = CatchExtender;
    self.SpeedBoost = SpeedBoost;
    self.CatchExtenderEnabled = CatchExtenderEnabled;
    self.SpeedBoostEnabled = SpeedBoostEnabled;
}
return self;
}

- (void) dealloc {
[super dealloc];
}

@end

次に、SettingsParser.h を使用して XML を解析します。

#import <Foundation/Foundation.h>

@class GlobalSettings;

@interface SettingsParser : NSObject {} 

+ (GlobalSettings *)loadData;
+ (void)saveData:(GlobalSettings *)saveData;

@end

および SettingsParser.m:

#import "SettingsParser.h"  
#import "GlobalSettings.h"  
#import "GDataXMLNode.h"

@implementation SettingsParser

+ (NSString *)dataFilePath:(BOOL)forSave {

NSString *xmlFileName = @"GlobalSettings";

/***************************************************************************
 This method is used to set up the specified xml for reading/writing.
 Specify the name of the XML file you want to work with above.
 You don't have to worry about the rest of the code in this method.
 ***************************************************************************/

NSString *xmlFileNameWithExtension = [NSString stringWithFormat:@"%@.xml",xmlFileName];    
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,     NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *documentsPath = [documentsDirectory     stringByAppendingPathComponent:xmlFileNameWithExtension];
if (forSave || [[NSFileManager defaultManager] fileExistsAtPath:documentsPath]) {
    return documentsPath;   
    NSLog(@"%@ opened for read/write",documentsPath);
} else {
    NSLog(@"Created/copied in default %@",xmlFileNameWithExtension);
    return [[NSBundle mainBundle] pathForResource:xmlFileName ofType:@"xml"];
}    
}

+ (GlobalSettings *)loadData {

/*************************************************************************** 
 This loadData method is used to load data from the xml file 
 specified in the dataFilePath method above.  

 MODIFY the list of variables below which will be used to create
 and return an instance of TemplateData at the end of this method.
 ***************************************************************************/

int currency;
BOOL BankerBossDefeated;
BOOL BabyBossDefeated;
BOOL DuckBossDefeated;
BOOL BaseBallBossDefeated;
BOOL NewtonBossDefeated;
BOOL CatchExtender;
BOOL SpeedBoost;
BOOL CatchExtenderEnabled;
BOOL SpeedBoostEnabled;


// Create NSData instance from xml in filePath
NSString *filePath = [self dataFilePath:FALSE];
NSData *xmlData = [[NSMutableData alloc] initWithContentsOfFile:filePath];
NSError *error;
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData options:0 error:&error];
if (doc == nil) { return nil; NSLog(@"xml file is empty!");}
NSLog(@"Loading %@", filePath);

/*************************************************************************** 
 This next line will usually have the most customisation applied because 
 it will be a direct reflection of what you want out of the XML file.
 ***************************************************************************/

NSArray *dataArray = [doc nodesForXPath:@"//GlobalSettings" error:nil];
NSLog(@"Array Contents = %@", dataArray);

/*************************************************************************** 
 We use dataArray to populate variables created at the start of this 
 method. For each variable you will need to:
    1. Create an array based on the elements in the xml
    2. Assign the variable a value based on data in elements in the xml
 ***************************************************************************/

for (GDataXMLElement *element in dataArray) {

    NSArray *currencyArray = [element elementsForName:@"currency"];       
    NSArray *BankerBossDefeatedArray = [element elementsForName:@"BankerBossDefeated"];   
    NSArray *BabyBossDefeatedArray = [element elementsForName:@"BabyBossDefeated"]; 
    NSArray *DuckBossDefeatedArray = [element elementsForName:@"DuckBossDefeated"]; 
    NSArray *BaseBallBossDefeatedArray = [element     elementsForName:@"BaseBallBossDefeated"]; 
    NSArray *NewtonBossDefeatedArray = [element elementsForName:@"NewtonBossDefeated"];
    NSArray *CatchExtenderArray = [element elementsForName:@"CatchExtender"];
    NSArray *SpeedBoostArray = [element elementsForName:@"SpeedBoost"];
    NSArray *CatchExtenderEnabledArray = [element elementsForName:@"CatchExtenderEnabled"];
    NSArray *SpeedBoostEnabledArray = [element elementsForName:@"SpeedBoostEnabled"];

    // currency
    if (currencyArray.count > 0) {
        GDataXMLElement *currencyElement = (GDataXMLElement *) [currencyArray objectAtIndex:0];
        currency = [[currencyElement stringValue] intValue];
    } 

    // BankerBossDefeated    
    if (BankerBossDefeatedArray.count > 0) {
        GDataXMLElement *BankerBossDefeatedElement = (GDataXMLElement *) [BankerBossDefeatedArray objectAtIndex:0];
        BankerBossDefeated = [[BankerBossDefeatedElement stringValue] boolValue];
    }

    // DuckBossDefeated    
    if (DuckBossDefeatedArray.count > 0) {
        GDataXMLElement *DuckBossDefeatedElement = (GDataXMLElement *) [DuckBossDefeatedArray objectAtIndex:0];
        DuckBossDefeated = [[DuckBossDefeatedElement stringValue] boolValue];
    }

    // BabyBossDefeated    
    if (BabyBossDefeatedArray.count > 0) {
        GDataXMLElement *BabyBossDefeatedElement = (GDataXMLElement *) [BabyBossDefeatedArray objectAtIndex:0];
        BabyBossDefeated = [[BabyBossDefeatedElement stringValue] boolValue];
    }

    // BaseBallBossDefeated    
    if (BaseBallBossDefeatedArray.count > 0) {
        GDataXMLElement *BaseBallBossDefeatedElement = (GDataXMLElement *) [BaseBallBossDefeatedArray objectAtIndex:0];
        BaseBallBossDefeated = [[BaseBallBossDefeatedElement stringValue] boolValue];
    }

    // NewtonBossDefeated    
    if (NewtonBossDefeatedArray.count > 0) {
        GDataXMLElement *NewtonBossDefeatedElement = (GDataXMLElement *) [NewtonBossDefeatedArray objectAtIndex:0];
        NewtonBossDefeated = [[NewtonBossDefeatedElement stringValue] boolValue];
    }
    // CatchExtender
    if (CatchExtenderArray.count > 0) {
        GDataXMLElement *CatchExtenderElement = (GDataXMLElement *) [CatchExtenderArray objectAtIndex:0];
        CatchExtender = [[CatchExtenderElement stringValue] boolValue];
    }
    // SpeedBoost
    if (SpeedBoostArray.count > 0) {
        GDataXMLElement *SpeedBoostElement = (GDataXMLElement *) [SpeedBoostArray objectAtIndex:0];
        SpeedBoost = [[SpeedBoostElement stringValue] boolValue];
    }

    // CatchExtenderEnabled
    if (CatchExtenderEnabledArray.count > 0) {
        GDataXMLElement *CatchExtenderEnabledElement = (GDataXMLElement *) [CatchExtenderEnabledArray objectAtIndex:0];
        CatchExtenderEnabled = [[CatchExtenderEnabledElement stringValue] boolValue];
    }
    // SpeedBoost
    if (SpeedBoostEnabledArray.count > 0) {
        GDataXMLElement *SpeedBoostEnabledElement = (GDataXMLElement *) [SpeedBoostEnabledArray objectAtIndex:0];
        SpeedBoostEnabled = [[SpeedBoostEnabledElement stringValue] boolValue];
    }

}

/*************************************************************************** 
 Now the variables are populated from xml data we create an instance of
 TemplateData to pass back to whatever called this method.

 The initWithExampleInt:exampleBool:exampleString will need to be replaced
 with whatever method you have updaed in the TemplateData class.
 ***************************************************************************/

//NSLog(@"XML value read for exampleInt = %i", exampleInt);
//NSLog(@"XML value read for exampleBool = %i", exampleBool);
//NSLog(@"XML value read for exampleString = %@", exampleString);

GlobalSettings *Data = [[GlobalSettings alloc] initWithcurrency:currency
                                                  BankerBossDefeated:BankerBossDefeated
                                               BabyBossDefeated:BabyBossDefeated     DuckBossDefeated:DuckBossDefeated BaseBallBossDefeated:BaseBallBossDefeated     NewtonBossDefeated:NewtonBossDefeated
                                                  CatchExtender:CatchExtender
                                                     SpeedBoost:SpeedBoost     CatchExtenderEnabled:CatchExtenderEnabled
                                                     SpeedBoostEnabled:SpeedBoostEnabled];

[doc release];
[xmlData release];
return Data;
[Data release];
}

+ (void)saveData:(GlobalSettings *)saveData {


/*************************************************************************** 
 This method writes data to the xml based on a TemplateData instance
 You will have to be very aware of the intended xml contents and structure
 as you will be wiping and re-writing the whole xml file.

 We write an xml by creating elements and adding 'children' to them.

 You'll need to write a line for each element to build the hierarchy // <-- MODIFY CODE ACCORDINGLY
 ***************************************************************************/

GDataXMLElement *GlobalSettingsElement = [GDataXMLNode elementWithName:@"GlobalSettings"];

GDataXMLElement *currencyElement = [GDataXMLNode elementWithName:@"currency" 
                                                       stringValue:[[NSNumber numberWithInt:saveData.currency] stringValue]];

GDataXMLElement *BankerBossDefeatedElement = [GDataXMLNode elementWithName:@"BankerBossDefeated"   
                                                        stringValue:[[NSNumber numberWithBool:saveData.BankerBossDefeated] stringValue]];

GDataXMLElement *BabyBossDefeatedElement = [GDataXMLNode elementWithName:@"BabyBossDefeated"   
                                                               stringValue:[[NSNumber numberWithBool:saveData.BabyBossDefeated] stringValue]];

GDataXMLElement *DuckBossDefeatedElement = [GDataXMLNode elementWithName:@"DuckBossDefeated"   
                                                               stringValue:[[NSNumber numberWithBool:saveData.DuckBossDefeated] stringValue]];

GDataXMLElement *BaseBallBossDefeatedElement = [GDataXMLNode elementWithName:@"BaseBallBossDefeated"   
                                                               stringValue:[[NSNumber numberWithBool:saveData.BaseBallBossDefeated] stringValue]];

GDataXMLElement *NewtonBossDefeatedElement = [GDataXMLNode elementWithName:@"NewtonBossDefeated"   
                                                               stringValue:[[NSNumber numberWithBool:saveData.NewtonBossDefeated] stringValue]];
GDataXMLElement *CatchExtenderElement = [GDataXMLNode elementWithName:@"CatchExtender"
                                                               stringValue:[[NSNumber numberWithBool:saveData.CatchExtender] stringValue]];
GDataXMLElement *SpeedBoostElement = [GDataXMLNode elementWithName:@"SpeedBoost"
                                                               stringValue:[[NSNumber numberWithBool:saveData.SpeedBoost] stringValue]];
GDataXMLElement *CatchExtenderEnabledElement = [GDataXMLNode elementWithName:@"CatchExtenderEnabled"
                                                          stringValue:[[NSNumber numberWithBool:saveData.CatchExtender] stringValue]];
GDataXMLElement *SpeedBoostEnabledElement = [GDataXMLNode elementWithName:@"SpeedBoostEnabled"
                                                       stringValue:[[NSNumber numberWithBool:saveData.SpeedBoost] stringValue]];


// Using the elements just created, set up the hierarchy
[GlobalSettingsElement addChild:currencyElement];
[GlobalSettingsElement addChild:BankerBossDefeatedElement];
[GlobalSettingsElement addChild:BabyBossDefeatedElement];
[GlobalSettingsElement addChild:DuckBossDefeatedElement];
[GlobalSettingsElement addChild:BaseBallBossDefeatedElement];
[GlobalSettingsElement addChild:NewtonBossDefeatedElement];
[GlobalSettingsElement addChild:CatchExtenderElement];
[GlobalSettingsElement addChild:SpeedBoostElement];
[GlobalSettingsElement addChild:CatchExtenderEnabledElement];
[GlobalSettingsElement addChild:SpeedBoostEnabledElement];

GDataXMLDocument *document = [[[GDataXMLDocument alloc] 
                               initWithRootElement:GlobalSettingsElement] autorelease];

NSData *xmlData = document.XMLData;

NSString *filePath = [self dataFilePath:TRUE];
NSLog(@"Saving data to %@...", filePath);
[xmlData writeToFile:filePath atomically:YES];
}

@end

編集:実際の問題はここから始まります:

メニュー クラスには、CatchExtender と SpeedBoost が有効になったときに表示される 2 つのスイッチがあります (これらはゲームのストアで購入します)。それらのスイッチでは、スイッチに応じて SpeedBoostEnabled と CatchExtenderEnabled を設定したいと考えています。

これらはスイッチです:

私の初期設定で:

if (GlobalSettings.CatchExtender == TRUE) {
        if(GlobalSettings.SpeedBoost == TRUE){
            catchSwitch = [[ UISwitch alloc ] initWithFrame: CGRectMake(220, 400, 10, 10)];
            catchSwitch.center = CGPointMake(240, 450);

            CCLabelTTF *catchLabel = [CCLabelTTF labelWithString:@"Catch Extender" fontName:@"Chalkduster" fontSize:15];
            catchLabel.color = ccWHITE;
            catchLabel.position = CGPointMake(240, 60);
            [self addChild: catchLabel];
        }else{
            catchSwitch = [[ UISwitch alloc ] initWithFrame: CGRectMake(160, 400, 10, 10)];
            catchSwitch.center = CGPointMake(160, 450);
            CCLabelTTF *catchLabel = [CCLabelTTF labelWithString:@"Catch Extender" fontName:@"Chalkduster" fontSize:15];
            catchLabel.color = ccWHITE;
            catchLabel.position = CGPointMake(160, 60);
            [self addChild: catchLabel];
        }

        catchSwitch.on = NO;  //set to be OFF at start
        catchSwitch.tag = 1;  // this is not necessary - only to find later
        [catchSwitch addTarget:self action:@selector(catchAction:) forControlEvents:UIControlEventValueChanged];
        [[[CCDirector sharedDirector] openGLView] addSubview:catchSwitch];


    }

    if (GlobalSettings.SpeedBoost == TRUE) {
        if(GlobalSettings.CatchExtender == TRUE){
            speedSwitch = [[ UISwitch alloc ] initWithFrame: CGRectMake(100, 400, 10, 10)];
            speedSwitch.center = CGPointMake(80, 450);
            CCLabelTTF *speedLabel = [CCLabelTTF labelWithString:@"Speed Enhancer" fontName:@"Chalkduster" fontSize:15];
            speedLabel.color = ccWHITE;
            speedLabel.position = CGPointMake(80, 60);
            [self addChild: speedLabel];
        }else{
            speedSwitch = [[ UISwitch alloc ] initWithFrame: CGRectMake(160, 400, 10, 10)];
            speedSwitch.center = CGPointMake(160, 450);
        }

        speedSwitch.on = NO;  //set to be OFF at start
        speedSwitch.tag = 1;  // this is not necessary - only to find later
        [speedSwitch addTarget:self action:@selector(speedAction:) forControlEvents:UIControlEventValueChanged];
        [[[CCDirector sharedDirector] openGLView] addSubview:speedSwitch];
    }

アクション:

- (void)catchAction:(id)sender
{
// Your logic when the switch it used
// NSLog(@"switchAction: value = %d", [sender isOn]);
if ([sender isOn]) {
    GlobalSettings *GlobalSettings = [SettingsParser loadData];
    GlobalSettings.CatchExtenderEnabled = TRUE;

    UIAlertView* dialog = [[UIAlertView alloc] init];
    [dialog setDelegate:self];
    [dialog setTitle:@"ON"];
    [dialog setMessage:@"Catch Extender is on"];
    [dialog addButtonWithTitle:@"Sweet!"];
    [dialog show];
    [dialog release];
    [SettingsParser saveData:GlobalSettings];

}else{
    GlobalSettings *GlobalSettings = [SettingsParser loadData];
    GlobalSettings.CatchExtenderEnabled = FALSE;
    UIAlertView* dialog = [[UIAlertView alloc] init];
    [dialog setDelegate:self];
    [dialog setTitle:@"OFF"];
    [dialog setMessage:@"Catch Extender is off"];
    [dialog addButtonWithTitle:@"Thanks"];
    [dialog show];
    [dialog release];
    [SettingsParser saveData:GlobalSettings];
}
}

- (void)speedAction:(id)sender
{
// Your logic when the switch it used
// NSLog(@"switchAction: value = %d", [sender isOn]);
if ([sender isOn]) {
    GlobalSettings *GlobalSettings = [SettingsParser loadData];
    GlobalSettings.SpeedBoostEnabled = TRUE;

    UIAlertView* dialog = [[UIAlertView alloc] init];
    [dialog setDelegate:self];
    [dialog setTitle:@"ON"];
    [dialog setMessage:@"Speed Enhancer is on"];
    [dialog addButtonWithTitle:@"Sweet!"];
    [dialog show];
    [dialog release];
    [SettingsParser saveData:GlobalSettings];

}else{
    GlobalSettings *GlobalSettings = [SettingsParser loadData];
    GlobalSettings.SpeedBoostEnabled = FALSE;
    UIAlertView* dialog = [[UIAlertView alloc] init];
    [dialog setDelegate:self];
    [dialog setTitle:@"OFF"];
    [dialog setMessage:@"Speed Enhancer is off"];
    [dialog addButtonWithTitle:@"Thanks"];
    [dialog show];
    [dialog release];
    [SettingsParser saveData:GlobalSettings];
    }
}

ゲーム レベルのデータを保持するクラスでは、これらのブール値を単純な if ステートメントで通常どおりチェックします。しかし、それは機能していないようです.ログではXMLファイルの値が変更されたように見えないため、設定が保存されていないようです..

長い投稿で申し訳ありませんが、この問題は私を悩ませています。

4

1 に答える 1

2

NSUserDefaultsこれまで Cocos2D を使用したことはありませんが、これは典型的な iOS アプリで次のように使用する場合とまったく同じように思えます。[[NSUserDefaults standardUserDefaults] setBool:YES ForKey:@"Key"];

于 2012-11-15T01:37:14.487 に答える