Проблема с производительностью DrawRect и NSTimer - PullRequest
0 голосов
/ 06 июля 2010

Я пытаюсь сделать анимацию игрового автомата, где вращаются барабаны. Для этого я использую drawRect для рисования изображений в пользовательском классе, который наследуется от UIView. Я использую nstimer для обновления положения изображений и вызываю [self setNeedsDisplay] для обновления чертежа. В симуляторе он выглядит очень хорошо, однако на устройстве он очень запаздывает. Мне было интересно, если я делаю что-то не так с моим методом рисования или есть какие-то лучшие решения.

- (void)drawRect:(CGRect)rect
{   
    [image1 drawInRect:CGRectMake(0, image1Position, 98, 80)];
    [image2 drawInRect:CGRectMake(0, image2Position, 98, 80)];
    [image3 drawInRect:CGRectMake(0, image3Position, 98, 80)];
}


- (void)spin
{
    // move each position down by 10 px
    image1Position -= MOVEMENT;
    image2Position -= MOVEMENT;
    image3Position -= MOVEMENT;
    // if any of the position <= -60 reset to 180
    if(image1Position < -50)
    {
        image1Position = 180;
    }
    if(image2Position < -50)
    {
        image2Position = 180;
    }
    if(image3Position < -50)
    {
        image3Position = 180;
    }
    [self setNeedsDisplay];
}

-(void)beginSpinAnimation
{       
    timer = [NSTimer scheduledTimerWithTimeInterval:SCROLL_TIME target:self selector:@selector(spin) userInfo:self repeats:YES];
}

Моя попытка CoreAnimation с помощью UIScrollView:

- (void) spinToNextReel
{   
    int y = self.contentOffset.y + 80;

    // if the current >= last element reset to first position (-30)
    if(y >= (80 *(elementCount+1) - 30))
    {
        y = -30;
    }

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDuration:SCROLL_TIME];
    [UIView setAnimationCurve:UIViewAnimationCurveLinear];

    self.contentOffset = CGPointMake(0, y);

    [UIView commitAnimations];

    if (!isSpinning && targetY == y)
    {
        NSLog(@"target is %d, y is %d", targetY, y);

        if(timer)
        {
            [timer invalidate];
            timer = nil;
        }
        [self playSound];
    }
}

Ответы [ 2 ]

4 голосов
/ 06 июля 2010

Я бы сказал, исследование CoreAnimation.Это сделано, чтобы делать то, что вы хотите сделать здесь.Это будет намного быстрее, чем то, что вы здесь делаете.

Что касается медленного, вызов drawInRect не самая быстрая вещь в мире.Что такое SCROLL_TIME?

1 голос
/ 06 июля 2010

Вы хотите использовать CoreAnimation, это будет намного проще и эффективнее.Сказав это, если вы настаиваете на попытке вручную анимировать таким образом, вы делаете пару вещей неправильно:

  1. Не пытайтесь перемещать постоянную величину через фиксированные интервалы, события таймера могут бытьс задержкой, и если это так, ваша анимация будет неравномерной, поскольку вы перемещаете постоянную величину для каждого события, а не для временного интервала.Вы должны записывать фактическую временную метку каждый раз, когда вы анимируете, сравнивать ее с предыдущей временной меткой и перемещать соответствующее количество пикселей.Это приведет к равномерному движению, даже если события задерживаются (фактически вы будете сбрасывать кадры).

  2. Не используйте NSTimer, используйте CADisplayLink ,Это свяжет ваш рисунок с собственной частотой обновления системы и синхронизирует его с любым другим текущим чертежом.

  3. Я знаю, что уже говорил, но изучите и используйте CoreAnimation, вы будете намного счастливее.

...