CAST II Game Engine Community

Please login or register.

Login with username, password and session length
Advanced search  

Author Topic: Создаём простую стрелялку. Урок за уроком.  (Read 1984 times)

0 Members and 1 Guest are viewing this topic.

PetrashEvgant

  • Guest

Уважаемый Baskoff!
      вместо water.cbf поместил я в тело программы файл <default.cbf>, поставляемый с прогой Cast2
      Результат сильно смешнама, если бы не грусть тоска из-за неудачного опыта анимационного зрелища на экране, выразившегося в странных поклонах и растягивании фигуры. Разъясите ошибку, что не так делали, если, кроме смены имени файла ничего не меняли.
Logged

Baskoff

  • Newbie
  • *
  • Posts: 10

Надоело копированием и перетаскиванием уроков заниматься. Продолжение на http://www.cast2.ucoz.ru/
« Last Edit: July 21, 2009, 09:58:01 AM by Baskoff »
Logged

Savoia

  • Newbie
  • *
  • Posts: 2

А еще уроки будут? если да, — то когда, если нет, — то почему.
Logged

Luarvic

  • Newbie
  • *
  • Posts: 32

Отличные уроки! (особенно учитывая что я самостоятельно делал все именно так что касается камеры и кнопок ;D)
Хотелось бы еще узнать как прилепить камеру к какомунить объекту например мешу и двигать меш а камера за ним, тоесть вид от 3-го лица реализовать. Перемещения я сделал а вот с вращениями проблемы.
В 4-м уроке  NewPosition:= Core.Renderer.MainCamera.GetPosition; можно вынести из ифов чтоб было меньше букаф.
Так держать, продолжай!
Logged

Baskoff

  • Newbie
  • *
  • Posts: 10
Урок 5
« Reply #6 on: June 29, 2009, 08:49:25 AM »

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

Для начала создадим 4 класса
  TTopKey = class(TSystemMessage) end;
  TDownKey = class(TSystemMessage) end;
  TTLeftKey = class(TSystemMessage) end;
  TTRiteKey = class(TSystemMessage) end;

Это классы для отправки сообщений.

Далее объявим 4 глобальных переменных:

  TopKeyRem:Boolean;
  DownKeyRem:Boolean;
  TRightKeyRem:Boolean;
  TLeftKeyRem:Boolean;

Каждая из них будет принимать значение True когда кнопка нажата, и False когда отпущена.

Далее в обработчик нажатия на кнопку добавим:

Core.Input.BindCommand(ini.ReadString('Keys', 'Top', 'R')+'+', TTopKey);
Core.Input.BindCommand(ini.ReadString('Keys', 'Top', 'R')+'-', TTopKey);
Core.Input.BindCommand(ini.ReadString('Keys', 'Down', 'F')+'+', TDownKey);
Core.Input.BindCommand(ini.ReadString('Keys', 'Down', 'F')+'-', TDownKey);

Core.Input.BindCommand(ini.ReadString('Keys', 'TLeft', 'Q')+'+', TTLeftKey);
Core.Input.BindCommand(ini.ReadString('Keys', 'TLeft', 'Q')+'-', TTLeftKey);
Core.Input.BindCommand(ini.ReadString('Keys', 'TRite', 'E')+'+', TTRiteKey);
Core.Input.BindCommand(ini.ReadString('Keys', 'TRite', 'E')+'-', TTRiteKey);

Смысл этих строчек был рассмотрен в предыдущих уроках, так что не останавливаемся, движемся дальше.

Далее, в обработчике сообщений напишем:

if Msg.ClassType = TTopKey then TopKeyRem:= not TopKeyRem;
if Msg.ClassType = TDownKey then DownKeyRem:= not DownKeyRem;
if Msg.ClassType = TTRiteKey then TRightKeyRem:= not TRightKeyRem;
if Msg.ClassType = TTLeftKey then TLeftKeyRem:= not TLeftKeyRem;

В обработчик таймера добавим переменную «Camera» тип «TCamera» и допишем:

Camera:= Core.Renderer.MainCamera;
if TopKeyRem = True then
begin

  Camera.Orientation := MulQuaternion( GetQuaternion(-0.05, Camera.RightVector), Camera.Orientation);
end;
if
DownKeyRem = True then
begin

  Camera.Orientation := MulQuaternion( GetQuaternion(0.05, Camera.RightVector), Camera.Orientation);
end;
if
TRightKeyRem = True then
begin

  Camera.Orientation := MulQuaternion( GetQuaternion(0.05, Camera.UpVector), Camera.Orientation);
end;
if
TLeftKeyRem = True then
begin

  Camera.Orientation := MulQuaternion( GetQuaternion(-0.05, Camera.UpVector), Camera.Orientation);
end;

не забываем добавить модуль «CAST2» в uses.

рассмотрим код:
if TopKeyRem = True then
begin

  Camera.Orientation := MulQuaternion( GetQuaternion(-0.05, Camera.RightVector), Camera.Orientation);
end;

Кватернион задает поворот и получается из угла и оси, вокруг которой надо поворачивать.
Здесь мы берем кватернион нужного нам поворота и множим (MulQuaternion) на кватернион текущей ориентации камеры.
В данном случае поворачивать надо вокруг вектора камеры, показывающего направление вправо -- Camera.RightVector.
При перемножении кватернионов их эффект (то есть поворот) складывается.

Компилируем, запускаем. Теперь при нажатии на клавиши камера не только перемещается, но ещё и вращается. Если скорость поворота не устраивает, увеличиваем или уменьшаем «0.05» именно на такой угол камера и поворачивается каждый раз.

Урок на этом окончен. Для любопытных выставляю проект со всеми файлами. Полностью рабочий.
« Last Edit: July 01, 2009, 01:00:44 AM by admin »
Logged

Baskoff

  • Newbie
  • *
  • Posts: 10
Урок 4
« Reply #5 on: June 24, 2009, 07:46:54 PM »

Нажатие клавиш, движение камеры.
И так. Продолжаем дорабатывать проект, который мы создали в 3-ом уроке. Мы уже научились запускать движок, загружать сцену, создавать камеру и выходить при нажатии на кнопку. Теперь научимся перехватывать нажатия не 1 клавиш, а так же не только момент нажатия но и отпускания. А так же научимся двигать камеру.

Для начала создадим 4 класса:

  TForwKey = class(TSystemMessage) end;
  TBackKey = class(TSystemMessage) end;
  TRightKey = class(TSystemMessage) end;
  TLeftKey = class(TSystemMessage) end;

Это классы для отправки сообщений.

Далее объявим 4 глобальных переменных:

  ForwKeyRem:Boolean;
  BackKeyRem:Boolean;
  RightKeyRem:Boolean;
  LeftKeyRem:Boolean;

Каждая из них будет принимать значение True когда кнопка нажата, и False когда отпущена.
Далее в обработчик нажатия на кнопку добавим:

Core.Input.BindCommand(ini.ReadString('Keys', 'forw', 'W')+'+', TForwKey);
Core.Input.BindCommand(ini.ReadString('Keys', 'forw', 'W')+'-', TForwKey);
Core.Input.BindCommand(ini.ReadString('Keys', 'back', 'S')+'+', TBackKey);
Core.Input.BindCommand(ini.ReadString('Keys', 'back', 'S')+'-', TBackKey);
Core.Input.BindCommand(ini.ReadString('Keys', 'right', 'D')+'+', TRightKey);
Core.Input.BindCommand(ini.ReadString('Keys', 'right', 'D')+'-', TRightKey);
Core.Input.BindCommand(ini.ReadString('Keys', 'left', 'A')+'+', TLeftKey);
Core.Input.BindCommand(ini.ReadString('Keys', 'left', 'A')+'-', TLeftKey);

Это и есть перехватчики нажатий на кнопки. Рассмотрим 2 первых строчки.

Core.Input.BindCommand(ini.ReadString('Keys', 'forw', 'W')+'+', TForwKey);

При нажатии на W отправить сообщение TForwKey. Именно «+» определяет что отправлять это сообщение при нажатии.

Core.Input.BindCommand(ini.ReadString('Keys', 'forw', 'W')+'-', TForwKey);

При отпускании W отправить сообщение TForwKey. Именно «-» определяет что отправлять это сообщение при отпускании.

То есть и при нажатии и при отпускании кнопки W мы посылаем сообщение TForwKey.

Далее, в обработчике сообещний напишем:
if Msg.ClassType = TForwKey then ForwKeyRem:= not ForwKeyRem;
if Msg.ClassType = TBackKey then BackKeyRem:= not BackKeyRem;
if Msg.ClassType = TRightKey then RightKeyRem:= not RightKeyRem;
if Msg.ClassType = TLeftKey then LeftKeyRem:= not LeftKeyRem;

Этим текстом  каждый раз будем «переворачивать» переменную. С True на False  и на оборот.
 
 В обработчике таймера добавим переменную NewPosition: TVector3s; Не забываем добавить в uses модель Base3D.

Так же допишем текст в обработчик таймера
if ForwKeyRem = True then
begin
  NewPosition:= Core.Renderer.MainCamera.GetPosition;
  Core.Renderer.MainCamera.SetPosition( AddVector3s (NewPosition, ScaleVector3s(Core.Renderer.MainCamera.ForwardVector, 2) ));
end;
if BackKeyRem = True then
begin

  NewPosition:= Core.Renderer.MainCamera.GetPosition;
  Core.Renderer.MainCamera.SetPosition( SubVector3s (NewPosition, ScaleVector3s(Core.Renderer.MainCamera.ForwardVector, 2) ));
end;
if
RightKeyRem = True then
begin

  NewPosition:= Core.Renderer.MainCamera.GetPosition;
  Core.Renderer.MainCamera.SetPosition( AddVector3s(NewPosition, ScaleVector3s(Core.Renderer.MainCamera.RightVector, 2) ));
end;
if
LeftKeyRem = True then
begin

  NewPosition:= Core.Renderer.MainCamera.GetPosition;
  Core.Renderer.MainCamera.SetPosition( SubVector3s(NewPosition, ScaleVector3s(Core.Renderer.MainCamera.RightVector, 2) ));
end;

рассмотрим первый if
if
ForwKeyRem = True then
begin

  NewPosition:= Core.Renderer.MainCamera.GetPosition;
  Core.Renderer.MainCamera.SetPosition( AddVector3s (NewPosition, ScaleVector3s(Core.Renderer.MainCamera.ForwardVector, 2) ));
end;

Если ForwKeyRem = True – будет складывать командой AddVector3s 2 вектора, тем самым заставляя камеру двигаться. Команда SubVector3s – это вычитание одного вектора из другого. Чтобы камера двигалась по живее, добавлено «ScaleVector3s» - это команда, с помощью которой мы увеличиваем вектор в 2 раза. Можно написать число больше или меньше, в зависимости от необходимой скорости движения камеры.

Компилируем, Запускаем. Теперь по нажатия на клавиш мы двигаемся!

Урок на этом окончен. Для любопытных выставляю проект со всеми файлами. Полностью рабочий.
« Last Edit: June 29, 2009, 09:22:25 AM by Baskoff »
Logged

Baskoff

  • Newbie
  • *
  • Posts: 10
Урок 3
« Reply #4 on: June 23, 2009, 11:29:37 PM »

Нажатие клавиш, INI файлы.
И так. Продолжаем мучать проект, который мы создали во 2-ом уроке. Мы уже научились запускать движок и загружать сцену.

Теперь научимся брать из ini фалов настройки и ловить нажатия клавиш.

Добавим в uses модуль IniFiles. И в обработчик нажатия на кнопку переменную «ini» тип «TIniFile» и переменную «ExitKey» тип «String».

Для начала добавим кнопку выхода. Для того, чтобы прочитать что-то из ini файла я написал следующий текст:

ini := TIniFile.Create('C:\MyIni.ini');
ExitKey = ini.ReadString('Keys', 'Exit', 'F4');

Открываем файл, читаем от туда переменную 'Exit' из раздела 'Keys'. Если там нет такой, то пишем в переменную не прочитанное значение а 'F4'.

Далее для перехвата сообщений надо создать класс, в который и будут поступать сообщения.
Добавляем в type:

TMessager = class
    procedure HandleMessage(const Msg: BaseMsg.TMessage);
end;

Это и есть класс, в который мы будем принимать сообщения.

Далее создаём глобальную переменную «Messager» тип «TMessager».
И добавляем процедуру.

procedure TMessager.HandleMessage(const Msg: BaseMsg.TMessage);
begin
if Msg.ClassType = TForceQuitMsg then form1.close;
end;

здесь сразу предусмотрели выход при получении сообщения «TForceQuitMsg».

Далее в обработчик нажатия на кнопку дописываем строки:
Starter.MessageHandler := Core.HandleMessage;
Core.MessageHandler := Messager.HandleMessage;

Это мы передаём нашей переменной все сообщения.

Так же для удобства удалим строку «while Starter.Process() do Core.Process();», создадим на форме таймер, поставим у него период равным единице и значение Enabled по умолчанию в False. И будем запускать таймер строкой «Timer1.Enabled:= true;». По обработчику таймера напишем: «Core.Process();» теперь наша сцена будет работать каждую миллисекунду.

Создаём файл «MyIni.ini» с содержимым

[Keys]
exit=F4

Запускаем. Теперь грузится сцена, и по нажатию на F4 мы выходим. Так же как и кнопка выхода будут делаться и остальные кнопки на движение, использование предметов и способностей.


Урок на этом окончен. Для любопытных выставляю проект со всеми файлами. Полностью рабочий.
« Last Edit: June 24, 2009, 08:14:59 PM by Baskoff »
Logged

Baskoff

  • Newbie
  • *
  • Posts: 10
Урок 2.
« Reply #3 on: June 23, 2009, 10:14:51 AM »

Загрузка сцен, создание камеры.

Для этого урока я использую файл «water.cbf» из демки с водой. Именно его мы сегодня и загрузим. И так, у нас есть проект с установленным движком, приступим.
Для начала добавим модуль «AppsInit» и в глобальных переменных объявим переменную  «Starter» тип «TAppStarter». У меня глобальные переменные приняли вид:

var
  Starter: TAppStarter;
  Form1: TForm1;

Далее создадим кнопку, по ней и будем загружать сцену.
В событии нажатия кнопки пишем:

  Starter := TWin32AppStarter.Create('CAST II Application', nil, [soSingleUser]);

Это создаётся новое окно. Пусто и безликое.

Далее надо запустить сам движок. Для этого добавляем в uses модуль «C2Core», создаём глобальную переменную «Core» тип «TCore», дальше в обработчике нажатия кнопки добавляем строку:

«Core := TCore.Create();»

 При попытке запуска это проекта компилятор будет ругаться. Надо создать фал «C2Defines.inc» в папке проекта. Подойдёт даже пустой файл. Ничего интересного не увидим, по прежнему пустое окно после нажатия на кнопку.

Двигаемся дальше. Добавляем модуль «C2DX8Render» и строки   

Core.Renderer := TDX8Renderer.Create(Core);
if not Core.Renderer.CreateDevice(Starter.WindowHandle, 0, false) then
begin

  //<обработать ошибку, если не лень>
  end;

Этими строками говорим движку что рендерить (отображать) сцены всё-таки надо.

Далее добавляем модули «WInput», «Basics», глобальную переменную «Stream» тип «Basics.TFileStream» и пишем строки:

Stream := Basics.TFileStream.Create('water.cbf');
if not Core.LoadScene(Stream) then
begin

  //<обработать ошибку, если не лень>
end;

while Starter.Process() do Core.Process();

Для этой сцены необходим ещё модули, отвечающие за анимацию, прорисовку, поэтому конечный список:

uses
 Basics, AppsInit, BaseTypes, C2Anim, C2FX, ACSAdv, C2GUI,
 C2Affectors, C2Grass, C2DX8Render, WInput, C2Core,
 
 Forms, Dialogs, Classes, Controls, StdCtrls;


Компилируем, запускаем. После нажатия на кнопку должны увидеть сцену с водой. Двигать камеру по ней пока нельзя, но уже хоть что-то. Анимация играется, свет горит.


Урок на этом окончен. Для любопытных выставляю полный текст модуля и проект со всеми файлами. Полностью рабочий.

unit Unit1;

interface

uses
 Basics, AppsInit, BaseTypes, C2Anim, C2FX, ACSAdv, C2GUI,
 C2Affectors, C2Grass, C2DX8Render, WInput, C2Core,
 
 Forms, Dialogs, Classes, Controls, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
  Starter: TAppStarter;
  Core: TCore;
  Stream:Basics.TFileStream;
 
implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Starter := TWin32AppStarter.Create('CAST II Application', nil, [soSingleUser]);
  Core := TCore.Create();

  Core.Renderer := TDX8Renderer.Create(Core);
  if not Core.Renderer.CreateDevice(Starter.WindowHandle, 0, false) then begin
    //<обработать ошибку, если не лень>
  end;

  Core.Input := TOSController.Create(Starter.WindowHandle, {$IFDEF OBJFPCEnable}@{$ENDIF}Core.HandleMessage);

  Stream := Basics.TFileStream.Create('water.cbf');
  if not Core.LoadScene(Stream) then begin
    //<обработать ошибку, если не лень>
  end;

  while Starter.Process do Core.Process();
end;


end.
« Last Edit: June 24, 2009, 08:11:53 PM by Baskoff »
Logged

Baskoff

  • Newbie
  • *
  • Posts: 10
Урок 1.
« Reply #2 on: June 23, 2009, 08:47:08 AM »

Подготовка к работе. Установка движка.

И так, приступим. У меня стоит Delphi 7, его и запускаем. Создаём новый проект, простая форма. Для начало нужно подключить сам движок к Delphi. Для этого качаем с сайта движок, потом закидываем его в папку «Lib», которая лежит в папке, куда установлена Delphi. По умолчанию это «C:\Program Files\Borland\Delphi7\». То-есть если Delphi стоит в каталоге по умолчанию, то нам нужна папка «C:\Program Files\Borland\Delphi7\Lib». В нёё копируем «units» из архива с движком. Кто ещё не понял что качать – вот ссылка на архив, в нём «source\units» - вот папку «units» и копируем в «C:\Program Files\Borland\Delphi7\Lib», если Delphi стоит в папке по умолчанию. В конце должны получить папку «C:\Program Files\Borland\Delphi7\Lib\units», где хранятся файлики и папки.
Далее надо Delphi сообщить что мы подкинули ей модулей. Для этого заходим в Tools - Environment Options... переходим на вкладку Library и добавляем к 1-вой строке строки:

;$(DELPHI)\Lib\units;$(DELPHI)\Lib\units\Oberon;$(DELPHI)\Lib\units\CAST2;$(DELPHI)\Lib\units\ACS;$(DELPHI)\Lib\units\dx8

Всё, движок должен быть подключён, и готов к использованию.
Чтобы проверить работоспособность добавим к стандартным модулям модуль AppsInit, то-есть у меня строка приняла вид

uses
  AppsInit,
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

Рекомендую модули движка писать выше остальных.
Далее добавим на форму кнопку и напишем в событии нажатия на нёё:

var
   Starter: TAppStarter;
begin
   Starter := TWin32AppStarter.Create('CAST II Application', nil, [soSingleUser]);
end;

Запускаем проект. Если компилятор на что-то ругатся, то всё верно. Надо создать файл «GDefines.inc» в папке с проектом. Подойдёт даже пустой файл. Запускам ещё раз. Если запустился – всё сделали правильно. При нажатии на кнопку должно появиться пустое окно. Это и есть окно движка. Пока оно пусто и безжизненное, но это же только начало!
« Last Edit: June 23, 2009, 07:22:35 PM by Baskoff »
Logged

Baskoff

  • Newbie
  • *
  • Posts: 10

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

У меня было 3 по русскому. Так что сразу прошу извинения за грамматику, хотя, с другой стороны, не диктант пишу.  :) И если такие умные – чего в уроки полезли?  ;)

Уроки взяты с сайта http://cast2.ucoz.ru/ Собственно сам свои уроки и перетащил  :) только там для все уроков после 1-го примеры есть рабочие.
« Last Edit: January 10, 2010, 02:16:46 PM by admin »
Logged
 

+ Quick Reply

With Quick-Reply you can write a post when viewing a topic without loading a new page. You can still use bulletin board code and smileys as you would in a normal post.

Warning: this topic has not been posted in for at least 120 days.
Unless you're sure you want to reply, please consider starting a new topic.

Name: Email:
Verification:
Please enter the number: 222: