Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Звук, графика и видео > Как грамотно реализовать анимацию?


Автор: Alix 15.12.2007, 10:51
Упрощу задачу, для более легкого понимания (реально все по-другому). Есть текстовой файл, с записями по одной в строке, вида:
timeshift image
где timeshift - время, когда надо отобразить этот image. (не точное, а "после наступления которого").

Программа запускается, запоминает в startTime время запуска (GetTickCount). В дальнейшем в Application.OnIdle вызывается функция, которая берет текущее время currentTime := GetTickCount - startTime, а затем просматривает записи от lastLine (инициализована -1), до той, у которой timeshift не будет > currentTime. По-хорошему, такая запись должна выбраться только одна. Затем рисуется соотвествующая картинка и lastLine меняется на индекс последней обработаной строки.

Вроде все хорошо, но есть три минуса:
1. Сильно грузит процессор
2. Не всегда OnIdle вызывается быстро. Не знаю чем обусловлено, но при нетронутом коде заход в OnIdle может происходить раза в 2-3 реже, в результате анимация начинает жутко тормозить. Почему так происходит пока не понял.
3. Часто OnIdle вызывается при уже вызванном OnIdle. Т.е. функция еще работает, а система решает вызвать ее еще раз. Решал с помощью doing : boolean; При заходе if doing then exit else doing := true, при выходе doing := false;
Использовать timer - не лучшая идея, т.к. работать с интервалом в 10-15 мс он не способен.

Как можно обойти эти недостатки?

Автор: Alexeis 15.12.2007, 12:24
Цитата(Alix @  15.12.2007,  10:51 Найти цитируемый пост)
Использовать timer - не лучшая идея, т.к. работать с интервалом в 10-15 мс он не способен.

  GetTickCount дает точно такое же разрешение как и таймер. Точнее только мультимедийный таймер и QueryPerformanceCounter 

Автор: OdesitVadim 3.1.2008, 23:06
я бы сделал по простому.
вначале весь файл загружается, сортируется, что бы картинки шли в нужном порядке. и составляется список пар время показа и адрес картинки. теперь запускаем поток, ставим ему приоритет выше среднего. его основной цикл будет выглядеть так. 
Код

for i:=0 to timelist.count-1 do
begin
  PostMessage(FormHandle, WM_USER, i,0);//FormHandle - заведомо переданный хендл формы, которая обрабатывает отрисовку
  Sleep(timelist[i].time);
end;

использование sleep в потоке вполне разумно - поток просто будет засыпать.
в основной форме делаем обработку сообщения, где то так
Код

procedure MyMess(var msg:TMessage); message WM_USER;
....
procedure TMyForm.MyMess(var msg:TMessage);
begin
  Image1.Picture.LoadFromFile(timelist[msg.wparam].filename);
end;

так как поток основное время будет спать, то приоритет можно сделать немного выше - что бы винда не пропускала его обработку. Единственный недостаток этой системы - в целом последовательность может немного разтянуться. (винда не гарантирует, что она точно выдержить все временные промежутки, но недодерживать она не будет, скорее передержит).
Но это решить просто - у нас ведь есть поле, которое указывает, в какое время нужно показывать картинку. С помощью GetTickCount вначале запоминаем начальное время, а потом в цикле запрашиваем и корректируем задержку.
Но! винда не гарантирует, что выдержит интервалы, которые короче 52 милисекунды. А на серверных вариантах - и все 130 (не уверен в точности числа, но точно чуть больше 100). Поэтому, если у вас будут интервалы меньше 0.1 секунды - то это плохая задумка. В таком случае лучше применить совершенно другие технологии - есть специальные программы, которые с набора картинок могут сделать видеофайл. Может это решит всё проблему?

Автор: Alix 3.1.2008, 23:14
я сомневаюсь в надежности данного метода, т.к. неизвестно сколько времени пройдет от посылки сообщения до приема, да и интервалы там поменьше 50мс будут. Впрочем проблему почти решило использование мультимедийного таймера и иная реализация "спец-эффектов". 
Что до видеофайла, то у отдельных картинок и качество выше будет и размер суммарный меньше.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)