简体   繁体   English

帧速率受到CADisplayLink和drawRect的影响

[英]Frame rate compromised with CADisplayLink and drawRect

My question is about iOS development. 我的问题是关于iOS开发。 I am writing a simple game in order to test the low level Core Graphics functions (contexts, layers, etc) and how to mix it with actual simple views... I explain it: I have a simple sprite in the screen, it is animated with the UIImageView properties, so the frame rate works perfectly. 我正在编写一个简单的游戏,以测试低级Core Graphics函数(上下文,图层等)以及如何将它与实际的简单视图混合...我解释一下:我在屏幕上有一个简单的精灵,它是使用UIImageView属性进行动画处理,因此帧速率非常有效。 After that, I added an infinite background that is being generated on the fly with bezier curves . 在那之后,我添加了一个无限的背景,它正在使用bezier curves生成。 To animate this, I use a CADisplayLink , calling a method "animate" on the background, that moves my points on the bezier curve , and then I call setNeedsDisplay . 为了制作动画,我使用CADisplayLink ,在背景上调用方法"animate" ,在bezier curve上移动我的点,然后调用setNeedsDisplay It works "more or less" well, but if I remove the background (or the setNeedsDisplay calling, so it does not get regenerated every frame) the frame rate increases a lot, so "anything" is not working correctly in this part... 它工作“或多或少”很好,但如果我删除背景(或setNeedsDisplay调用,因此它不会每帧重新生成)帧速率会增加很多,所以“任何东西”在这部分中无法正常工作。 。

I have also tried a double buffering system, but it works worse than my current code. 我也尝试了一个双缓冲系统,但它比我目前的代码更糟糕。 I though about using a thread too, but I really don't find anything hard for CPU to do on background. 我虽然也使用了一个线程,但我真的没有找到任何难以让CPU在后台做的事情。

Here is the code: 这是代码:

//This is called automatically with CADDisplayLink.
- (void) animate:(CADisplayLink *)sender
{
    //Check for deleting the first point.
    float x = points[firstPoint].x;
    if ( x < -2*DIST ) {
        CGFloat lastX = points[lastPoint].x;
        lastPoint = firstPoint;
        firstPoint = ((firstPoint + 1) % (TOTAL_POINTS));
        points[lastPoint] = CGPointMake(lastX + DIST, [self getNextY]);
    }

    //Move points
    for(int i = 0; i < TOTAL_POINTS; i++) {
        points[i].x -= 7;
    }

    //Mark as "needed to redraw"
    [self setNeedsDisplay];

}

- (void)drawRect:(CGRect)rect
{    
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetLineWidth(context, 3.0);
    CGContextSetRGBStrokeColor(context, 0, 0, 0, 1.0);
    CGContextSetRGBFillColor(context, 1.0, 0, 0, 1.0);
    CGContextSetLineCap(context, kCGLineCapRound);

    //Create path
    CGMutablePathRef path = CGPathCreateMutable();

    //Draw the curve
    [self drawBezierCurveInPath:path];

    //Close and add path
    CGPathAddLineToPoint(path, NULL, 485, -5);
    CGPathAddLineToPoint(path, NULL, -5, -5);
    CGPathCloseSubpath(path);

    CGContextAddPath(context, path);

    CGContextSetFillColorWithColor(context, bg2);

    //    [[UIColor redColor] setFill];
    [[UIColor blackColor] setStroke];

    CGContextDrawPath(context, kCGPathFillStroke);    

    //Release
    CGPathRelease(path);

    //Paint time.
    playintIntervalView.text = [NSString stringWithFormat:@"%f", playingInterval];
}

- (void) drawBezierCurveInPath: (CGMutablePathRef) path
{
    CGPoint fp = midPoint(points[firstPoint], points[(firstPoint+1)%TOTAL_POINTS]);
    CGPathMoveToPoint(path, NULL, fp.x, fp.y);

    int i = firstPoint;
    for (int k = 0; k < TOTAL_POINTS-2; k++) {
        previousPoint2 = points[i];
        previousPoint1 = points[(i+1)%TOTAL_POINTS];
        currentPoint = points[(i+2)%TOTAL_POINTS];

        // calculate mid point
        CGPoint mid2 = midPoint(currentPoint, previousPoint1);

        CGPathAddQuadCurveToPoint(path, nil, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y); 

        i = (i + 1) % TOTAL_POINTS;        
    }

}

I would prefer to store a UIBezierPath (so I can then make some collision tests) but it doesn't allow you to just remove ONE point (when it leaves the screen on the left), so I would have to initialize it every frame too... Am I missing anything? 我更喜欢存储一个UIBezierPath (所以我可以进行一些碰撞测试)但它不允许你只删除一个点(当它离开屏幕在左边)时,所以我必须每帧都初始化它......我错过了什么吗?

This is probably a bit late, but using CADisplayLink in this situation to animate is a bad idea. 这可能有点晚了,但在这种情况下使用CADisplayLink来制作动画是一个坏主意。 You should look into CoreAnimation for efficient animations of paths. 您应该查看CoreAnimation以获得有效的路径动画。

The issue here is that you're trying to redraw 60 times a second and the code in drawRect probably doesn't complete in the milliseconds that you have for that. 这里的问题是你试图每秒重绘60次,而drawRect中的代码可能没有在你拥有的毫秒内完成。 By removing setNeedsDisplay, you're basically telling it not to update. 通过删除setNeedsDisplay,你基本上告诉它不要更新。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM