2009-05-21 9 views
2

Je travaille actuellement sur un jeu iPhone et j'ai besoin de créer de l'animation à la volée. L'animation est basée sur plusieurs images, et comme la gamme de combinaisons d'images est trop grande et qu'il est impossible de pré-créer toutes les séquences, j'aimerais pouvoir recalculer un ensemble d'images chaque fois que la situation change.La mémoire fuit dans la fonction de création d'image

La fonction crée une série d'images à utiliser comme séquence d'animation. J'ai besoin d'aide avec deux choses:

  1. Il y a plusieurs grandes fuites de mémoire que je vais avoir du mal à trouver - je besoin d'aide pour les localiser
  2. Depuis que je suis nouveau à l'iPhone, je veux savoir si est une meilleure façon de le faire, si vous avez une meilleure idée sur la façon de l'écrire, s'il vous plaît partager ...

code:

(void) updateImages:(int) smallPicID 
{ 
    CGRect smallPicRect; 
    smallPicRect.size = CGSizeMake(25.0f, 25.0f); 

    //TODO: add smallPic location for every image. Currently the values only match the first image... 
    static const CGPoint smallPicLocation[11][SMALLPIC_LOCATION_COUNT] = 
    { 
     { {126.0f, 153.0f},{105.0f, 176.0f}, {115.0f, 205.0f}, {145.0f, 211.0f}, {166.0f, 188.0f}, {156.0f, 159.0f} }, 
     { {183.0f, 91.0f}, {201.0f, 97.0f}, {205.0f, 115.0f}, {191.0f, 127.0f}, {173.0f, 122.0f}, {169.0f, 124.0f} }, 
     { {183.0f, 91.0f}, {201.0f, 97.0f}, {205.0f, 115.0f}, {191.0f, 127.0f}, {173.0f, 122.0f}, {169.0f, 124.0f} }, 
     { {183.0f, 91.0f}, {201.0f, 97.0f}, {205.0f, 115.0f}, {191.0f, 127.0f}, {173.0f, 122.0f}, {169.0f, 124.0f} }, 
     { {183.0f, 91.0f}, {201.0f, 97.0f}, {205.0f, 115.0f}, {191.0f, 127.0f}, {173.0f, 122.0f}, {169.0f, 124.0f} }, 
     { {183.0f, 91.0f}, {201.0f, 97.0f}, {205.0f, 115.0f}, {191.0f, 127.0f}, {173.0f, 122.0f}, {169.0f, 124.0f} }, 
     { {183.0f, 91.0f}, {201.0f, 97.0f}, {205.0f, 115.0f}, {191.0f, 127.0f}, {173.0f, 122.0f}, {169.0f, 124.0f} }, 
     { {183.0f, 91.0f}, {201.0f, 97.0f}, {205.0f, 115.0f}, {191.0f, 127.0f}, {173.0f, 122.0f}, {169.0f, 124.0f} }, 
     { {183.0f, 91.0f}, {201.0f, 97.0f}, {205.0f, 115.0f}, {191.0f, 127.0f}, {173.0f, 122.0f}, {169.0f, 124.0f} }, 
     { {183.0f, 91.0f}, {201.0f, 97.0f}, {205.0f, 115.0f}, {191.0f, 127.0f}, {173.0f, 122.0f}, {169.0f, 124.0f} }, 
     { {183.0f, 91.0f}, {201.0f, 97.0f}, {205.0f, 115.0f}, {191.0f, 127.0f}, {173.0f, 122.0f}, {169.0f, 124.0f} } 
    }; 

    for(int i = 0; i < self.m_finalImages.count; ++i) 
    { 
     // start with base image 
     UIImage * baseImg = [self.m_finalImagesEmpty objectAtIndex:i]; 
     CGImageRef baseImgCtx = baseImg.CGImage; 

     // Create the bitmap context that matches the baseImg parameters 
     CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
     CGContextRef newImgCtx = CGBitmapContextCreate(NULL, 
                 CGImageGetWidth(baseImgCtx), 
                 CGImageGetHeight(baseImgCtx), 
                 8, 0, colorSpace, 
                 (kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst)); 
     CGColorSpaceRelease(colorSpace); 

     if (newImgCtx == NULL) 
     { 
      // error creating context 
      assert(0); 
      return; 
     } 

     // Get empty drum image width, height. 
     size_t w = CGImageGetWidth(baseImgCtx); 
     size_t h = CGImageGetHeight(baseImgCtx); 
     CGRect rect = {{0,0},{w,h}}; 

     // Draw the image to the bitmap context. 
     // newImgCtx now contains the full empty drum image. 
     CGContextDrawImage(newImgCtx, rect, baseImgCtx); 

     CGContextSaveGState(newImgCtx); 
     // translate & scale because of origin difference between UIKit and CG 
     CGContextTranslateCTM(newImgCtx, 0, h); 
     CGContextScaleCTM(newImgCtx, 1, -1); 

     int startLocation = 0; 
     int endLocation = SMALLPIC_LOCATION_COUNT; 

     // for each location 
     for(int j = startLocation; j < endLocation; j++) 
     { 
      // if its empty, nothing to do, move to next bullet 
      if (m_locationStatus[j] == CY_EMPTY) 
       continue; 

      UIImage * srcImg; 
      switch (m_locationStatus[j]) 
      { 
       case CY_FULL: srcImg = [self.m_finalImagesLoaded objectAtIndex:i]; break; 
       case CY_USED: srcImg = [self.m_finalImagesSpent objectAtIndex:i]; break; 
      } 

      // create small image containing only the smallpic from the src img 
      smallPicRect.origin = smallPicLocation[i][j]; 
      CGImageRef smallpicCGImg = CGImageCreateWithImageInRect(srcImg.CGImage, smallPicRect); 

      // draw the smallpic into the new context 
      CGContextDrawImage(newImgCtx, smallPicRect, smallpicCGImg);   

      CGImageRelease(smallpicCGImg); 
     } 

     CGContextRestoreGState(newImgCtx); 

     // update the image from the context 
     UIImage *baseImg = [self.m_finalImages objectAtIndex:i]; 
     CGImageRef imgref = CGBitmapContextCreateImage(newImgCtx); 
     //[baseImg release]; 
     [baseImg initWithCGImage:imgref]; 

     CGContextRelease(newImgCtx); 
    } 
} 
+0

Voici un fil de discussion connexe sur le site d'Apple: http://discussions.apple.com/thread.jspa?threadID=1664673 – Demi

Répondre

2

les premières choses qui sautent à moi sont les création d'imgref à proximité la fin avec un CGBitmapContextCreateImage(), mais pas de CGImageRelease() correspondant, et le message initWithCGImage: baseImg qui ne fait que mâcher de la mémoire. Je pense que vous voulez remplacer la section commençant par « mettre à jour l'image du contexte » avec quelque chose comme:

CGImageRef imgref = CGBitmapContextCreateImage(newImgCtx); 
UIImage *replacmentBaseImg = [[UIImage alloc] initWithCGImage:imgref]; 
CGImageRelease(imgref); 

[self.m_finalImages replaceObjectAtIndex:i withObject:replacementBaseImg]; 
[replacementBaseImg release]; 

CGContextRelease(newImgCtx); 

Cela suppose que m_finalImages est un NSMutableArray et que vous avez correctement vos autres images libéré qui ont été insérées dans ce tableau, de sorte que lorsque vous les remplacez, ils sont désaffectés. Sur une note de structure plus importante, vous pouvez souhaiter dessiner vos sous-images plus petites dans CALayers individuels, puis les permuter dans et hors de l'écran aux différents emplacements pour accomplir votre animation. Le dessin au quartz est coûteux et les calayers sont des images mises en cache stockées sous forme de textures sur le GPU. D'autres personnes ont effectué ces animations basées sur sprites en utilisant CALayers et ont obtenu des performances impressionnantes.