Thread
На страницу 1, 2 След.
| Автор
| Сообщение |
 Evgeny
Постоянный участник

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

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

Возраст: 51
Знак зодиака: 
Зарегистрирован: 26.06.2005
Сообщения: 152
Откуда: Омск
|
|
|
Цитата |
|
Все то что что у меня работает через таймер, строит картинку именно в памяти. Выод готовой картинки происходит общеизвестно, по событию WM_PAINT, напрямую на канвас ничего не выводится, я в свое время намучился с мерцанием.
Вот пример того кода. что я хотел использовать:
| delphi: | {$H-} {$R winp.res} Program WinPlasm; uses Windows, Messages; const width = 256; height = 200; data_size = width * height; IDR_MENU = 100; IDM_SIZE = 32003; IDM_EXIT = 32004; IDM_CPU = 32000; IDM_CPU_OPT = 32001; IDM_MMX = 32002; IDM_MMX_OPT = 32005; type TRGB32 = packed array[0..3] of Byte; const ClassName : PCHAr = 'WowkaClass'; var win : HWND; wc : WNDCLASSEX; msg : TMsg; hThread : HWND; menu : HMENU; real_width, real_height, optimal_width, optimal_height: Integer; mas : array[0..data_size] of TRGB32; function IntToStr(n : Integer) : String; begin Result := ''; while n > 0 do begin Result := chr(ord('0') + (n mod 10)) + Result; n := n div 10 end; end; function DrawThread(dr_win : DWORD) : DWORD; stdcall; label now; const cl_mas : array[0..4] of TRGB32 = ( ($FF, 0, 0, 0), ($FF,$C0, 0, 0), ($FF,$80,$40, 0), ($FF,$FF,$FF, 0), ( 0, 0, 0, 0)); var bitmap : TBitMapInfo; DC : HDC; m, I, J, time1, time2, dtime, count : Integer; s : String; buf : array[0..63] of Char; begin time2 := GetTickCount - 1; count := 0; Result := 0; with bitmap.bmiHeader do begin biSize := SizeOf(bitmap.bmiHeader); biPlanes := 1; biClrImportant := 0; biWidth := width; biHeight := height; biBitCount := 32; biCompression := BI_RGB; biSizeImage := 0; biXPelsPerMeter := 0; biYPelsPerMeter := 0; biClrUsed := 0; end; 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; function MainProc(Wnd: HWND; Msg, wParam, lParam: Longint): Longint; stdcall; var idMain : DWORD; begin Result := 0; case msg of WM_CREATE : hThread := CreateThread(NIL, DWORD(1024 * 4), @DrawThread, Pointer(wnd), DWORD(0), idMain); WM_SIZE : begin real_width := LOWORD(lParam); real_height := HIWORD(lParam); if (real_width = width) and (real_height = height) then CheckMenuItem(menu, IDM_SIZE, MF_BYCOMMAND or MF_CHECKED) else CheckMenuItem(menu, IDM_SIZE, MF_BYCOMMAND or MF_UNCHECKED); Result := DefWindowProc(wnd, msg, wparam, lparam); end; WM_KEYDOWN : if wParam = 27 then PostMessage(wnd, WM_CLOSE, 0, 0) else Result := DefWindowProc(wnd, msg, wparam, lparam); WM_COMMAND: case LOWORD(wParam) of IDM_EXIT : PostMessage(wnd, WM_CLOSE, 0, 0); IDM_SIZE : MoveWindow(wnd, 30, 30, optimal_width, optimal_height, TRUE); end; WM_DESTROY: begin TerminateThread(hThread, 0); PostQuitMessage(0); end; else Result := DefWindowProc(wnd, msg, wparam,lparam) end; end; begin ZeroMemory(@wc, SizeOf(wc)); with wc do begin cbSize := SizeOf(wc); hInstance := hInstance; Style := CS_HREDRAW or CS_VREDRAW; hbrBackground := COLOR_GRAYTEXT; lpfnWndProc := @MainProc; lpszClassName := ClassName; lpszMenuName := PChar(IDR_MENU); end; RegisterClassEx(wc); optimal_width := 520 + GetSystemMetrics(SM_CXSIZEFRAME) * 2; optimal_height := 22 + GetSystemMetrics(SM_CYSIZEFRAME) * 2 + GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYMENU); win := CreateWindowEx(0, ClassName, 'HelloWords', WS_OVERLAPPEDWINDOW, 30, 30, optimal_width, optimal_height, 0, 0, hInstance, NIL); ShowWindow(win, SW_SHOWDEFAULT); UpdateWindow(win); menu := GetMenu(win); CheckMenuItem(menu, IDM_SIZE, MF_BYCOMMAND or MF_CHECKED); CheckMenuItem(menu, IDM_CPU, MF_BYCOMMAND or MF_CHECKED); EnableMenuItem(menu, IDM_CPU, MF_BYCOMMAND or MF_DISABLED); // pascal version dont support optimization EnableMenuItem(menu, IDM_CPU_OPT,MF_BYCOMMAND or MF_DISABLED or MF_GRAYED); EnableMenuItem(menu, IDM_MMX_OPT,MF_BYCOMMAND or MF_DISABLED or MF_GRAYED); EnableMenuItem(menu, IDM_MMX, MF_BYCOMMAND or MF_DISABLED or MF_GRAYED); while GetMessage(msg, 0, 0, 0) do begin TranslateMessage(msg); DispatchMessage(msg) end; ExitProcess(0); end.
|
Самостоятельно такой код работает быстро, а в паре с таймером тормозит последний. И тут уже не важно как оптимизирован код, почему тормозит таймер? Почему приведенный код медленно работает, если его также перевести на таймер. Весь прикол в том, что я действительно использую GDI и не хотел бы в данном случае использовать DirectX. Может затея конечно дурацкая, но я хотел внизу основной картинки сделать небольшое подобие воды и похоже ничего хорошего из этого не выйдет. Если это поможет, можно привести и код работы таймера, только кусок несколько великоват. _________________ Здесь Вы там не найдете |
|
| В начало |
|
 |
DrPass
Знающий :) /Почетный Модератор/

Возраст: 31
Знак зодиака: 
Зарегистрирован: 02.05.2002
Сообщения: 5709
Откуда: Донецк
|
|
|
Цитата |
|
Нет, как бы ничего неожиданного и не происходит. Вот этот код
| Цитата: | 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
Откуда: Омск
|
|
|
Цитата |
|
Код, который я привел, писАл не я. У меня все указанные замечание были учтены с первого раза, а вот Sleep я не ставил, нужно поробовать. _________________ Здесь Вы там не найдете |
|
| В начало |
|
 |
 Evgeny
Постоянный участник

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

Возраст: 31
Знак зодиака: 
Зарегистрирован: 02.05.2002
Сообщения: 5709
Откуда: Донецк
|
|
|
Цитата |
|
| Цитата: | | Если использовать DirectX, а с ним я никогда не работал, то на сколько это ускорит вывод? |
Собственно вывод это ускорит на порядок, а то и больше. Но я сильно подозреваю, что причина этих 70 мсек кроется не в выводе через GDI, а в неоптимизированном алгоритме обсчета. _________________ Да пребудет с вами Сила! |
|
| В начало |
|
 |
 Evgeny
Постоянный участник

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

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

Возраст: 51
Знак зодиака: 
Зарегистрирован: 26.06.2005
Сообщения: 152
Откуда: Омск
|
|
|
Цитата |
|
В цикле, по таймеру или через поток (оба варианта дают одинаковую скорость), построение картинки ведется в дополнительный буфер, а потом разом выводится.
Добавлено спустя 11 минут 1 секунду:
Вот процедура отрисовки:
| delphi: | procedure BrickOut(TDC : HDC); var Y, X : Integer; K : Byte; begin if isBroken then begin BitBlt(bmPlayTmp.Canvas.Handle, 0, 0, bmPlay.Width, bmPlay.Height, TDC, 0, 0, SRCCOPY); for Y := 0 to 14 do for X := 0 to 12 do begin K := LevelBuf[Y * 13 + X]; if (K <> 0) then begin // выведем тень блоков DropShadow(X * 40 + 10, Y * 20 + 88, 40, 20, bmPlayTmp.Canvas.Handle, 120); // выведем блоки if K = 9 then 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)) else if K = 10 then 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)) else 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)); end; end; BitBlt(TDC, 0, 0, bmPlay.Width, bmPlay.Height, bmPlayTmp.Canvas.Handle, 0, 0, SRCCOPY); isBroken := False; end else BitBlt(TDC, 0, 0, bmPlay.Width, bmPlay.Height, bmPlayTmp.Canvas.Handle, 0, 0, SRCCOPY); end; procedure PlayScreenOut; const FlashColor : array[0..7] of Integer = ($0000FF, $0080FF, $00FFFF, $00FF00, $FFFF00, $FF0000, $FF00FF, $800080); var Y, X, I, J : Integer; K : Byte; aRect, bRect : TRect; OBR : HBRUSH; OPEN : HPEN; z:dword; begin z:=gettickcount; if isBusy then Exit; isBusy := True; // очистим игровое поле PatBlt(TDC, 0, 0, bmPlay.Width, bmPlay.Height, BLACKNESS); // ======================= // рисование игрового поля // ======================= if isLevelStart or isNewBoard then BitBlt(TDC, 0, 0, bmPlay.Width, bmPlay.Height, bmBkTemp.Canvas.Handle, 0, 0, SRCCOPY) else begin if not isPause and isAppActive then // куда двигать фон begin case bkScroll of bsLeftBottom : begin dec(bkPoint.X); inc(bkPoint.Y); end; bsLeft : begin dec(bkPoint.X); bkPoint.Y := 0; end; bsLeftTop : begin dec(bkPoint.X); dec(bkPoint.Y); end; bsTop : begin bkPoint.X := 0; dec(bkPoint.Y); end; bsTopRight : begin inc(bkPoint.X); dec(bkPoint.Y); end; bsRight : begin inc(bkPoint.X); bkPoint.Y := 0; end; bsRightBottom : begin inc(bkPoint.X); inc(bkPoint.Y); end; bsBottom : begin bkPoint.X := 0; inc(bkPoint.Y); end; end; end; if bkPoint.X < 0 then bkPoint.X := bkWidth - 1; if bkPoint.Y < 0 then bkPoint.Y := bkHeight - 1; if bkPoint.X >= bkWidth then bkPoint.X := 0; if bkPoint.Y >= bkHeight then bkPoint.Y := 0; BitBlt(TDC, 0, 0, bmPlay.Width, bmPlay.Height, bmBkTemp.Canvas.Handle, bkPoint.X, bkPoint.Y, SRCCOPY); end; // ============================== // рисование тени на игровом поле // ============================== DropShadow(0, 0, 20, bmPlay.Height, TDC, {bmPlay.Width, bmPlay.Height,} 120); DropShadow(20, 0, bmPlay.Width, 14, TDC, {bmPlay.Width, bmPlay.Height,} 120); // рисуем блоки BrickOut(TDC); // это при постоянной прорисовке съедало половину времени // =============== // появление доски // =============== if isNewBoard then begin 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)); end else begin if GetAsyncKeyState(VK_LEFT) < 0 then MoveBoard(-OffsetBoard); if GetAsyncKeyState(VK_RIGHT) < 0 then MoveBoard(OffsetBoard); // Мигание краев доски/Flashing edge boards if not isLevelStart then begin OBR := SelectObject(bmBoard.Canvas.Handle, CreateSolidBrush(FlashColor[(FlashBoard shr 1) and 15])); try ExtFloodFill(bmBoard.Canvas.Handle, 0, 9, GetPixel(bmBoard.Canvas.Handle, 0, 9), FLOODFILLSURFACE); ExtFloodFill(bmBoard.Canvas.Handle, 62, 9, GetPixel(bmBoard.Canvas.Handle, bmBoard.Width - 1, 9), FLOODFILLSURFACE); finally DeleteObject(SelectObject(bmBoard.Canvas.Handle, OBR)); end; inc(FlashBoard); end; // рисуем мяч и его тень if not isBallStart and not isLevelStart then begin DrawBitmap(BoardPos.X + ((bmBoard.Width - bmBall[0].Width) div 2) + 10, BoardPos.Y - bmBall[0].Height + 10, bmBallSh, bmBallShM, TDC); 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)); end; // Рисуем тень доски/Draw shade of the board DrawBitmap(BoardPos.X + 10, BoardPos.Y + 10, bmBoardSh, bmBoardShM, TDC); // Рисуем доску/Draw board 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)); // выводим остаток досок/deduce remainder of the boards for I := 0 to Life - 2 do 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)); end; // ======================================= // показать номер при старте нового уровня // ======================================= if islevelStart then begin SetRect(aRect, 0, bmPlay.Height - 140, bmPlay.Width, bmPlay.Height - 100); DrawPath(TDC, PChar('Уровень ' + IntToStr(Level)), aRect, 3, 0, spRightBottom, True, 'Times New Roman', 30, [fsBold, fsItalic], [tsCenter, tsSingle], $FFFFFF, $000FF); OffsetRect(aRect, 0, 40); DrawPath(TDC, PChar('готов'), aRect, 3, 0, spRightBottom, True, 'Times New Roman', 30, [fsBold, fsItalic], [tsCenter, tsSingle], $FFFFFF, $0000FF); end; // =========== // вывод паузы // =========== if isPause or not isAppActive then begin OBR := SelectObject(TDC, CreateSolidBrush($C7FFBE)); OPEN := SelectObject(TDC, CreatePen(PS_SOLID, 2, $0000FF)); try SetRectEmpty(aRect); DrawShadowTextDC(TDC, 'Pause', aRect, 5, $FF0000, $C0C0C0, spRightBottom, True, 'Times New Roman', 34, [fsBold], [tsSingle, tsCenter, tsCalc]); InflateRect(aRect, 40, 20); OffsetRect(aRect, (bmPlay.Width - (aRect.Right - aRect.Left)) div 2 + 40, (bmPlay.Height - (aRect.Bottom - aRect.Top)) div 2 + 20); OffsetRect(aRect, 8, 8); FillRect(TDC, aRect, GetStockObject(BLACK_BRUSH)); OffsetRect(aRect, -8, -8); Rectangle(TDC, aRect.Left, aRect.Top, aRect.Right, aRect.Bottom); DrawShadowTextDC(TDC, 'Pause', aRect, 5, $FF0000, $C0C0C0, spRightBottom, True, 'Times New Roman', 34, [fsBold], [tsSingle, tsCenter]); finally DeleteObject(SelectObject(TDC, OPEN)); DeleteObject(SelectObject(TDC, OBR)); end; end; // =========== // вывод звезд // =========== if not isPause and isAppActive and not islevelStart and not isNewBoard then begin with StarGray do begin for I := 0 to Count - 1 do // видимость звезды if Visible[I] then begin // остался ли блок на месте if LevelBuf[Coo[I].Y * 13 + Coo[I].X] = 0 then Continue; if Delay[I] > 0 then begin dec(Delay[I]); Continue; end; 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)); inc(Rep[I]); if Rep[I] > 2 then begin Rep[I] := 0; inc(Frame[I]); if Frame[I] > 9 then begin Frame[I] := 0; dec(Total[I]); if Total[I] = 0 then begin Visible[I] := False; dec(Enabled); end; end; end; end; end; with StarBrown do begin for I := 0 to Count - 1 do if Visible[I] then begin if LevelBuf[Coo[I].Y * 13 + Coo[I].X] = 0 then Continue; if Delay[I] > 0 then begin dec(Delay[I]); Continue; end; 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)); inc(Rep[I]); if Rep[I] > 2 then begin Rep[I] := 0; inc(Frame[I]); if Frame[I] > 9 then begin Frame[I] := 0; dec(Total[I]); if Total[I] = 0 then begin Visible[I] := False; dec(Enabled); end; end; end; end; end; end; // =================================== // вывод игрового поля на пред-игровое // =================================== BitBlt(bmMain.Canvas.Handle, 27, 27, bmPlay.Width, bmPlay.Height, TDC, 0, 0, SRCCOPY); if not isLevelStart and not isNewBoard and not isPause and isAppActive then // двигать стены begin inc(Wall.PipeOffset, 2); if Wall.PipeOffset > 25 then Wall.PipeOffset := 0; // вывести пламя PlotFireHead; FireLoop; Move(TempMem^, FireMem^, FireWidth * FireHeight); Inverse; StretchDIBits(bmMain.Canvas.Handle, 27, SizeY - 42, bmPlay.width, 42, 0, 0, FireWidth, FireHeight, ResMem, DIB^, DIB_RGB_COLORS, SRCCOPY); if isFPS then begin count := count + 1; time1 := GetTickCount; dtime := time1 - time2; if dtime > 10 then begin SetRect(aRect, 34, 30, 180, 60); DrawShadowTextDC(bmmain.Canvas.Handle, PChar(Format('FPS %d', [MulDiv(count, 1000, dtime)])), aRect, 2, $0000FF, $C0C0C0, spRightBottom, True, 'Times New Roman', 20, [fsBold], [tsLeft]); count := 0; time2 := time1; end; end; end; BitBlt(Wall.bmTemp.Canvas.handle, 0, 0, Wall.bmTemp.Width, Wall.bmTemp.Height, Wall.bmPipe_hr.Canvas.Handle, 25 - Wall.PipeOffset, 0, SRCCOPY); BitBlt(bmMain.Canvas.Handle, bmMain.Width div 2, 2, Wall.bmTemp.Width, Wall.bmTemp.Height, Wall.bmTemp.canvas.Handle, 0, 0, SRCCOPY); BitBlt(Wall.bmTemp.Canvas.handle, -7, 0, Wall.bmPipe_hl.Width, Wall.bmPipe_hl.Height, Wall.bmPipe_hl.Canvas.Handle, Wall.PipeOffset, 0, SRCCOPY); BitBlt(bmMain.Canvas.Handle, Wall.bmCorner_l.Width - 1, 2, Wall.bmTemp.Width, Wall.bmTemp.Height, Wall.bmTemp.canvas.Handle, 0, 0, SRCCOPY); 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); 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); 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)); 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)); 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); // =================================== // ========================= // выводим в основной канвас // ========================= BitBlt(DC, 0, 0, bmMain.Width, bmMain.Height, bmMain.Canvas.Handle, 0, 0, SRCCOPY); isBusy := False; z:=gettickcount-z; textout(dc, 200, 40, pchar(inttostr(z)), length(inttostr(z))); end;
|
_________________ Здесь Вы там не найдете |
|
| В начало |
|
 |
DrPass
Знающий :) /Почетный Модератор/

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

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

Возраст: 31
Знак зодиака: 
Зарегистрирован: 02.05.2002
Сообщения: 5709
Откуда: Донецк
|
|
|
Цитата |
|
Я ж сказал - строить изображение в матрице. Соответственно, вывод осуществляется простым присваиванием. Прозрачность - умножение цветов на показатель альфа-канала и сложение.
То, что в DirectX, выполняется аппаратно. Там можно  _________________ Да пребудет с вами Сила! |
|
| В начало |
|
 |
 Evgeny
Постоянный участник

Возраст: 51
Знак зодиака: 
Зарегистрирован: 26.06.2005
Сообщения: 152
Откуда: Омск
|
|
|
Цитата |
|
Если не сложно, приведите хотя бы простой пример, а то я что то совсем торможу. _________________ Здесь Вы там не найдете |
|
| В начало |
|
 |
DrPass
Знающий :) /Почетный Модератор/

Возраст: 31
Знак зодиака: 
Зарегистрирован: 02.05.2002
Сообщения: 5709
Откуда: Донецк
|
|
|
Цитата |
|
В общих чертах как-нибудь так:
| delphi: | type TMapPoint = record R,G,B,Alpha: byte; end; TMap = array[0..1023, 0..767] of TMapPoint; TSprite = array of array of TMapPoint; procedure BltToMap(AMap: TMap; x, y: integer; ASprite: TSprite); var i,j: integer; begin for i:= 0 to Length(ASprite) - 1 do for j:= 0 to Length(ASprite[i]) - 1 do begin 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) 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) 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) end; end;
|
_________________ Да пребудет с вами Сила! |
|
| В начало |
|
 |
|
| Страница 1 из 2 |
На страницу 1, 2 След. |
Новая тема
Ответить
Печать
|
Вы можете начинать темы Вы можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете голосовать в опросах Вы не можете присоединять файлы в этом форуме Вы можете скачивать файлы в этом форуме
|
|