- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Графика DirectX в Delphi - Михаил Краснов
Шрифт:
Интервал:
Закладка:
// Обновить положения и воспроизвести монстров
for wrkl := 0 to NumMonsters - 1 do Monsters [wrkl].Show;
Warrior.Show; // Вывод воина поверх пролетающих, монстров
UpdateBul; // Удалить пули, вылетевшие за пределы экрана
// Обновить положения и отобразить пули
for wrkl := 0 to NumBullets - I do Bullets [wrkl].Show;
// Определить столкновение монстров и пуль
for s1 := 0 to NumMonsters - 1 do
for s2 := 0 to NumBullets - 1 do
if Monsters [s1].Live and SpritesCollidePixel (Monsters [s1],
Bullets [s2]) then begin
// Попавшая пуля перемещается за границы экрана
Bullets [s2].PosY := -10;
DeadMonster (s1); // Заменить образ монстра
end;
// Столкновения монстров, берутся в расчет только живые чудовища
for s1 := 0 to NumMonsters - 2 do
for s2 := si + 1 to NumMonsters - 1 do
if Monsters [s1].Live and Monsters [s2].Live and
SpritesCollidePixel (Monsters [si], Monsters[s2]) then begin
Monsters [si].Hit(Monsters [s2]);
Monsters [s2].Hit(Monsters [si]);
end;
Result := DDJDK;
end;
Больших усилий мне стоило при подготовке данного примера то, что не бросается сразу же в глаза - уверенное восстановление поля игры. Для достижения этого приходится восстанавливать поверхности всех спрайтов, и тех, что уже выводились, и тех, что ни разу не появлялись на экране. Вследствие чего процесс восстановления происходит тоже очень долго. Здесь я опять вывожу на первичную поверхность пустой фон.
Итак, воспроизведение множества спрайтов выполняется с удовлетворительной скоростью. Наиболее слабыми местами этой пробной игры являются чересчур долгая инициализация и восстановление объектов. Также при каждом попадании в чудовище смена цепочки кадров чересчур затягивается, и в такие моменты происходит ощутимое торможение в работе игры.
Очередной пример является развитием предыдущего - это игра аналогичного жанра, поменялись только фон и вид нашего бойца (рис. 5.4).
Скорость работы игры повысилась существенно, инициализация и восстановление происходят мгновенно, и нет ощутимой паузы в моментах замены картинки спрайтов.
Однажды я уже говорил, что, в случае применения множества образов, оптимальным решением является использование одной поверхности. Если в предыдущем примере каждый объект спрайта имеет собственную поверхность, то в этом проекте заведена одна единственная поверхность, хранящая все используемые образы. Прием простой, но, как видим, очень эффективный.
Образы спрайтов хранятся в единственном компоненте класса Timage (рис. 5.5).
В принципе, это и не обязательно. Главное, повторюсь, то, что используется одна поверхность. Она может заполняться отдельными образами или единым, как в нашем примере, но при выводе спрайтов применяется не индивидуальная поверхность спрайта, а поверхность Foosimages, обслуживающая все спрайты. Вот как выглядит теперь код воспроизведения воина:
procedure TWarrior.Show;
begin
if Direction = dirRight
// rcRect устанавливается в координатах образа, хранящего все картинки
then SetRect (rcRect, 0, 70, SpriteWidth, 70 + SpriteHeight)
else SetRect (rcRect, SpriteWidth, 70, 2 * SpriteWidth, 70 +
SpriteHeight);
// Осуществляется блиттинг FDDSImages, а не поверхности спрайта
frmDD.FDDSBack.BltFast(PosX, PosY, frmDD.FDDSImages, @rcRect,
DDBLTFAST_DONOTWAIT or DDBLTFAST_SRCCOLORKEY);
end;
Также этот пример отличается от предыдущего тем, что пространство игры не ограничивается одним экраном, воин может продвигаться дальше правой границы, всего я использую два растровых фона, каждый размером 640x480 пикселов. Напоминаю, что некоторые видеокарты не позволяют создавать поверхности, превышающие в размерах первичную поверхность. Поэтому для хранения этих растров использую две поверхности - Foosone и FDDSTWO. Значение целочисленной переменной iftRect указывает ширину прямоугольника, вырезаемого из второй поверхности:
SetRect(rcRectOne, IftRect, 0, ScreenWidth, ScreenHeight);
// Первый фон
FDDSBack.BltFast(0, 0, FDDSOne, @rcRectOne, DDBLTFAST_WAIT);
if IftRect > 0 then begin // Присутствует ли часть второго фона
SetRect(rcRectTwo, 0, 0, IftRect, ScreenHeight);
FDDSBack.BltFast(ScreenWidth - IftRect, 0, FDDSTwo, SrcRectTwo,
DDBLTFAST_WAIT);
end;
Работа с клавиатурой
При изучении двух предыдущих примеров вам, наверняка, не понравилась скорость перемещения нашего воина, и, возможно, вы гадали, почему я не установил величину приращения побольше. Объяснение вы найдете в настоящем разделе.
Начинающие "игроделы" часто рассуждают так: если традиционный графический вывод совершенно не годится для масштабной игры, и для обеспечения быстрой графики надо искать другие пути, то управление, построенное на получении информации обычными способами, вполне подходит. Имея опыт разработки программ бухучета, вы не испытывали особых проблем со скоростью ввода данных, и, возможно, полагаете, что, если ваша игра использует для ввода только клавиатуру и мышь, вам не стоит напрягаться и изучать новые для вас методы организации ввода от традиционных устройств. Если это так, то вас ждет большой сюрприз, вы сами убедитесь, как сильно может улучшиться игра, если отказаться от привычных обработчиков событий, связанных с устройствами ввода.
Обычно игры используют функции библиотеки Directlnput для организации управления, с ними мы и бегло познакомимся в данном разделе. Эта библиотека является частью DirectX и содержит набор функций для обеспечения пользовательского ввода с максимальной скоростью. Высокая скорость работы даже с традиционными устройствами обеспечивается тем, что Directlnput обходит часто применяемые механизмы операционной системы и обращается к устройствам напрямую. Поэтому установленные в системе параметры, такие как частота повтора символов для клавиатуры или чувствительность мыши, не влияют на скорость ввода.
Directlnput использует модель СОМ. Посему, после изучения DirectDraw, нам будет легко знакомиться с ним: мы встретим здесь знакомые понятия главного объекта и интерфейсов.
Разбирая очередной пример (проект каталога Ех05), я попутно расскажу об основных понятиях библиотеки Directlnput. По виду пример представляет собой обычное оконное приложение, в компоненте класса тмето выводятся скан-коды нажимаемых клавиш, нажатие кнопки Clear приводит к очистке его содержимого (рис. 5.6).
В списке "uses помимо обычных для Delphi модулей мною вписан DirectlnputS.
Глобальная переменная Dlnput обеспечивает доступ к функциям Directinput:
var
Dinput : IDIRECTINPUT8 = nil; // Главный объект Directinput
// Интерфейс доступа к устройству ввода
DIKeyboard : IDIRECTINPUTDEVICE8 = nil;
Впервые в наших примерах мы обращаемся к интерфейсам именно восьмой версии DirectX. Обращу внимание на это событие, чтобы оно не прошло для вас незамеченным.
Следующая пользовательская функция предназначена для подготовки работы (обработку ошибок оставлю только для первого действия):
function TfrmDX.Or.CreateDevlce : HRF.SULT;
var
hRet : HRESULT; // Результат действий
dipdw : TDIPROPDWORD; // Вспомогательная структура, задание параметров
begin
// Создание главного объекта Directlnput
hRet := DirectlnputSCreate (hlnstance, DIRECTINPUT_VERSION,
IID_IDirectInput8, DInput, nil);
if Failed (hRet) then begin
Result := hRet;
Exit
end;
// Создание объекта ввода информации от клавиатуры
hRet := DInput.CreateDevice (GUID_SysKeyboard, DIKeyboard, nil);
// Задаем формат данных, получаемых от устройства
hRet := DIKeyboard.SetDataFormat(c_dfDIKeyboard);
// Задаем уровень кооперации
hRet := DIKeyboard.SetCooperativeLevel(Handle, DISCL_NONEXCLUSIVE or
DISCL_BACKGROUND);
// Параметры для буферной схемы получения данных
ZeroMemory (Sdipdw, SizeOf (dipdw)); with dipdw do begin
diph.dwSize := SizeOf(TDIPROPDWORD);
diph.dwHeaderSize := SizeOf(TDIPROPHEADER);
diph.dwObj := 0;
diph.dwHow := DIPHJDEVICE;
dwData := SAMPLE_BUFFER_SIZE;
end;
// Задаем параметры буфера
hRet := DIKeyboard.SetProperty(DIPROP_BUFFERSIZE, dipdw.diph);
// Установили связь с устройством ввода
Result := DIKeyboard.Acquire;
end;
Для создания главного объекта из библиотеки Directlnput должна использоваться функция DirectlnputSCreate. Аргументы ее таковы:
* указатель на вызывающий поток; версия DirectX, в которой создано приложение; идентификатор требуемого интерфейса; переменная, в которую помещается результат.
Последний аргумент - указатель на показатель агрегирования (разновидность наследования; термин, специфичный для СОМ) - обычно равен nil.
В случае удачи функция возвращает ноль. Такому значению соответствует константа DI_OK, определенная в модуле Directinputs.
Метод CreateDevice главного объекта используется для создания нового объекта устройства. У этого метода три аргумента:
* идентификатор нужного устройства; переменная, в которую помещается результат; показатель агрегирования.
В качестве идентификатора для клавиатуры передаем константу GUID_SysKeyboard.
Перед захватом устройства необходимо вызвать метод setoataFormat объекта, связанного с устройством ввода. Здесь описывается формат, в котором вводимые данные возвращаются устройством. Для стандартного устройства задаем стандартный формат.
Также обязательным действием является определение степени контроля над устройством, задание уровня кооперации, другим словом. Для этого вызывается метод setcooperativeLevel, первый аргумент которого - идентификатор окна приложения.

