0

アプリのレンダリングループを特定の方法で整理する必要があります(理由があります)。

私が持っているとしましょう

Sprite *sprite = [[Sprite alloc] initWithContentsOfFile:@"sprite.png"]; // some sprite

while (true) {
    [Graphics update];
    sprite.x = (sprite.x + 1) % 1024 // moving sprite by one pixel each frame
    [Input update];
    [self update];
}

Graphics.updateは、1つのフレームをレンダリングし、次のフレームまで実行を遅らせる必要があります(レンダリングではありません)。

@interface Graphics () {
    static BOOL _frozen;
    static int _count;
    static int _frameCount;
    static float _frameRate;
    static double _lastFrameTimestamp;
}

@end

@implementation Graphics

+ (void)initialize {
    _frozen = NO
    _count = 0
    _frameCount = 0
    _frameRate = 30.0
    _lastFrameTimestamp = CACurrentMediaTime()
}

+ (void)freeze {
    _frozen = YES;
}

+ (void)update {
    if _frozen
      return
    end

    Video.nextFrame // some OpenGL ES magic to render next frame

    _count++

    now = CACurrentMediaTime()
    waitTill = _lastFrameTimestamp + _count * (1.0 / _frameRate)

    if now <= waitTill
      sleep(waitTill - now)
    else
      _count = 0
      _lastFrameTimestamp = CACurrentMediaTime()
    end

    _frameCount++
}

@end

どういうわけかそれは動作し、スプライトは動いています。しかし、ホームに行くとapplicationWillResignActiveが呼び出されず、アプリに戻ると黒い画面が表示され、しばらくするとアプリがクラッシュします。

これが私が移植しようとしていることです:https ://bitbucket.org/lukas/openrgss/src/7d9228cc281207fe00a99f63b507198ea2596ead/src/graphics.c (Graphics_update関数)

4

2 に答える 2

2

whileループの代わりにCoreAnimationDisplayLinkを使用してみることができます。これは、グラフィックスフレームワークで通常行われる方法です。currentRunLoopは、1/60秒ごとにupdateメソッドを呼び出します。

NSRunLoopを使用している場合は、アップデートでスリープ呼び出しを削除する必要があります。

CADisplayLink *displayLink;

// Set your update method
displayLink = [CADisplayLink displayLinkWithTarget:[Graphics class] 
                                          selector:@selector(update)];
// Set fps to device refresh rate (60)
[displayLink setFrameInterval:1.0f];

// Add your display link to current run loop
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

// Stop updating
[displayLink invalidate];

最後の行は実行を停止するので、ループが完了するまでそれを呼び出さないでください。

于 2013-01-03T10:32:37.770 に答える
1

Sparrowを使用している場合は、次のように処理する必要があります。

SPSprite *sprite = [[SPSprite alloc] initWithContentsOfFile:@"sprite.png"]; // some sprite

[self addEventListener:@selector(enterFrame:) atObject:self forType:SP_EVENT_TYPE_ENTER_FRAME];

-(void)enterFrame:(SPEnterFrameEvent*)e {
    [Graphics update];
    sprite.x += 1; // moving sprite by one pixel each frame
    [Input update];
    [self update];
}

Sparrowは、SP_ENTER_FRAME_EVENTを使用してゲームループを管理します。再度レンダリングするたびに呼び出されます。1秒間に約30回(構成は可能ですが)。

于 2013-01-20T17:27:09.517 に答える