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(1フレームあたり16.7ミリ秒)よりも頻繁に表示されることはありません。私が見ているように、ここには少なくとも2つのオプションがあります。

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 に答える