Читаем Графика DirectX в Delphi полностью

Переменная Pict данного типа хранит растровое изображение, а массив заполняется в пользовательской процедуре, вызываемой в начале работы приложения и при каждом восстановлении поверхностей:

function TfrmDD.Prepare : HRESULT; var

desc : TDDSURFACEDESC2;

i, j : Integer;

hRet : HRESULT;

begin

hRet := Clear; // Очистка первичной поверхности

if Failed (hRet) then begin Result := hRet;

Exit;

end;

// Посередине экрана выводится картинка с черепом hRet := FDDSPrimary.BltFast (193, 113, FDDSImage, nil,

DDBLTFAST_WAIT or DDBLTFAST_SRCCOLORKEY);

if Failed (hRet) then begin Result := hRet; Exit;

end;

ZeroMemory (@desc, SizeOf(desc));

desc.dwSize := SizeOf(desc);

// Запираем поверхность

hRet := FDDSPrimary.Lock (nil, desc, DDLOCK_WAIT, 0);

if Failed (hRet) then begin

Result := hRet;

Exit;

end;

// Считываем в массив Pict содержимое нужных пикселов экрана for i := 0 to 255 do

for j := 0 to 255 do

Pict [i, j] := PBYTE (Integer (desc.IpSurface) +

(j + 113) * desc.lPitch + (i + 193)); Result := FDDSPrimary.Unlock (nil);

end;

Заполнить массив можно многими разными способами, например напрямую из растра. Также обращаю внимание, что массив можно заполнять и из содержимого поверхности FDDSImage, без промежуточного блиттинга на первичную. Если ключом является не черный цвет, следует анализировать цвет каждого пиксела и отбрасывать пиксел с цветом ключа, а при использовании черного цвета в качестве ключа можно просто копировать значения пикселов в массив. Так мы будем поступать в последующих примерах.

Переменная Angle хранит текущее значение угла поворота растрового изображения в радианах. Изменяется ее значение при обновлении окна через некоторый промежуток времени:

function TfrmDD.UpdateFrame : HRESULT; var

hRet : HRESULT; begin

Result := DD FALSE;

ThisTickCount := GetTickCount;

if ThisTickCount - LastTickCount > 30 then begin

Angle := Angle +0.1; // Угол в радианах

// Надо уберечься от переполнения

if Angle > 2 * Pi then Angle := Angle - 2 * Pi;

while True do begin

if Failed (Rotating) then begin // Поворот на Angle

hRet := RestoreAll;

if Failed (hRet) then begin // Неустранимая ошибка Result := hRet; Exit; end

end else Break end;

LastTickCount := GetTickCount; end;

Result := DD_OK; end;

Пользовательская функция Rotating, несмотря на свое название, не содержит кода самого поворота картинки, а лишь заменяет содержимое части экрана:

function TfrmDD.Rotating : HRESULT;

var

desc : TDDSURFACEDESC2;

i, j : Byte;

Image : TByteArray;

hRet : HRESULT;

begin

ZeroMemory (@desc, SizeOf(desc));

desc.dwSize := SizeOf(desc); // Получаем растр из первоначального путем

// поворота на угол Alpha относительно середины растра

Image := Rotate (Pict, 127, 127, Angle);

hRet := FDDSPrimary.Lock (nil, desc, DDLOCK_WAIT, 0);

if Failed (hRet) then begin Result := hRet;

Exit;

end;

// Заполняем блок экрана новым растром for i := 0 to 255 do

for j := 0 to 255 do

PByte (Integer (desc.IpSurface) + (j + 113) * desc.lPitch +

i + 193)Л := Image [i, j]; Result := FDDSPrimary.Unlock (nil);

end;

Самая интересная функция примера - пользовательская функция, возвращающая растр, повернутый на заданный угол относительно указанной точки:

function TfrmDD.Rotate (const pictOriginal : TByteArray; // Исходный растр

// Точка в растре, задающая оси поворота

const iRotationAxis, jRotationAxis: Integer;

const ug : Single): TByteArray; // Угол, радианы

type // Тип, соответствующий одной строке массива

wrkByteArray = Array [0..255] of Byte;

var

i, j :Integer;

iOriginal: Integer;

iPrime: Integer;

jOriginal: Integer;

jPrime: Integer;

RowOriginal :^wrkByteArray;

RowRotated :^wrkByteArray;

sinTheta :Single;

cosTheta :Single;

begin

sinTheta := sin(ug); // Для оптимизации синусы и косинусы

cosTheta := cos(ug); // Запоминаем в рабочих переменных

for j := 255 downto 0 do begin // Строки результирующего массива

RowRotated := @result [j, 0]; // Указатель на очередную строку

jPrime := j - jRotationAxis; // Смещение от оси по Y

for i := 255 downto 0 do begin // Цикл по столбцам

iPrime := i - iRotationAxis; // Смещение от оси по X

iOriginal := iRotationAxis + trunc(iPrime * cosTheta -

jPrime * sinTheta); // Координаты нужной точки по X

jOriginal := JRotationAxis + trunc(iPrime * sinTheta +

jPrime * cosTheta); // Координаты нужной точки по Y

// После поворота некоторые точки на границе

//не имеют аналога в старом растре

if (iOriginal >= 0) and (iOriginal <= 255) and // He границы

(jOriginal >= 0) and (jOriginal <= 255) then begin

// Копируем в новый растр точку RowOriginal := SpictOriginal[jOriginal, 0];

RowRotated'^ [i] := RowOriginal^[iOriginal]

end

else RowRotated[i] := 0; // Границы заполняем черным цветом

end

end;

end;

В этом и следующем примерах я не применяю двойную буферизацию. Если же с использованием вашей видеокарты по этой причине шоу разворачивается слишком медленно, в качестве упражнения установите двойную буферизацию.

Визуальные эффекты

В данном разделе мы закрепим наши навыки непосредственного доступа к пикселам и научимся создавать некоторые несложные эффекты.

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных