views:

98

answers:

2

Gday, I am trying to create a tiled map for my game, i have had this previously working using other xml methods but i had memory leaks and all sorts of errors. However i had a map load time of about 2.5 - 3 seconds.

So i rewrote all of the code using NSMutableStrings and NSStrings. After my best attempt at optomizing it i had a map load time of 10 - 11 seconds, which is far too slow.

So i have now rewritten the code using char* arrays, only to now have a load time of 18 seconds -_-.

Here is the latest code, i don't know much c so i could have easily botched the whole thing up.

  FILE* file = fopen(a, "r");
  fseek(file, 0L, SEEK_END);
  length = ftell(file);
  fseek(file,0L, SEEK_SET);
  char fileText[length +1];

  char buffer[1024];// = malloc(1024);
  while(fgets(buffer, 1024, file) != NULL)
  {
        strncat(fileText, buffer, strlen(buffer));
  }
  fclose(file);
  [self parseMapFile:fileText];




- (void)parseMapFile:(char*)tiledXML
{


      currentLayerID = 0;
      currentTileSetID = 0;
      tileX = 0;
      tileY = 0;

      int tmpGid;
      NSString* tmpName;
      int tmpTileWidth;
      int tmpTileHeight;
      int tilesetCounter = 0;

      NSString* tmpLayerName;
      int tmpLayerHeight;
      int tmpLayerWidth;
      int layerCounter = 0;
      tileX = 0;
      tileY = 0;
      int tmpFirstGid = 0;


      int x;
      int index;
      char* r;
      int counter = 0;
      while ((x = [self findSubstring:tiledXML substring:"\n"]) != 0)
      {
            counter ++;
            char result[x + 1];
            r = &result[0];
            [self substringIndex:tiledXML index:x newArray:result];
            tiledXML += x+2;
            index = 0;

            if (counter == 1)
            {
                  continue;
            }
            else if (counter == 2)
            {
                  char result1[5];
                  index = [self getStringBetweenStrings:r substring1:"th=\"" substring2:"\"" newArray:result1];
                  if (r != 0);
                        mapWidth = atoi(result1);

                  r += index +1;
                  index = 0;
                  index = [self getStringBetweenStrings:r substring1:"ht=\"" substring2:"\"" newArray:result1];
                  if (r != 0);
                        mapHeight = atoi(result1);

                  r += index +1;
                  index = 0;
                  index = [self getStringBetweenStrings:r substring1:"th=\"" substring2:"\"" newArray:result1];
                  if (r != 0);
                        tileWidth = atoi(result1);

                  r += index +1;
                  index = 0;
                  index = [self getStringBetweenStrings:r substring1:"ht=\"" substring2:"\"" newArray:result1];
                  if (r != 0);
                        tileHeight = atoi(result1);

                  continue;

            }

            char result2[50];
            char result3[3];

            if ((index = [self getStringBetweenStrings:r substring1:" gid=\"" substring2:"\"" newArray:result3]) != 0)
            {

                  tmpGid = atoi(result3);

                  if(tmpGid == 0)
                  {
                        [currentLayer addTileAtX:tileX y:tileY tileSetID:-1 tileID:0 globalID:0];
                  } 
                  else
                  {
                        [currentLayer addTileAtX:tileX 
                              y:tileY 
                              tileSetID:[currentTileSet tileSetID] 
                              tileID:tmpGid - [currentTileSet firstGID] 
                              globalID:tmpGid];
                 }               
                  tileX ++;

                  if (tileX > [currentLayer layerWidth]-1)
                  {
                        tileY ++;
                        tileX = 0;
                  }



            }
            else if ((index = [self getStringBetweenStrings:r substring1:"tgid=\"" substring2:"\"" newArray:result2]) != 0)
            {

                  tmpFirstGid = atoi(result2);

                  r += index +1;
                  index = 0;
                  index = [self getStringBetweenStrings:r substring1:"me=\"" substring2:"\"" newArray:result2];
                  if (r != 0);
                        tmpName = [NSString stringWithUTF8String:result2];


                  r += index +1;
                  index = 0;
                  index = [self getStringBetweenStrings:r substring1:"th=\"" substring2:"\"" newArray:result2];
                  if (r != 0);
                   tmpTileWidth = atoi(result2);


                  r += index +1;
                  index = 0;
                  index = [self getStringBetweenStrings:r substring1:"ht=\"" substring2:"\"" newArray:result2];
                  if (r != 0);
                        tmpTileHeight = atoi(result2);

            }
            else if ((index = [self getStringBetweenStrings:r substring1:"rce=\"" substring2:"\"" newArray:result2]) != 0)
            {


                   currentTileSet = [[TileSet alloc] initWithImageNamed:[NSString stringWithUTF8String:result2] name:tmpName tileSetID:tilesetCounter firstGID:tmpFirstGid tileWidth:tmpTileWidth tileHeight:tmpTileHeight spacing:0];
                   [tileSets addObject:currentTileSet];
                   [currentTileSet release];
                   tilesetCounter ++;


            }
            else if ((index = [self getStringBetweenStrings:r substring1:"r name=\"" substring2:"\"" newArray:result2]) != 0)
            {

                  tileX = 0;
                  tileY = 0;

                  tmpLayerName = [NSString stringWithUTF8String:result2];

                  r += index +1;
                  index = 0;
                  index = [self getStringBetweenStrings:r substring1:"th=\"" substring2:"\"" newArray:result2];
                  if (r != 0);
                        tmpLayerWidth = atoi(result2);


                  r += index +1;
                  index = 0;
                  index = [self getStringBetweenStrings:r substring1:"ht=\"" substring2:"\"" newArray:result2];
                  if (r != 0);
                        tmpLayerHeight = atoi(result2);

                  currentLayer = [[Layer alloc] initWithName:tmpLayerName layerID:layerCounter layerWidth:tmpLayerWidth layerHeight:tmpLayerHeight];
                  [layers addObject:currentLayer];
                  [currentLayer release];
                  layerCounter ++;

            }


      }







}




-(void)substringIndex:(char*)c index:(int)x newArray:(char*)result
{
      result[0] = 0;
      for (int i = 0; i < strlen(c); i++)
      {
            result[i] = c[i];
            if (i == x)
            {
                  result[i+1] = '\0';
                  break;

            }

      } 
}


-(int)findSubstring:(char*)c substring:(char*)s
{
      int sCounter = 0;
      int index = 0;

      int d;
      for (int i = 0; i < strlen(c); i ++)
      {
            if (i > 500)//max line size
                  break;
            if (c[i] == s[sCounter])
            {
                  d = strlen(s);
                  sCounter ++;

                  if (d > sCounter)
                  {

                  }
                  else
                  {
                        index = i - (d);
                        break;
                  }
            }
            else
                  sCounter = 0;

       }
                return index;


 }

-(int)getStringBetweenStrings:(char*)c substring1:(char*)s substring2:(char*)s2 newArray:(char*)result
{
      int sCounter = 0;
      int sCounter2 = 0;
      int index = 0;
      int index2 = 0;

      int d;
      for (int i = 0; i < strlen(c); i ++)
      {

            if (index != 0)
            {
                  if (c[i] == s2[sCounter2])
                  {
                        d = strlen(s2);
                        sCounter2 ++;

                        if (d > sCounter2)
                        {

                        }
                        else
                        {
                              index2 = i - (d);
                              break;
                        }
                  }
                  else
                       sCounter2 = 0;


             }
             else
             {
                   if (c[i] == s[sCounter])
                   {
                        d = strlen(s);
                        sCounter ++;

                        if (d > sCounter)
                        {

                        }
                        else
                        {
                              index = i;

                        }
                  }
                  else
                        sCounter = 0;

            }

      }
      if (index != 0 && index2 != 0)
            [self substringIndex:(c + index+1) index:index2-index-1 newArray:result];

 return index;
}

(I know it's a lot of code to be putting in here) I thought the by using basic char arrays i could drastically increase the performance, at least over the initial node based code that i was replacing.

Thanks for all your efforts.

+1  A: 

It looks like you are scanning the entire array each time you're looking for a newline rather than starting where you left off?

Try using strtok, which does this for you.

Derrick Johnson
+1  A: 

I'd highly recommend going back and using NSXMLParser, or if you have to roll your own use libxml or something like that. XML parsers are non-trivial and very much solved. If you're having memory leaks, there are plenty of tools in Xcode that can help you track that down.

Your other alternatives are using property lists, which can be binary serialised, or CoreData.

Benno