views:

545

answers:

2

I am trying to code a global lookup table of sorts.

I have game data that is stored in character/string format in a plist, but which needs to be in integer/id format when it is loaded.

For instance, in the level data file, a "p" means player. In the game code a player is represented as the integer 1. This let's me do some bitwise operations, etc. I am simplifying greatly here, but trying to get the point across. Also, there is a conversion to coordinates for the sprite on a sprite sheet.

Right now this string->integer, integer->string, integer->coordinate, etc. conversion is taking place in several places in code using a case statement. This stinks, of course, and I would rather do it with a dictionary lookup.

I created a class called levelInfo, and want to define the dictionary for this conversion, and then class methods to call when I need to do a conversion, or otherwise deal with level data.

NSString *levelObjects = @"empty,player,object,thing,doohickey";
int levelIDs[] = [0,1,2,4,8];
// etc etc

@implementation LevelInfo

+(int) crateIDfromChar: (char) crateChar {
    int idx = [[crateTypes componentsSeparatedByString:@","] indexOfObject: crateChar];
    return levelIDs[idx];
}

+(NSString *) crateStringFromID: (int) crateID {
    return [[crateTypes componentsSeparatedByString:@","] objectAtIndex: crateID];
}

@end

Is there a better way to do this? It feels wrong to basically build these temporary arrays, or dictionaries, or whatever for each call to do this translation. And I don't know of a way to declare a constant NSArray or NSDictionary.

Please, tell me a better way....

+1  A: 

Declare it static so it only needs to be created once.

Chuck
+3  A: 

If you want an array to be available to all the code in your class, just declare it outside the @implementation context, and then initialize it in your class's +initialize method.

NSArray *levelObjects;

@implementation LevelInfo

+ (void) initialize
 {
 if (!levelObjects)
   levelObjects = [[NSArray alloc]
    initWithObjects:@"empty",@"player",@"object",@"thing",@"doohickey",nil];
 }

// now any other code in this file can use "levelObjects"

@end
NSResponder
Ah, so `+initialize` initializes class-level content? It is called once I assume?
Jeff B
Yes; it is equivalent to init, but for classes. It is conventional to check the class in the initialize call, to prevent subclasses from resetting your class variables. The above code should be safe from that.
Paul Lynch
Thanks. Sometimes googling is hard when you don't know what to google for.
Jeff B
Don't depend on +initialize only being sent once. Code defensively; that's why I have the if (!levelObjects) test in there.
NSResponder