KnigaRead.com/

Михаил Краснов - Графика DirectX в Delphi

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Михаил Краснов, "Графика DirectX в Delphi" бесплатно, без регистрации.
Перейти на страницу:

XPos := NewXPos; ZPos := NewZPos;

end;


end;


// Обработка клавиатуры

Result := DIKeyboard.GetDevicestate(SizeOf(KeyBuffer), @KeyBuffer);

if KeyBuffer[DIK_ESCAPE] and $80 <> 0 then begin // Esc

Close;

Exit;

end;


// Нажата клавиша "вправо", вычисляем новое положение в пространстве

if KeyBuffer[DIK_RIGHT] and $80 <> 0 then begin

XPos := XPos - sin(RotY) * 0.05;

ZPos := ZPos - cos(RotY) * 0.05;

end;


// Нажата клавиша "влево"

if KeyBuffer[DIK_LEFT] and $80 <> 0 then begin

XPos := XPos + sin(RotY) * 0.05;

ZPos := ZPos + cos(RotY) * 0.05;

end;


// Нажата клавиша "вниз"

if KeyBuffer[DIK_DOWN] and $80 о 0 then begin

XPos := XPos + sin(RotY - Pi / 2) * 0.05;

ZPos := ZPos + cos(RotY - Pi / 2) * 0.05;

end;


// Нажата клавиша "вверх" if KeyBuffer[DIK_UP] and $80 <> 0 then begin

XPos := XPos + sin(RotY + Pi / 2) * 0.05;

ZPos := ZPos + cos(RotY + Pi / 2) * 0.05;

end;


// Нажата клавиша "F", показывать ли значение FPS

if KeyBuffer[DIK_F] and $80 <> 0 then begin

flgFPS := not flgFPS; // Обращение значения флага

Sleep (50); // Маленькая пауза

end;


// Клавиша <Page Up>, голову задираем вверх

if KeyBuffer[DIK_PRIOR] and $80 <> 0 then begin

Lookupdown := Lookupdown + 0.05;

if Lookupdown > 1 then Lookupdown := 1;

end;


// Клавиша <Page Down>, голову опускаем вниз

if KeyBuffer[DIK_NEXT] and $80 <> 0 then begin

Lookupdown := Lookupdown - 0.05;

if Lookupdown < -1 then Lookupdown := -1;

end;


end;


Обратите внимание, что при перемещении с помощью мыши осуществляется проверка, нет ли на пути движения препятствия, стены комнаты или ящика. При нажатии клавиш такую проверку не произвожу, и игрок свободно проходит через все препятствия. Опускаю я проверку, чтобы определить, сильно ли она замедляет работу программы.

Для проверки того, свободен ли путь, я применяю самый простой метод: в заднем буфере сцена воспроизводится в новой точке, взгляд наблюдателя при этом повернут в направлении движения. Глаз наблюдателя опускаем ближе к полу, и выясняем цвет точки, расположенной прямо по ходу движения. Поскольку пол окрашивается красным, а препятствия и фон - синим, то синий цвет контрольной точки означает, что игрок вплотную подошел к непреодолимому препятствию или выходит за границу сектора:


function TfrmD3D.TestRender (const XPos, ZPos, RotY : Single) : BOOL;

var

i : Integer; matView : TD3DMatrix; d3dlr : TD3DLOCKED_RECT;

dwDstPitch : DWORD; DWColor : DWORD;

В : Byte; // Доля синего пиксела контрольной точки

begin

В := 0; // Предотвращение замечаний компилятора

// Смотрим на сцену из новой точки, по вертикали - ближе к полу

SetViewMatrix(matView, D3DVector(XPos, 0,1, ZPos),

D3DVector(XPos + cos(RotY), 0.1,

ZPos -sin(RotY)), ZVector); // Упрощенное воспроизведение сцены

with FD3DDevice do begin

Clear(0, nil, D3DCLEAR_TARGET or D3DCLEAR_ZBUFFER,

$000000FF, 1.0, 0); BeginScene;

// Отключаем источники света

-SetRenderState(D3DRS_LIGHTING, DWORD (False)); // Использовать диффузный компонент описания вершин SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);

SetTransform(D3DTS_VIEW, matView);

SetStreamSource(0, FD3DVB, SizeOf(TNormDiffTextVertex));

SetVertexShader(D3DFVF_NORMDIFFTEXTVERTEX); SetTransform(D3DTS_WORLD, IdentityMatrix);

end;


// Рисуем только комнату

for i := 0 to NumTriangles - 1 do with FD3DDevice do

DrawPrimitive(D3DPT_TRIANGLELIST, 1*3, 1);

with FD3DDevice do begin

EndScene;

// Получаем доступ к заднему буферу

GetBackBuffer (О, D3DBACKBUFFER_TYPE_MONO, FD3SurfBack);

SetRenderState(D3DRS_LIGHTING, DWORD (True));

end;


// Запираем задний буфер

FD3SurfBack.LockRect (d3dlr, nil, D3DLOCK_READONLY);

dwDstPitch := d3dlr.Pitch;

// Определяем долю синего в контрольной точке case

FD3DfmtFullscreen of D3DFMT_X8R8G8B8 : begin

DWColor := PDWORD (DWORD(d3dlr.pBits) + TestPointY * dwDstPitch +

TestPointX * 4)^; В := DWColor and $lf;

end;


D3DFMT_R5G6B5 : begin

DWColor := PDWORD (DWORD(d3dlr.pBits) + TestPointY * dwDstPitch +

TestPointX * 2}Л; В := DWColor and $lf;

end;


end;


FDSSurfBack.UnLockRect;

// Нет синего цвета, значит можно пройти

Result := not (В <> 0);

end;


Синий цвет взят мною в качестве контрольного, поскольку для его вырезки требуется минимум операций. Замечу, что код этой функции можно дополнительно оптимизировать, например, вполне можно обойтись без использования промежуточной переменной DWColor.

Если установлен 24-битный режим, соответствующий формату D3DFMT_R8G8B8, то Х-координату контрольной точки надо умножить на 3, именно столько байт отводится для одного пиксела в этом режиме.

Контрольная точка для определения столкновения с препятствиями берется одна - посередине экрана по горизонтали, на 10 пикселов выше нижней границы экрана:


ScreenWidth := GetSystemMetrics(SM_CXSCREEN);

ScreenHeight := GetSystemMetrics(SM_CYSCREEN);

TestPointX := ScreenWidth div 2;

TestPointY := DWORD{ScreenHeight - 10);

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

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

Что вы узнали в этой главе

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

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

Закончилась глава примером простого движка трехмерной игры.


Заключение


Надеюсь, книга принесла вам пользу и удовольствие, но, возможно, у вас появились и замечания, которыми обязательно поделитесь со мной: [email protected]

С данной книгой вы начали знакомство с DirectX, но это только вводное руководство, которое охватывает лишь небольшую толику огромной темы. В ней, например, нет ни слова о библиотеке Direct3DX, а это очень важная тема. Отказался я от ее рассмотрения постольку, поскольку для программ, написанных на Delphi, доступна она лишь в виде дополнительных и нестандартных файлов. Тем не менее после прочтения книги вам легко будет разобраться с этой библиотекой, существенно упрощающей многие действия, такие, например, как загрузка текстур.

Книга закончилась, но тема ее не закрыта вместе с ней, и, наверняка, вы пожелаете узнать нечто большее. Я хочу указать вам места, где вы найдете еще массу информации. Помимо адресов, указанных во введении, приведу еще несколько полезных ссылок.

ПРИЛОЖЕНИЕ 1

Глоссарий


2D Graphics

Двумерная графика. Действие в такой графике происходит на одной плоскости.

3D Graphics

Трехмерная графика. Графическое отображение на дисплее трехмерной сцены.

Alpha

Альфа. Коэффициент прозрачности. В описание цвета может входить специальная составляющая, называемая альфа-каналом.

Alpha blending

Альфа-смешение. Смешивание значений цветов исходного и результирующего пикселов для достижения эффекта прозрачности и просвечивания.

Alpha channel

Альфа-канал. Массив значений, определяющих способ объединения пикселов изображения-источника с изображением-приемником. Альфа-буфер может использоваться для реализации прозрачности, размытия границ и создания тумана.

Ambient

Окружающая среда. Источник света, который светит одинаково во всех направлениях, все объекты освещаются с равной интенсивностью.

API (Application Programming Interface)

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

Back buffer

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

BitBLT (Bit BLock Transfer)

Графическая операция, при которой прямоугольная область пикселов копируется между различными участками памяти с учетом требований графической памяти.

Bitmap

Прямоугольный битовый массив. Чаще всего применяется для хранения образа растра.

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*