Информатика и образование
  Мобильная версия сайта            
               
[Главная] [Новости]
[Статьи]
[Проекты]
[Ссылки]
[Автор]
               
    [Архив новостей]        
               
  [Форум] на форуме можно задать вопрос, посмотреть ответы на часто задаваемые вопросы  
       
  Здравствуйте! Вы попали на информационно-образовательный сайт посвященный информатике, информационным технологиям и компьютерным играм. Подробнее о целях и задачах сайта в разделе Главная. [English version of this page here...]    
       
  [Базовые уроки по DirectX] [Основы DirectMusic на Delphi] [Основы DirectInput8 на Delphi] [Основы DirectSound8 на Delphi]    
  [Разработка компьютерной игры] [Пример игры Donuts3D] [Delphi DirectX]    
       
  Эмулятор электронной игры Электроника ИМ-02 "Ну, Погоди!"    
       
  триал-версия, 1,34 Mb   скачайте полную версию игры, зарегистрируйтесь и получите бесплатно полный исходный код игры для компиляции в delphi 7 или 2006 и уроки delphi directx 8.1 содержащие статьи по созданию собственной 2D/3D игры в среде delphi directx    
       
  Урок 5 Построение классов игровых объектов и других необходимых классов    
       
  О том, что потребуется для данного урока читайте в основном разделе - уроки delphi directx 8.1    
       
  Далее у читателя подразумевается наличие базовых знаний языка Delphi.    
       
  [назад] [страница 1] [далее] [к содержанию]    
       
 

На протяжении предыдущих 4 уроков мы рассмотрели как строится базовый каркас D3D-приложения, узнали некоторые детали разработки игры.

Теперь пришло время познакомиться с созданием собственно игровых единиц, отвечающих за формирование игры и игрового процесса.

   
       
 

Начнём с того, что спросим себя: для чего вообще нужны игровые объекты?

Исходя из концепции ООП (объектно-ориентированного программирования) любую прикладную задачу можно сформулировать таким образом, чтобы использовать классы объектов и методы взаимодействия их между собой.

В разработке игр это также применимо. Объект обладает определенными свойствами, имеет методы и может реагировать на определенные события. Создание игровых объектов также обусловлено тем, что для их использования часто требуется несколько типов ресурсов логически связанных между собой. Например, для модели персонажа требуется также текстура, с персонажем могут быть связаны определенные виды звуков и т.д.

Помимо этого любой игровой объект имеет множество характеристик, которые удобно представить именно в виде свойств, и чем сложнее игра, тем больше игровых объектов, сложнее наборы их характеристик и взаимосвязи между объектами.

   
       
 

Если объекты достаточно просты и не используют методы, то их можно представить в виде простых переменных или структур.

Какие типы объектов бывают?

Всё это зависит от фантазии разработчика, его возможностей и опыта. Можно привести примеры множества игровых объектов, которые так или иначе имеют место в большинстве игр: игровое меню, игровая камера, главный герой (или игрок), различные виды врагов, бонусов, объект игровой карты и т.д.

Нет никакой жесткой схемы или правил для выделения тех или иных игровых объектов. Однако чем тщательнее будет проработан каждый объект и его связи с другими объектами, тем легче разобраться в создании игры и ее модификациях.

Этот процесс является итеративным. Хорошие и проработанные объекты создаются постепенно, по мере совершенствования и улучшения кода игры. Это всё тесно связано с хорошими правилами и хорошим стилем программирования.

Чем яснее удастся решить задачу и выполнить ее реализацию, тем проще будет в дальнейшем вносить дополнительные улучшения и совершенствовать код.

В любом случае следует начинать с некоторой заготовки, шаблона, которые мы сейчас и рассмотрим.

   
       
 

Возьмем объект игрока. Если игра трехмерная, то для игрока должна быть своя модель персонажа и текстура или даже несколько их видов. Игрок в зависимости от жанра игры должен будет выполнять определенную игровую задачу. Эта задачи может включать ряд трудностей, включающих влияние на персонажа: утрату здоровья, силы, приобретение опыта, очков и т.п. Всё это находит отражение в свойствах объекта игрока.

Самый простой вариант - это произвести класс объекта игрока напрямую от TObject и добавить в него необходимые поля, свойства и методы. Класс может также реагировать на определенные события, но систему событий лучше использовать не обычную для типичных объектов приложений, а свою, внутренюю, игровую или же на первых порах можно вообще обойтись без неё.

   
       
 

Вот пример описания класса объекта игрока взятый из исходного кода игры проекта "Нечто: Необъяснимое".

TPlayerHero = class(TAnimGameCreature)
private
//FAction: TCharActions;
//FAnimationEnded: Boolean;


procedure DoAnimateProc(TimeLapsed: Single; hr: HResult);

//function GetTerrainHigh(x, z: Single): Single;
protected

procedure SetAnimationParam(Value: Integer); override;

function DoRender: HResult; override;
function DoFrameMove: HResult; override;
//function DoFrameMove2(TimeLapsed: Single): HResult; override;

function DoInitDeviceObjects(pd3dDevice: IDirect3DDevice8): HResult; override;
function DoRestoreDeviceObjects: HResult; override;
function DoInvalidateDeviceObjects: HResult; override;
function DoDeleteDeviceObjects: HResult; override;

public

constructor Create;
destructor Destroy; override;


end;

   
       
  Как видим данный класс производится от некоторого базового класса - TAnimGameCreature и имеет целый ряд методов, связанных в основном с использованием анимированной 3D-модели персонажа. Внутренние особенности класса - его свойства реализованы внутри TAnimGameCreature. Посмотрим его описание -    
       
  TAnimGameCreature = class(TD3D_GDOListItem)
private
FAction: Integer;
FDoAnimate: TAnimateProc;

protected

procedure SetAnimationParam(Value: Integer); virtual;

function DoRender: HResult; override;
function DoFrameMove: HResult; override;

function DoInitDeviceObjects(pd3dDevice: IDirect3DDevice8): HResult; override;
function DoRestoreDeviceObjects: HResult; override;
function DoInvalidateDeviceObjects: HResult; override;
function DoDeleteDeviceObjects: HResult; override;

public

Character: TAnimatedMesh;

Pos, Orient: TD3DXVector3;
YAxisAngle: Single;
Delay: Single; //длительность воспроизведения анимации
IdleDelay: Single; //длительность бездействия

CurrentAnimDelay: Single; //временная задержка для воспроизведения текущей анимации
IdleAnimDelay: Single; //временная задержка анимации бездействия

GameScene: TD3D_GDOListItem;

constructor Create;
destructor Destroy; override;

function Animate(TimeLapsed: Single): HResult;

property Action: Integer read FAction write SetAnimationParam;
property DoAnimate: TAnimateProc read FDoAnimate write FDoAnimate;
end;

   
       
 

Как видим данный класс происходит от класса TD3D_GDOListItem. Такое наследование связано с тем, что данный объект будет являться элементом списка графических объектов TD3D_GDOList. Помимо этого вы видите ряд полей и свойств описанных в данном классе.

Конечно же данные классы достаточно односложны. В реальных более сложных играх всё будет гораздо более насыщенным различными свойствами, методами и кодом. Однако не пытайтесь сразу же начинать со сложного.

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

   
       
  Если взять исходный код игры "Ну, Погоди!", то здесь Вы обнаружите полное отсутствие самостоятельных классов игровых объектов. Игра достаточно проста, поэтому всё, что нужно в качестве игровых объектов удалось описать лишь структурами данных определенных типов. Использования классов производных от TObject или каких-то других не потребовалось.    
       
 

В игре "Ну, Погоди!" свойства и необходимые данные игрока представлены внутри самого класса игрового приложения.

Так например,

WolfPos: TTraysNum; //положение волка

определяет текущее положение волка из возможных 4х (см. описание TTraysNum)

GameScore, ShowedGameScore: Integer; //

определяет текущий и отображаемый счет игры

ShtrafGameScore: Single; //счет штрафных очков

показывает количество штрафов, три штрафных очка приводят к завершению игры - проигрышу

Аналогично игровой объект яйцо - также представлен в виде полей класса приложения -

Trays: TEggPos; //позиция яиц на лотке
TraysSet: set of TTraysNum; //номера лотков с которых могут катиться яйца
TraysIndex: TTraysIndex; //индексы номеров лотков
//используются в генераторе новых яиц

   
       
  CreatedEggsNum: Integer; //количество созданных яиц

NewEggTimeCounter: Single; //счетчик появления нового яйца на лотке
NewEggTimeLimit: Single; //предел времени по прошествии которого
//будет создано новое яйцо на лотке

MoveEggTimeCounter, MoveEggTimeLimit: Single; //счетчик и предел
//времени для очередного шага продвижения яиц по лоткам

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

Если вспомнить мой опыт в этой области, то я в своё время начинал изучать Delphi5 в 2002 году, пытаясь создать логическую игру Логика цвета. Естественно, что ни о каком DirectX речи не шло. Это была простая игра-окно с рядом кнопочек. Нужно было угадывать цвета которые задумал компьютер, при этом он давал небольшие логические подсказки на каждом шаге.

Чуть позднее, когда опыт программирования был мной приобретен и усвоены несколько книг по программированию, я перешел к проекту игры "Дорога в Город". Это было уже в 2003. Толчком к освоению DelphiX и созданию игры "Дорога В город" послужила попытка устроиться в одну небольшую фирму, занимавшуюся разработкой компьютерных игр. Моих знаний конечно же оказалось для этого недостаточно, кроме того, требовалось знание все-таки C++ и DirectX, а не Delphi. Однако такой опыт и требования предъявленные при этом послужили мне своеобразной планкой, к которой я стремился. Прошло некоторое время и игра была воплощена, а я уже стал подумывать над созданием 3D-игр. Так появилась библиотека Delphi DirectX 8.1. Конечно основой этой библиотеки послужили работы Алексея Баркового по конверсии кода и примеров из DirectX SDK на C++ в Delphi (http://www.clootie.ru)

Но Алексей Барковой написал именно SDK для Delphi. В его интересы не входила практическая сторона - попытка создания при помощи этого SDK полноценной игры. Для этого не хватало некоторых исходников, кроме того, не было самого главного - примера игры, который можно было бы переделать на Delphi и который послужил бы основой для создания полноценной игры.

У меня под рукой оказалась Microsoft DirectX SDK 8.1 и там был как раз пример игры Donuts3D. Я поставил перед собой задачу реализовать эту игру на Delphi 7, и эта задача удалась. При этом появилось несколько новых исходников, которые и сформировали библиотеку Delphi DirectX 8.1. Дело пошло дальше и появились проекты "Нечто: Необъяснимое" и "Ну, Погоди!".

   
       
  Чтобы лучше понять и усвоить то, что было извлечено из опыта создания игры (проект "Нечто: Необъяснимое", кстати еще пока не завершен, находится в стадии разработки), я приступил к написанию этих уроков.    
       
  Советую и Вам, если Вы всерьез решились научиться создавать собственные игры и перевести это дело в дальнейшем в разряд Вашей основной или параллельной работы, вести для себя своеобразные дневники разработки, небольшие уроки и статьи. С одной стороны это позволяет лучше уяснить изучаемый материал, а с другой - это послужит хорошим материалом для тех, кто еще только учится писать свои игры, делает в этом свои первые шаги и не обладает таким опытом, который есть у Вас.    
       
 

Итак, это было небольшое отступление от основной темы нашего урока.

Как видим важным элементом создания новой игры является собственно придумывание и описание ее игрового процесса, геймплея и основных идей. Ну и конечно же не последнюю роль играет создание игрового контента - графики, сюжета, музыки, звука.

   
       
  Теперь мы переходим к практической части нашего урока. В рамках неё мы рассмотрим реализацию реальных игровых классов для использования в проекте "Нечто: Необъяснимое. Нить накала". Будет показано как реализованы 2 микро-игры в мини-игре "в плену желаний" для главы 7.    
       
  "В плену желаний" - 8,55 Mb-готовый проект CoD (8,55 Mb)    
       
  Код будет основан на исходном коде игры проекта "Нечто: Необъяснимое". Приложение будет работать в обычном режиме за исключением того, что после выбора пункта меню [новая игра] будет выводится не экран выбора глав, а сразу же титульный экран данной мини-игры.    
       
 

Для использования кнопок меню [начать] и [закончить] и вывода их в нажатом состоянии подойдет класс TD3DImage2D описанный в модуле D3DGUI.pas (его Вы найдете в исходном коде игры "Ну, Погоди!").

Для рассчета относительных координат и масштабных коэффициентов вывода изображений методом TD3DImage2D.DrawScaled воспользуйтесь следующими правилами

относительные координаты экрана x = -1..1, y = 1..3

для разрешения экрана 1024х768

текстура кнопки 512х512, ее пиксельные координаты (относительно левого верхнего угла экрана) -

497, 268

масштабный коэффициент длины (x)

экран 1024/2 = 512 - это масштабный коэффициент 0.5 для длины экрана

[отношение длины к ширине] = 1024 : 768 = 1,33333333...

масштабные коэффициенты вывода текстуры 512х512 -

x_scale = 0.5*1.333333 = 0.66

y_scale = 0.5*1.333333 = 0.66

Относительные координаты вывода -

x, y = -0.02, 1.70

рассчет координат осуществляется исходя из следующих соображений

512, 384 - центр экрана (0, 0)

x = (497-512)/512 = -0.029296875

y = (268+384)/384 = 1.6979166666

   
       
 

Удобство относительных координат состоит в том, что они не зависят от разрешения экрана. Попробуйте выполнить те же рассчеты для разрешения 800х600 и получите те же масштабные коэффициенты и те же относительные координаты.

Важно также обратить внимание на то, что для анимированных объектов ТЕКСТУРА ОБЯЗАТЕЛЬНО ДОЛЖНА БЫТЬ КВАДРАТНОЙ, т.е. - 32х32, 64х64, 128х128, 256х256, 512х512, 768х768б 1024х1024, 2048х2048 иначе при выводе анимации будут возникать сдвиги картинки!

Для неанимированных изображений можно использовать и не квадратные изображения текстур, как например title.jpg - это если посмотреть в ресурсы проекта (Media\Textures\captivity) картинка размером 1024х768

   
       
 

Я не буду здесь приводить исходный код, Вы можете просто скачать

готовый проект (CoD) (8,55 Mb) или исходный код примера (GameClasses) (1,3 Mb)

   
       
 

готовый проект (CoD) (8,55 Mb) представляет из себя базовую оболочку игры "Нечто: Необъяснимое" с реализованной мини-игрой "в плену желаний".

исходный код примера (GameClasses) предназначен для сборки с использованием библиотеки delphi directx 8.1 включенную в исходный код игры "Ну, Погоди!". Содержит демонстрацию вывода титульной заставки, экранного меню (обработка пунктов меню [начать] и [закончить], игрового курсора

   
       
 

Вопросы которые предстоит решить читателю:

Как сделать вывод курсора и пунктов выбранных меню с прозрачным фоном, как это имеет место в готовом проекте (CoD)?

При выходе из полноэкранного режима нажатием [закончить] происходит ошибка, как ее устранить?

   
       
 

Если Вы правильно ответите на поставленные вопросы, значит можно считать, что урок Вами усвоен и можно переходить к следующему.

   
       
  [назад] [страница 1] [далее] [к содержанию]    
       
  Если Вы затрудняетесь с ответом, то можете посмотреть их - ответы на поставленные вопросы    
       
       
       
  по всем вопросам пишите на megainformatic@mail.ru или оставьте сообщение на форуме    
       
 

 

Обновления и новости о развитии Delphi DirectX проекта
смотри на сайтах:

http://www.megainformaticsite.pochta.ru

http://www.megainformatic.boom.ru

http://www.megainformatic.narod.ru

 

   
       
     
 

Cвои пожелания, вопросы или заметки отправляйте на:

megainformatic@mail.ru или пишите на форуме

 
     
   Обмен ссылками  
     
     
             
 
 
         
(с) МЕГА ИНФОРМАТИК 2006-2009
Hosted by uCoz