- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Графика DirectX в Delphi - Михаил Краснов
Шрифт:
Интервал:
Закладка:
Такой способ общения с пользователем ущербен еще по той причине, что он не работает в палитровом режиме. Из-за этого я не мог рекомендовать его для применения в функции вывода сообщения об ошибке, используемой нами в предыдущих примерах.
Учтите, что наш хранитель экрана требует небольших доработок, для оконного режима следует различать установленное разрешение рабочего стола. т. к. при 32-битной глубине возможно искаженное масштабирование образов.
Использование отсечения в полноэкранном приложении
Имея дело с Delphi, вам наверняка жалко будет потерять все ее прелести и мощь разработки диалоговых средств, расстаться с визуальными компонентами только потому, что при перемещении окна могут остаться серые пятна.
Специально для этого случая я подготовил пример, иллюстрирующий, как можно эффектно комбинировать обычный вывод средствами GDI и DirectDraw. Это проект каталога Ex11, где посередине экрана отображается репродукция самого популярного шедевра живописи, а по бокам разбросаны стандартные интерфейсные элементы (рис. 5.11).
В программе задается режим 800x600 пикселов, уровень доступа - исключительный. При воспроизведении происходит блиттинг на первичную поверхность содержимого вспомогательной поверхности, а для того, чтобы воспроизведение осуществлялось только в пределах центральной области экрана, я использую отсечение, знакомое нам по оконным приложениям. Но теперь оно ограничивает строго определенную область экрана, а не связывается с окном приложения. Если ранее для связывания отсечения с окном использовался метод SetHWnd, то в этом примере вызывается метод SetciipList. В общем случае последний метод может применяться для создания и непрямоугольных областей вывода, для описания их служат регионы:
var
rgn : TRgnData; // Вспомогательная переменная, описьшает набор регионов
wrk : TRECT; // Прямоугольник, описывающий наш единственный регион
...
SetRect {wrk, 230, 0, 620, 600); // Задаем область вывода на экране
with rgn.rdh do begin // Заполняем поля структуры
dwSize := SizeOf (RGNDATAHEADER); // Это обязательно, как всегда
iType := RDH_RECTANGLES; // Единственно возможное значение поля
nCount := 1; // Количество задействованных регионов
nRgnSize := Sizeof(TRECT); // Размер единицы информации
end;
PRECT(@rgn.Buffer)Л := wrk; // Заносим в буфер наш единственный регион
if FDD.CreateClipper(0, FDDClipper, nil) = DD_OK then begin
FDDClipper.SetClipList (@rgn, 0); // Задаем область отсечения
FDDSPrimary.SetClipper (FDDClipper) ;
end;
Замечу, что вспомогательная структура, представленная здесь, является системной и не связана исключительно с DirectX. Заполняя поле buffer этой структуры, вы можете получить холсты замысловатой формы.
Приведу еще один способ работы с методом SetciipList. Вот код, который способствует отсечению, аналогичному отсечению предыдущего примера:
var
hrg : HRGN; // Регион
rgnDataBuffer: Array [0..1023] of BYTE; // Массив списка регионов
...
hrg := CreateRectRgn (230, 0, 620, 600); // Создание нужного региона
// Заполняем массив данными
GetRegionData(hrg, SizeOf(rgnDataBuffer), @rgnDataBuffer);
DeleteObject(hrg);
if FDD.CreateClipper(0, FDDClipper, nil) = DD_OK then begin
FDDClipper.SetClipList (@rgnDataBuffer, 0); // Задаем отсечение
FDDSPrimary.SetClipper(FDDClipper);
end;
Отсечение для полноэкранных приложений может использоваться и для того, чтобы полностью решить проблему с выводом образов вблизи границ. В проекте каталога Ех12 курсор заменен логотипом DirectX, динамически меняющим свой размер. Для такой ситуации задание положения курсора становится трудной задачей. Мы не можем пользоваться решениями предыдущих примеров с замененным курсором приложения. Присовокупление отсечения к экрану позволяет совершенно не задумываться о текущем размере образа курсора и его положении, при его воспроизведении вблизи границ образ отсекается совершенно корректно (рис. 5.12).
Аналогично предыдущему примеру, объект отсечения строится на основе региона, но здесь регион представляет собой простой прямоугольник, связанный с размерами экрана:
SetRect (wrk, О, О, 800, 600);
with rgn.rdh do begin
dwSize := SizeOf (RGNDATAHEADER);
Type := RDH_RECTANGLES;
nCount := 1;
nRgnSize := Sizeof(TRECT);
end;
PRECT(@rgn.Buffer)Л := wrk;
if FDD.CreateClipper(0, FDDClipper, nil) = DD_OK then begin
FDDClipper.SetClipList (@rgn, 0);
FDDSBac k.SetClipper(FDDC1ippe r);
end;
При перерисовке кадра образ курсора растягивается на величину Scale:
function TfrmDD.UpdateFrame : HRESULT;
var
hRet : HRESULT;
wrkRect : TRECT;
begin
// Вывод фона
hRet := FDDSBack.Blt (nil, FDDSBackGround, nil, DDBLT WAIT, nil);
if Failed (hRet) then begin Result := hRet; Exit; end;
// Прямоугольник области образа курсора
SetRect (wrkRect, mouseX, mouseY, mouseX + Scale, mouseY + Scale);
// Масштабирование образа курсора, используется цветовой ключ
hRet := FDDSBack.Blt (SwrkRect, FDDSImage, nil, DDBLT_WAIT or
DDBLT_fCEYSRC, nil) ; if Failed (hRet) then begin
Result := hRet;
Exit;
end;
Result := FDDSPrimary.Flip(nil, DDFLIP_WAIT)
end;
Библиотека CDX
Наверняка многие из читателей этой книги захотят создать собственную вспомогательную библиотеку, облегчающую программирование приложений на основе DirectDraw. Прежде чем приступать к этому мероприятию, стоит познакомиться с уже готовыми решениями. В данном разделе вас ждет краткий экскурс по функциям очень популярной библиотеки CDX, реализованной по лицензии GNU. Библиотека написана на С, и я перевел на Delphi лишь небольшую ее часть, а полностью библиотеку вы можете получить по адресу http://www.cdx.sk/.
Начнем с проекта каталога Ех13, простейшего примера, выводящего на экране по ходу своей работы разноцветные прямоугольники (рис. 5.13).
В списке uses добавилось подключение модуля coxscreenx, а перечень переменных, связанных с графикой, совсем короткий:
GameScreen : CDXScreen;
Вообще, код сильно упрощается, а инициализация графики сведена к одному оператору:
GameScreen := CDXScreen.CreateCDXScreenCustomBPP(Handle, ScreenWidth,
ScreenHeight, ScreenBitDepth);
Код перерисовки окна также состоит из одного действия:
GameScreen.GetAppFrontBuffer.Rect(random(ScreenWidth),
random(ScreenHeight),
random(ScreenWidth),
random(ScreenHeight),
random(254));
To есть, рисуем очередной прямоугольник прямо на переднем буфере.
Работа приложения завершается после нажатия любой клавиши. По окончании работы приложения удаляется наш единственный объект:
if Assigned (GameScreen) then GameScreen.Destroy;
Подход, предлагаемый CDX, вам сильно напомнит то, что мы встречали в реализации модуля DDUtil для восьмой версии DirectX, но исторически первой появилась CDX. Библиотека специально предназначена для разработки игр и охватывает не только DirectDraw, но и все остальные модули DirectX.
Следующий пример, проект каталога Ех14, иллюстрирует некоторые моменты работы с фоном. Экран разбит на четыре части, в каждой из которых выводится своя фоновая картинка (рис. 5.14).
По нажатии клавиш управления курсором ландшафт в каждом секторе циклически сдвигается. В программе появились дополнительные переменные, связанные с фоном и обработкой клавиатуры:
Gamelnput : CDXInput; // Объект, связанный с вводом
GameScreen : CDXScreen; // Главный объект вывода
Landscape : CDXTile; // Загружаемая картинка
Mapl : CDXMap; // Секторы, отдельные окна экрана
Мар2 : CDXMap;
МарЗ : CDXMap;
Мар4 : CDXMap;
MapScrollSpeed : Integer = 4; // Скорость передвижения фона
К Зафужаемая картинка объединяет четыре шаблона заполнения окна, каждый имеет размеры 64x64 пикселов:
procedure ТfrmDD.FormCreate(Sender: TObject);
begin
Gamelnput := CDXInput.CreateCDXInput; // Инициализация ввода
Gamelnput.Create(HInstance, Handle);
GameScreen := CDXScreen.CreateCDXScreenCustomBPP(Handle, ScreenWidth, ScreenHeight, ScreenBitDepth);
GameScreen.LoadPalette('Anim.bmp1); // Палитровый режим
// Загрузка картинки с 4-мя шаблонами заполнения экрана, 64x64 пиксела
Landscape := CDXTile.CDXTileCustom(GameScreen,'Anim.bmp',64, 64, 4);
// Создаем четыре схемы заполнения фона
Mapl := CDXMap.CDXMap(Landscape, GameScreen);
Mapl.CreateMap(64, 64, 1);
Map2 := CDXMap.CDXMap(Landscape, GameScreen);
Map2.CreateMap(64, 64, 2) ;
МарЗ := CDXMap.CDXMap(Landscape, GameScreen);
Map3.CreateMap(64, 64, 3);
Map4 := CDXMap. CDXMap (Landscape, GameScreen);
Map4.CreateMap(64, 64, 4);
end;
Поскольку нумерация шаблонов основана на нуле, в картинки включают дополнительный, неиспользуемый фон, идущий первым.
Код обработки клавиш легко читается, смысл всех действий вам должен быть понятен:
function KeyDown (Key : Byte): BOOL; // Вспомогательная функция
begin
Result := Gamelnput.Keys[Key] = 128; // Нажата ли клавиша
end;
procedure UpdateKeys; // Процедура обработки клавиатуры
begin
if KeyDown(DIK_RIGHT) then begin // Стрелка вправо
Mapl.WrapScrollRight(MapScrollSpeed); // Сдвиг вправо содержимого
Map2.WrapScrollRight(MapScrollSpeed); // Всех четырех окон
МарЗ.WrapScrollRight(MapScrollSpeed);
Мар4.WrapScrollRight(MapScrollSpeed);
end;
if KeyDown(DIK_LEFT) then begin // Стрелка влево
Mapl.WrapScrollLeft(MapScrollSpeed);
Map2.WrapScrollLeft(MapScrollSpeed);
МарЗ.WrapScrollLeft(MapScrollSpeed);
Map4.WrapScrollLeft(MapScrollSpeed);
end;
if KeyDown(DIK_UP) then begin // Стрелка вверх
Mapl.WrapScrollUp(MapScrollSpeed);
Map2.WrapScrollUp(MapScrollSpeed);
МарЗ.WrapScrollUp(MapScrollSpeed);
Map4.WrapScrollUp(MapScrollSpeed);
end;
if KeyDown(DIK_DOWN) then begin // Стрелка вниз

