Создание базового движка для игры. Часть 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]
Все остальное, что не попадает ни под одну категорию.

Мини-Опрос
Чем вы пользуетесь для создания игр?
Всего ответов: 473

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

 Главная » Статьи » Программирование » 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 | Просмотров: 2744 | Добавил: ДядяВолк (11.08.2010) | Рейтинг: 0.0/0
Теги: движка, Графика, клавиатура, игры, Создание, для, Часть 1, базового
Источник: http://quadrathell.cn.ua/ | Автор: Михаил Христосенко |
HTML ссылка на материал:
BB ссылка на материал:
Похожие материалы :
Возможно вам будет интересно:
Броня для игрока (1)
Создание многопользовательской(online) игры на Game Maker. (часть 2) (0)
Создание многопользовательской(online) игры на Game Maker. (часть 1) (0)
Физика (Blitz 3D) (0)
Создание заставки (Intro) (0)
Game Maker. Начало (1)
Создание Платформенной Игры Copyright 2001 by Mark Overmars (0)
Урок для начинающих по Game Maker v8 (платформенная игра) (1)
AI часть 1 (0)
PHP - Базовые понятия (0)
Циклы (0)
Исключения в C++ (0)
Как рисовать спрайты в DXDraw DelphiX (0)
Полный туториал по использованию Radimp (2)
Урок по PaintNET (1)
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Мы в социальных сетях

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

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


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

Ваш IP: 54.211.207.116

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

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

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

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

На сайте были:
ZiP

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