|
::Главная страница :: С++/Си :: Статьи :: Часть 2 |
DirectDraw® - это часть выпущенного компанией Microsoft программного продукта Microsoft® DirectX® 5 Software Development Kit (SDK). Для тех из вас, кто живет на необитаемых островах, скажу, что DirectX 5 SDK - последняя версия инструмента разработчика, изначально называвшаяся Game SDK. DirectX 5 SDK содержит набор динамически подключаемых библиотек (DLL) для ускорения операций с графикой, сервисы для работы с 3D, ускорение обработки звука, расширенные функции связи, функции для работы с джойстиком и CD-ROM.
Хотя тем для описания в DirectX 5 SDK очень много, в этой статье я собираюсь рассказать, как начать программировать графическую часть игры с помощью DirectDraw. Этот процесс относительно прост, хотя и требует незначительных познаний интерфейсов OLE и Component Object Model (COM). Однако, не паникуйте. Вся информация, которую вам нужно знать об OLE и COM, будет изложена в статье.
После прочтения этой статьи вы будете в состоянии написать простую игру с использованием DirectDraw. Однако в статье рассматриваются лишь основные моменты программирования DirectDraw. В примерах рассматриваются только полноэкранные режимы с переключением страниц. Я не собираюсь рассказывать о применении DirectDraw в окне, наложениях текстур на 3D поверхность, использования видеоклипов на поверхностях DirectDraw, или как рендерить поверхности с использованием DirectDraw. Если вы интересуетесь этими темами, можно почитать документацию по DirectX 5. (Документация DirectX 5 находится в библиотеке MSDN™ в разделе Platform SDK/Graphics and Multimedia Services.)
DirectX 5 SDK может работать как под платформой Windows® 95, так и Windows NT® 5.0. Далее предполагается, что вы используете IBM-PC–совместимый компьютер под управлением Windows 95. Плюс, для программирования, компилирования, и запуска программ, использующих DirectDraw, вам нужен инсталлированный DirectX 5 SDK. Вы можете скачать SDK по адресу http://www.microsoft.com/directx/resources/devdl.htm. DirectX 5 SDK также распространяется через библиотеку MSDN (только для подписчиков уровня Professional или выше).
Также предполагается, что у вас есть C или C++ компилятор, способный откомпилировать 32-битное приложение, и что у вас есть достаточный запас знаний по программированию на C или C++. Возможно использование других языков программирования для работы с DirectX 5 SDK, но в статье они не рассматриваются. Также вам необходимы познания в программировании под Windows.
Если вы используете компилятор C, вам необходимо проинсталлировать Win32® SDK. Win32 SDK содержит библиотеки, которые нужны вам, чтобы создать исполняемые файлы из примеров, поставляемых с DirectX 5 SDK.
DirectDraw - одна из компонент DirectX 5 SDK. DirectDraw был создан для быстрой работы; библиотека позволяет получить доступ к оборудованию на самом нижнем уровне, исключая многочисленные надстройки, обычно связанные с программированием Windows-based графики. Это делает DirectDraw идеальным средством для программирования игр, где самое главное - быстрый вывод графики на экран.
Но, конечно, основное преимущество DirectDraw - это то, что предоставляется одинаковый (общий) интерфейс к видеоадаптерам различных производителей Вам не нужно беспокоиться о том, на каком оборудовании будет работать ваша программа. DirectDraw использует информацию, находящуюся на абстрактном аппаратном уровне (HAL - Hardware Abstraction Level) для определения возможностей видеоадаптера. (Информация HAL - забота производителя видеоадаптера.) HAL определяет общий интерфейс между видеоадаптерами различных производителей и приложением, использующим DirectDraw.
Однако, DirectDraw не ограничивает вас только аппаратными возможностями видеоадаптера. Если вашей игре нужно специфичное оборудование или поддержка специфичных функций, а такого оборудования нет или функция не поддерживается, ваше приложение будет использовать уровень эмуляции аппаратуры (HEL - Hardware Emulation Level), включенный в DirectDraw. В этом случае DirectDraw использует встроенную эмуляцию для "создания" тех условий, которые требуются. Конечно, у HEL есть свои недостатки, в основном связанные с быстродействием. Этот вопрос будет рассмотрен позже, в статье Determining the Capabilities of the Display Hardware.
Следующий рисунок показывает связь между DirectDraw и графическими компонентами Windows:
Рисунок 1. Связь между DirectDraw и графическими компонентами Windows
API DirectDraw состоит из объекта DirectDraw, который представляет собой индивидуальный адаптер дисплея. Кроме того, API содержит объект DirectDrawSurface, который представляет собой поверхность, объект DirectDrawPalette, представляющий палитру поверхности, и объект DirectDrawClipper, представляющий список клипов. Объект DirectDraw можно использовать для создания объектов DirectDrawSurface и DirectDrawPalette. (Также с помощью объекта DirectDraw можно создать объект DirectDrawClipper, однако обычно DirectDrawClipper создают независимо.) Единственные объекты, нужные для создания игр - DirectDraw, DirectDrawSurface, и DirectDrawPalette.
Для понимания, как работают эти объекты вам нужны некоторые знания по технологии OLE и ее интерфейсу COM. Интерфейс COM - базис всего программирования DirectDraw. Если вы уже знакомы с OLE, вы можете пропустить следующий раздел, где будет рассказано, что вам нужно знать об OLE.
DirectDraw был спроектирован на основе OLE и интерфейса COM. Если вы не знакомы с программированием OLE начало программирования DirectDraw может показаться вам очень трудным. Хотя много бумаги ушло на многотомовые издания книг об OLE и интерфейсе COM, для программирования DirectDraw вам нужно знать всего лишь несколько вещей.
Для начала, дадим определение OLE и инетрфейсу COM. OLE - это объектно-ориентированная технология, разработанная Microsoft для совместного использования информации процессами. COM - Component Object Model (компонентная объектная модель) - интерфейс, используемый при программировании OLE. Теперь, когда вы знаете эти определения, можете их забыть - они не используются в программировании. Вместо этого давайте изучим самый минимум, который необходимо знать об интерфейсе COM, чтобы использовать DirectDraw.
В основном, интерфейс COM основан на трех составляющих: объектах, интерфейсах и методах. Объект - по существу, черный ящик. Вам не нужно знать ничего об устройстве этого объекта, так как все, что вам нужно для взаимодействия с этим объектом, заключено в интерфейсе. Суть взаимодействия через интерфейс - использование методов. Образно объект можно представить в виде интегральной микросхемы (для тех, кому ближе аппаратная часть). Взаимодействие с микросхемой(объектом) заключается в подаче и снятии электрических сигналов (методы) с выводов микросхемы (интерфейс).
Все интерфейсы COM выводятся из интерфейса IUnknown OLE. Интерфейс IUnknown поддерживает жизненный цикл объекта DirectDraw. В дополнение, он определяет доступные интерфейсы данного объекта. Интерфейс IUnknown состоит из трех методов: AddRef, Release, и QueryInterface.
AddRef и Release ответственны за хранение числа ссылок на интерфейс. Когда создается экземпляр объекта, число ссылок устанавливается в 1. Если какая-нибудь функция возвращает указатель на интерфейс, ассоциированный с этим объектом, функция должна вызывать метод AddRef для увеличения числа ссылок на 1. (Если другое приложение обращается к этому объекту, число ссылок также увеличивается. Для нашей статьи это уточнение не имеет значение, так как только одно приложение будет использовать наши объекты.)
Когда вы завершили использование интерфейса, вы должны вызвать метод Release для уменьшения числа ссылок на 1. Для того, чтобы удалить из памяти объект, число ссылок должно равняться 0. Как только число ссылок объекта равняется 0, он удаляется и все его интерфейсы становятся "неправильными" (invalid).
Третий метод IUnknown, QueryInterface, запрашивает объект о поддержке определенного интерфейса. Если интерфейс поддерживается, QueryInterface возвращает указатель на этот интерфейс.
Как методы AddRef, QueryInterface, и Release связаны с DirectDraw? Во-первых, нет причин использовать AddRef или QueryInterface в простых играх, использующих только DirectDraw. Функции, создающие различные типы объектов DirectDraw должны заботиться об увеличении числа ссылок и возвращении указателей на интерфейсы. Вам неоходимо выполнить Release для каждого неявно созданного указателя. Если эти требования не выполнять, ваши программы будут заканчиваться с "утечкой памяти". В следующих примерах я покажу как все делается. (Вам понадобится использовать AddRef и QueryInterface, если ваша программа использует объекты DirectDraw, уже используемые другим приложением. Если вы используете Direct3D, необходимо использовать QueryInterface для возврата указателя на интерфейс Direct3D. Оба эти случая находятся за пределами рассмотрения данной статьи.)
Теперь давайте посмотрим на пример кода на C, использующего метод интерфейса IDirectDraw:
ddrval = lpDD->lpVtbl->SetDisplayMode( lpDD, ScreenX, ScreenY, ScreenBpp );
В этой строчке кода вы используете метод SetDisplayMode для установки видеорежима и получения результата этой операции (успешно/неудачно). Это не так важно. Важно то, как получается указатель на метод, который вы используете. Вы не можете получить прямой доступ к методам интерфейса IDirectDraw. Когда создается экземпляр объекта, создается таблица виртуальных функций, называемая vtable, которая содержит указатели на все методы интерфейса. Единственная возможность вызвать методы интерфейса - использовать указатели из этой таблицы. В предыдущем примере указатель на объект DirectDraw (lpDD)указывает на указатель, содержащий адрес таблицы vtable (lpVtbl), которая в свою очередб содержит указатели на все методы объекта—в нашем случае это метод SetDisplayMode. Связь между нашим приложением и интерфейсом объекта представлена на следующем рисунке:
Рисунок 2.
Следующий пример показывает, как сделать то же с использованием C++:
ddrval = lpDD->SetDisplayMode( ScreenX, ScreenY, ScreenBpp );
Заметим, что указатель на vtable явно больше не используется. Указатель на vtable неявный, и C++ автоматически подставляет lpDD как первый параметр. Указатель this больше не нужен, так как С++ вызывает метод относительно, используя указатель на текущий объект (в нашем случае, lpDD).
Если вы хотите узнать больше об OLE и интерфейсе COM, можете почитать книгу "Inside OLE" (автор Kraig Brockschmidt, MSDN Library/Books/Inside OLE). Это лучшая книга, объясняющая как работают OLE и COM. Я рекомендую прочитать первую главу и половину второй для хорошего понимания принципов функционирования интерфейса COM. Это поможет понять связи между DirectDraw и интерфейсом COM (если вы не поняли моих объяснений).
Я отмечал ранее, что вам нужно проинсталлировать на компьютер DirectX 5 SDK. Также вам нужно проинсталлировать компилятор C или C++. Предположим, вы используете Microsoft Visual C++® версии 5.0 и вы проинсталлировали компилятор и SDK в каталоги по умолчанию. Если вы используете другой компилятор или проинсталлировали SDK в другой каталог на жестком диске, вам нужно внести соответствующие изменения в примеры, приведенные ниже.
Так как моя цель - показать основы программирования DirectDraw, давайте используем некоторые элементарные примеры, поставляемые с DirectX 5 SDK. Они показывают, как инициализировать DirectDraw и использовать методы DirectDraw. Просмотрев эти примеры, вам будет легче понять более сложный пример игры, находящийся на CD DirectX 5 SDK.
Но перед началом работы нужно настроить окружение компилятора для работы с DirectX 5 SDK. Как это сделать, зависит от того, как вы используете Visual C++ для компиляции примеров. Я покажу вам правильную настройку в случае использования Microsoft Developer Studio, или при использовании утилиты NMAKE из командного режима.
Для тех из вас, кому нравится работать с удобным графическим интерфейсом, Visual C++ предлагает Microsoft Developer Studio. Для начала компилирования примеров из DirectX 5 SDK, вам нужно создать новый проект, подключить к нему несколько файлов и настроить окружение таким образом, чтобы компилятор нашел нужные библиотеки и включаемые файлы. Рассмотрим по пунктам, что же нужно сделать для того, чтобы откомпилировать первый пример, DDEX1.
Открыв Microsoft Developer Studio создайте новый проект:
Для подключения к проекту файлов проделайте следующие действия:.
Следующие шаги описывают, как назначить директорию, из которой будут браться включаемые файлы.
Выбираем каталог, где находятся библиотеки.
Наконец, подключаем нужные библиотеки:
Вы наверное удивляетесь, почему C:\DXSDK\SDK\INC, C:\DXSDK\SDK\SAMPLES\MISC и C:\DXSDK\SDK\LIB нужно двигать в самый верх поля Directories. Это нужно из-за того, что Visual C++ версии 5.0 уже содержит все библиотеки и включаемые файлы от DirectX 3. Чтобы быть увереным, что используются файлы DirectX 5, мы вынуждены поставить их самыми первыми в списке. В этом случае Visual C++ 5.0 найдет эти файлы первыми и не будет использовать старые файлы DirectX 3.
Многие операции, проделанные нами только что будут повторяться в дальнейших проектах.
Если вам (как и мне) нравится утилита командной строки NMAKE, то вам нужно прописать пути к каталогам, содержащим библиотеки и включаемые файлы DirectX 5. Так как в Visual C++ 5.0 используются длинные имена, то нужно проделать дополнительную работу, чтобы зставить NMAKE работать нормально. Я дам вам несколько подсказок, чтобы вы представляли, что нужно сделать.
1. @echo
off
2. set INCLUDE=%INCLUDE%;C:\DXSDK\SDK\INC
3. set LIB=%LIB%;C:\DXSDK\SDK\LIB
1. command /E:1000
что добавит тысячу байт к уже выделенному объему. Заметим, что эту строку надо выполнить первой в окне MS-DOS, так как все установки переменных окружения, выполненные до этой команды будут потеряны.
Для того, чтобы откомпилировать какой-нибудь пример зайдите в каталог, его содержащий (C:\DXDSK\SDK\SAMPLES\DDEX4, например) и введите:
NMAKE
В каталоге, в котором вы находитесь создастся папка DEBUG и туда поместится откомпилированный исполняемый файл.
Начальный размер памяти, выделяемый под переменные окружения окна MS-DOS в Windows 95 можно изменить следующим образом:
Для использования DirectDraw сначала нужно создать экзепляр объекта DirectDraw object, который будет представлять адаптер дисплея, а затем использовать методы интерфеса. Также необходимо создать один или несколько экземпляров объекта DirectDrawSurface для отображения вашей игры.
Для демонстрации посмотрим, как DDEX1 из DirectX 5 SDK создает объект DirectDraw, затем создает основную поверхность и затем переключается между поверхностями.
Замечание Файлы примера DDEX написаны на C++. Если вы используете компилятор C, вам нужно модифицировать файлы чтобы они откомпилировались. (По крайней мере, вам нужно добавить vtable и указатель this для методов интерфейса.)
Инициализация DirectDraw в примере DDEX1 содержится в функции doInit.
/*
|
Каждый из проделанных шагов необходим для создания объекта DirectDraw, а созданием и подготовкой поверхности мы займемся в следующих разделах.
Для создания экземпляра объекта DirectDraw ваше приложение может использовать функцию API DirectDrawCreate. (Заметим, что я употребил слово "может".Есть по-крайней мере еще одна возможность создания объекта DirectDraw — с использованием функции OLE CoCreateInstance — но это не обсуждается в данной статье).В DirectDrawCreate передается глобальный идентификатор (GUID) который определяет устройство вывода и в большинстве случаев он устанавливается в NULL (что говорит о том, что используется устройство вывода по умолчанию), адрес указателя, определяющий местонахождение создаваемого объекта DirectDraw, и третий параметр всегда устанавливается в NULL (используется для будущих расширений).
Следующий пример показывает, как создавать объект DirectDraw и определять, удачно ли завершилась эта операция:
ddrval = DirectDrawCreate(
NULL, &lpDD, NULL ); |
Тематические
ссылки
|
Ваша ссылка | Ваша ссылка |
Обмен кнопками, ведение статистики, реклама. |
|||