如何在没有Cocos2d的情况下在Xcode中为精灵表设置动画?

时间:2012-02-07 22:39:29

标签: ios xcode animation sprite

我正在开发一个简单的应用程序,在用户移动滑块时动画图像。这可以通过单个图像轻松完成,但由于显而易见的原因,该方法效率低下。

目前,我将动画分为14张精灵表,每张16张图片。我创建了一个方法,使用CGImageCreateWithImageInRect来查找滑块指示的当前图像,并使用该图像更新图像视图。这有效,但不是流畅的。我想我理解为什么,但我不知道该怎么办。虽然我可以使用Cocos2d或OpenGL ES,但我很顽固并且相信没有它们就可以实现。我只是想知道如何。

以下是一些示例代码:

- (void)setUp{

NSString *string;
NSString *bundleString = [[NSBundle mainBundle] bundlePath];
dsRedPathArray = [[NSMutableArray alloc] initWithCapacity:15];
for (int i = 0; i < 14; i++)
{
  string = [bundleString stringByAppendingFormat:@"/dsRedAni_%d.png", i];
  [dsRedPathArray addObject:string];
}

//initial image starts at (0, 1) of image dsRedAni_9
currentImage = [UIImage imageWithContentsOfFile:[dsRedPathArray objectAtIndex:9]];  
currentRef = CGImageCreateWithImageInRect(currentImage.CGImage, CGRectMake(495, 0,     kModelWidth, kModelHeight));   

modelView.image = [UIImage imageWithCGImage:currentRef];
 }

- (IBAction)sliderMoved:(UISlider*)sender
{
  [self animateModel:sender.value];
}

- (void)animateModel:(int)index
{
  index += 1;
  imageIndex = (index / 16) + 9;
  if (imageIndex > 13)
  {
    imageIndex = -14 + imageIndex;
  }
  currentX = kModelWidth * (index % 4);
  currentY = kModelHeight * ((index / 4) % 4);

  currentRect = CGRectMake(currentX, currentY, kModelWidth, kModelHeight);
  currentImage = [UIImage imageWithContentsOfFile:[dsRedPathArray objectAtIndex: (imageIndex)]];    
  currentRef = CGImageCreateWithImageInRect(currentImage.CGImage, currentRect);

  modelView.image = [UIImage imageWithCGImage:currentRef];
}

提前感谢您的帮助。

2 个答案:

答案 0 :(得分:4)

我终于找到了一种非常快速和有效的,如果非传统的方式,在没有API的任何外部帮助的情况下循环我的精灵表的每个部分。我没有花费时间和精力将图像切割成上下文或单个文件,而是发现以我所需的图像大小创建UIView然后将整个sprite表作为UIImageView添加到视图中更有效率。 。

当view.clipsToBounds设置为YES时,视图充当我的精灵表的掩码,将可见部分限制为我想在工作表上循环的每个图像的大小。为了给出动画的效果,我只需使用imageview.center将视图周围的精灵表移动到所需的图像坐标。因此,在一张包含16张图像的精灵表中,我只需要进行一次调用即可显示图像,然后在动画中的每一帧中移动它。

- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
  [self setUp];
  self.backgroundColor = [UIColor clearColor];
  self.clipsToBounds = YES;
}
return self;
}

- (void)setUp
{
  //assign |lastImageIndex| a number not equal to |imageIndex|
  lastImageIndex = -1;

  modelImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 1924, 1708)];

  NSString *string;
  NSString *bundleString = [[NSBundle mainBundle] bundlePath];
  UIImage *image;
  if (!imageArray)
  {
    imageArray = [[NSMutableArray alloc] init];
    NSLog(@"Init egfp |imageArray|");
  }

  for (int i = 0; i < 10; i++)
  {
    string = [bundleString stringByAppendingFormat:@"/moleculeAni_%d.png", i];
    image = [UIImage imageWithContentsOfFile:string];
    [imageArray addObject:image];
    if (i == 9)
    {
      NSLog(@"Filled egfp |imageCache|");
    }
  }

  [self addSubview:modelImageView];  
}

- (void)animateModel:(int)index
{
  if (index != 1)
  {
   index -= 1;
  }
  imageIndex = (index / 16);

  if (imageIndex < 9)
  {
    currentX = 962 - (481 * (index % 4));
    currentY = 854 - (427 * ((index / 4) % 4));
  }
  else
  {
    currentX = 962 - (481 * (index % 4));
    currentY = 427 - (427 * ((index / 4) % 4));
  }

  if (imageIndex != lastImageIndex)
  {
    if (imageIndex < 9 && onLastFrame)
    {
      modelImageView.frame = CGRectMake(0, 0, 1924, 1708);
      onLastFrame = NO;
    }
    else if (imageIndex == 9 && !onLastFrame)
    {
      modelImageView.frame = CGRectMake(0, 0, 1924, 854);
      onLastFrame = YES;
    }


    NSLog(@"Image: %d", imageIndex);
    tempImage = [imageArray objectAtIndex:imageIndex];
    modelImageView.image = tempImage;
  }

  modelImageView.center = CGPointMake(currentX, currentY);

  lastImageIndex = imageIndex;
}

此处的大部分代码用于确定imageview需要移动的位置以显示正确的图像。这是采用我上面解释的方法,并将其分布在10个精灵表中,每个精灵表均匀分布16个图像(除了最后一个有8个)。当程序每隔16帧在图像之间交换时,唯一的减速就出现了。为了解决这个问题,我的控制器可以快速浏览另一个视图下方的所有图像(如窗帘),因此用户只能访问加载屏幕。图像循环后,窗帘视图将被移除,动画(由带滑块的用户控制)会像黄油一样移动。

答案 1 :(得分:2)

执行此操作的一种方法是使用CGImageCreateWithImageInRect剪切图像,就像您从上面开始一样。然后,将它们添加到数组中:

myArray addObject:[UIImage imageWithCGImage:currentRef];

接下来使用带有setAnimationImages的UIImageView,如下所示:

UIImageView *myAnimationImageView;
[myAnimationImageView setAnimationImages:myArray];

然后你可以开始动画了。

这里有一个很好的项目:https://github.com/r3econ/UIImage-Sprite-Additions