unit Bullet;

interface       

uses
  _Geometry,   
  Frost.Forms, 
  Frost.Renderers,
  Frost.Engine,
  Frost.GL,
  Frost.Utils,
  Planetoid,
  OpenGL;

const
  HEIGHT = 0.04;
  BULLET_SPEED = 16;
  MAX_BULLETS = 800;

type
TBullet = class(TComponent)
  protected
    class var FMesh: TMesh;
  protected
    FActive: Boolean;
    FBulletBody: TGameObject;
    FLife: Single;
    FOwner: TGameObject;
    FBulletSpeed: Single;
    function GetPosition: TVector3;
  public
    PreviosPosition: TVector3;
    class procedure Init();
    class procedure Fire(Owner: TGameObject; Spread: TMatrix3; Speed: Single = BULLET_SPEED);
    procedure Hide;
    procedure OnStart(); override;
    procedure OnUpdate(const Delta: Double); override;
    procedure OnDestroy(); override;
    property Active: Boolean read FActive write FActive;   
    property Position: TVector3 read GetPosition;
    property Owner: TGameObject read FOwner;
  end;

var
  Bullets: array [0..MAX_BULLETS] of TBullet;

implementation

uses
  WorldScene;

{$REGION 'Cylinder'}
function CreateBulletMesh(Radius: Single = 0.2; Length: Single = 1): TMesh;
var
  Vertex:   TVertexes;
  Textures: TTextures;
  Faces: TFaces;
  i: Integer;
begin
  SetLength(Vertex, 4);
  SetLength(Textures, 4);
  SetLength(Faces, 2);
  Vertex[0] := Vector3( Radius * 0.6, 0, Length);
  Vertex[1] := Vector3( Radius, 0,-Length);
  Vertex[2] := Vector3(-Radius, 0,-Length);
  Vertex[3] := Vector3(-Radius * 0.6, 0, Length);
  Textures[0] := Vector2(0, 0);
  Textures[1] := Vector2(1, 0);
  Textures[2] := Vector2(1, 1);
  Textures[3] := Vector2(0, 1);
  Faces[0] := Face( 0, 1, 2);
  Faces[1] := Face( 0, 2, 3);

  Result := TMesh.Create(Faces, Vertex, Textures, nil);
  SetLength(Vertex, 0);
  SetLength(Textures, 0);
  SetLength(Faces, 0);
end;
{$ENDREGION}

{$REGION 'BaseEnemy'}
class procedure TBullet.Init;
var
  i: Word;
begin
  for i := 0 to MAX_BULLETS do
    Bullets[i] :=  TBullet.Create(
     TGameObject.Create(
       nil));
end;

class procedure TBullet.Fire(Owner: TGameObject; Spread: TMatrix3; Speed: Single = BULLET_SPEED);
var          
  i: Word;
begin
  for i := 0 to MAX_BULLETS do
    if (not Bullets[i].FActive) then
    begin              
      Bullets[i].FOwner := Owner;
      Bullets[i].FActive := True;
      Bullets[i].FBulletSpeed := Speed;
      Bullets[i].GameObject.LocalRotation := Spread * Owner.LocalRotation;
      Bullets[i].GameObject.LocalRotation := Bullets[i].GameObject.LocalRotation;
      Bullets[i].FLife := 10;
      break;
    end;
end;

function TBullet.GetPosition: TVector3;
begin
  Result := VECTOR3_NULL;
  if (FBulletBody <> nil) then
    Result := FBulletBody.Position; 
end;

procedure TBullet.Hide;
begin
//  FActive := False;
  FLife := 0.01;
  FBulletBody.LocalPosition := VECTOR3_NULL;
end;

procedure TBullet.OnStart;
begin
  if FMesh = nil then
    FMesh := CreateBulletMesh(0.02, 0.10);
  FActive := false;
  GameObject.LocalPosition := Vector3(0, 0, 0);
  FBulletBody := TGameObject.Create(GameObject);
//  FBulletBody.LocalPosition := Vector3(0, TPlanetoid.Instance.Radius + HEIGHT, 0);
  FBulletBody.AddComponent(TMeshRenderer.CreateMeshRenderer(FMesh, TColorMaterial.Create(Vector3(0.8,0.8,1))));
end;

procedure TBullet.OnUpdate(const Delta: Double);
begin
  if (FActive) then
  begin
    FBulletBody.LocalPosition := Vector3(0, TPlanetoid.Instance.Radius + HEIGHT, 0);
    PreviosPosition := FBulletBody.Position;
    GameObject.LocalRotation := Rotate( delta * FBulletSpeed, Vector3(1, 0, 0)) * GameObject.LocalRotation;
    FLife := FLife - Delta;
    if (FLife < 0) then
    begin
      FBulletBody.LocalPosition := VECTOR3_NULL;
      FActive := false;
    end;
  end;
end;

procedure TBullet.OnDestroy;
begin

end;
{$ENDREGION}

end.
