Создание базового движка для игры. Часть 1. Графика и клавиатура - Delphi, Pascal, ObjectPascal - Программирование
Навигация по сайту
Сайт:

Дополнительно:

Файловый архив:

Каталог статей:

Форум:


Категории раздела
Delphi, Pascal, ObjectPascal [18]
Программирование на Delphi, Pascal, ObjectPascal
C, C++, C# [7]
Программирование на C, C++, C#
ПХП (PHP) [6]
Все что связано с программированием на PHP.
DirectX [0]
Программирование с использованием графического API DirectX
OpenGL [0]
Программирование с использованием графического API OpenGL
Работа с базами данных (БД) [0]
Работа с базами данных MySQL и т.д. Разработка, теории, алгоритмы.
Сетевое программирование [0]
Сетевое программирование, организация сетей.
Программирование игр [0]
Все что связано с программированием игр, организацией их разработки.
Работа с мультимедиа данными [0]
Загрузка, обработка, воспроизведение и все что связано со звуком и видео.
Работа с устройсвами ввода и вывода [0]
Программирование устройств ввода и вывода. Работа с геймпадом, рулем и многим другим.
Программирование HTML 5 игр [0]
Программирование HTML 5 игр, html верстка, JS (JavaScript)
Остальное [0]
Все остальное, что не попадает ни под одну категорию.

Мини-Опрос
Сколько Вам лет?
Всего ответов: 1451

Партнеры сайта
....

 Главная » Статьи » Программирование » Delphi, Pascal, ObjectPascal » Создание базового движка для игры. Часть 1. Графика и клавиатура

Создание базового движка для игры. Часть 1. Графика и клавиатура

00:40
В этом уроке мы научимся создавать базовый движок под игру, с полным экрано и прочими штучками =)
давайте начнем.
Создайте новый проект. Сразу назовите форму fMain. На форму киньте таймер и назовите его StepEvent интервал задайте одному (Interval: 1). Теперь создайте новый модуль (File / New / Unit)
в Uses пропишите следующее (вписывайте после ключевого слова interface):
uses
Graphics, ExtCtrls, Windows, Classes, JPEG;

Эти модули нам нужны для рисовании графики. Теперь создадим базовые классы:

TCoordinates = record
X: Integer;
Y: Integer;
end;

TDevice = class
public
Width: Integer;
Height: Integer;
Windowed: Boolean;

procedure Update;
constructor Create;
end;

TSprite = class
public
Position: TCoordinates;
Tag: Integer;
Name: String;
Image: TImage;

constructor Create;
end;

TCamera = class
public
Position: TCoordinates;
Clamp: TCoordinates;
CameraObject: TSprite;
Width: Integer;
Height: Integer;

procedure Update;
constructor Create;
end;

TScene = class
public
SpritesCount: Integer;
Sprites: array[0..999] of TSprite;
Camera: TCamera;

function AddSprite: TSprite;
procedure LoadFromFile(const FileName: String);
constructor Create;
end;

TViewer = class(TImage)
public
Device: TDevice;
Scene: TScene;
BackBuffer: TImage;

procedure Update;
constructor Create(AOwner: TComponent);
end;

Здесь TCoordinates это координаты объекта, камеры и т.д... TDevice - это у нас экран он нам нужен для того что бы мы могли сделать игру не в оконном режиме. TSprite - собственно сам спрайт. TCamera - камера, она нам понадобится, если мы хотим делать "скролл" тоесть комнату любых размеров. TScene - сама сцена, в которой находится массив спрайтов и камера. TViewer - место на котором мы будем рисовать. Теперь давайте опишем процедуры и функции, которые мы создали. После ключевого слова implementation впишите следующее:


//*TDevice*//
procedure TDevice.Update;
var
DeviceMode: TDevMode;
begin
if Windowed then
begin
ChangeDisplaySettings(TDevMode(nil^), CDS_FULLSCREEN);
end else
begin
with DeviceMode do
begin
dmSize := SizeOf(DeviceMode);
dmPelsWidth:= Width;
dmPelsHeight:= Height;
dmBitsPerPel:= 32;
dmFields:= DM_PELSWIDTH or DM_PELSHEIGHT or DM_BITSPERPEL;
end;
ChangeDisplaySettings(DeviceMode, CDS_FULLSCREEN);
end;
end;

constructor TDevice.Create;
begin
inherited Create;
Width:= 800;
Height:= 600;
Windowed:= true;
end;

//*TSprite*//
constructor TSprite.Create;
begin
inherited Create;

Image:= TImage.Create(nil);
Image.Visible:= false;
Image.AutoSize:= true;
end;

//*TCamera*//
procedure TCamera.Update;
begin
if CameraObject <> nil then
begin
if CameraObject.Position.X > Position.X + Clamp.X div 2 then
Position.X:= CameraObject.Position.X - Clamp.X div 2;
if CameraObject.Position.X < Position.X - Clamp.X div 2 then
Position.X:= CameraObject.Position.X + Clamp.X div 2;
if CameraObject.Position.Y > Position.Y + Clamp.Y div 2 then
Position.Y:= CameraObject.Position.Y - Clamp.Y div 2;
if CameraObject.Position.Y < Position.Y - Clamp.Y div 2 then
Position.Y:= CameraObject.Position.Y + Clamp.Y div 2;
end;
end;

constructor TCamera.Create;
begin
inherited Create;
Clamp.X:= 320;
Clamp.Y:= 0;
end;

//*TScene*//
function TScene.AddSprite: TSprite;
begin
Sprites[SpritesCount]:= TSprite.Create;
Result:= Sprites[SpritesCount];
SpritesCount:= SpritesCount + 1;
end;

procedure TScene.LoadFromFile(const FileName: String);
begin
end;

constructor TScene.Create;
begin
inherited Create;
SpritesCount:= 0;
end;

//*TViewer*//
procedure TViewer.Update;
Var
i: Integer;
begin
BackBuffer.Canvas.CopyRect(Rect(0,0,Width,Height),Canvas,Rect(0,0,Width,Height));
BackBuffer.Canvas.Brush.Color:= $000000;
BackBuffer.Canvas.FillRect(Rect(0,0,Width,Height));

for i:= 0 to Scene.SpritesCount - 1 do
BackBuffer.Canvas.Draw((Scene.Sprites[i].Position.X - (Scene.Sprites[i].Image.Width div 2)) -
(Scene.Camera.Position.X - (Scene.Camera.Width div 2)),
(Scene.Sprites[i].Position.Y - (Scene.Sprites[i].Image.Height div 2)) -
(Scene.Camera.Position.Y - (Scene.Camera.Height div 2)),
Scene.Sprites[i].Image.Picture.Graphic);

Canvas.CopyRect(Rect(0,0,Width,Height),BackBuffer.Canvas,Rect(0,0,Width,Height));
end;

constructor TViewer.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
BackBuffer:= TImage.Create(nil);
BackBuffer.Parent:= Parent;
BackBuffer.Visible:= false;
end;


сохраните модуль под именем uGraphics. Далее в главном модуле в uses допишите модуль uGraphics. Теперь вернемся на форму. В обработчике событий формы OnCreate пропишиете следующее:


GameDevice:= TDevice.Create;
GameCamera:= TCamera.Create;
GameScene:= TScene.Create;
GameViewer:= TViewer.Create(nil);

with GameViewer do
begin
Parent:= fMain;
Device:= GameDevice;
Scene:= GameScene;
Scene.Camera:= GameCamera;
Width:= fMain.ClientWidth;
Height:= fMain.ClientHeight;
BackBuffer.Width:= Width;
BackBuffer.Height:= Height;
GameCamera.Width:= Width;
GameCamera.Height:= Height;
end;


так же не забудьте объявить глобальные переменные:

GameDevice: TDevice;
GameCamera: TCamera;
GameScene: TScene;
GameViewer: TViewer;


теперь в обработчике событий таймера впишите следующее:


GameViewer.Update;
GameCamera.Update;


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


with GameScene.AddSprite do
begin
Image.Picture.LoadFromFile('Data\Images\1.bmp');
Image.Transparent:= true;
end;


Запустите приложение, у вас должно получиться вроде этого:

Поэкспериментируйте немного с параметрами, например с параметром Position если ввести в обработчик событий в таймере строчку:
GameScene.Sprites[0].Position.X:= GameScene.Sprites[0].Position.X + 4;
то наш спрайт полетит вправо =)
Теперь давайте разберемся с клавиатурой... создайте новый модуль и переименуйте его в uSystem. Я приведу полный код модуля:


unit uSystem;

interface

uses
Windows;

function OnKey(key: Char): Boolean; overload;
function OnKey(key: Word): Boolean; overload;

implementation

//*Keyboard*//

function OnKey(key: Char): Boolean;
var
vk : Integer;
begin
vk:= VkKeyScan(key) and $FF;
if vk <> $FF then
Result:= (GetAsyncKeyState(vk) < 0)
else Result:= False;
end;

function OnKey(key: Word): Boolean;
begin
Result:= (GetAsyncKeyState(key) < 0);
end;

end.

Как обычно добавьте модель uSystem в uses главного модуля. Теперь в обработчике события таймера введите следующее:



if OnKey(VK_LEFT) then GameScene.Sprites[0].Position.X:= GameScene.Sprites[0].Position.X - 4;
if OnKey(VK_RIGHT) then GameScene.Sprites[0].Position.X:= GameScene.Sprites[0].Position.X + 4;
if OnKey(VK_UP) then GameScene.Sprites[0].Position.Y:= GameScene.Sprites[0].Position.Y - 4;
if OnKey(VK_DOWN) then GameScene.Sprites[0].Position.Y:= GameScene.Sprites[0].Position.Y + 4;


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



with GameScene.AddSprite do
begin
Image.Picture.LoadFromFile('Data\Images\1.bmp');
Image.Transparent:= true;
Position.X:= 250;
end;

GameScene.Camera.CameraObject:= GameScene.Sprites[0];

Второй объект нам нужен для того что бы заметить изменения. Теперь если походить по комнате, можно увидет как камера передвигается вместе с нами =) Ну на сегодня все =) В следующем уроке мы научимся сталкиваться с объектами, воспроизводить анимацию и музыку =) а щас приведу полный код того что у меня получилось из этого:
uMain (Главный модуль)



unit uMain;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, uGraphics, uSystem;

type
TfMain = class(TForm)
StepEvent: TTimer;
procedure FormCreate(Sender: TObject);
procedure StepEventTimer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
fMain: TfMain;
GameDevice: TDevice;
GameCamera: TCamera;
GameScene: TScene;
GameViewer: TViewer;

implementation

{$R *.dfm}

procedure TfMain.FormCreate(Sender: TObject);
begin
GameDevice:= TDevice.Create;
GameCamera:= TCamera.Create;
GameScene:= TScene.Create;
GameViewer:= TViewer.Create(nil);

with GameViewer do
begin
Parent:= fMain;
Device:= GameDevice;
Scene:= GameScene;
Scene.Camera:= GameCamera;
Width:= fMain.ClientWidth;
Height:= fMain.ClientHeight;
BackBuffer.Width:= Width;
BackBuffer.Height:= Height;
GameCamera.Width:= Width;
GameCamera.Height:= Height;
end;

with GameScene.AddSprite do
begin
Image.Picture.LoadFromFile('Data\Images\1.bmp');
Image.Transparent:= true;
end;

with GameScene.AddSprite do
begin
Image.Picture.LoadFromFile('Data\Images\1.bmp');
Image.Transparent:= true;
Position.X:= 250;
end;

GameScene.Camera.CameraObject:= GameScene.Sprites[0];
end;

procedure TfMain.StepEventTimer(Sender: TObject);
begin
GameViewer.Update;
GameCamera.Update;

if OnKey(VK_LEFT) then GameScene.Sprites[0].Position.X:= GameScene.Sprites[0].Position.X - 4;
if OnKey(VK_RIGHT) then GameScene.Sprites[0].Position.X:= GameScene.Sprites[0].Position.X + 4;
if OnKey(VK_UP) then GameScene.Sprites[0].Position.Y:= GameScene.Sprites[0].Position.Y - 4;
if OnKey(VK_DOWN) then GameScene.Sprites[0].Position.Y:= GameScene.Sprites[0].Position.Y + 4;
end;

end.

uGraphics:



unit uGraphics;

interface

uses
Graphics, ExtCtrls, Windows, Classes, JPEG;

type
TCoordinates = record
X: Integer;
Y: Integer;
end;

TDevice = class
public
Width: Integer;
Height: Integer;
Windowed: Boolean;

procedure Update;
constructor Create;
end;

TSprite = class
public
Position: TCoordinates;
Tag: Integer;
Name: String;
Image: TImage;

constructor Create;
end;

TCamera = class
public
Position: TCoordinates;
Clamp: TCoordinates;
CameraObject: TSprite;
Width: Integer;
Height: Integer;

procedure Update;
constructor Create;
end;

TScene = class
public
SpritesCount: Integer;
Sprites: array[0..999] of TSprite;
Camera: TCamera;

function AddSprite: TSprite;
procedure LoadFromFile(const FileName: String);
constructor Create;
end;

TViewer = class(TImage)
public
Device: TDevice;
Scene: TScene;
BackBuffer: TImage;

procedure Update;
constructor Create(AOwner: TComponent);
end;

implementation

//*TDevice*//
procedure TDevice.Update;
var
DeviceMode: TDevMode;
begin
if Windowed then
begin
ChangeDisplaySettings(TDevMode(nil^), CDS_FULLSCREEN);
end else
begin
with DeviceMode do
begin
dmSize := SizeOf(DeviceMode);
dmPelsWidth:= Width;
dmPelsHeight:= Height;
dmBitsPerPel:= 32;
dmFields:= DM_PELSWIDTH or DM_PELSHEIGHT or DM_BITSPERPEL;
end;
ChangeDisplaySettings(DeviceMode, CDS_FULLSCREEN);
end;
end;

constructor TDevice.Create;
begin
inherited Create;
Width:= 800;
Height:= 600;
Windowed:= true;
end;

//*TSprite*//
constructor TSprite.Create;
begin
inherited Create;

Image:= TImage.Create(nil);
Image.Visible:= false;
Image.AutoSize:= true;
end;

//*TCamera*//
procedure TCamera.Update;
begin
if CameraObject <> nil then
begin
if CameraObject.Position.X > Position.X + Clamp.X div 2 then
Position.X:= CameraObject.Position.X - Clamp.X div 2;
if CameraObject.Position.X < Position.X - Clamp.X div 2 then
Position.X:= CameraObject.Position.X + Clamp.X div 2;
if CameraObject.Position.Y > Position.Y + Clamp.Y div 2 then
Position.Y:= CameraObject.Position.Y - Clamp.Y div 2;
if CameraObject.Position.Y < Position.Y - Clamp.Y div 2 then
Position.Y:= CameraObject.Position.Y + Clamp.Y div 2;
end;
end;

constructor TCamera.Create;
begin
inherited Create;
Clamp.X:= 320;
Clamp.Y:= 0;
end;

//*TScene*//
function TScene.AddSprite: TSprite;
begin
Sprites[SpritesCount]:= TSprite.Create;
Result:= Sprites[SpritesCount];
SpritesCount:= SpritesCount + 1;
end;

procedure TScene.LoadFromFile(const FileName: String);
begin
end;

constructor TScene.Create;
begin
inherited Create;
SpritesCount:= 0;
end;

//*TViewer*//
procedure TViewer.Update;
Var
i: Integer;
begin
BackBuffer.Canvas.CopyRect(Rect(0,0,Width,Height),Canvas,Rect(0,0,Width,Height));
BackBuffer.Canvas.Brush.Color:= $000000;
BackBuffer.Canvas.FillRect(Rect(0,0,Width,Height));

for i:= 0 to Scene.SpritesCount - 1 do
BackBuffer.Canvas.Draw((Scene.Sprites[i].Position.X - (Scene.Sprites[i].Image.Width div 2)) -
(Scene.Camera.Position.X - (Scene.Camera.Width div 2)),
(Scene.Sprites[i].Position.Y - (Scene.Sprites[i].Image.Height div 2)) -
(Scene.Camera.Position.Y - (Scene.Camera.Height div 2)),
Scene.Sprites[i].Image.Picture.Graphic);

Canvas.CopyRect(Rect(0,0,Width,Height),BackBuffer.Canvas,Rect(0,0,Width,Height));
end;

constructor TViewer.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
BackBuffer:= TImage.Create(nil);
BackBuffer.Parent:= Parent;
BackBuffer.Visible:= false;
end;

end.

uSystem:



unit uSystem;

interface

uses
Windows;

function OnKey(key: Char): Boolean; overload;
function OnKey(key: Word): Boolean; overload;

implementation

//*Keyboard*//

function OnKey(key: Char): Boolean;
var
vk : Integer;
begin
vk:= VkKeyScan(key) and $FF;
if vk <> $FF then
Result:= (GetAsyncKeyState(vk) < 0)
else Result:= False;
end;

function OnKey(key: Word): Boolean;
begin
Result:= (GetAsyncKeyState(key) < 0);
end;

end.

P.S.: Удачи в игростроении
Авторские права принадлежат Каыблину Андрею (Xakep) (с) 2008 год


Категория: Delphi, Pascal, ObjectPascal | Просмотров: 2809 | Добавил: ДядяВолк (11.08.2010) | Рейтинг: 0.0/0
Теги: движка, Графика, клавиатура, игры, Создание, для, Часть 1, базового
Источник: http://quadrathell.cn.ua/ | Автор: Михаил Христосенко |
HTML ссылка на материал:
BB ссылка на материал:
Похожие материалы :
Возможно вам будет интересно:
С чего начать создание игры для начинающих? (13)
Сохранение и чекпоинты (0)
Создание арканойда шаг за шагом в XNA Game Studio (0)
Знакомство с Движком! (0)
3d Rad - Про конструктор (0)
Создаем платформер. Scirra Construct (4)
То, что нужно знать всем, кто движется в сфере геймдева. (1)
Многопоточность (0)
PHP и MySQL – Теоретический курс. Введение. (2)
Создание света (освещение уровня) (0)
Установка Yogurt3D и Adobe Stage3D API на ваш компьютер. (0)
Borland Assembler (BASM) уроки для начинающих (урок 7 часть 1) (0)
Серия уроков по 3d Rad (0)
Полный туториал по использованию Radimp (2)
Обмен информацией по TCP/IP-протоколу (Delphi) (0)
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Мы в социальных сетях

Поиск
Поиск по всему сайту:
Поиск по разделу:

Панель пользователя
Здравствуйте, Гость


Ник:
Пароль:
Запомнить :

Ваш IP: 54.145.218.90

Случайные конструкторы

Случайные движки

Случайные статьи

Статистика
Онлайн всего: 7
Гостей: 7
Пользователей: 0

На сайте были:
AxenusKa1971 , FireOfSteel , NeoCoda , lechenienarkomania

При полном или частичном копировании материалов сайта ссылка на Make-Games.ru обязательна. Make-Games.ru © 2008 - 2017 Хостинг от uWeb
Топ Разработка игр Рейтинг@Mail.ru