[Главная] [Новости] [Статьи] [Игры] [Проекты] | [Автор] | |||
Основы 3D-программирования DirectX8.1 в Delphi 6-7: теоретические и практические основы создания игр. | ||||
Вывод
Заставки |
||||
Продолжаем серию уроков, посвященных разработке Delphi DirectX игры. В данном уроке показано как вывести 2D-изображение на поверхность 3D-сцены. Дополнительно показан один из способов "затухания" экрана для эффектного вывода фирменной заставки. | ||||
[Все уроки] | ||||
Урок построен в форме упражнений. В упражнениях даются примеры модификаций исходного кода и краткое описание того, что при этом наблюдается и как это объясняется. | Выполняя упражнения Вы лучше вникнете в суть проблемы. | |||
ПОСТАНОВКА ЗАДАЧИ: Требуется организовать вывод 2D-изображения (текстуры) в 3-х мерной сцене. | В чём суть проблемы? Суть в том, что при программировании Direct3D для вывода 2D-изображений отсутствуют специальные методы. Как это организовать - решаем вместе. | |||
Для выполнения упражнений Вам понадобится: - архив с исходным кодом; (588 Кб) - архив с ОБЩИМ КОДОМ; (772 Кб) |
Архив с исходным кодом содержит пример решения поставленной задачи, архив с общим кодом - содержит дополнительный общий код необходимый при разработке Delphi DirectX 8.1 - приложений. | |||
Для начала откомпилируйте пример и запустите приложение. Убедитесь, что всё работает. (Если нет, то читайте файлы readme.txt приложенные к архивам) |
||||
Нормально работающий пример (см. файл game_gui.exe внутри архива game_gui.rar) должен давать следующий результат: создание нормального Windows-окна, постепенное проявление на экране заставки, выдерживание ее некоторое время, затухание, вывод некототорой 3D-сцены (поверхность суши). Выход из приложения - [Escape]. |
||||
Рассмотрим содержание примера с исходным кодом (game_gui.dpr). Приложение построено на принципах стандартного WinAPI-приложения. Для лучшего уяснения того, что это такое обратитесь к предыдущим урокам. Хорошим стартом в понимании разработки Delphi DirectX - игр является также пример игры - Donuts3D. |
||||
Класс приложения - TD3DGameApp. Название класса чисто условное и его легко изменить в своих приложениях. Если Вы заглянете в исходный код (файл Main.pas проекта game_gui.dpr), то увидите что данный класс производится от TD3DAbstractApp. Основа данного класса приложения - из Donuts3D с небольшими изменениями. | ||||
Лучше уяснить структуру и функционирование данного класса можно рассмотрев пример Donuts3D. В контексте данного урока важны следующие опорные моменты: SplashGameGUI: TD3DImage2D; //внутри класса объявлено следующее поле В методе TD3DGameApp.DrawScreenSplash помимо прочего вызывается метод - SplashGameGUI.DrawScaled(-1.05, 0.55, 0.9, 1.34, 1.34, DrawD3DImage2D_Filtered, Alpha); Это и есть вывод заставки на экран. |
||||
Как видим, для вывода 2D-изображения в 3D-сцене используется класс TD3DImage2D. Реализация этого класса находится в модуле D3DGUI.pas. Этот модуль и этот класс могут послужить Вам примером того, как разработать новые классы для выполнения необходимых действий по подготовке игрового процесса. Ссылка на D3DGUI добавлена в uses модуля Main.pas | ||||
Вообще говоря, вывод 2D-изображения в 3D-сцене можно осуществить так, как это делается при выводе 2D-спрайтов (см. Donuts3D). Но тогда обязательно требуется использование камеры (CD3DCamera). Это не составляет никакой проблемы, как раз наоборот, рядом с игровым меню, на заднем плане, может отрисовываться какая-либо анимированная демонстрационная сцена игры, что даже улучшит внешний вид игрового экрана меню. Однако при этом нужно не забывать про то, что методы вывода 2D-изображения методом 2D-спрайтов (технология, известная под названием Billboarding) должны вызываться там же, где используется камера. В противном случае Вы будете ломать голову почему всё написано правильно, а 2D-изображения так и нет в сцене. | ||||
Обратите внимание на код внутри методов TD3DGameApp.DrawScreenSplash и TD3DGameApp.DrawDisplayList Оба они содержат вызов метода Draw2DPictures; Однако результат появляется только в методе TD3DGameApp.DrawDisplayList. Почему? Именно по указанной причине: в методе TD3DGameApp.DrawScreenSplash нет установки вида из камеры (CD3DCamera.SetViewParams). В методе DrawDisplayList установка вида из камеры происходит в методе UpdateDisplayList, который вызывается из FrameMove. FrameMove вызывается в методе Run до метода Render. А уже Render содержит соответствующий вызов TD3DGameApp.DrawDisplayList. Если Вам не совсем понятно что к чему, обратитесь к схеме Структура функционирования типового DirectX-приложения, а также к исходному коду. |
||||
В модуле D3DGUI.pas применяется более изящное решение. Если Вы хоть немного разбирались с Delphi DirectX, то наверное уже задавались вопросом каким образом осуществляется вывод текста. Для этого служит типовой модуль D3DFont.pas (представляющий собой адаптацию D3DFont.h + D3DFont.cpp из DirectX SKD). Там вы найдете класс CD3DFont. Внимательно посмотрев на реализацию методов DrawText и DrawTextScaled Вы найдете ответ на вопрос. | ||||
В модуле D3DGUI.pas как раз и применяется данное решение, т.е. вывод 2D-изображения осуществляется практически аналогично выводу текста классом CD3DFont. Есть конечно и некоторые отличия, но их Вы найдете в D3DGUI.pas | ||||
Расскажем теперь о правилах использования класса TD3DImage2D (эти правила касаются использования любых Direct3D8-производных объектов сцены - т.е. всего того, что будет отрисовываться на экране через D3D или помогать этому процессу - моделей, текстур, эффектов (шейдеры) и т.п.). | ||||
- внутри класса приложения или в виде отдельной переменной объявить поле с данным типом - Some2DImage: TD3DImage2D; - в методе создания приложения создать экземпляр класса
- в методе RestoreDeviceObjects приложения вызвать метод
- в методе InvalidateDeviceObjects приложения Some2DImage.InvalidateDeviceObjects;
- в методе DestroyDeviceObjects приложения ============================================================
Для задания ключевого (прозрачного) цвета служит свойство Some2DImage.ColorKey := $00000000;
Для хранения имени и пути загруженного файла текстуры свойство- SomeFilename := Some2DImage.TexFilename;
Some2DImage.Draw(x, y, Flags, Alpha);Some2DImage.Draw(x,
y, Flags, Alpha);Some2DImage.Draw(x, y, Flags, Alpha);
Some2DImage.DrawScaled(x,
y, z: Single; fXScale, fYScale: Single; // то же, что и предыдущий метод, но x, y, z - не в пикселях, а в координатной системе Viewport (-1..+1). fXScale, fYScale задают масштаб в долях от окна Viewport (1 - во весь Viewport, 0.5 - в 1/2 от Viewport и т.д.). Такая система задания масштаба удобна тем, что не зависит от размеров окна 3D-сцены. Размеры окна в пикселях могут быть любые. Параметры Flags и Alpha - те же, что и в предыдущем методе.
|
||||
Чтобы лучше уяснить себе использование данного класса переходим к упражнениям. | ||||
В методе TD3DGameApp.DrawScreenSplash происходит вывод заставки - SplashGameGUI.DrawScaled(-1.05, 0.55, 0.9, 1.34, 1.34, DrawD3DImage2D_Filtered, Alpha); Попробуйте в качестве флага указать 0, т.е. - SplashGameGUI.DrawScaled(-1.05, 0.55, 0.9, 1.34, 1.34, 0, Alpha); Результатом будет вывод более четкого, но без плавного перехода (antialiasing) по краям изображения. Замечание: после внесения изменений в код не забывайте перекомпилировать приложение, а уж после запускать и смотреть что получилось! |
||||
Каким образом реализуется плавное появление, а затем затухание для заставки? Сначала попробуйте изменить строчку - SplashGameGUI.DrawScaled(-1.05, 0.55, 0.9, 1.34, 1.34, DrawD3DImage2D_Filtered, Alpha); вместо Alpha введите 255 - SplashGameGUI.DrawScaled(-1.05, 0.55, 0.9, 1.34, 1.34, DrawD3DImage2D_Filtered, 255); указанная особенность вывода заставки пропала. Заставка просто отображается в течении 9 секунд (SplashDelay). Выше данной строки расположен следующий код - Period
:= SplashDelay/3; if
DXUtil_Timer(TIMER_GETAPPTIME) < Period then |
||||
Как вы уже наверное догадались проявление и затухание заставки организовано за счет изменения значения Alpha - полупрозрачности полигона, на котором рисуется текстура заставки. | ||||
Прокомментируем указанные строки. Все время отображения заставки (SplashDelay) делится на 3 части и называется период. Момент изменения (фаза) вычисляется по указанной формуле. | ||||
Далее всё еще проще - за промежуток времени меньше, чем Период значение Alpha изменяется по косинусоидальной кривой, т.е. от 0 до 255 (см. формулу). | ||||
За промежуток времени от Период до 2 Периода значение Alpha остается постоянным. И, наконец, в промежуток времени от 2 Периодов до SplashDelay значение Alpha изменяется по синусоиде - от 255 до 0. | ||||
Т.к. во время показа заставки никаких полезных действий не производится, то в дальнейшем цикле разработки игрового проекта, можно использовать эту стадию начала работы игры для параллельного выполнения каких-либо полезных, но скрытых от пользователя действий: загрузка игровых моделей, подготовка сцены и т.п. | ||||
Это было лишь краткое знакомство с выводом титульной фирменной заставки. Для лучшего уяснения данного материала нужно обязательно написать собственное приложение и тщательно проработать все показанные особенности. Для разработки действительного игрового проекта дополнительно потребуется решение следующих вопросов: - создание и использование анимированных 2D-изображений для вывода меню и анимированных заставок (это касается расширения возможностей класса TD3DImage2D); - создание и использование игрового меню; - помещение используемых моделей, текстур в специальный библиотечный файл и организация загрузки из него (необходимо для целей защиты авторских прав на изображения, чтобы они не хранились открыто в папке ресурсов игры, а были бы доступны только исполнимому файлу или специально написанной утилите для просмотра ресурсных библиотек). |
||||
[Назад] [Все уроки] | ||||
[Главная] [Новости] [Статьи] [Игры] | ||||
(c) Мега Информатик 2006-2007 |