2012-02-20 12 views
14

Tengo una animación que consta de 100 imágenes. Quiero poder mostrar la animación a través de una secuencia de cuadros. Por ejemplo, en lugar de mostrar la animación de 0:00 segundos a 0:32 segundos, prefiero usar el Marco 0 al Cuadro 32. Necesito hacer esto porque necesito MUCHO control sobre la animación (incluso la diferencia de uno) el marco crearía el resultado incorrecto). Dibujé cada fotograma personalmente, así que sé la imagen de cada fotograma.¿Mostrando animación por cuadro?

¿De todos modos puedo hacer esto en Cocoa, usando Objective-C? ¿Cómo haría esto? Todo lo que tengo son 100 imágenes y no tengo idea de cómo proceder desde aquí. Y también, ¿sería esto "laggy" en comparación con especificar por tiempo?

Preferiría una respuesta detallada porque no pude encontrar ningún recurso en línea y soy completamente nuevo en esto.

Tenga en cuenta que estoy utilizando OS X, no iOS, así que no proporcione respuestas relacionadas con iOS. Estoy trabajando con Xcode 3.2.6 en Snow Leopard.

Respuesta

7

La manera de tener el mayor control sería almacenar todas sus imágenes en una matriz. Si usted nombró sus imágenes algo así como "frame.png" (es decir, "frame1.png"), puede cargar rápidamente todas sus imágenes como esta:

frames = [[NSMutableArray alloc] init]; // In header: NSMutableArray *frames; 
for (int i = 1; i < 100; i++) // 100 can be replaced for any number of frames. 
{ 
    NSString *filename = [NSString stringWithFormat:@"frame%i.png", i]; 
    [frames addObject:[NSImage imageNamed:filename]]; 
} 

Lo que esto hace es crea una matriz y la llena de NSImage s nombrado después de sus archivos. El %i se sustituye en la cadena por el valor actual de i.

Ahora, necesitará otra variable para realizar un seguimiento del marco actual. Algo así como . Esto puede aumentarse en cada bucle de actualización o establecerse en un valor específico, lo que le proporciona un control completo sobre el fotograma mostrado.

Luego, en su bucle de render, que puede hacer que lo que el marco se almacena actualmente como esto:

[(NSImage *)[frames objectAtIndex:currentFrame - 1] drawAtPoint:animPos fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0f]; 

donde animPos es un NSPoint que contiene la posición que desea llamar al. El - 1 está en el índice, por lo que puede consultar sus cuadros comenzando por 1 en lugar de 0. Este código extrae la imagen en el cuadro currentFrame y la muestra en la pantalla.

Dado que está utilizando una matriz, también asegúrese de comprobar currentFrame nunca es igual a un valor mayor que el número máximo de marcos, algo así como: if (currentFrame > 100) currentFrame = 1;. Esto provocaría que la animación se repitiera, ya que cuando llega al último cuadro, el marco actual se volvería a establecer en el índice inicial de la matriz. Para obtener más información sobre el dibujo, debe consultar: Cocoa Drawing Guide y NSImage Class Reference. Además, si necesita más información sobre cómo actualizar el marco cada incremento de tiempo, consulte NSTimer Class Reference.

+0

¿Dónde iría el código de bucle de renderizado? ¿A qué clase me refiero? ¿Sería un NSImageView? – fdh

+0

el código 'drawAtPoint:' puede ir en cualquier clase que desee. No es necesario que se realice dentro de un NSImageView, y puede mostrarse en cualquier lugar de la ventana, incluso sin vistas. Si no tiene muchas clases, puede ser más fácil dejarlo en el delegado de la aplicación. Sin embargo, si desea usar un NSImageView, puede usar '[NSImageView setImage: (NSImage *) [frames objectAtIndex: currentFrame - 1]]' en lugar de 'drawAtPoint' y permita que la vista maneje la representación, el posicionamiento, etc. – wquist

+0

Gracias ¡Tú, funciona! – fdh

0

Ha intentado crear subclases NSAnimation, y tener que cambiar la imagen que se muestra cada pulso?

EDIT:

En primer lugar, se crea una subclase de NSAnimation. A continuación, anule setCurrentProgress: llamando a su implementación de superclase, y haga que cambie la vista según currentValue. Consulte la siguiente guía para más instrucciones detalladas: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/AnimationGuide/Articles/TimingAnimations.html#//apple_ref/doc/uid/TP40003581-SW1

+0

¿Podrías ampliar? ¿Cómo haría esto? Nunca he trabajado con NSAnimation antes. – fdh

+0

Es un proceso bastante simple, explicado claramente en la documentación para NSAnimation. Ver mi edición para más detalles. – Daniel

+0

¿Alguien sabe por qué todas estas respuestas fueron downvoted? – Daniel

2

Usted puede utilizar este código para su cuadro por cuadro de animación. Espero que esto te ayudará.

// create the view that will execute our animation 
UIImageView* imageListView = [[UIImageView alloc] initWithFrame:self.view.frame]; 

// load all the frames of our animation 
imageListView.animationImages = [NSArray arrayWithObjects:  
          [UIImage imageNamed:@"campFire01.gif"], 
          [UIImage imageNamed:@"campFire02.gif"], 
          [UIImage imageNamed:@"campFire03.gif"], 
          [UIImage imageNamed:@"campFire04.gif"], 
          [UIImage imageNamed:@"campFire05.gif"], 
          [UIImage imageNamed:@"campFire06.gif"], 
          [UIImage imageNamed:@"campFire07.gif"], 
          [UIImage imageNamed:@"campFire08.gif"], 
          [UIImage imageNamed:@"campFire09.gif"], 
          [UIImage imageNamed:@"campFire10.gif"], 
          [UIImage imageNamed:@"campFire11.gif"], 
          [UIImage imageNamed:@"campFire12.gif"], 
          [UIImage imageNamed:@"campFire13.gif"], 
          [UIImage imageNamed:@"campFire14.gif"], 
          [UIImage imageNamed:@"campFire15.gif"], 
          [UIImage imageNamed:@"campFire16.gif"], 
          [UIImage imageNamed:@"campFire17.gif"], 
           //all your 100 images// , nil]; 

// all frames will execute in 1.75 seconds 
imageListView.animationDuration = 1.75; 
// repeat the annimation forever 
imageListView.animationRepeatCount = 0; 
// start animating 
[imageListView startAnimating]; 
// add the animation view to the main window 
[self.view addSubview:imageListView]; 
+1

Esto solo funciona en iOS, la pregunta es sobre OS X. –

1

Puede considerar el uso de CADisplayLink. He aquí un ejemplo de cómo se usa:

En su método de inicialización, la configuración de visualización de enlace:

CADisplayLink* displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(playAnimation:)]; 
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];  

A continuación, agregue el método:

- (void)playAnimation:(CADisplayLink*)displayLink 
{ 
    // Set the right image to display 
    self.imageToDisplay = TheRightImageBasedOnYourAnimationSequence 

    [self setNeedsDisplay]; 
} 

Y por último, en el drawRect: Método , muestra la imagen. La clase ha CADisplayLink atributos para controlar la duración de las imágenes, etc ...

1

Reiterar la respuesta de @ wquist: -

frames = [[NSMutableArray alloc] init]; // In header: NSMutableArray *frames; 
for (int i = 1; i < 100; i++) // 100 can be replaced for any number of frames. 
{ 
    NSString *filename = [NSString stringWithFormat:@"frame%i.png", i]; 
    [frames addObject:[NSImage imageNamed:filename]]; 
} 

En el pasado he tenido una serie de animaciones con nombres tales como image_00000.png , image_00001.png y para cuidarlos usé algo como esto: -

NSString *filename = [NSString stringWithFormat:@"frame%05d.png", i]; 
Cuestiones relacionadas