Творец. День второй. Кастинг актёров

Пришло время свергнуть с престола Брэда Пита и Анджелину Джоли и устроить свой кастинг актёров. Ибо заваривается эпическое кино... Свет, камера, мотор!

Хм, похоже, наш выбор невелик, потому что GLScene предоставляет только один компонент для работы с анимированными персонажами – GLActor. Он поддерживает, во-первых, форматы Quake (MD2 и MD3), а также скелетную анимацию (SMD), которая, как вы понимаете, являет собой (вкупе с хорошим физическим движком) фундамент успеха любой игры – ведь никому не интересно смотреть на деревянные болванки, послушно падающие после смерти по стойке «смирно».

Open Актёр
Давайте сразу полюбуемся на GLActor в действии. Демка находится по адресу GLScene\Demos\meshes\actor. Запускаем исходник и сразу компилируем демку. Естественно, загрузится приложение, в котором мы сможем просмотреть возможности этого компонента. Итак, в списке анимаций содержится всё, что нам нужно: тут и бег, и стрельба, и отдавание чести (в переносном смысле, разумеется), и различные виды смерти. Я думаю, вы заметили кнопку «Load Weapon». Да, оружие – это отдельный анимированный объект. Объясняется это следующим: на оружие тоже накладывается текстура (если монстр с оружием был бы одним объектом, то пришлось бы использовать так называемые «декали», т.е. текстура на текстуре – к чему нам лишние заморочки?). Кроме того, в случае смерти, оружие должно отделиться от монстра – опять же, если это будет один объект, то ничего подобного не получилось бы. Также существует прелестная функция сглаживания анимации – мы создаём 3-4 кадра, а движок растягивает, «сглаживает» их до 8-10 кадров. Согласитесь, удобно.

Кастинг
Пороемся теперь в исходнике программы. Щёлкните два раза по компоненту GLScene1 на форме. Обратите внимание на один полезный приём комбинирования объектов: GLActor2 вложен в GLActor1. По сути, оружие является потомком монстра. Отсюда вытекает одинаковая координата при движении – опять же, меньше головной боли. В объекте-пустышке DummyCube всё стандартно: освещение и камера – то, что и должно там находиться.

Обратимся к коду. В процедуре создания формы загружается сама моделька монстра, текстура для неё и список анимации в формате AAF. Откройте, кстати, этот файл через Блокнот и ознакомьтесь с принципом построения списка. Всё просто: название, начальный кадр, конечный кадр. Теперь всё внимание на строчку

Actor1.Animations.SetToStrings
(CBAnimations.Items);

Так мы все имена анимаций (stand, run, attack…) перенесли в выпадающий список. Однако, если мы вернём имя анимации компоненту GLActor, то он сопоставит его с именем в файле AAF и воспроизведёт соответствующий отрезок времени. В обычной игре создавать специальный лист не обязательно.
Загрузка оружия вынесена отдельной процедурой, но мы будем загружать всё сразу. Посмотрите на конец процедуры. Здесь идёт получение списка анимаций для GLActor2, который уже есть у GLActor1, и синхронизация GLActor1 и GLActor2 (то есть проигрывание одинаковых по номеру кадров):

Actor2.Animations.Assign(Actor1.Animations);
Actor2.Synchronize(Actor1);

Указание анимации идёт вот так:

Actor1.SwitchToAnimation(CBAnimations.Text, True);

К примеру, вместо CBAnimations.Text можно написать 'stand'. Также стоит заметить, что у нашей модели оружия нет анимации, начинающейся со 173 кадра. Поэтому логично его скрыть, пока у монстра проигрывается анимация со 173 кадра (в вашем варианте у оружия могут быть и 173-198 кадры – тогда скрывать его необязательно):

Actor2.Visible:=(Actor1.NextFrameIndex>173);

Здесь идёт проверка ложности утверждения Actor1.NextFrameIndex>173. И наконец, запускаем анимацию такими строчками:

Actor1.AnimationMode:=aamLoop;
Actor2.AnimationMode:=aamLoop;

а останавливаем вот так:

Actor1.AnimationMode:=aamNone;
Actor2.AnimationMode:=aamNone;

Не забудьте указать сглаживание анимации:

Actor1.FrameInterpolation:=afpLinear;
Actor2.FrameInterpolation:=afpLinear;

Принят на работу
В нашем проекте мы можем записать весь приведённый код в процедуру Form.Create, создав предварительно два объекта GLActor из вкладки Mesh Objects и переименовав их в Player и Weapon. Оружие сделайте потомком игрока, перетащив Weapon на Player, и не забудьте поменять в коде программы Actor1 и Actor2 на Player и Weapon. Также удалите объект GLSphere1 и замените все Sphere1 в коде на Player. Поместите все нужные файлы в папку с проектом (waste.md2, weaponwaste.md2, waste.jpg, weaponwaste.jpg и quake2Animations.aaf) и укажите в коде корректные пути к ним. Теперь при запуске вместо сферы на месте появления игрока окажется Player с оружием в руке. Помашите актёру ручкой.

Командный центр
В следующей статье разберёмся с управлением игрока при помощи клавиатуры и мышки, а потом помозгуем над созданием каких-либо хоть немного осознанных действий монстров.


Рекомендуем почитать: