GLScene - Космосим на GLScene. Часть 2
Автор: Daddy
WEB-сайт: http://daddy.mirgames.ru
Часть 2. Простейшее движение корабля, эффекты пламени, фон, создание планет, астероидов.
Зазвезденный фон
Есть различные методы создания звездного фона. В большинстве игр для этой цели используются или сферы(кубы) с соответствующей текстурой или спрайты. В общем-то спрайты они даже лучше, чем сферы, хоть и требуют некоторых знаний стереометрии и спрайтовая реализация куда сложнее. Лучше они тем, что меньше искажений, да и проще хранить спрайты, чем текстуру размером 6400x4800. Да и скорость вывода зачастую больше, но все же для начала проще реализовать сферу. Ну в GLScene реализовать это проще простого, хотя я уверен, что на картах с 8Мб или 16Мб видео это может сильно тормозить. Ну что ж, допустим, что у камеры DepthOfView установлен 400. Значит сферу надо создавать размером около 390.
Далее после создания сферы встает другая проблема - текстура, при наложении текстуры на сферу она сильно искажается. Для этого надо подредактировать текстуру под сферу. У кого есть Adobe Photoshop с помощью необходимых фильтров могут добиться этого, у меня же его нет, но вот прога, переведенная мною с С++ на Дельфи, она сделает все, что необходимо.
Воспользовавшись моей прогой и получил необходимую текстуру надо сделать банальное. Просто зайти в свойство Material у некоторой Sphere и добавить туда текстурку. Ну и придется каждый тик Cadencer-а приравнивать позицию сферы к позиции камеры, чтобы объект не мог долететь до границы. Правда в GLScene есть небольшая фича с рендерингом и прозрачные объекты на этом шаре рендериться не будут, но на этот случай вот этот файл. Просто замените такой же файл в GLScene этим. Что делает этот файл. Этот файл делает у всех объектов дополнительное свойство Sorted. То есть дает возможность указывать следует сортировать этот объект или нет. Для незнающих поясню: GLScene сортирует объекты по некоторому принципу, или "прозрачное последним", или "чем ближе тем раньше". Рекомендую второе. Кроме того этот файл добавляет в каденесер фичу Cadencer.deltaTime - и каждый тик каденсера туда этот deltatime и записывается.
Планетарный класс
В общем-то так называемый планетарный класс вот он:
unit planet;
interface
uses Windows, GLScene, GLVectorFileObjects, GLObjects, GLCadencer,
GLWin32Viewer, GLMisc, GLTexture, jpeg, Graphics, GLThorFX, GLFireFX, Geometry,
VectorTypes, inifiles, sysutils, option;
type
TAsteroid = class
private
fmodel: TFreeForm;
rolla, turna, pitcha, speed: Single;
Sp: TVector4f;
public
procedure Life;
constructor Create(path: string; cadencer: TGLCadencer);
end;
TMoon = class
private
fmodel: TSphere;
rotationspeed: Single;
length: Single;
espeed: Single;
angle: Single;
kx, ky, kz: Single;
public
procedure Life;
constructor Create(inif: TMemIniFile; num: Integer; planet: TSphere);
end;
TPlanet = class
private
fmodel: TSphere;
rotationspeed: Single;
Moons: array[1..12] of TMoon;
public
property Model: TSphere read fmodel write fmodel;
constructor Create(path: string; cadencer: TGLCadencer);
procedure Life;
end;
implementation
constructor TPlanet.Create(path: string; cadencer: TGLCadencer);
var
inif: TMemIniFile;
i: Integer;
begin
inif := TMemIniFile.Create(path);
rotationspeed := inif.ReadFloat('General', 'rotationspeed', 0);
fmodel := TSphere(cadencer.Scene.Objects.AddNewChild(TSphere));
fmodel.Slices := MainOption.Slice;
fmodel.Stacks := MainOption.Stack;
fmodel.Material.Texture.Image.LoadFromFile('images\textures\planets\' +
inif.ReadString('General', 'Texture', ''));
fmodel.Material.Texture.TextureMode := tmModulate;
fmodel.Material.Texture.Enabled := True;
fmodel.Radius := inif.ReadFloat('General', 'radius', 10);
fmodel.Pitch(inif.ReadFloat('General', 'pitch', 0));
fmodel.Roll(inif.ReadFloat('General', 'roll', 0));
fmodel.Turn(inif.ReadFloat('General', 'turn', 0));
with fmodel.Position do
begin
x := inif.ReadFloat('General', 'x', 0);
y := inif.ReadFloat('General', 'y', 0);
z := inif.ReadFloat('General', 'z', 0);
end;
for i := 1 to inif.ReadInteger('General', 'mooncount', 0) do
Moons[i] := TMoon.Create(inif, i, fmodel);
inif.Destroy;
end;
procedure TPlanet.Life;
var
i: Byte;
begin
fmodel.Turn(rotationspeed);
i := 1;
while Assigned(Moons[i]) do
begin
Moons[i].Life;
inc(i);
end;
end;
//----------------------------------
//----------------------------------
constructor TMoon.Create(inif: TMemIniFile; num: Integer; planet: TSphere);
var
Sect: string;
begin
Sect := 'Moon' + IntToStr(num);
fmodel := TSphere(planet.AddNewChild(TSphere));
length := inif.ReadFloat(Sect, 'length', 10);
fmodel.Slide(length);
rotationspeed := inif.ReadFloat(Sect, 'rotationspeed', 0);
fmodel.Slices := MainOption.Slice;
fmodel.Stacks := MainOption.Stack;
fmodel.Radius := inif.ReadFloat(Sect, 'radius', 3);
fmodel.Material.Texture.Image.LoadFromFile('images\textures\planets\' +
inif.ReadString(Sect, 'Texture', ''));
fmodel.Material.Texture.TextureMode := tmModulate;
fmodel.Material.Texture.Enabled := True;
fmodel.Pitch(inif.ReadFloat(Sect, 'pitch', 0));
fmodel.Turn(inif.ReadFloat(Sect, 'turn', 0));
fmodel.Roll(inif.ReadFloat(Sect, 'roll', 0));
kx := inif.ReadFloat(Sect, 'kx', 1);
ky := inif.ReadFloat(Sect, 'ky', 1);
kz := inif.ReadFloat(Sect, 'kz', 1);
angle := inif.ReadFloat(Sect, 'startangle', 0);
espeed := inif.ReadFloat(Sect, 'speed', 0);
end;
procedure TMoon.Life;
begin
fmodel.Turn(rotationspeed);
angle := angle + espeed;
if angle > 360 then
angle := angle - 360;
with fmodel.Position do
begin
X := cos(DegToRad(angle)) * length * kx;
Y := cos(DegToRad(angle)) * length * ky;
Z := sin(DegToRad(angle)) * length * kz;
end;
end;
constructor TAsteroid.Create(path: string; cadencer: TGLCadencer);
var
inif: TMemIniFile;
begin
inif := TMemIniFile.Create(path);
fmodel := TFreeForm(cadencer.Scene.Objects.AddNewChild(TFreeForm));
fmodel.LoadFromFile('models/asteroids/' + inif.ReadString('General', 'Model',
''));
with fmodel.Material do
begin
Texture.Image.LoadFromFile('images/textures/asteroids/' +
inif.ReadString('General', 'Texture', ''));
Texture.TextureMode := tmModulate;
Texture.Disabled := False;
end;
fmodel.Scale.Scale(0.01);
fmodel.Position.X := inif.ReadFloat('General', 'X', 0);
fmodel.Position.Y := inif.ReadFloat('General', 'Y', 0);
fmodel.Position.Z := inif.ReadFloat('General', 'Z', 0);
Randomize;
fmodel.PitchAngle := inif.ReadFloat('General', 'StartPitch', random(360));
fmodel.TurnAngle := inif.ReadFloat('General', 'StartTurn', random(360));
fmodel.RollAngle := inif.ReadFloat('General', 'StartRoll', random(360));
rolla := inif.ReadFloat('General', 'RollSpeed', 0);
pitcha := inif.ReadFloat('General', 'PitchSpeed', 0);
turna := inif.ReadFloat('General', 'TurnSpeed', 0);
Sp := fmodel.AbsoluteDirection;
speed := inif.ReadFloat('General', 'Speed', 0);
ScaleVector(Sp, speed);
end;
procedure TAsteroid.Life;
begin
fmodel.Roll(rolla);
fmodel.Pitch(pitcha);
fmodel.Turn(turna);
fmodel.Translate(Sp[0], Sp[1], Sp[2]);
end;
end.
Все планеты хрянятся в отдельном ini-файле, вот его формат:
[General]
Name=%Имя планеты, в общем-то не нужно, но в будущем может пригодиться%
Texture=%Название файла с текстурой%
radius=%Радиус планеты%
rotationspeed=%Скорость вращения вокруг своей оси%
mooncount=%Количество лун%
x=%Координата X%
y=%Координата Y%
z=%Координата Z%
pitch=%Стартовый Pitch планеты, можно даже сказать её ось%
roll=%Аналогично Roll%
turn=%И Turn%
[MoonN] (N - номер луны)
Name=%Название первой луны%
Texture=%Название файла с текстурой%
radius=%Радиус%
rotationspeed=%Скорость вращения вокруг своей оси%
speed=%Скорость вращения вокруг планеты%
pitch=%Pitch оси луны%
roll=%Pitch оси луны%
turn=%Pitch оси луны%
length=%Расстояние до планеты%
startangle=%Начальная позиция по орбите планеты в градусах%
kx=%Коэффициент для растягивания орбиты%
ky=%Коэффициент для растягивания орбиты%
kz=%Коэффициент для растягивания орбиты%
Орбита считается как косинус или синус умноженный на соответствующий коэффициент и на расстояние до планеты. Для движения планеты и лун и объекта TPlanet есть функция Life, вызов которой надо написать в каденсере. Все текстуры должны находятся в папке: images\textures\planets. Модели для астероидов в папке models\asteroids\. Для астероидов в папке images\textures\asteroids\. Формат представления ini-файлов астероидов:
[General]
Model=%Модель%
Texture=%Текстура%
#x=%Положение можно не указывать%
#y=%Положение можно не указывать%
#z=%Положение можно не указывать%
StartPitch=%Начальный Pitch%
StartRoll=%Начальный Roll%
StartTurn=%Начальный Turn%
Speed=%Скорость движения%
PitchSpeed=%Скорость вращения%
RollSpeed=%Скорость вращения%
TurnSpeed=%Скорость вращения%
Класс корабля
unit engine;
interface
uses SysUtils, Windows, GLScene, GLVectorFileObjects, GLObjects, GLCadencer,
GLWin32Viewer, GLMisc, Math, GLTexture, jpeg, Graphics, GLThorFX, GLFireFX,
Geometry, VectorTypes, keyboard, inifiles, option;
type
TCustomShip = class
private
fmodel: TFreeForm;
dummy: TDummyCube;
speed, maxspeed, accel: single;
numengine: integer;
ksrot: Single;
maxsrot: Single;
Rotated: Boolean;
pits, turs, rols: single;
kpitch, kturn, kroll: single;
distance: single;
fengine: array[1..10] of TDummyCube;
flaser: array[1..10] of TCylinder;
fenginesprite: array[1..10] of TSprite;
flight: array[1..10] of TGLLightSource;
ffire: array[1..10] of TGLFireFXManager;
fcad: TGLCadencer;
IntervalK: Word;
Acceled: Boolean;
public
property target: TDummyCube read dummy write dummy;
procedure Rotate(pitch, turn, roll: single);
procedure Move;
procedure Life;
procedure Stop;
procedure Fire(TargetObj: TGLBaseSceneObject);
constructor Create(path: string; cadencer: TGLCadencer);
end;
TShip = class(TCustomShip)
private
fcamera: TGLCamera;
Pricel: TSprite;
public
property camera: TGLCamera read fcamera write fcamera;
procedure Rotate(pitch, turn, roll: single);
procedure Life;
constructor Create(path: string; cadencer: TGLCadencer);
end;
TAIShip = class(TCustomShip)
private
kAttack: single;
kDrive: single;
kMoral: single;
kAvoid: single;
kKam: single;
IQ: single;
kShab: single;
public
procedure Brain(Target: TCustomShip);
end;
implementation
//TCustomShip-------------------------------------------------
constructor TCustomShip.Create(path: string; cadencer: TGLCadencer);
var
f: text;
s, s2: string;
v, m: Single;
i, n: Integer;
FX: TGLBFireFX;
inif, inim: TMemIniFile;
begin
maxspeed := 0.05;
speed := 0;
pits := 0;
turs := 0;
rols := 0;
ksrot := 0.07;
maxsrot := 3;
inim := TMemIniFile.Create(path);
dummy := TDummyCube(cadencer.Scene.Objects.AddNewChild(TDummyCube));
maxspeed := inim.ReadFloat('General', 'maxspeed', 0.05);
kroll := inim.ReadFloat('General', 'rollspeed', 3);
kturn := inim.ReadFloat('General', 'turnspeed', 3);
kpitch := inim.ReadFloat('General', 'pitchspeed', 3);
accel := inim.ReadFloat('General', 'acceleration', 0.01);
fcad := cadencer;
fmodel := TFreeForm(dummy.AddNewChild(TFreeForm));
fmodel.LoadFromFile('models\' + inim.ReadString('General', 'type', '') + '\' +
inim.ReadString('General', 'name', '') + '\' + inim.ReadString('General',
'model', ''));
fmodel.Material.Texture.Image.LoadFromFile('images\textures\ships\' +
inim.ReadString('General', 'texture', ''));
fmodel.Material.Texture.Disabled := False;
fmodel.Material.Texture.TextureMode := tmModulate;
s2 := inim.ReadString('General', 'fire', '');
fmodel.Scale.X := inim.ReadFloat('General', 'scale', 0.01);
fmodel.Scale.Y := inim.ReadFloat('General', 'scale', 0.01);
fmodel.Scale.Z := inim.ReadFloat('General', 'scale', 0.01);
fmodel.Position.Y := -0.4;
fmodel.Pitch(90);
AssignFile(f, 'data\engine\' + inim.ReadString('General', 'engine', '') +
'.eng');
Reset(f);
readln(f, n);
readln(f, m);
readln(f, s);
numengine := n;
for i := 1 to n do
begin
//-----------Огонь
if MainOption.Fire then
begin
inif := TMemIniFile.Create('data/pfx/fire/' + s2 + '.ini');
IntervalK := inif.ReadInteger('General', 'IntervalK', 2000);
fengine[i] := TDummyCube(dummy.AddNewChild(TDummyCube));
ffire[i] := TGLFireFXManager.Create(fcad.Scene);
ffire[i].Reference := fengine[i];
with ffire[i] do
begin
cadencer := TGLCadencer(fcad);
firedensity := inif.ReadFloat('General', 'density', 0.0);
fireradius := inif.ReadFloat('General', 'radius', 0.0);
firedir.X := 0;
firedir.Y := 0;
firedir.Z := 0;
MaxParticles := inif.ReadInteger('General', 'maxparticles', 0);
ParticleInterval := inif.ReadFloat('General', 'interval', 0);
ParticleLife := inif.ReadInteger('General', 'life', 1);
ParticleSize := inif.ReadFloat('General', 'size', 1);
InnerColor.Red := inif.ReadFloat('InnerColor', 'Red', 0);
InnerColor.Blue := inif.ReadFloat('InnerColor', 'Blue', 0);
InnerColor.Green := inif.ReadFloat('InnerColor', 'Green', 0);
OuterColor.Red := inif.ReadFloat('InnerColor', 'Red', 0);
OuterColor.Blue := inif.ReadFloat('InnerColor', 'Blue', 0);
OuterColor.Green := inif.ReadFloat('InnerColor', 'Green', 0);
InitialDir.X := 0;
InitialDir.Y := 0;
InitialDir.Z := 0.2;
end;
inif.Free;
FX := TGLBFireFX.Create(fengine[i].Effects);
FX.Manager := ffire[i];
end;
//-----------Свет от огня
if MainOption.FireLight then
begin
inif := TMemIniFile.Create('data/pfx/fire/' + s2 + '.ini');
flight[i] := TGLLightSource(dummy.AddNewChild(TGLLightSource));
flight[i].Diffuse.Blue := inif.ReadFloat('InnerColor', 'Blue', 0);
flight[i].Diffuse.Green := inif.ReadFloat('InnerColor', 'Green', 0);
flight[i].Diffuse.Red := inif.ReadFloat('InnerColor', 'Red', 0);
flight[i].LightStyle := lsOmni;
inif.Free;
end;
//-----------Спрайт
if MainOption.Sprite then
begin
fenginesprite[i] := TSprite(dummy.AddNewChild(TSprite));
Randomize;
fenginesprite[i].AlphaChannel := Random(10000) / Random(4000);
fenginesprite[i].Scale.X := m;
fenginesprite[i].Scale.Y := m;
fenginesprite[i].Scale.Z := m;
fenginesprite[i].Material.Texture.Image.LoadFromFile(s);
fenginesprite[i].Material.Texture.Disabled := false;
fenginesprite[i].Material.BlendingMode := bmAdditive;
fenginesprite[i].Material.Texture.TextureMode := tmReplace;
fenginesprite[i].Material.Texture.TextureWrap := twNone;
end;
read(f, v);
if MainOption.Fire then
fengine[i].Translate(v, 0, 0);
if MainOption.Sprite then
fenginesprite[i].Translate(v, 0, 0);
if MainOption.FireLight then
flight[i].Translate(v, 0, 0);
read(f, v);
if MainOption.Fire then
fengine[i].Translate(0, v, 0);
if MainOption.Sprite then
fenginesprite[i].Translate(0, v, 0);
if MainOption.FireLight then
flight[i].Translate(v, 0, 0);
read(f, v);
if MainOption.Fire then
fengine[i].Translate(0, 0, v);
if MainOption.Sprite then
fenginesprite[i].Translate(0, 0, v);
if MainOption.FireLight then
flight[i].Translate(v, 0, 0);
end;
CloseFile(f);
end;
procedure TCustomShip.Rotate(pitch, turn, roll: single);
begin
pits := pits + pitch;
turs := turs + turn;
rols := rols + roll;
Rotated := True;
end;
procedure TCustomShip.Move;
begin
if speed < maxspeed then
speed := speed + accel;
Acceled := True;
end;
procedure TCustomShip.Stop;
begin
if speed > 0 then
begin
speed := speed - accel * 2;
if speed < 0 then
speed := 0;
end;
Acceled := True;
end;
procedure TCustomShip.Life;
var
i: Byte;
Vec: TVector4f;
RightVector: TAffineVector;
Up, Dir: TAffineVector;
begin
if (pits > maxsrot) or (pits < -maxsrot) then
pits := sign(pits) * maxsrot;
if (turs > maxsrot) or (turs < -maxsrot) then
turs := sign(turs) * maxsrot;
if (rols > maxsrot) or (rols < -maxsrot) then
rols := sign(rols) * maxsrot;
dummy.Pitch(pits * fcad.Delta * 10);
dummy.Turn(turs * fcad.Delta * 10);
dummy.Roll(rols * fcad.Delta * 10);
if pits > 0 then
begin
pits := pits - ksrot;
if pits < 0 then
pits := 0;
end;
if rols > 0 then
begin
rols := rols - ksrot;
if rols < 0 then
rols := 0;
end;
if turs > 0 then
begin
turs := turs - ksrot;
if turs < 0 then
turs := 0;
end;
if pits < 0 then
begin
pits := pits + ksrot;
if pits > 0 then
pits := 0;
end;
if rols < 0 then
begin
rols := rols + ksrot;
if rols > 0 then
rols := 0;
end;
if turs < 0 then
begin
turs := turs + ksrot;
if turs > 0 then
turs := 0;
end;
if MainOption.Fire then
begin
if Rotated then
begin
SetVector(Up, dummy.Up.AsVector);
SetVector(Dir, dummy.Direction.AsVector);
VectorCrossProduct(Dir, Up, RightVector);
MakeVector(vec, rightvector);
ScaleVector(vec, 0.2);
NegateVector(vec);
end;
for i := 1 to numengine do
begin
ffire[i].Disabled := not Acceled;
ffire[i].ParticleInterval := 1 / ((speed + maxspeed / 500) * IntervalK);
if Rotated then
ffire[i].InitialDir.AsVector := vec;
end;
end;
Rotated := False;
if speed > 0 then
begin
speed := speed - accel / 2;
Acceled := True;
if speed < 0 then
speed := 0;
end;
dummy.Slide(speed * 100 * fcad.Delta);
// fcad.Scene.Objects.FindChild('Star',False).Position:=dummy.Position;
if Assigned(flaser[1]) then
flaser[1].Slide(0.1);
end;
procedure TCustomShip.Fire(TargetObj: TGLBaseSceneObject);
begin
if Assigned(flaser[1]) then
flaser[1].Destroy;
flaser[1] := TCylinder(fcad.Scene.Objects.AddNewChild(TCylinder));
with flaser[1] do
begin
BottomRadius := 0.05;
TopRadius := 0.05;
RollAngle := dummy.RollAngle;
TurnAngle := dummy.TurnAngle;
PitchAngle := dummy.PitchAngle;
Position := dummy.Position;
//Direction:=TargetObj.Position;
Height := 2;
end;
end;
//TShip-------------------------------------------------
constructor TShip.Create(path: string; cadencer: TGLCadencer);
begin
inherited;
fcamera := TGLCamera(dummy.AddNewChild(TGLCamera));
Pricel := TSprite(dummy.AddNewChild(TSprite));
with Pricel.Material do
begin
Texture.Image.LoadFromFile('images/sprites/ships/pricel.bmp');
BlendingMode := bmAdditive;
Texture.Enabled := True;
end;
Pricel.Scale.Scale(0.3);
with fcamera do
begin
Position.X := 2;
Position.Y := -0.3;
DepthOfView := MainOption.DepthView;
CameraStyle := csPerspective;
FocalLength := 100;
SceneScale := 0.5;
Direction.Z := -1;
Turn(-90);
Pitch(10);
//TGLLightSource(AddnewChild(TGLLightSource)).ConstAttenuation:=2;
end;
end;
procedure TShip.Rotate(pitch, turn, roll: single);
begin
inherited;
end;
procedure TShip.Life;
var
deltatime: double;
begin
inherited;
//При Rotate вместо 30*deltatime поставь строчки внизу
if isKeyDown(vk_up) then
Rotate(0, 0, kroll);
if isKeyDown(vk_down) then
Rotate(0, 0, -kroll);
if isKeyDown(vk_left) then
Rotate(kpitch, 0, 0);
if isKeyDown(vk_right) then
Rotate(-kpitch, 0, 0);
// if isKeyDown(33) then fcamera.MoveObjectAround(fmodel,kpitch/3,0);
// if isKeyDown(34) then fcamera.MoveObjectAround(fmodel,-kpitch/3,0);
if isKeyDown(vk_insert) then
Move
else
Acceled := False;
if isKeyDown(vk_delete) then
Stop;
if distance < speed * 40 then
begin
distance := distance + speed / 2;
fcamera.Move(-speed / 2);
fcamera.Lift(speed / 10);
end
else
begin
fcamera.Move(speed / 2);
fcamera.Lift(-speed / 10);
distance := distance - speed / 2;
end;
end;
//TAIShip-------------------------------------------------
procedure TAIShip.Brain(Target: TCustomShip);
var
Vect: TVector4f;
begin
if dummy.DistanceTo(Target.dummy) > 10 then
begin
Stop;
exit;
end;
dummy.Direction := Target.dummy.Position;
dummy.Direction.Rotate(YVector, -90);
Move;
{
Life;
if (dummy.Position.X > Target.dummy.Position.X) then
dummy.Position.X := dummy.Position.X - 0.01
else
dummy.Position.X := dummy.Position.X + 0.01;
if (dummy.Position.Y > Target.dummy.Position.Y) then
dummy.Position.Y := dummy.Position.Y - 0.01
else
dummy.Position.Y := dummy.Position.Y + 0.01;
if (dummy.Position.Z > Target.dummy.Position.Z) then
dummy.Position.Z := dummy.Position.Z - 0.01
else
dummy.Position.z := dummy.Position.Z + 0.01;
MakeVector(Vect, Target.dummy.Position.X - dummy.Position.X,
Target.dummy.Position.Y - dummy.Position.Y, Target.dummy.Position.Z -
dummy.Position.Z);
}
end;
end.
Небольшое описание:
- TCustomShip - минимальный класс для любого корабля
- TShip - класс для "человеческого" корабля
- TAIShip - небольшой класс минимального AI, тупого до невозможности.
Как им пользоваться:
В FormCreate надо будет нечто вроде этого:
AIShip:=TAIShip.Create('data\ships\storm.ini',GLCadencer1);
Ship:=TShip.Create('data\ships\shark.ini',GLCadencer1);
GLSceneViewer1.Camera:=Ship.camera;
AIShip.Life;
Естественно в var должны быть указаны соответствующие переменные. А в GLCadencer1Progress требуется указать:
if not Assigned(Ship) then exit;
AIShip.Brain(Ship);
Ship.Life;
Plan.Life;
Asteroid.Life;
AIShip.Life;
О том, как там все работает напишу в следующей статье, так сказать во второй части к этой части, а пока можете попытаться разобраться самим, кроме того надо еще доделать процедуры Brain и Fire, а пока немного о формате для корабля:
[General]
type=%Тип корабля%
name=%Название корабля%
model=%Файо модели%
maxspeed=%Максимальная скорость%
acceleration=%Ускорение%
turnspeed=%Скорость Turn%
pitchspeed=%Скорость Pitch%
rollspeed=%Скорость Roll%
texture=%Файл текстуры%
fire=%Файл описывающий пламя%
engine=%Файл описывающий расположение двигателей%
lasercount=%Количество лазеров%
scale=%Scale корабля%
[LaserType]
glowsize=%Размер свечения для лазмерного луча%
maxpoints=%MaxPoints для ThorFX лазерного луча%
vibrate=%Vibrate для ThorFX лазерного луча%
wildness=%Wildness для ThorFX лазерного луча%
speed=%Скорость движения луча%
[LaserN] %N - номер лазера%
x=%Позиция создания относительно корабля%
y=%Позиция создания относительно корабля%
z=%Позиция создания относительно корабля%
Формат файлов для огня:
[General]
Density=2,5
Radius=0,00
MaxParticles=1400
Interval=0,00001
Life=10
Size=0,08
InteravlK=1000
[InnerColor]
Red=1
Green=1
Blue=0,5
[OuterColor]
Red=1
Green=1
Blue=0,5
Вышеприведенные свойства соответствуют аналогичным у любого FireFX. А приведенные, как пример - наиболее оптимальные. Формат для двигателей:
4
0.46
images\sprites\lensef\yrengine.bmp
0.33 -0.17 0.34
0.33 -0.65 0.34
0.33 -0.17 -0.34
0.33 -0.65 -0.34
Первая строка - количество engine-ов (NE). Далее размер для спрайта свечения у engine-а. Далее текстурка для спрайта. В следующих NE строках позиции каждого спрайта (они используются и для пламени).
Еще небольшое примечание:
Файлы engine-ов хранятся в папках data\engine\ и имеют расширение .eng
Файлы FireFX хранятся в папках data\pfx\fire\ и имеют расширение ini.
Модели хранятся в папках models\%Тип корабля%\%Название корабля%\
Текстуры хранятся в папке images\textures\ships\
В общем вот работающие файлы этой статьи, разве что без текстуры для звезд, да и без нее весит 2Мб.
|