Продолжаю серию постов о игростроении..
____________________________________________________________________________________
Что мы делаем для рисования? В начале мы должны взять холст на котором мы будем рисовать. В DelphiX наш холст - это компонент TDXDraw (который находится на вкладке DelphiX). Щёлкаем компонент TDXDraw правой кнопкой мыши, после по форме появится своеобразное окно. Теперь разберёмся с рисованием на нашем холсте. Рисование на холсте схоже с рисованием графиков.
(прошу прощение,но я не художник :) )
То есть минимальный координат по x и y - 0.
Холст можно представить как таблицу при координатах которой он имеет свой цвет. Например:
x,y | 1 |
1 | $0000FF |
Теперь давайте создадим нашего героя - mario. После Строк
implementation {$R *.DFM} |
type TMarioHero= class(TImageSprite) protected procedure DoCollision(Sprite: TSprite; var Done: Boolean); override; procedure DoMove(MoveCount: Integer); override; end; |
Мы объявляем класс TMarioHero. Его "папа" TImageSprite - это значит, что его "ребёнок" т.е. TMarioHero умеет всё , что умеет его "папа". procedure DoMove(MoveCount: Integer); override; Разбираем по кусочкам выше написанный код. Мы описали процедуру с названием DoMove и входящими параметрами ( грубо говоря то, что в скобках ). Входящий параметр у нас один MoveCount - кол-во передвижения нашего героя. После ":" мы пишем тип переменной у нас он Integer(целый числовой). И наконец самое интересное слово override ,выше я говорил, что ребёнок умеет всё, что умеет его отец. Отец же умеет передвигаться, но зарезервированное слово - override означает, что сыночек или же наш герой делает - это по-своему. |
procedure DoCollision(Sprite: TSprite; var Done: Boolean); override; |
Теперь снова вернёмся к теории( но не надолго!). Я уже упоминал в прошлых постах о том, что DirectX я выбрал из-за того, что он умеет работать не только с графикой, но и с устройствами ввода.
Чудесный компонент TDXInput(который позволяет работать и с мышкой, и с джойстиком, что не мало важно в программировании!)
(который также находится на вкладке DelphiX)
позволяет нам не удручаться сложным программированием над устройствами ввода, а сразу начать работу над главной задачей.
Так как компонент уже сам знает какое действие было совершенно т.е. было ли отпускание в низ или вверх нам остаётся только настроить по каким клавишам будет то или иное действие. Щёлкнув по нашему компоненту дважды мы тем самым увидим окно
TDXInput Editor
имеющие две вкладки Джойстик(Joystick) и Клавиатура(Keyboard).
На первой установки для работы с Джойстиком , а на второй события клавиатуры.
Такие как : Вверх(UP), Вниз(Down),Вправо(Left),Влево(Right) и дополнительно 32 настраиваемых.
Теперь нам нужно написать, что будет делать герой при движении(которое настраивается в DXInput). Находим строки написанные нами "про mario":
ставим указатель мыши на слово DoMove после "кликаем", что бы указатель редактирования был активен именно на имени процедуры DoMove. Нажимаем сочетание клавиш Ctrl+Shift+C Delphi сам создаст процедуру и нам не нужно будет описывать её (в какой-то части) самим. Сгенерированный Delphi код:
procedure TMarioHero.DoMove(MoveCount: Integer); begin inherited; end; |
Зарезервированное слово inherited зовёт "папу" , что бы он сделал всё , что он умеет, а далее за дело берёмся мы. Мне лично не нравиться как в данный раз поступил Delphi. Более понятно будет мне как программисту и
procedure TMarioHero.DoMove(MoveCount: Integer); begin inherited DoMove(MoveCount); end; |
Пока мы оставим - эти процедуры и перейдём к "разминке".
Я совсем забыл предупредить Вас о тоне(или стиле) программирования. Каждому созданному компоненту не нужно оставлять его стандартное имя, лучше переименовать его по его виду деятельности. Например мы уже имеем два компонента - это DXInput1 и DXDraw1, но красивее было бы им оставить название, но убрать числитель. И тогда мы получим DXInput и DXDraw. Конечно - это не суровое правило, но всё же прежде всего для себя будет удобнее.
Зачем им менять имена? Для того, что бы легче было понять основное назначение компонента. |
DXImageList - это просто список изображений. Он поддерживает такие типы файлов:
*.jpeg
*.bmp
*.ico
и другие менее распространённые форматы. Для работы со списком у компонента существует св-во Items.
Кликнув по его значению мы перейдём в выше названный список. Чтобы добавить элемент в список нужно кликнуть по кнопке Add New(Item)
При создании имя(name) пустое, т.е. не чему не присвоено. Как же мы будем обрамляться к изображению без имени? Переименуем! Я предлагаю имя - background. Но получается, что мы лишь назвали элемент списка не присвоив ему его картинку. Загрузит её очень легко! Кликнув по значении Изображения(Picture) "вылетит" форма окна Picture Editor.
Нажав кнопку загрузить(Load) откроется всем знакомые Диалог открытия файла.
Предлагаю Вам в качастве фона загрузить - это изображение(В конце поста приведена ссылка на скачивание всех изображений).
Теперь мы должны "рассказать" компоненту о том, что он должен делать. Всё , что мы должны делать перед созданием формы происходит при событии OnCreate. Для этого нужно выделить форму , что бы Объектный инспектор(Object Inspecter) показал св-ва формы. В кладке События(Events) Необходимо найти событие OnCreate и щёлкнуть по его значению. Delphi сам создаст процедуру.
procedure TMainForm.FormCreate(Sender: TObject); begin //Тут мы описываем действия при старте. end; |
*Создать фон
*Передвигающегося Mario(Он пока не будет бегать плавно)
Перед всем мы должны объяснить, что наш холст должен рисовать всё, что мы ему скажем.
Для этого добавим компонент TDXTimer. Создадим событие OnTimer:
procedure TMainForm.DXTimerTimer(Sender: TObject; LagCount: Integer); begin { изменения } DXDraw.Surface.Fill(0); DXSpriteEngine.Draw; DXDraw.Flip; end; |
Св-во Enabled и ActiveOnly должны иметь значение True.
Оптимальное значение Interval - 33ж.
1.) Создаём фон.
Компоненты DelphiX очень удобны, я уже не раз говорил об этом. И теперь мы создадим класс у которого "папа" будет - DXSpriteEngine.Engine(более специфического спрайта, чем ранее используемый нами) и тогда "сын" будет уметь всё, что его отец.
Теперь пояснения я буду приводить после каждой строки после знаков // |
procedure TMainForm.FormCreate(Sender: TObject); begin //Тут мы описываем действия при старте. with TBackgroundSprite.Create(DXSpriteEngine.Engine) do // всё , что будет далее описано в программных скобках будет свойствами от TBackgroundSprite.Create(DXSpriteEngine.Engine) begin image := ImageList.Items.Find('background'); // картинкой будет наш загруженный в компонент ImageList элемент списка background Image.Transparent := false; //убираем прозрачность SetMapSize(800,640); //устанавливаем ширину фона равной всему холсту, так как она не будет изменяться Z := 0; Tile := false; //устанавливаем не тайловый фон(не состоящий из кусочков изображений) end; end; |
С первым нашим заданием мы справились!
2.) Вот он, Марио.
Теперь займёмся нашим героем. Вам необходимо найти раздел var.
Если вы правильно делали указанное выше ваш раздел должен иметь примерно такой код
var MainForm: TMainForm; |
MarioHero:= TMarioHero.Create(DXSpriteEngine.Engine); //создаём используя умения "папы" нашего героя with TMarioHero(PlayerSprite) do //начинаем с ним работать begin Image := ImageList.Items.Find('mario'); //загружаем его спрайт X := 400; //координат по X Y := 350; //координат по Y Z := 3; //координат по Z Width := Image.Width; //ширина - равна ширине спрайта Height := Image.Height; //высота также end; //конец работы с героем |
procedure TMainForm.FormCreate(Sender: TObject); var MarioHero: TSprite; // наш герой - марио begin //Тут мы описываем действия при старте. {-- создаём фон --} with TBackgroundSprite.Create(DXSpriteEngine.Engine) do // всё , что будет далее описано в программных скобках будет свойствами от TBackgroundSprite.Create(DXSpriteEngine.Engine) begin image := ImageList.Items.Find('background'); // картинкой будет наш загруженный в компонент ImageList элемент списка background Image.Transparent := false; //убираем прозрачность SetMapSize(800,640); //устанавливаем ширину фона равной всему холсту, так как она не будет изменяться Z := 0; Tile := false; //устанавливаем не тайловый фон(не состоящий из кусочков изображений) end; {-- создаём героя --} MarioHero:= TMarioHero.Create(DXSpriteEngine.Engine); //создаём используя умения "папы" нашего героя with TMarioHero(MarioHero) do //начинаем с ним работать begin Image := ImageList.Items.Find('mario'); //загружаем его спрайт X := 10; //координат по X Y := 300; //координат по Y Z := 3; //координат по Z Width := Image.Width; //ширина - равна ширине спрайта Height := Image.Height; //высота также end; //конец работы с героем end; |