CAKeyframeAnimation над кривой Безье останавливается (постоянно), когда adBannerView расширяется

Итак, я только что реализовал adBannerView в своем приложении (базовая игра-жонглирование), которое при расширении (т. е. вызывает bannerViewActionShouldBegin для делегата) заставляет CAKeyFrameAnimations на CALayers (над определенными кривыми Безье) постоянно останавливаться и вызывать анимациюDidStop для своего делегата. Под постоянно я подразумеваю примерно раз в 0,001 секунды.

Я уже внедрил в свою игру метод паузы, который при вызове (через действие, привязанное к UIButton) устанавливает скорость CALayer для каждого объекта мяча на 0,0, эффективно останавливая их посреди анимации. Существует логическое условие, определяющее, поставлена ​​ли игра на паузу, которое определяет, какая часть кода паузы выполняется при вызове метода. Вот код:

- (IBAction)pauseButton:(id)sender {
    if (isPaused == NO) {
        isPaused = YES;
        [_pauseButtonOutlet setImage:playButtonImage forState:UIControlStateNormal];
        [_pauseButtonOutlet setImage:playButtonImage forState:UIControlStateSelected];
        for (x = 0; x < [ballsArray count]; x++) {
            [[ballsArray objectAtIndex:x] setTimeOffset:[[ballsArray objectAtIndex:x] convertTime:CACurrentMediaTime() fromLayer:nil]];
            [[ballsArray objectAtIndex:x] setBeginTime:CACurrentMediaTime()];
            [[ballsArray objectAtIndex:x] setSpeed:0.0];
        }
        [_statusLabel setText:@"Paused"];

    } else if (isPaused == YES) {
        isPaused = NO;
        [_pauseButtonOutlet setImage:pauseButtonImage forState:UIControlStateNormal];
        [_pauseButtonOutlet setImage:pauseButtonImage forState:UIControlStateSelected];
        for (x = 0; x < [ballsArray count]; x++) {
            [[ballsArray objectAtIndex:x] setTimeOffset:[[ballsArray objectAtIndex:x] convertTime:CACurrentMediaTime() fromLayer:nil]];
            [[ballsArray objectAtIndex:x] setBeginTime:CACurrentMediaTime()];
            [[ballsArray objectAtIndex:x] setSpeed:1.0];
        }
        [_statusLabel setText:@""];

    }

}

Этот метод также служит (или я так думал) удобным способом приостановить работу приложения, пока содержимое adBannerView расширяется. Однако я обнаружил, что когда я возвращаюсь к интерфейсу, мои шары CALayer будут в конце своей анимации (точка, в которой персонаж их ловит), но игра все равно будет приостановлена. При снятии паузы они продолжаются, как будто анимация начинается заново (когда мяч приземляется, анимация останавливается и создается новая в противоположном направлении).

Я подумал, что, возможно, что-то происходит со слоем представления во время отображения рекламы (поскольку в начале каждой анимации я перемещаю сам CALayer в конечную точку, но все равно анимирую слой представления по кривой Безье от начальной точки ). Но после добавления быстрого оператора NSLog к моим методам animationDidStop (я говорю «методы», потому что всего существует четыре класса мячей, каждый из которых предназначен для анимации по определенному пути, и каждый имеет свой собственный метод делегата animationDidStop), я обнаружил, что для по какой-то странной причине методы остановки для всех созданных шаров вызываются непрерывно и через очень короткие интервалы (~ 0,001 с). Эта активность прекращается, когда реклама закрывается (и я использую bannerViewActionDidFinish, чтобы снова вызвать функцию паузы, автоматически возобновляющую игру).

Я бы хотел, чтобы кто-нибудь помог мне с этим. Я сформулировал псевдорешение (получить позиции мяча при паузе из баннера, создать массивы nsnumber для значений x и y и после отмены паузы перезапустить анимацию с точки, где они остановились, с кривой Безье, контрольные точки и основные точки которой рассчитываются динамически), но это делает анимацию нерегулярной и не соответствующей стандартной анимации мяча. Я был бы очень признателен за возможность просто возобновить анимацию с того места, где она остановилась, как в обычном методе паузы.

Спасибо, что прочитали все это, и любая помощь очень ценится. Кроме того, если вам нужно/хотите увидеть остальную часть моего кода, я буду рад помочь.

Обновление: после небольшого рассмотрения кода я могу предположить, что отображение баннера заставляет анимацию преждевременно останавливаться, что заставляет его (мяч CALayer) вызывать метод animationDidStop для своего делегата. Поскольку этот метод автоматически создает новую анимацию, создается бесконечный цикл «новая-стоп-новая-стоп-новая-и т. д.». Это также объясняет, почему иногда мяч оказывается на стороне, противоположной той, на которую он должен был приземлиться, а иногда он приземляется на ожидаемой стороне.

Из этого я делаю вывод, что при расширении adBannerView прекращается вся CAAnimation. Если я прав насчет этого, есть ли способ обойти это?


person ghostsax    schedule 18.07.2014    source источник


Ответы (1)


Возможно, когда вы возобновите работу слоя, вы сможете проверить, добавлена ​​ли анимация. Если нет, вы можете добавить новую анимацию с правильным timeOffset.

Кроме того, есть ли причина, по которой вы не используете быстрое перечисление по сравнению с использованием for (x = 0; x ‹ [ballsArray count]; x++)?

person Wan Lutfi Wan Hatta    schedule 19.07.2014
comment
Я думал над тем, чтобы сделать что-то подобное. Мой вопрос: как создать анимацию кривой Безье, в которой анимированный слой уже частично проходит через анимацию (при условии, что это то, что вы подразумеваете под смещением по времени). А насчет того, как я перечисляю, ну, я не знаю. Я много работал с BASIC и C, прежде чем перешел к Objective C, и мне просто удобнее делать это по старинке. Ржу не могу. - person ghostsax; 20.07.2014
comment
Вы можете просто добавить ту же анимацию кривой Безье. Затем установите timeOffset анимации на приостановленное timeOffset. Вот как вы перечисляете в obj c, for (CALayer *ball in ballsArray) { [ball setTimeOffset:[ball convertTime:CACurrentMediaTime() fromLayer:nil]]; } - person Wan Lutfi Wan Hatta; 20.07.2014
comment
Итак, прежде чем рекламный баннер будет открыт (bannerViewActionShouldBegin), я добавляю значения NSNumber в offsetsArray, которые содержат число типа double, которое возвращается при вызове метода timeOffset для анимированных CALayers. Когда я закрываю bannerView (bannerViewActionDidFinish), я создаю новые анимации для каждого слоя с их исходными путями кривой Безье и делаю следующее: устанавливаю время начала каждой анимации на CACurrentMediaTime(), устанавливаю скорость на 1,0 и устанавливаю timeOffset к номеру, записанному ранее. Однако это все еще не работает. У вас есть какой-то конкретный способ сделать это? - person ghostsax; 24.07.2014
comment
Когда баннер закончен и вы проверили отсутствие анимации для этого слоя, сначала вы должны установить скорость слоя = 1, timeOffset = 0, beginTime = 0. Затем вам просто нужно установить timeOffset для вашей анимации. Анимация должна начинаться с заданного timeOffset. Я использовал эту технику раньше. Попробуйте, если получится. CAKeyFrameAnimations *positionAnim = ...; positionAnim.timeOffset = смещение времени; - person Wan Lutfi Wan Hatta; 25.07.2014
comment
TimeOffset для positionAnim означает, что точная продолжительность анимации начального слоя до запуска баннера, например, может составлять 3 секунды. - person Wan Lutfi Wan Hatta; 25.07.2014