Приложение с расширяющейся анимированной строкой в ​​iOS ... Howto - PullRequest
1 голос
/ 29 июля 2010

Основная идея
очень легко. Упрощенно можно сказать ... линия, похожая на змею, реализованная, скажем, линией 3px, расширяется по экрану, собирая и взаимодействуя с различными вещами, может управляться с помощью пользовательского ввода. Как непрерывную линию, которую вы бы нарисовали ручкой.

Я уже начал читать документацию Apple по Quartz / CG. Как я теперь понимаю, мне нужно поместить код рендеринга в drawRect из UIView. Затем мне нужно было бы установить таймер (нашел некоторые ответы / сообщения тут и там, но ничего конкретного), который срабатывает x раз в секунду и вызывает setNeedsDisplay в UIView.

Вопрос:
Как реализовать следующее: Имейте целую змею в UIView 1 / (Layer?), Рисуйте новую часть в UIView 2, объединяйте их так, чтобы новая часть добавлялась в UIView 1 (или CALayer вместо views?). Я четко спрашиваю об этом, потому что прочитал, что не следует перерисовывать один и тот же контент снова и снова, а только новую / движущуюся часть. Я надеюсь, что вы можете предоставить мне некоторый пример кода или некоторые детали, какие классы я должен использовать, и стратегию их использования / какие вызовы сделать.


Редактировать
Хорошо, я вижу, что моя идея или то, что я читал раньше, чтобы реализовать это с помощью Кварца и других взглядов, не так мудры ... ( Даниэль Бляйстайнер )
Итак, я перешел на OpenGL сейчас, я изучаю его, читаю примеры, записи в блоге Джеффа Ламарша по OpenGL и т. Д. Я думаю, я бы смог нарисовать мою линию. Я думаю, что я создал бы классы для кривых, прямых линий / изменений направления и т. Д., А затем по пользовательскому вводу я бы создал связанные объекты (в зависимости от ввода рулевого управления), сохранил их в массиве, а затем заново создал и перерисовал всю линию, читая свойства объекта из объектов, хранящихся в массиве на каждом кадре. Простую линию, которую я бы нарисовал так (код Beginning iPhone Development)

glDisable(GL_TEXTURE_2D);
GLfloat vertices[4];    
// Convert coordinates
vertices[0] = start.x;
vertices[1] = start.y;
vertices[2] = end.x;
vertices[3] = end.y;
glLineWidth(3.0);
glVertexPointer (2, GL_FLOAT , 0, vertices);
glDrawArrays (GL_LINES, 0, 2);

Может быть, я даже найду способ противостоять ему, но

  1. теперь мне более любопытно, достаточно ли хороша моя идея или есть какие-то лучше разработанные стратегии для этого
  2. и, возможно, кто-то может сказать мне, как разделить код для hud'а, рисование линии и некоторые меню, которые мне придется отображать, например. в начале ... чтобы можно было легко переходить от одного "вида" к другому (как с исчезновением)? Некоторые намеки?

Может быть, вы также читали книгу, в которой объясняется, как решать подобные проблемы? Или вы можете указать мне другой хороший код ответа / примера, так как у меня огромные проблемы с поиском примеров "анимированных рисунков".

это привело меня немного дальше, но для меня это все еще немного расплывчато. Я не знаю, как реализовать «путь обновления, который вы рисуете (только с необходимыми точками + последняя точка, которая движется)»

Ответы [ 2 ]

0 голосов
/ 09 декабря 2011

Используйте OpenGL ES.Затем вам нужно будет создать функцию или метод цикла выполнения, которые будут вызываться CADisplayLink от 30 до 60 раз в секунду.60 - максимум.

Так как же это работает?

1) Создайте свойство assign для CADisplayLink.НЕ сохраняйте свой CADisplayLink, поскольку ссылки на отображение и таймеры сохраняют свою цель.В противном случае вы бы создали цикл сохранения, который может вызвать проблемы с оставленной памятью (что еще хуже, чем утечка, и намного сложнее обнаружить).

@property (nonatomic, assign) CADisplayLink *displayLink;

2) Создать и запланировать CADisplayLink:

- (void)startRunloop {
    if (!animating) {
        CADisplayLink *dl = [[UIScreen mainScreen] displayLinkWithTarget:self selector:@selector(drawFrame)];
        [dl setFrameInterval:1];
        [dl addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        self.displayLink = dl;

        animating = YES;
    }
}

Некоторые вещи, на которые следует обратить внимание: -setFrameInterval:1 говорит CADisplayLink не пропускать ни одного кадра.Это означает: вы получаете максимальный FPS.НО: это может быть плохо, если вашему коду требуется больше 1/60 секунды.В этом случае лучше установить это значение, например, равным 2.Делает вашу анимацию более плавной.

3) В вашем методе -drawFrame делайте ваш рисунок OpenGL ES как обычно.Разница лишь в том, что этот код вызывается несколько раз в секунду.Просто следите за временем и определите в своем коде, что вы хотите нарисовать, и как вы хотите, чтобы оно было нарисовано.Если бы вы анимировали прямоугольник, движущийся снизу слева вверху справа с продолжительностью анимации 1 секунда, вы просто интерполировали бы кадры анимации между началом и концом, применяя функцию, которая принимает время t в качестве аргумента.Есть тысячи способов сделать это.Это один из них.

4) Когда вы закончите или хотите остановить рисование OpenGL ES, просто сделайте недействительным или сделайте паузу в CADisplayLink.Примерно так:

- (void)stopRunloop {
    if (animating) {
        [self.displayLink invalidate];
        self.displayLink = nil;
        animating = NO;
    }
}
0 голосов
/ 31 июля 2010

Не пытайтесь объединять разные представления ... У setNeedsDisplay есть параметр rect, который сообщает основной графической части, что только определенная часть экрана должна быть визуализирована снова. Уважайте этот параметр в вашем методе drawRect, и этого должно быть достаточно для стандартных 2D-игр и инструментов.

Если вы намереваетесь использовать насыщенную графику, нет другого выбора, кроме как использовать OpenGL. Производительность в несколько раз выше, и вам не придется заботиться об оптимизации ... OpenGL много делает в фоновом режиме.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...