MobiLab.ru - программирование для сотовых телефонов и КПК: Symbian C++ и OPL; J2ME, Mobile Basic, MIDlet Pascal, Windows CE, Linux. Есть форум и раздел о безопасности.
В избранное Сделать домашней Контакт
Меню
Главная
Новости
Документация
  - J2ME
  - Android
  - Symbian C++
  - Symbian OPL
  - Basic
  - Windows CE 
  - Linux
  - OpenGL ES
Безопасность
Книги
Софт
Проекты
Форум
Ссылки
Контакт

Книги


Заказать

Философия JavaБрюс Эккель
Цена:

Подпишись на рассылку



Реклама
Значит, нам нужна труба. Хорошо, я куплю трубу оцинкованную - она наилучшим способом подойдёт.... Те, кто думают: "Куплю копии часов, ведь это лучший подарок" - абсолютно правы. Нанесение рисунка на плитку - плитка мозаика. Мозаика на складе, под заказ.


10 января 2008 г. - Анимация в Symbian приложениях



Наиболее простой вариант – использовать таймер (например - CPeriodic) для организации задержки между сменой кадров. По окончанию задержки рассчитывать и отображать очередной кадр. Реализация может быть следующей:

  • В заголовочном файле класса-котейнера (AppView) необходимо объявить:

    public:
       void DrawNewFrame(); // отображение очередного кадра
     
    private:
       static void Period( TAny* aPtr );
       CPeriodic* iPeriodicTimer;

  • При создании AppView, в методе ConstructL(), добавить инициализацию и запуск таймера:

    iPeriodicTimer = CPeriodic::NewL( CActive::EPriorityStandard );
    // указываем минимально возможные интервалы
    iPeriodicTimer->Start( 1, 1, TCallBack( CSmileDialog::Period, this) );

  • Реализовать статический метод Period():

    void CYourAppView :: Period( TAny* aPtr )
    {
       CYourAppView view = static_cast< CYourAppView *>( aPtr );
       // расcчет и отображение очередного кадра
       view->DrawNewFrame();
    }

У данного подхода есть свои достоинства и недостатки.

Достоинства:

  • Простота реализации
  • Компактность
  • Не требуется каких-либо специальных capabilities

Недостатки:

  • Для организации задержки используется активны объект - таймер. Активные объекты реализуют кооперативную многозадачность. Активных объектов, в рамках одного приложения, может быть достаточно много - соответственно, нет гарантий того, что callback-функция будет вызываться таймером через строго равные промежутки времени (другой активный объект может слишком долго не передавать управление). В результате, анимация может получиться "рваной". Частично эту проблему можно решить, указав таймеру при создании более высокий приоритет, однако это может помочь далеко не всегда.
  • Клиентский процесс имеет низкий приоритет (по сравнению с серверными процессами), соответственно, более высокоприоритетные процессы могут излишне часто его "вытеснять" – в результате анимация, опять же, может получиться "рваной".

Анимация в Symbian на стороне сервера

В Symbian представлены специальные возможности для создания качественной анимации. Подход следующий:

  • Отображение кадров происходит благодаря плагину к Window Server. Плагин выполняется ввиде отдельной DLL с полиморфным интерфейсом. Соответственно, функционирует плагин в рамках высокоприоритетной серверной нити.
  • Для взаимодействия с серверной частью приложения создается клиентская DLL со статическим интерфейсом. Эта библиотека реализует механизм пересылки команд серверу.
  • Основное приложение взаимодействует с клиентской библиотекой для активация и передачи команд серверу.

Такой подход исключает недостатки, возникающие при реализации анимации на стороне клиента. Отрисовка кадров происходит в рамках высокоприоритетной серверной нити, количество одновременно функционирующих активных объектов, необходимых для отображения, легко сводится к минимуму. Однако у такого подхода, помимо возросшей сложности, есть еще один существенный недостаток. Для всех трех компонентов необходим расширенный набор возможностей (capabilities): PowerMgmt ReadDeviceData WriteDeviceData ProtServ. Соответственно, для установки этого примера на смартфон потребуется сертификат разработчика.

В качестве примера рассмотрим приложение в котором осуществляется вращение двух параллелепипедов в разных плоскостях.

Symbian анимация

Вращение осуществляется благодаря постоянному изменению углов поворота. Для расчета координат вершин параллелепипедов в каждый момент времени производится умножение вектора с координатами на матрицу поворота. Текущий параллелепипед выбирается с помощью кнопок 1,2. Приращение углов поворота можно менять(с помощью кнопок влево-вправо) и сбрасывать(кнопка 0) с помощью индикаторов - для этого нужный индикатор необходимо предварительно выбрать (вверх-вниз).

Исходный код данного примера: AnimExampleSrc.zip.

Реализация серверной части

Для создания серверной DLL нужно реализовать собственного потомка класса CAnimDll, в нем должна быть реализована чистая виртуальная функция-фабрика CAnim* CreateInstanceL( TInt aType ). Эта функция, как видно из прототипа, возвращает указатель на созданный объект-потомок абстрактного класса CAnim.

class CAnimServerDll : public CAnimDll
{
   public:
      CAnimServerDll();
 
   public:
      IMPORT_C CAnim* CreateInstanceL( TInt aType );
};

В Symbain представлены три потомка класса CAnim, которые можно использовать для создания анимации: CWindowAnim, CFreeTimerWindowAnim, CSpriteAnim. В этом примере используется класс, порожденный от CWindowAnim.

class CAnimation : public CWindowAnim, public MTimerNotifier
{
   public:
      CAnimation( TInt aNo );
      virtual ~CAnimation();
 
   public: // MTimerNotifier
      void TimedOut();
 
   public:
      void ConstructL( TAny* aArgs, TBool aHasFocus );
      TInt CommandReplyL( TInt aCommand, TAny* aArgs );
      void Command( TInt aCommand, TAny* aArgs );
 
      void Redraw();
      void Animate( TDateTime* aDateTime );
 
      void FocusChanged( TBool /*aState*/ ) {}
      TBool OfferRawEvent( const TRawEvent &aRawEvent );
 
   private:
      CParallelepiped *iPrl; // вся логика расчета и отображения объекта
      TInt iNo; // номер объекта
      CAnimTimer* iServerTimer;
};

Данный класс реализует интерфейс MTimerNotifier так как для задержки между отображением кадров используется собственный таймер CAnimTimer. Следует отметить, что у объектов, порожденных от CAnim, уже есть специализированный таймер, который может использоваться системой для аналогичных целей, однако в данном случае он не используется. Поэтому Timeout() содержит собственный вызов Animate() (с помощью члена-данного iFunctions, который предварительно отключает графический контекст, а затем вызывает метод Animate() данного класса) и инициирует новую задержку таймера.

void CAnimation::TimedOut()
{
   // установка значения задержки таймера для следующего вызова
   iServerTimer->After( KTimerPeriod );
   // с помощью данного вызова происходит отрисовка текущего кадра
   iFunctions->Animate( 0 );
}

Метод Animate(), в свою очередь, производит расчет новых координат вершин параллелепипеда и инициирует обновление экрана.

void CAnimation::Animate( TDateTime* /* aDateTime */ )
{
   // расчет новых координат
   iPrl->Calc();
   // экран должен быть обновлен
   iWindowFunctions->Invalidate( iWindowFunctions->WindowSize() );
}

Обновление экрана производится в методе Redraw() который отображает параллелепипед, координаты которого были рассчитаны предварительно.

void CAnimation::Redraw()
{
   // отображение очередного кадра
   iPrl->Draw( *iGc );
}

Методы CommandReply(), Command() - это обработчики команд, полученных от клиента. Оба метода объявлены как чистые виртуальные в предке, в качестве параметров, принимают идентификатор команды TInt aCommand и ее параметры TAny* aArgs. В данном примере используется только метод Command(). Рассмотрим, каким образом передаются параметры команд:

Клиентская часть инициирует команду:

TPckgBuf<TInt> param;
   param() = 55;
   RAnim::Command( KChangeGaugeValue, param );

Серверная часть ( CAnim :: Command() ) ее обрабатывает:

switch( aCommand )
   {
      ...
      case KChangeGaugeValue:
          TInt cmdValue = *( STATIC_CAST( TInt*, aArgs ) );
          ...
          break;
   }

Для корректной сборки серверной библиотеки необходимо правильно задать ряд параметров проекта (см. mmp-файл):

TARGETTYPE: ani
UID2: 0x10003b22

Клиентская библиотека

Для создания клиентской библиотеки необходимо реализовать собственного потомка класса RAnimDll

class RAnimClientDll : public RAnimDll
{
   public:
      IMPORT_C RAnimClientDll( RWsSession& aSession );
};

Кроме того, необходимо реализовать класс, который инициализирует серверную анимацию и предоставляет интерфейс для посылки команд. Класс должен быть потомком RAnim:

class RAnimation : public RAnim
{
   public:
      IMPORT_C RAnimation( RAnimDll& aAnimDll );
      IMPORT_C void CreateAnimation( onst RWindowBase& aDevice, TInt aType, TDisplayMode aMode );
 
      IMPORT_C void AnimCommand( TInt aCommand, const TPtrC8 &aArgs );
      IMPORT_C void AnimCommand( TInt aCommand );
 
   public:
 
      IMPORT_C void ChangeCurrentValue( TBool aInc );
      IMPORT_C void ChangeCurrent( TBool aNext );
      IMPORT_C TInt CurrentGauge();
 
      // команды, обрабатываемые на сервере
      enum KAnimCommands
      {
         KReset = 1,
         KResolutionChange = 2,
         KChangeFocus = 3,
         KChangeGauge = 4,
         KChangeGaugeValue = 5
      };
 
   private:
      TInt iDx, iDy, iDz; // значение приращений углов поворота
      TInt* iCurrent; // текущее приращение
};

Метод CreateAnimation() используется для инициализации серверного объекта – для этого вызывается метод предка RAnim :: Construct(). В качестве параметра создаваемому объекту передается значение TDisplayMode, которое используется для конструирования объектов, отвечающих за двойную буферизацию.

Методы AnimCommand() используются для передачи команд серверному объекту, команды могут быть как с параметрами, так и без них.

Методы:

  • ChangeCurrentValue() - изменяет значение текущего индикатора и посылает команду серверу
  • ChangeCurrent() – изменяет текущий индикатор и посылает команду серверу
  • CurrentGauge() – возвращает значение текущего индикатора

Использование в пользовательском интерфейсе

Для взаимодействия с серверной частью в рамках GUI, нужно использовать клиентскую библиотеку.

Для инициализации и загрузки сервером библиотеки с анимацией необходимо вызвать метод Load() у объекта класса RAnimClientDll (потомок RAnimDll). В качестве параметра этот метод принимает полное имя файла серверной библиотеки. Нужно учитывать - на эмуляторе и в реальном устройстве строки, содержащие полный путь до библиотеки, не совпадают.

Для каждого серверного объекта, отвечающего за отображение анимации, создается клиентская часть с помошью которой выполняется инициализация и посылка команд. В данном примере, для отображения двух параллелепипедов в рамках AppUi, создаются два объекта класса RAnimation. Эти объекта создаются в конструкторе AppUi, а в методе ConstructL() инициализируют серверную часть с помощью метода CreateAnimation().

AppUi содержит обработчик событий клавиатуры - метод HandleKeyEventL(). В нем, в зависимости от нажатой клавиши, вызываются функции объектов класса RAnimation результатом которых является посылка команд на сервер.

Замечание: для того чтобы приложение, содержащее данное GUI, успешно скомпоновалось, необходимо в список библиотек (в mmp-файле) добавить клиентскую библиотеку - в данном случае AnimClient.lib


Автор: Den.
Оригинал статьи размещен на Forum Nokia Wiki.

Новости
Sony Ericsson SDK 2.5.0.6 for the Java™ ME Platform

Конкурс для разработчиков Windows Mobile Developers 2009

Вышел Android 1.6 SDK

Motodev Studio for Android

Открыта продажа приложений через Sony Ericsson PlayNow Area


Новые статьи
Отрисовка SVG в J2ME без использования JSR 226 API.

Создание моноширинного векторного шрифта для Java2ME.

Использование векторной графики и анимации в Java ME (JSR 226 API)

Обзор существующих Java ME SDK

Создаем игру с помощью визуальных средств NetBeans. Урок 4 – Соединение с удаленным сервером

Создание Google Android виджетов

Создаем игру с помощью визуальных средств NetBeans. Урок 3 – Задаем логику управления персонажем

Создаем игру с помощью визуальных средств NetBeans. Урок 2 – NetBeans Game Builder

Создаем игру с помощью визуальных средств NetBeans. Урок 1 – NetBeans Visual Designer

Знакомство с Android. Часть 2: Переходы между формами


Реклама



Rambler's Top100


© 2005-2009 MobiLab.ru
При использовании материалов сайта ссылка на www.mobilab.ru обязательна