Chertenok.ru - все о программировании
Вход  |  Регистрация  |  Поиск 
Праздник
Завтра :

День славянской письменности и культуры


Thread
На страницу 1, 2  След.

Новая тема  Ответить  Печать Предыдущая тема  Следующая тема
Автор Сообщение
Пол:Муж Evgeny
Постоянный участник


Возраст: 51
Знак зодиака: Козерог
Зарегистрирован: 26.06.2005
Сообщения: 152
Откуда: Омск
СообщениеВс, 09-Сен-2007 20:13    Заголовок сообщения: Thread
Цитата

Имеется программа с большим количеством отрисовок завязанных на таймер. Также имеется программа визуального эффекта постооенного на закольцованном потоке. Я попытался подпрограмму эффектов встроить в свою, но закольцованный поток сильно подтормаживает таймер в основной программе. Тогда я снизил приоритет потока. отрисовка эффекта сильно затормозилась, хотя основная программа стала работать нормально. Попробовал подпрограмму эффектов перевести на таймер, тот же самое, сильно притормаживает отрисовка. Как мне все-таки совместить несовместимое. И чтобы программа не притормаживала и эффект быстро отрисовывался?
_________________
Здесь Вы там не найдете
В начало
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
DrPass
Знающий :)
/Почетный Модератор/


Возраст: 31
Знак зодиака: Лев
Зарегистрирован: 02.05.2002
Сообщения: 5709
Откуда: Донецк
СообщениеВс, 09-Сен-2007 20:45 
Цитата

А что по такому общему описанию можно сказать конкретного? Ровным счетом ничего. Может, ты рисуешь на GDI-устройстве, тогда воспользуйся DirectX или хотя бы строй картинку в памяти, а потом разом ее выводи. Может, у тебя вычисления неоптимизированы, может, алгоритм взаимодействия потоков плохой или обработка сообщений таймера криво сделана.
_________________
Да пребудет с вами Сила!
В начало
Посмотреть профиль Отправить личное сообщение
Пол:Муж Evgeny
Постоянный участник


Возраст: 51
Знак зодиака: Козерог
Зарегистрирован: 26.06.2005
Сообщения: 152
Откуда: Омск
СообщениеПн, 10-Сен-2007 22:38 
Цитата

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

delphi:
  1.  
  2. {$H-}
  3. {$R winp.res}
  4. Program WinPlasm;
  5.  
  6. uses
  7.   Windows, Messages;
  8.  
  9. const
  10.   width  = 256;
  11.   height        = 200;
  12.   data_size     = width * height;
  13.   IDR_MENU      = 100;
  14.   IDM_SIZE      = 32003;
  15.   IDM_EXIT      = 32004;
  16.   IDM_CPU       = 32000;
  17.   IDM_CPU_OPT   = 32001;
  18.   IDM_MMX       = 32002;
  19.   IDM_MMX_OPT   = 32005;
  20.  
  21. type
  22.   TRGB32        = packed array[0..3] of Byte;
  23.  
  24. const
  25.   ClassName : PCHAr = 'WowkaClass';
  26.  
  27. var
  28.   win      : HWND;
  29.   wc        : WNDCLASSEX;
  30.   msg      : TMsg;
  31.   hThread       : HWND;
  32.   menu    : HMENU;
  33.   real_width,
  34.   real_height,
  35.   optimal_width,
  36.   optimal_height: Integer;
  37.   mas      : array[0..data_size] of TRGB32;
  38.  
  39. function IntToStr(n : Integer) : String;
  40. begin
  41.   Result := '';
  42.   while n > 0 do
  43.     begin
  44.       Result := chr(ord('0') + (n mod 10)) + Result;
  45.       n := n div 10
  46.     end;
  47. end;
  48.  
  49. function DrawThread(dr_win : DWORD) : DWORD; stdcall;
  50. label
  51.   now;
  52. const
  53.   cl_mas : array[0..4] of TRGB32 = (
  54.             ($FF,  000),
  55.             ($FF,$C0,  00),
  56.             ($FF,$80,$400),
  57.             ($FF,$FF,$FF,  0),
  58.             (  0000));
  59. var
  60.   bitmap : TBitMapInfo;
  61.   DC     : HDC;
  62.   m, I, J,
  63.   time1,
  64.   time2,
  65.   dtime,
  66.   count  : Integer;
  67.   s      : String;
  68.   buf    : array[0..63] of Char;
  69. begin
  70.   time2  := GetTickCount - 1;
  71.   count  := 0;
  72.   Result := 0;
  73.   with bitmap.bmiHeader do
  74.   begin
  75.     biSize          := SizeOf(bitmap.bmiHeader);
  76.     biPlanes        := 1;
  77.     biClrImportant  := 0;
  78.     biWidth         := width;
  79.     biHeight        := height;
  80.     biBitCount      := 32;
  81.     biCompression   := BI_RGB;
  82.     biSizeImage     := 0;
  83.     biXPelsPerMeter := 0;
  84.     biYPelsPerMeter := 0;
  85.     biClrUsed       := 0;
  86.   end;
  87.  
  88. now:
  89.  
  90.   count := count + 1;
  91.   time1 := GetTickCount;
  92.   dtime := time1 - time2;
  93.   if dtime > 500 then
  94.   begin
  95.     s := 'Plasma ' + IntToStr(real_width) + 'x' + IntToStr(real_height) + '  ' +
  96.                      IntToStr((count * 1000) div dtime) + ' FPS';
  97.     m := Length(s);
  98.     Move(s[1], buf, m);
  99.     buf[m] := #0;
  100.     SendMessage(dr_win, WM_SETTEXT, 0, Integer(@buf));
  101.     count := 0;
  102.     time2 := time1;
  103.   end;
  104.   J := random(4);
  105.   m := data_size - random(width)
  106.   for I := 0 to 3 do
  107.     mas[m + I] := cl_mas[J];
  108.   for I := 1 to data_size - width do
  109.     for J := 0 to 2 do
  110.       mas[I][J] := ((mas[I][J] + 3) shr 2) + ((mas[I + 1][J] + 2) shr 3) +
  111.                    ((mas[I - 1][J] + 2) shr 3) + (mas[I + width][J] shr 1);
  112.   DC := GetDC(dr_win);
  113.   StretchDIBits(DC, 0, 0, real_width, real_height, 0, 0, width, height,
  114.                 @mas, bitmap, DIB_RGB_COLORS, SRCCOPY);
  115.   ReleaseDC(dr_win, DC);
  116.   goto now;
  117. end;
  118.  
  119. function MainProc(Wnd: HWND; Msg, wParam, lParam: Longint): Longint; stdcall;
  120. var
  121.   idMain  : DWORD;
  122. begin
  123.   Result := 0;
  124.   case msg of
  125.     WM_CREATE : hThread := CreateThread(NIL, DWORD(1024 * 4), @DrawThread, Pointer(wnd), DWORD(0), idMain);
  126.  
  127.     WM_SIZE :
  128.     begin
  129.       real_width  := LOWORD(lParam);
  130.       real_height := HIWORD(lParam);
  131.       if (real_width = width) and (real_height = height) then
  132.         CheckMenuItem(menu, IDM_SIZE, MF_BYCOMMAND or MF_CHECKED)
  133.       else
  134.         CheckMenuItem(menu, IDM_SIZE, MF_BYCOMMAND or MF_UNCHECKED);
  135.       Result := DefWindowProc(wnd, msg, wparam, lparam);
  136.     end;
  137.    
  138.     WM_KEYDOWN :
  139.     if wParam = 27 then
  140.       PostMessage(wnd, WM_CLOSE, 0, 0)
  141.     else
  142.       Result := DefWindowProc(wnd, msg, wparam, lparam);
  143.  
  144.     WM_COMMAND:
  145.     case LOWORD(wParam) of
  146.       IDM_EXIT : PostMessage(wnd, WM_CLOSE, 0, 0);
  147.       IDM_SIZE : MoveWindow(wnd, 30, 30, optimal_width, optimal_height, TRUE);
  148.     end;
  149.  
  150.     WM_DESTROY:
  151.     begin
  152.       TerminateThread(hThread, 0);
  153.       PostQuitMessage(0);
  154.     end;
  155.   else
  156.     Result := DefWindowProc(wnd, msg, wparam,lparam)
  157.   end;
  158. end;
  159.  
  160. begin
  161.   ZeroMemory(@wc, SizeOf(wc));
  162.   with wc do
  163.   begin
  164.     cbSize        := SizeOf(wc);
  165.     hInstance     := hInstance;
  166.     Style         := CS_HREDRAW or CS_VREDRAW;
  167.     hbrBackground := COLOR_GRAYTEXT;
  168.     lpfnWndProc   := @MainProc;
  169.     lpszClassName := ClassName;
  170.     lpszMenuName  := PChar(IDR_MENU);
  171.   end;
  172.  
  173.   RegisterClassEx(wc);
  174.  
  175.   optimal_width  := 520 + GetSystemMetrics(SM_CXSIZEFRAME) * 2;
  176.   optimal_height := 22  + GetSystemMetrics(SM_CYSIZEFRAME) * 2 +
  177.                              GetSystemMetrics(SM_CYCAPTION) +
  178.                              GetSystemMetrics(SM_CYMENU);
  179.  
  180.   win := CreateWindowEx(0, ClassName, 'HelloWords', WS_OVERLAPPEDWINDOW,
  181.                         30, 30, optimal_width, optimal_height,
  182.                         0, 0, hInstance, NIL);
  183.  
  184.   ShowWindow(win, SW_SHOWDEFAULT);
  185.   UpdateWindow(win);
  186.  
  187.   menu := GetMenu(win);
  188.   CheckMenuItem(menu, IDM_SIZE, MF_BYCOMMAND or MF_CHECKED);
  189.   CheckMenuItem(menu, IDM_CPU, MF_BYCOMMAND or MF_CHECKED);
  190.   EnableMenuItem(menu, IDM_CPU, MF_BYCOMMAND or MF_DISABLED);
  191.   // pascal version dont support optimization
  192.   EnableMenuItem(menu, IDM_CPU_OPT,MF_BYCOMMAND or MF_DISABLED or MF_GRAYED);
  193.   EnableMenuItem(menu, IDM_MMX_OPT,MF_BYCOMMAND or MF_DISABLED or MF_GRAYED);
  194.   EnableMenuItem(menu, IDM_MMX, MF_BYCOMMAND or MF_DISABLED or MF_GRAYED);
  195.  
  196.   while GetMessage(msg, 0, 0, 0) do
  197.   begin
  198.     TranslateMessage(msg);
  199.     DispatchMessage(msg)
  200.   end;
  201.  
  202.   ExitProcess(0);
  203. end.
  204.  


Самостоятельно такой код работает быстро, а в паре с таймером тормозит последний. И тут уже не важно как оптимизирован код, почему тормозит таймер? Почему приведенный код медленно работает, если его также перевести на таймер. Весь прикол в том, что я действительно использую GDI и не хотел бы в данном случае использовать DirectX. Может затея конечно дурацкая, но я хотел внизу основной картинки сделать небольшое подобие воды и похоже ничего хорошего из этого не выйдет. Если это поможет, можно привести и код работы таймера, только кусок несколько великоват.

_________________
Здесь Вы там не найдете
В начало
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
DrPass
Знающий :)
/Почетный Модератор/


Возраст: 31
Знак зодиака: Лев
Зарегистрирован: 02.05.2002
Сообщения: 5709
Откуда: Донецк
СообщениеПн, 10-Сен-2007 23:11 
Цитата

Нет, как бы ничего неожиданного и не происходит. Вот этот код

Цитата:
now:
count := count + 1;
time1 := GetTickCount;
dtime := time1 - time2;
if dtime > 500 then
begin
s := 'Plasma ' + IntToStr(real_width) + 'x' + IntToStr(real_height) + ' ' +
IntToStr((count * 1000) div dtime) + ' FPS';
m := Length(s);
Move(s[1], buf, m);
buf[m] := #0;
SendMessage(dr_win, WM_SETTEXT, 0, Integer(@buf));
count := 0;
time2 := time1;
end;
J := random(4);
m := data_size - random(width);
for I := 0 to 3 do
mas[m + I] := cl_mas[J];
for I := 1 to data_size - width do
for J := 0 to 2 do
mas[I][J] := ((mas[I][J] + 3) shr 2) + ((mas[I + 1][J] + 2) shr 3) +
((mas[I - 1][J] + 2) shr 3) + (mas[I + width][J] shr 1);
DC := GetDC(dr_win);
StretchDIBits(DC, 0, 0, real_width, real_height, 0, 0, width, height,
@mas, bitmap, DIB_RGB_COLORS, SRCCOPY);
ReleaseDC(dr_win, DC);
goto now;
end;

- это же бесконечная молотилка далеко не самых легких операций. Посмотри сперва на процессор, он у тебя должен быть забит по самое нехочу. По крайней мере, одним ядром, которому меньше повезло (если проц многоядерный) Улыбка
Потом добавь в цикл "передышку" для проца в виде Sleep(50), хотя бы, и попробуй еще раз. Регулировкой интервала Sleep можно добиться оптимального значения между частотой кадров и уровнем изнасилования компьютера.
А потом еще замени goto на что-то более приличное. Быстрее работать не станет, но зато код будет без пошлостей :)
И да, все эти DC := GetDC(dr_win)/ReleaseDC(dr_win, DC) достаточно выполнить один раз, первое - при запуске потока, второе - при завершении его работы. А не дергать контекст по-новой на каждой итерации цикла. Тоже заметно "облегчишь" его.

_________________
Да пребудет с вами Сила!
В начало
Посмотреть профиль Отправить личное сообщение
Пол:Муж Evgeny
Постоянный участник


Возраст: 51
Знак зодиака: Козерог
Зарегистрирован: 26.06.2005
Сообщения: 152
Откуда: Омск
СообщениеВт, 11-Сен-2007 13:50 
Цитата

Код, который я привел, писАл не я. У меня все указанные замечание были учтены с первого раза, а вот Sleep я не ставил, нужно поробовать.
_________________
Здесь Вы там не найдете
В начало
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
Пол:Муж Evgeny
Постоянный участник


Возраст: 51
Знак зодиака: Козерог
Зарегистрирован: 26.06.2005
Сообщения: 152
Откуда: Омск
СообщениеПн, 17-Сен-2007 17:28 
Цитата

Я попробовал перевести отработку отрисовки полностью на поток, положение это не исправило. Слишком долго отрабатывается основная процедура отрисовки - в среднем 70 mSec. Если использовать DirectX, а с ним я никогда не работал, то на сколько это ускорит вывод? Возможно вопрос покажется глупым, но хотелось бы знать.
_________________
Здесь Вы там не найдете
В начало
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
DrPass
Знающий :)
/Почетный Модератор/


Возраст: 31
Знак зодиака: Лев
Зарегистрирован: 02.05.2002
Сообщения: 5709
Откуда: Донецк
СообщениеПн, 17-Сен-2007 19:57 
Цитата

Цитата:
Если использовать DirectX, а с ним я никогда не работал, то на сколько это ускорит вывод?

Собственно вывод это ускорит на порядок, а то и больше. Но я сильно подозреваю, что причина этих 70 мсек кроется не в выводе через GDI, а в неоптимизированном алгоритме обсчета.

_________________
Да пребудет с вами Сила!
В начало
Посмотреть профиль Отправить личное сообщение
Пол:Муж Evgeny
Постоянный участник


Возраст: 51
Знак зодиака: Козерог
Зарегистрирован: 26.06.2005
Сообщения: 152
Откуда: Омск
СообщениеПн, 17-Сен-2007 20:12 
Цитата

Да уже оптимизировал все что можно, но от циклов никуда не деться, а они как раз и съедают большую часть времени. Очень много выводится мелких деталей, да и картинка сплошь динамическая, требующая постоянного обновления - вот и результат тормозов.
_________________
Здесь Вы там не найдете
В начало
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
DrPass
Знающий :)
/Почетный Модератор/


Возраст: 31
Знак зодиака: Лев
Зарегистрирован: 02.05.2002
Сообщения: 5709
Откуда: Донецк
СообщениеПн, 17-Сен-2007 20:46 
Цитата

А как реализовано построение картинки? Правильным вариантом было бы сперва сделать просто матрицу, каждый элемент которой хранил бы цвет соответствующего пиксела. А потом разом ее перенести на GDI-девайс. Прямой вывод на GDI каждого элемента действительно может круто замедлить работу
_________________
Да пребудет с вами Сила!
В начало
Посмотреть профиль Отправить личное сообщение
Пол:Муж Evgeny
Постоянный участник


Возраст: 51
Знак зодиака: Козерог
Зарегистрирован: 26.06.2005
Сообщения: 152
Откуда: Омск
СообщениеПн, 17-Сен-2007 20:54 
Цитата

В цикле, по таймеру или через поток (оба варианта дают одинаковую скорость), построение картинки ведется в дополнительный буфер, а потом разом выводится.

Добавлено спустя 11 минут 1 секунду:

Вот процедура отрисовки:

delphi:
  1.  
  2. procedure BrickOut(TDC : HDC);
  3. var
  4.   Y, X  : Integer;
  5.   K     : Byte;
  6. begin
  7.   if isBroken then
  8.   begin
  9.     BitBlt(bmPlayTmp.Canvas.Handle, 0, 0, bmPlay.Width, bmPlay.Height, TDC, 0, 0, SRCCOPY);
  10.     for Y := 0 to 14 do
  11.       for X := 0 to 12 do
  12.       begin
  13.         K := LevelBuf[Y * 13 + X];
  14.         if (K <> 0) then
  15.         begin
  16.           // выведем тень блоков
  17.           DropShadow(X * 40 + 10, Y * 20 + 88, 40, 20, bmPlayTmp.Canvas.Handle, 120);
  18.           // выведем блоки
  19.           if K = 9 then 
  20.             BltTransparent(bmPlayTmp.Canvas.Handle, X * 40, Y * 20 + 78, 40, 20, bmShine.Canvas.Handle, 0, 180, 40, 20, GetPixel(bmShine.Canvas.Handle, 180, bmShine.Height - 1))
  21.           else if K = 10 then 
  22.             BltTransparent(bmPlayTmp.Canvas.Handle, X * 40, Y * 20 + 78, 40, 20, bmShine.Canvas.Handle, 0, 80, 40, 20, GetPixel(bmShine.Canvas.Handle, 80, bmShine.Height - 1))
  23.           else
  24.             BltTransparent(bmPlayTmp.Canvas.Handle, X * 40, Y * 20 + 78, 40, 20, bmBrick[K - 1].Canvas.Handle, 0, 0, 40, 20, GetPixel(bmBrick[K - 1].Canvas.Handle, 0, bmBrick[K - 1].Height - 1));
  25.         end;
  26.       end;
  27.     BitBlt(TDC, 0, 0, bmPlay.Width, bmPlay.Height, bmPlayTmp.Canvas.Handle, 0, 0, SRCCOPY);
  28.     isBroken := False;
  29.   end
  30.   else
  31.     BitBlt(TDC, 0, 0, bmPlay.Width, bmPlay.Height, bmPlayTmp.Canvas.Handle, 0, 0, SRCCOPY);
  32. end;
  33.  
  34. procedure PlayScreenOut;
  35. const
  36.   FlashColor    : array[0..7] of Integer =
  37.                   ($0000FF, $0080FF, $00FFFF, $00FF00,
  38.                    $FFFF00, $FF0000, $FF00FF, $800080);
  39. var
  40.   Y, X, I, J    : Integer;
  41.   K          : Byte;
  42.   aRect, bRect  : TRect;
  43.   OBR      : HBRUSH;
  44.   OPEN    : HPEN;
  45. z:dword;
  46. begin
  47. z:=gettickcount;
  48.   if isBusy then
  49.     Exit;
  50.   isBusy := True;
  51.  
  52.   // очистим игровое поле
  53.   PatBlt(TDC, 0, 0, bmPlay.Width, bmPlay.Height, BLACKNESS);
  54.  
  55.   // =======================
  56.   // рисование игрового поля
  57.   // =======================
  58.   if isLevelStart or isNewBoard then
  59.     BitBlt(TDC, 0, 0, bmPlay.Width, bmPlay.Height, bmBkTemp.Canvas.Handle, 0, 0, SRCCOPY)
  60.   else
  61.   begin
  62.     if not isPause and isAppActive then  // куда двигать фон
  63.     begin
  64.       case bkScroll of
  65.         bsLeftBottom :
  66.         begin
  67.           dec(bkPoint.X);
  68.           inc(bkPoint.Y);
  69.         end;
  70.         bsLeft :
  71.         begin
  72.           dec(bkPoint.X);
  73.           bkPoint.Y := 0;
  74.         end;
  75.         bsLeftTop :
  76.         begin
  77.           dec(bkPoint.X);
  78.           dec(bkPoint.Y);
  79.         end;
  80.         bsTop :
  81.         begin
  82.           bkPoint.X := 0;
  83.           dec(bkPoint.Y);
  84.         end;
  85.         bsTopRight :
  86.         begin
  87.           inc(bkPoint.X);
  88.           dec(bkPoint.Y);
  89.         end;
  90.         bsRight :
  91.         begin
  92.           inc(bkPoint.X);
  93.           bkPoint.Y := 0;
  94.         end;
  95.         bsRightBottom :
  96.         begin
  97.           inc(bkPoint.X);
  98.           inc(bkPoint.Y);
  99.         end;
  100.         bsBottom :
  101.         begin
  102.           bkPoint.X := 0;
  103.           inc(bkPoint.Y);
  104.         end;
  105.       end;
  106.     end;
  107.  
  108.     if bkPoint.X < 0 then bkPoint.X := bkWidth - 1;
  109.     if bkPoint.Y < 0 then bkPoint.Y := bkHeight - 1;
  110.     if bkPoint.X >= bkWidth  then bkPoint.X := 0;
  111.     if bkPoint.Y >= bkHeight then bkPoint.Y := 0;
  112.  
  113.     BitBlt(TDC, 0, 0, bmPlay.Width, bmPlay.Height, bmBkTemp.Canvas.Handle, bkPoint.X, bkPoint.Y, SRCCOPY);
  114.   end;
  115.  
  116.   // ==============================
  117.   // рисование тени на игровом поле
  118.   // ==============================
  119.   DropShadow(0, 0, 20, bmPlay.Height, TDC, {bmPlay.Width, bmPlay.Height,} 120);
  120.   DropShadow(20, 0, bmPlay.Width, 14, TDC, {bmPlay.Width, bmPlay.Height,} 120);
  121.  
  122.  
  123.   // рисуем блоки
  124.  
  125.   BrickOut(TDC);        // это при постоянной прорисовке съедало половину времени
  126.  
  127.   // ===============
  128.   // появление доски
  129.   // ===============
  130.   if isNewBoard then
  131.   begin
  132.     BltTransparent(TDC, BoardPos.X, BoardPos.Y, bmNewBoard.Width, 14, bmNewBoard.Canvas.Handle, 0, (NewBoard shr 1) * 14, bmNewBoard.Width, 14, GetPixel(bmNewBoard.Canvas.Handle, 0, bmNewBoard.Height - 1));
  133.   end
  134.   else
  135.   begin
  136.     if GetAsyncKeyState(VK_LEFT) < 0 then
  137.       MoveBoard(-OffsetBoard);
  138.     if GetAsyncKeyState(VK_RIGHT) < 0 then
  139.       MoveBoard(OffsetBoard);
  140.  
  141.  
  142.     // Мигание краев доски/Flashing edge boards
  143.  
  144.     if not isLevelStart then
  145.     begin
  146.       OBR := SelectObject(bmBoard.Canvas.Handle, CreateSolidBrush(FlashColor[(FlashBoard shr 1) and 15]));
  147.       try
  148.         ExtFloodFill(bmBoard.Canvas.Handle, 09, GetPixel(bmBoard.Canvas.Handle, 09), FLOODFILLSURFACE);
  149.         ExtFloodFill(bmBoard.Canvas.Handle, 62, 9, GetPixel(bmBoard.Canvas.Handle, bmBoard.Width - 1, 9), FLOODFILLSURFACE);
  150.       finally
  151.         DeleteObject(SelectObject(bmBoard.Canvas.Handle, OBR));
  152.       end;
  153.       inc(FlashBoard);
  154.     end;
  155.  
  156.     // рисуем мяч и его тень
  157.  
  158.     if not isBallStart and not isLevelStart then
  159.     begin
  160.       DrawBitmap(BoardPos.X + ((bmBoard.Width - bmBall[0].Width) div 2) + 10, BoardPos.Y - bmBall[0].Height + 10, bmBallSh, bmBallShM, TDC);
  161.       BltTransparent(TDC, BoardPos.X + ((bmBoard.Width - bmBall[0].Width) div 2), BoardPos.Y - bmBall[0].Height, bmBall[0].Width, bmBall[0].Height, bmBall[0].Canvas.Handle, 0, 0, bmBall[0].Width, bmBall[0].Height, GetPixel(bmBall[0].Canvas.Handle, 0, bmBall[0].Height - 1));
  162.     end;
  163.    
  164.     // Рисуем тень доски/Draw shade of the board
  165.  
  166.     DrawBitmap(BoardPos.X + 10, BoardPos.Y + 10, bmBoardSh, bmBoardShM, TDC);
  167.  
  168.     // Рисуем доску/Draw board
  169.  
  170.     BltTransparent(TDC, BoardPos.X, BoardPos.Y, bmBoard.Width, bmBoard.Height, bmBoard.Canvas.Handle, 0, 0, bmBoard.Width, bmBoard.Height, GetPixel(bmBoard.Canvas.Handle, 0, bmBoard.Height - 1));
  171.  
  172.     // выводим остаток досок/deduce remainder of the boards
  173.    
  174.     for I := 0 to Life - 2 do
  175.       BltTransparent(TDC, I * bmMiniBoard.Width + 10, 457, bmMiniBoard.Width, bmMiniBoard.Height, bmMiniBoard.Canvas.Handle, 0, 0, bmMiniBoard.Width, bmMiniBoard.Height, GetPixel(bmMiniBoard.Canvas.Handle, 0, bmMiniBoard.Height - 1));
  176.   end;
  177.    
  178.   // =======================================
  179.   // показать номер при старте нового уровня
  180.   // =======================================
  181.   if islevelStart then
  182.   begin
  183.     SetRect(aRect, 0, bmPlay.Height - 140, bmPlay.Width, bmPlay.Height - 100);
  184.     DrawPath(TDC, PChar('Уровень ' + IntToStr(Level)), aRect, 3, 0, spRightBottom, True, 'Times New Roman', 30, [fsBold, fsItalic], [tsCenter, tsSingle], $FFFFFF, $000FF);
  185.     OffsetRect(aRect, 0, 40);
  186.     DrawPath(TDC, PChar('готов'), aRect, 3, 0, spRightBottom, True, 'Times New Roman', 30, [fsBold, fsItalic], [tsCenter, tsSingle], $FFFFFF, $0000FF);
  187.   end;
  188.  
  189.   // ===========
  190.   // вывод паузы
  191.   // ===========
  192.   if isPause or not isAppActive then
  193.   begin
  194.     OBR  := SelectObject(TDC, CreateSolidBrush($C7FFBE));
  195.     OPEN := SelectObject(TDC, CreatePen(PS_SOLID, 2, $0000FF));
  196.     try
  197.       SetRectEmpty(aRect);
  198.       DrawShadowTextDC(TDC, 'Pause', aRect, 5, $FF0000, $C0C0C0, spRightBottom, True, 'Times New Roman', 34, [fsBold], [tsSingle, tsCenter, tsCalc]);
  199.       InflateRect(aRect, 40, 20);
  200.       OffsetRect(aRect, (bmPlay.Width - (aRect.Right - aRect.Left)) div 2 + 40, (bmPlay.Height - (aRect.Bottom - aRect.Top)) div 2 + 20);
  201.       OffsetRect(aRect, 8, 8);
  202.       FillRect(TDC, aRect, GetStockObject(BLACK_BRUSH));
  203.       OffsetRect(aRect, -8, -8);
  204.  
  205.       Rectangle(TDC, aRect.Left, aRect.Top, aRect.Right, aRect.Bottom);
  206.       DrawShadowTextDC(TDC, 'Pause', aRect, 5, $FF0000, $C0C0C0, spRightBottom, True, 'Times New Roman', 34, [fsBold], [tsSingle, tsCenter]);
  207.     finally
  208.       DeleteObject(SelectObject(TDC, OPEN));
  209.       DeleteObject(SelectObject(TDC, OBR));
  210.     end;
  211.   end;
  212.  
  213.   // ===========
  214.   // вывод звезд
  215.   // ===========
  216.   if not isPause and isAppActive and not islevelStart and not isNewBoard then
  217.   begin
  218.     with StarGray do
  219.     begin
  220.       for I := 0 to Count - 1 do
  221.         // видимость звезды
  222.         if Visible[I] then
  223.         begin
  224.           // остался ли блок на месте
  225.           if LevelBuf[Coo[I].Y * 13 + Coo[I].X] = 0 then
  226.             Continue;
  227.           if Delay[I] > 0 then
  228.           begin
  229.             dec(Delay[I]);
  230.             Continue;
  231.           end;
  232.           BltTransparent(TDC, Coo[I].X * 40 + 14, Coo[I].Y * 20 + 82, 11, bmStarGray.Height, bmStarGray.Canvas.Handle, Frame[I] * 11, 0, 11, 11, GetPixel(bmStarGray.Canvas.Handle, 0, bmStarGray.Height - 1));
  233.           inc(Rep[I]);
  234.           if Rep[I] > 2 then
  235.           begin
  236.             Rep[I] := 0;
  237.             inc(Frame[I]);
  238.             if Frame[I] > 9 then
  239.             begin
  240.               Frame[I] := 0;
  241.               dec(Total[I]);
  242.               if Total[I] = 0 then
  243.               begin
  244.                 Visible[I] := False;
  245.                 dec(Enabled);
  246.               end;
  247.             end;
  248.           end;
  249.         end;
  250.     end;
  251.  
  252.     with StarBrown do
  253.     begin
  254.       for I := 0 to Count - 1 do
  255.         if Visible[I] then
  256.         begin
  257.           if LevelBuf[Coo[I].Y * 13 + Coo[I].X] = 0 then
  258.             Continue;
  259.           if Delay[I] > 0 then
  260.           begin
  261.             dec(Delay[I]);
  262.             Continue;
  263.           end;
  264.           BltTransparent(TDC, Coo[I].X * 40 + 14, Coo[I].Y * 20 + 82, 11, bmStarBrown.Height, bmStarBrown.Canvas.Handle, Frame[I] * 11, 0, 11, 11, GetPixel(bmStarBrown.Canvas.Handle, 0, bmStarBrown.Height - 1));
  265.           inc(Rep[I]);
  266.           if Rep[I] > 2 then
  267.           begin
  268.             Rep[I] := 0;
  269.             inc(Frame[I]);
  270.             if Frame[I] > 9 then
  271.             begin
  272.               Frame[I] := 0;
  273.               dec(Total[I]);
  274.               if Total[I] = 0 then
  275.               begin
  276.                 Visible[I] := False;
  277.                 dec(Enabled);
  278.               end;
  279.             end;
  280.           end;
  281.         end;
  282.     end;
  283.   end;
  284.  
  285.   // ===================================
  286.   // вывод игрового поля на пред-игровое
  287.   // ===================================
  288.   BitBlt(bmMain.Canvas.Handle, 27, 27, bmPlay.Width, bmPlay.Height, TDC, 0, 0, SRCCOPY);
  289.   if not isLevelStart and not isNewBoard and
  290.      not isPause and isAppActive then      // двигать стены
  291.   begin
  292.     inc(Wall.PipeOffset, 2);
  293.     if Wall.PipeOffset > 25 then
  294.       Wall.PipeOffset := 0;
  295.  
  296.     // вывести пламя
  297.     PlotFireHead;
  298.     FireLoop;
  299.     Move(TempMem^, FireMem^, FireWidth * FireHeight);
  300.     Inverse;
  301.     StretchDIBits(bmMain.Canvas.Handle, 27, SizeY - 42, bmPlay.width, 42, 0, 0, FireWidth, FireHeight,
  302.                   ResMem, DIB^, DIB_RGB_COLORS, SRCCOPY);
  303.  
  304.     if isFPS then
  305.     begin
  306.       count := count + 1;
  307.       time1 := GetTickCount;
  308.       dtime := time1 - time2;
  309.       if dtime > 10 then
  310.       begin
  311.         SetRect(aRect, 34, 30, 180, 60);
  312.         DrawShadowTextDC(bmmain.Canvas.Handle, PChar(Format('FPS %d', [MulDiv(count, 1000, dtime)])), aRect, 2, $0000FF, $C0C0C0, spRightBottom, True, 'Times New Roman', 20, [fsBold], [tsLeft]);
  313.         count := 0;
  314.         time2 := time1;
  315.       end;
  316.     end;
  317.   end;
  318.  
  319.   BitBlt(Wall.bmTemp.Canvas.handle, 0, 0, Wall.bmTemp.Width, Wall.bmTemp.Height, Wall.bmPipe_hr.Canvas.Handle, 25 - Wall.PipeOffset, 0, SRCCOPY);
  320.   BitBlt(bmMain.Canvas.Handle, bmMain.Width div 2, 2, Wall.bmTemp.Width, Wall.bmTemp.Height, Wall.bmTemp.canvas.Handle, 0, 0, SRCCOPY);
  321.  
  322.   BitBlt(Wall.bmTemp.Canvas.handle, -7, 0, Wall.bmPipe_hl.Width, Wall.bmPipe_hl.Height, Wall.bmPipe_hl.Canvas.Handle, Wall.PipeOffset, 0, SRCCOPY);
  323.   BitBlt(bmMain.Canvas.Handle, Wall.bmCorner_l.Width - 1, 2, Wall.bmTemp.Width, Wall.bmTemp.Height, Wall.bmTemp.canvas.Handle, 0, 0, SRCCOPY);
  324.  
  325.   BitBlt(bmMain.Canvas.Handle, 2, bmMain.Height - Wall.bmPipe_vl.Height + Wall.PipeOffset, Wall.bmPipe_vl.Width, Wall.bmPipe_vl.Height, Wall.bmPipe_vl.canvas.Handle, 0, 0, SRCCOPY);
  326.   BitBlt(bmMain.Canvas.Handle, bmMain.Width - Wall.bmPipe_vr.Width - 2, bmMain.Height - Wall.bmPipe_vr.Height + Wall.PipeOffset, Wall.bmPipe_vr.Width, Wall.bmPipe_vr.Height, Wall.bmPipe_vr.canvas.Handle, 0, 0, SRCCOPY);
  327.  
  328.   BltTransparent(bmMain.Canvas.Handle, 0, 0, Wall.bmCorner_l.Width, Wall.bmCorner_l.Height, Wall.bmCorner_l.canvas.Handle, 0, 0, Wall.bmCorner_l.Width, Wall.bmCorner_l.Height, GetPixel(Wall.bmCorner_l.Canvas.Handle, 0, Wall.bmCorner_l.Height - 1));
  329.   BltTransparent(bmMain.Canvas.Handle, bmMain.Width - Wall.bmCorner_r.Width, 0, Wall.bmCorner_r.Width, Wall.bmCorner_r.Height, Wall.bmCorner_r.canvas.Handle, 0, 0, Wall.bmCorner_r.Width, Wall.bmCorner_r.Height, GetPixel(Wall.bmCorner_r.Canvas.Handle, 0, Wall.bmCorner_r.Height - 1));
  330.   BitBlt(bmMain.Canvas.Handle, (bmMain.Width - Wall.bmCorner_c.Width) div 2, 0, Wall.bmCorner_c.Width, Wall.bmCorner_c.Height, Wall.bmCorner_c.canvas.Handle, 0, 0, SRCCOPY);
  331.   // ===================================
  332.  
  333.   // =========================
  334.   // выводим в основной канвас
  335.   // =========================
  336.   BitBlt(DC, 0, 0, bmMain.Width, bmMain.Height, bmMain.Canvas.Handle, 0, 0, SRCCOPY);
  337.  
  338.   isBusy := False;
  339. z:=gettickcount-z;
  340. textout(dc, 200, 40, pchar(inttostr(z)), length(inttostr(z)));
  341. end;
  342.  

_________________
Здесь Вы там не найдете
В начало
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
DrPass
Знающий :)
/Почетный Модератор/


Возраст: 31
Знак зодиака: Лев
Зарегистрирован: 02.05.2002
Сообщения: 5709
Откуда: Донецк
СообщениеПн, 17-Сен-2007 21:10 
Цитата

Ну вот и сразу огромное поле для оптимизации. Никаких BitBlt, BltTransparent и GetPixel. И, соответственно, никаких Canvas кроме последнего DC, на который будет выводиться уже построенная картинка.
_________________
Да пребудет с вами Сила!
В начало
Посмотреть профиль Отправить личное сообщение
Пол:Муж Evgeny
Постоянный участник


Возраст: 51
Знак зодиака: Козерог
Зарегистрирован: 26.06.2005
Сообщения: 152
Откуда: Омск
СообщениеПн, 17-Сен-2007 21:43 
Цитата

Чем выводить, если не ипользовать BitBlt? Ну GetPixel я могу использовать на стадии загрузки ресурса, ну а как мне выводить также частично прозрачные фрагменты, ведь даже в DirectX имеется нечто подобное - BltFast.
_________________
Здесь Вы там не найдете
В начало
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
DrPass
Знающий :)
/Почетный Модератор/


Возраст: 31
Знак зодиака: Лев
Зарегистрирован: 02.05.2002
Сообщения: 5709
Откуда: Донецк
СообщениеПн, 17-Сен-2007 22:11 
Цитата

Я ж сказал - строить изображение в матрице. Соответственно, вывод осуществляется простым присваиванием. Прозрачность - умножение цветов на показатель альфа-канала и сложение.
То, что в DirectX, выполняется аппаратно. Там можно :)

_________________
Да пребудет с вами Сила!
В начало
Посмотреть профиль Отправить личное сообщение
Пол:Муж Evgeny
Постоянный участник


Возраст: 51
Знак зодиака: Козерог
Зарегистрирован: 26.06.2005
Сообщения: 152
Откуда: Омск
СообщениеПн, 17-Сен-2007 22:16 
Цитата

Если не сложно, приведите хотя бы простой пример, а то я что то совсем торможу.
_________________
Здесь Вы там не найдете
В начало
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
DrPass
Знающий :)
/Почетный Модератор/


Возраст: 31
Знак зодиака: Лев
Зарегистрирован: 02.05.2002
Сообщения: 5709
Откуда: Донецк
СообщениеПн, 17-Сен-2007 23:02 
Цитата

В общих чертах как-нибудь так:
delphi:
  1. type
  2.   TMapPoint = record
  3.     R,G,B,Alpha: byte;
  4.   end;
  5.   TMap = array[0..1023, 0..767] of TMapPoint;
  6.   TSprite = array of array of TMapPoint;
  7.  
  8. procedure BltToMap(AMap: TMap; x, y: integer; ASprite: TSprite);
  9. var
  10.   i,j: integer;
  11. begin
  12.   for i:= 0 to Length(ASprite) - 1 do
  13.     for j:= 0 to Length(ASprite[i]) - 1 do
  14.     begin
  15.       AMap[i + x, j + y].R:= round(AMap[i + x, j + y].R * (255 - ASprite[i, j].Alpha)/255 + ASprite[i, j].R * ASprite[i, j].Alpha/255)
  16.       AMap[i + x, j + y].G:= round(AMap[i + x, j + y].G * (255 - ASprite[i, j].Alpha)/255 + ASprite[i, j].G * ASprite[i, j].Alpha/255)
  17.       AMap[i + x, j + y].B:= round(AMap[i + x, j + y].B * (255 - ASprite[i, j].Alpha)/255 + ASprite[i, j].B * ASprite[i, j].Alpha/255)
  18.     end;
  19. end;

_________________
Да пребудет с вами Сила!
В начало
Посмотреть профиль Отправить личное сообщение
Показать сообщения:   
Страница 1 из 2 На страницу 1, 2  След.
Перейти:  
Новая тема  Ответить  Печать

Вы можете начинать темы
Вы можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете присоединять файлы в этом форуме
Вы можете скачивать файлы в этом форуме
хостинг от .masterhost 
Rambler's Top100