|
|
|||||||||||||||||||||||||||||
|
Создание Анимации в DelphiИсточник: delphiexpert Владимир Любаев
В этом примере показано, как, объеденив классы Delphi с функциями Win32 GDI, можно добиться анимации упрощенного избражения эльфа. Исходные тексты можно взять здесь. Запустить пример. unit MainFrm; Как это работает. Анимационный проект состоит из фонового изображения и нарисованного на нем эльфа в виде летающего блюдца, которое перемещается в пределах области клиента фона. Фон представлен растровым изображением разбросанных по небу звезд (рис 1). Рис 1. Эльф составлен из двух растров размером 64x32. О них речь пойдет ниже, а пока рассмотрим, что происходит в программе. В приведенном модуле определяется класс TSprite, который содержит поля, предназначенные для хранения позиций эльфа на изображении фона, и два объекта типа TBitmap для хранения растровых изображений эльфа. Конструктор TSprite.Create создает оба экземпляра класса TBitmap и загружает их реальными растрами. Оба растровых изображения эльфа и фоновый растр содержатся в файле ресурсов, который привязывается к проекту путем включения в основной модуль следующей инструкции: { $R SPRITES.RES }. После загрузки растра устанавливаются границы изображения эльфа. Деструктор TSprite.Destroy освобождает оба экземпляра растра. Главная форма содержит два объекта типа TBitmap, объект TSprite и индикаторы напрвлений, задающие линию движения эльфа. Кроме того, в главной форме определены два метода: MyIdleEvent(), служащий обработчиком событий Application.OnIdle, и DrawSprite(), предназначенный для рисования изображения эльфа. Обработчик событий FormCreate() создает оба экземпляра класса TBitmap и загружает каждый одним и тем же растровым изображением (зачем - разберемся чуть ниже). Затем создается экземпляр класса TSprite, устанавливаются значения индикаторов направлений и обработчику событий Application.OnIdle назначается метод MyIdleEvent(). Наконец, обработчик событий формы FormCreate() изменяет размеры формы в соответствии с размерами фонового изображения. Метод FormPaint() выполняет рисование на канве фона BackGnd1. Метод FormDestroy() освобождает экземпляры классов TBitmap и TSprite. Метод MyIdleEvent() вызывает метод DrawSprite(), который перемещает и рисует эльфа на существующем фоне. Метод MyIdleEvent() вызывается, когда приложение находится в состоянии ожидания, т.е. когда пользователь не выполняет никаких действий, на которые приложению следовало бы отреагировать. Метод DrawSprite() изменяет расположение эльфа на изображении фона. Для этого требуется выполнить немало инструкций - ведь сначала нужно стереть старое изображение эльфа, а затем нарисовать его на новом месте, сохраняя цвет фона вокруг реального изображения эльфа. Кроме того, метод DrawSprite() должен выполнить эти действия без мерцания. Для достижения поставленных целей процесс рисования выполняется на "внеэкранном" растре BackGnd2. Растры BackGnd2 и BackGnd1 являются точными копиями фонового изображения, однако BackGnd1 никогда не модифицируется (поэтому его можно назвать чистой копией фона). По завершении рисования модифицированная область растра BackGnd2 копируется на канву формы. Это позволяет за одно обращение к функции BitBlt() выполнить как стирание на канве формы, так и рисование эльфа в новой позиции. Какие же опреции выполняются с растром BackGnd2? Во-первых, из BackGnd1 в BackGnd2 копируется прямоугольный участок, превышающий по размерам область, занимаемую самим эльфом. Тем самым гарантируется стирание изображения эльфа с растра BackGnd2. После этого растр FAndImage копируется в BackGnd2 на его новой позиции с помощью поразрядной опреции AND (логическое И). Это приводит к созданию черного пятна с силуэтом эльфа, но с сохранением цветов в области растра BackGnd2, окружающей черный силуэт. Растр FAndImage показан на (рис 2). Рис 2. На рис 2 эльф представлен черными пикселами, а изображение вокруг эльфа состоит из белых пикселей. Черный цвет имеет значение, равное 0, а белый - 1. В табл. 1 и 2 приведены результаты выполнения опреции AND с белым и черным цветами. Табл. 1 "Опреция AND с черным цветом"Фон Значение Цвет
Табл. 2 "Операция AND с белым цветом"Фон Значение Цвет
Эти таблицы показывают, как выполнение операции логического И приводит к зачернению области, занимаемой эльфом на растре BackGnd2. В табл. 1 столбец "Значение" представляет цвет пискселя. Если пиксель на растре BackGnd2 содержит некоторый произвольный цвет, то объединение этого цвета с черным при использовании оператора AND заставит этот пиксель полностью почернеть. Аналогичная операция, выполненная над тем же цветом и абсолютно белым "коллегой" никак не отразится наисходном цвете, как видно в табл. 2. А поскольку цвет фона, на котором находится эльф в растре FAndImage, был белым, то пиксели на растре BackGnd2 копируются без изменения своих цветов. После копирования растра FAndImage в объект BackGnd2 растр FOrImage должен быть скопирован в то же самое место растра BackGnd2, чтобы заполнить черное пятно, созданное объединением растра FAndImage с реальными цветами эльфа. Растр FOrImage таже имеет прямоугольник, окружающий реальное изображение эльфа. И вновь мы сталкиваемся с задачей получения цветов эльфа для растра BackGnd2 и одновременным сохранением цветов этого растра в области, окружающей эльфа. Это достигается объединением растров FOrImage и BackGnd2 с использованием оператора OR (лигическое ИЛИ). Растр FOrImage показан на (рис 3). Рис 3. Обратите внимание на то, что область, окружающая изображение эльфа, окрашена в черный цвет. В табл. 3 показаны результаты выполнения операции ИЛИ с растрами FOrImage и BackGnd2. Из табл. 3 следует, что если растр BackGnd2 содержит произвольный цвет, то после операции лигического сложения с черным цветом останется тот же цвет растра BackGnd2. Табл. 3 "Операция OR с черным цветом"Фон Значение Цвет
Напомним, что все рисование выполняется на "внеэкранном" растре. По завершении рисования достаточно только одного обращения к функции BitBlt(), чтобы стереть и скопировать изображение эльфа. В описанном способе создания анимации нет ничего необычного. Вы можете сами расширить функциональные возможности класса, связанные с переме. Ссылки по теме
|
|