1

我有一些动画需要在非常特定的时间出现在屏幕上,这些动画存储在 SQLite 数据库中。我打算做的是使用 nstimer 来保持时间并在达到特定时间时弹出动画。

我正在考虑使用 NSTimer 来计算声音文件和动画的持续时间,然后在达到某些点时弹出屏幕动画。问题是设置的时间是这样的 55.715000 秒,所以非常准确,这些需要与将与动画一起播放的音轨同步。

首先这是否可能,其次我如何比较这些特定的时间,我似乎面临的问题是代码运行不够快,时间跳跃超过 0.001 秒。

我不了解 openGLES 或 Cocos2d,学习这些在时间尺度上是不可行的。

4

2 回答 2

2

如果您的视觉效果需要与音频完全同步(例如,动画必须出现在节拍上的音乐应用程序),那么您需要使用以下方法。它适用于非常旧的 iPhone 硬件,并且在运行时基本上不会出错。

  1. 预渲染视觉效果的每个“帧”,以便将每个“帧”存储为全屏图像。这可以在桌面上完成,或者您可以在手机上运行渲染逻辑,然后将输出作为像素捕获到文件中。

  2. 将每一帧保存为像素数组后,通过 iOS 上的标准 AVAudioPlayer API 播放音频。此 API 负责音频播放并报告您将用来确定要显示哪个视频帧的时间。

  3. 播放音频后,获取“时间”并将其除以视频帧率,以确定要显示的 N 个图像数组中的哪个图像。获取图像数据并将其包装在 CGImageRef/UIImage 中,这将以最佳方式将图像数据传输到屏幕上。

如果您想查看此方法的有效源代码,请查看AVSync。此示例代码显示了我在应用商店中名为 iPractice 的应用中使用的实现。它非常快,即使在旧 iPhone 3G 上也能以 30FPS 运行。

于 2013-06-15T21:19:17.620 回答
0

无论您的计时有多准确,您都不会让设备的显示频率超过大约 60Hz(每帧 16.7 毫秒)。在我看来,您至少有两个选择:

1)使用CADisplayLink回调检查音频的播放进度,并在每个动画及时触发。

显示链接计时器的创建方式与常规类似NSTimers

-(void)viewDidLoad
{
    // ...
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(scheduleAnimations:)];
    [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)scheduleAnimations:(CADisplayLink *)displayLink
{
    // get playback time from player object
    // iterate queue of timings
    //     if the timestamp of a timing is equal to or less than the playback time
    //         create its animation for immediate execution
    //         remove it from the queue
}

2)创建动画集合,将它们各自的beginTime属性设置为适当的触发时间(或者,如果使用隐式或基于块的动画,则使用delay参数)。

[CATransaction begin];
// iterate collection of timings
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"key"];
    animation.startTime = /* time to trigger animation */
    animation.removedOnCompletion = NO;
    [layer addAnimation:animation forKey:nil];
[CATransaction commit];
于 2012-12-07T19:32:48.203 回答