unit Field;

interface

uses
  QuadEngine, Vec2f, Collision, Resources, Winapi.Windows, mSettings, Inputs, Controls, Math, SysUtils;

type
  TGameMode = (gmClassic, gmSingle);
  TFieldMode = (fmArrangement, fmShooting, fmFlight);

  TFieldMapItemType = (fgitNone, fgitShip, fgitDestroyed);
  TShipGunType = (sgtNone, sgtCore, sgtBuckshot);
  TShipType = (stShip4, stShip3, stShip2, stShip1);
  TSideMode = (smSight, smForce, smPath, smOk);

const
  SHIP_TYPE: array[TShipType] of Integer = (4, 3, 2, 1);
  SHIP_TYPE_T: array[1..4] of TShipType = (stShip1, stShip2, stShip3, stShip4);

type
  TField = class;
  TShip = class;
  TSide = class;

  PFieldMapItem = ^TFieldMapItem;
  TFieldMapItem = record
    Position: TPoint;
    Ship: TShip;
    IsDraw, IsBusy: Boolean;
  end;

  PShipGun = ^TShipGun;
  TShipGun = record
    GunType: TShipGunType;
    Position: TVec2f;
    IsShot: Boolean;
    Angle: Single;
  end;

  TFieldItemSide = record
    BeginPoint, EndPoint: Single;
    Item: TShip;
  end;

  TGonfigComp = record
    Force, Angle: Single;
    vAngle, vForce: TVec2f;
  end;

  TGunShot = record
    Point, PointStart, Angle, Vecror, Gravitation, GunPoint, DrawPoint: TVec2f;
    IsKill: Boolean;
    Scale: Single;
    Gun: TShipGunType;
  end;

  TShip = class
  private
    FQuad: IQuadRender;
    FPosition, FStartPosition: TVec2f;
    FShipType: TShipType;
    FAngle, FAngleDraw: Single;
    FIsArrangement: Boolean;
    FIsPlayer: Boolean;

    FHP: Integer;
    FGuns: array of TShipGun;
    procedure SetAngle(value: Single);
    function GetGun(Index: Integer): PShipGun;

  public
    constructor Create(AQuad: IQuadRender; APosition: TVec2f; AShipType: TShipType; IsPlayer: Boolean = False);
    procedure InitGun;
    procedure Process(const dt: Double);
    procedure Draw;
    procedure NextAngle;
    procedure RefreshPosition;
    function GetRect: T2DRect;
    function GetLine: T2DLine;
    function GunCount: Integer;
    procedure Clear;
    function GetAllGunsShots: Boolean;


    property Position: TVec2f read FPosition write FPosition;  
    property Angle: Single read FAngle write SetAngle;
    function GetGunPosition(Gun: TShipGun; Angle: Single = -1): TVec2f;
    
    property StartPosition: TVec2f read FStartPosition write FStartPosition;
    property ShipType: TShipType read FShipType;
    property IsArrangement: Boolean read FIsArrangement write FIsArrangement;
    property IsPlayer: Boolean read FIsPlayer write FIsPlayer;
    property Gun[Index: Integer]: PShipGun read GetGun;
    property HP: Integer read FHP write FHP;
  end;

  TIsBusyConf = record
    MinX, MaxX, MinY, MaxY: Integer;
  end;
  
  TFieldMap = class
  private
    FItems: array[0..19, 0..9] of TFieldMapItem;
    FQuad: IQuadRender;
    FGameMode: TGameMode;
    FField: TField;
    FPositionLeft, FPositionRight: TVec2f;
    function GetItem(X, Y: Integer): PFieldMapItem;
    function GetIsBusyConf(P: TPoint): TIsBusyConf;
  public
    constructor Create(AQuad: IQuadRender; AField: TField);
    procedure Init;
    function GetRect(X, Y: Integer): T2DRect;

    procedure Draw;
    procedure DrawFields;
    procedure SetIsBusy(Item: PFieldMapItem);  
    function GetIsBusy(Item: PFieldMapItem): Boolean;

    property Item[X, Y: Integer]: PFieldMapItem read GetItem;
    property PositionLeft: TVec2f read FPositionLeft write FPositionLeft;
    property PositionRight: TVec2f read FPositionRight write FPositionRight;
  end;

  TField = class
  private
    FLogo: Boolean;
    FTime: Single;
    FShips: array of TShip;
    FQuad: IQuadRender;
    FGameMode: TGameMode;
    FMode: TFieldMode;
    FPosition: TVec2f;
    FAngle: Single;
    FMouse: TVec2f;
    FRound: Integer; 

    FShipMove: TShip;
    FShipMopePosition: TVec2f;
    FShipMopeCount: Integer;

    FMap: TFieldMap;
    FSide: TSide;
    FStroke: Boolean;

    FGrav: TVec2f;

    FGunShot: array of TGunShot;

    procedure ProcessMouse;
    function GetShip(Index: Integer): TShip;
    function GetGunShotIsKill: Boolean;
  public
    constructor Create(AQuad: IQuadRender; AGameMode: TGameMode = gmClassic);
    procedure InitClassic;
    destructor Destroy; override;
    procedure FreeShips;
    procedure DelShips(IsPlayer: Boolean);
    procedure NextShip;
    procedure AddGunShot(StartPointDraw, StartPoint, AngleVector, Vecror, Gravitation: TVec2f; Gun: TShipGunType);
    procedure ClearGunShot;
    function TestShot(Len: Single; Graviti: TVec2f): TGonfigComp;

    function GunShotCount: Integer;
    function GetShipIsArrangement: Boolean;

    procedure Process(const dt: Double);
    procedure ProcessShips(const dt: Double);
    procedure Draw;
    procedure DrawShips;
    procedure DrawMouse;
    procedure DrawGunShot;
    procedure ClearShips(IsPlayer: Boolean);
    function GetShips(IsPlayer: Boolean): TShip;
    function GetShipsAtack(IsPlayer: Boolean): TShip;
    procedure GoToShooting;
    function ShipsCount: Integer;

    procedure ShipRandom(IsPlayer: Boolean);

    property GameMode: TGameMode read FGameMode;
    property Ship[Index: Integer]: TShip read GetShip;
    property Mouse: TVec2f read FMouse;
  end;

  TPathConfig = record
    point, sPoint: TVec2f;
    Num: Integer;
    Draw: Boolean;
  end;

  TSide = class
  private
    FQuad: IQuadRender;
    FField: TField;
    FShip: TShip;
    FGun: PShipGun;
    FPosition, FGrav: TVec2f;
    FAngle: Single;
    FMouse: TVec2f;
    FIsOk: Boolean;
    FGunNum: Integer;
    FLine: T2DLine;
    FMinX: Single;
    FTime: Single;
    FPoints: array of TFieldItemSide;


    FStartVector, FStartPosition: Tvec2f;

    FGunPoint: TVec2f;
    FMode: TSideMode;
    FForce: Single;
    FVectorForceDraw, FVectorForce: TVec2f;
    FAngleForce: Single;

    FPathConfig: TPathConfig;

    function PointsCount: Integer;
    procedure ProcessMouse;
    procedure PointsAdd(ABegin, AEnd: Single; AItem: TShip);
    function GetMaxPoint: Single;
    function GetMinPoint: Single;
    procedure DrawArrowForce;
    procedure RenderPath;
  public
    constructor Create(AQuad: IQuadRender; Field: TField; Ship: TShip; grav: TVec2f);
    procedure Process(const dt: Double);
    procedure Draw;
    procedure DrawMouse;
    procedure DrawShip;
    property IsOk: Boolean read FIsOk;
  end;

implementation

{ TShip }

constructor TShip.Create(AQuad: IQuadRender; APosition: TVec2f; AShipType: TShipType; IsPlayer: Boolean = False);
begin
  FQuad := AQuad;
  FShipType := AShipType;
  FPosition := APosition;
  FStartPosition := APosition;
  FAngle := 0;
  FAngleDraw := FAngle;
  FIsArrangement := False;
  FIsPlayer := IsPlayer;
  InitGun;
  FHP := SHIP_TYPE[FShipType]*3;
end;

procedure TShip.Draw;
var
  i, count: Integer;
  Point: TVec2f;
  Color: Cardinal;
begin
  if FHp > 0 then
    Color := $FFFFFFFF
  else
    Color := $55FFFFFF;

  FQuad.SetBlendMode(qbmSrcAlpha);
  Textures.Ship.DrawRotFrame(FPosition.X, FPosition.Y, FAngleDraw, 1, SHIP_TYPE[FShipType] - 1, Color);

  count := Length(FGuns);
  for i := 0 to count - 1 do
  begin
    Point := GetGunPosition(FGuns[i]);
    Textures.ShipGun.DrawRotFrame(Point.X, Point.Y, FGuns[i].Angle, 1, SHIP_TYPE[FShipType] - 1, Color);
  end;

  if FHp > 0 then
  begin
    FQuad.Rectangle(FPosition.X-16, FPosition.Y-16, FPosition.X+16, FPosition.Y-12, $FF000000);
    FQuad.Rectangle(FPosition.X-15, FPosition.Y-15, FPosition.X+15 - 30*((SHIP_TYPE[FShipType]*3-FHp) / (SHIP_TYPE[FShipType]*3)), FPosition.Y-13, $FF00FF00);
  end;
 // Textures.Hp.DrawFrame(FPosition.X - 16, FPosition.Y - 10, 1);

  //FQuad.Rectangle(GetLine.a.X-2, GetLine.a.Y-2, GetLine.b.X+2, GetLine.b.Y+2, $55FF0000);

  //FQuad.Rectangle(GetRect.X, GetRect.Y, GetRect.X + GetRect.W, GetRect.Y + GetRect.H, $55FF0000);
end;

function TShip.GetAllGunsShots: Boolean;
var
  i: Integer;
begin
  Result := True;
  for i := 0 to GunCount - 1 do
    if not FGuns[i].IsShot then
      Exit(False);
end;

function TShip.GetGun(Index: Integer): PShipGun;
begin
  Result := @FGuns[Index];
end;

function TShip.GetGunPosition(Gun: TShipGun; Angle: Single = -1): TVec2f;
begin
  if Angle < 0 then
    Angle := FAngleDraw;
  Angle := Angle/180*Pi;
  Result.X := -sin(Angle) * Gun.Position.Y + cos(Angle) * Gun.Position.X + FPosition.X;
  Result.Y := cos(Angle) * Gun.Position.Y + sin(Angle) * Gun.Position.X + FPosition.Y;
end;

function TShip.GetLine: T2DLine;
begin
  if (FAngle = 90) or (FAngle = 270) then
  begin
    Result.a.Y := FPosition.Y;
    Result.a.X := FPosition.X - 20* (SHIP_TYPE[FShipType] - 1) - 5;
    Result.b.Y := FPosition.Y;
    Result.b.X := FPosition.X + 20 * (SHIP_TYPE[FShipType] - 1) + 5;
  end
  else
  begin
    Result.a.X := FPosition.X;
    Result.a.Y := FPosition.Y - 20 * (SHIP_TYPE[FShipType] - 1) - 5;
    Result.b.X := FPosition.X;
    Result.b.Y := FPosition.Y + 20 * (SHIP_TYPE[FShipType] - 1) + 5;
  end;
end;

function TShip.GetRect: T2DRect;
var
  H: Integer;
begin
  case FShipType of
    stShip1: H := 10;
    stShip2: H := 8;
    stShip3: H := 4;
    stShip4: H := 1;
  end;
  if (FAngle = 90) or (FAngle = 270) then
  begin
    Result.X := FPosition.X - 20 * SHIP_TYPE[FShipType];
    Result.Y := FPosition.Y - 20 + H;
    Result.W := 40 * SHIP_TYPE[FShipType];
    Result.H := 40 - H * 2;
  end
  else
  begin
    Result.X := FPosition.X - 20 + H;
    Result.Y := FPosition.Y - 20 * SHIP_TYPE[FShipType];
    Result.W := 40 - H * 2;
    Result.H := 40 * SHIP_TYPE[FShipType];
  end;
end;

function TShip.GunCount: Integer;
begin
  Result := Length(FGuns);
end;

procedure TShip.InitGun;
begin

  case FShipType of
    stShip4: 
    begin
      SetLength(FGuns, 3);
      FGuns[0].GunType := sgtCore;  
      FGuns[0].Position := TVec2f.Create(0, 55);
      FGuns[0].Angle := Random(360);  
      FGuns[1].GunType := sgtCore;  
      FGuns[1].Position := TVec2f.Create(0, 20);
      FGuns[1].Angle := Random(360);  
      FGuns[2].GunType := sgtCore;  
      FGuns[2].Position := TVec2f.Create(0, -58);
      FGuns[2].Angle := Random(360);
    end;
    stShip3: 
    begin
      SetLength(FGuns, 2);
      FGuns[0].GunType := sgtCore;  
      FGuns[0].Position := TVec2f.Create(0, 35);
      FGuns[0].Angle := Random(360);  
      FGuns[1].GunType := sgtCore;  
      FGuns[1].Position := TVec2f.Create(0, -42);
      FGuns[1].Angle := Random(360);
    end;
    stShip2: 
    begin
      SetLength(FGuns, 1);
      FGuns[0].GunType := sgtBuckshot;
      FGuns[0].Position := TVec2f.Create(0, 18);
      FGuns[0].Angle := Random(360);
    end;
    stShip1: 
    begin
      SetLength(FGuns, 1);
      FGuns[0].GunType := sgtBuckshot;
      FGuns[0].Position := TVec2f.Create(0, 5);
      FGuns[0].Angle := Random(360);
    end;
  end;
end;

procedure TShip.NextAngle;
begin
  FAngle := FAngle + 90;
  if FAngle > 360 then
  begin
    FAngle := FAngle - 360;
    FAngleDraw := FAngleDraw - 360;
  end;
end;

procedure TShip.Process(const dt: Double);
begin
  if FAngleDraw < FAngle then
  begin
    FAngleDraw := FAngleDraw + 180 * dt;
    if FAngleDraw > FAngle then
      FAngleDraw := FAngle;
  end;
end;

procedure TShip.RefreshPosition;
begin
  FAngle := 0;
  FAngleDraw := FAngle;
  FPosition := FStartPosition;
end;

procedure TShip.SetAngle(value: Single);
begin
  FAngle := value;
  FAngleDraw := value; 
end;

procedure TShip.Clear;
var
  i: Integer;
begin
  FIsArrangement := False;
  for i := 0 to GunCount - 1 do
    FGuns[i].IsShot := False;
end;

{ RField }

procedure TField.AddGunShot(StartPointDraw, StartPoint, AngleVector, Vecror, Gravitation: TVec2f; Gun: TShipGunType);
var
  l: Integer;
begin
  l := Length(FGunShot);
  SetLength(FGunShot, l + 1);
  FGunShot[l].GunPoint := StartPointDraw;
  FGunShot[l].DrawPoint := StartPointDraw;
  FGunShot[l].Point := StartPoint;
  FGunShot[l].PointStart := StartPoint;
  FGunShot[l].Angle := AngleVector;
  FGunShot[l].Vecror := Vecror;
  FGunShot[l].Gravitation := Gravitation;
  FGunShot[l].IsKill := False;
  FGunShot[l].Scale := 1;
  FGunShot[l].Gun := Gun;
end;

procedure TField.ClearGunShot;
begin
  SetLength(FGunShot, 0);
end;

procedure TField.ClearShips(IsPlayer: Boolean);
var
  i, g, Count: Integer;
begin
  Count := Length(FShips);
  for i := 0 to Count - 1 do
    if FShips[i].IsPlayer = IsPlayer then
      FShips[i].Clear;
end;

constructor TField.Create(AQuad: IQuadRender; AGameMode: TGameMode);
begin
  FLogo := False;
  FPosition := TVec2f.Create(Settings.WindowWidth / 2, Settings.WindowHeight / 2);
  FAngle := 0;
  FTime := 0;
  FQuad := AQuad;
  FGameMode := AGameMode;
  FMode := fmArrangement;
  FMap := TFieldMap.Create(FQuad, Self);
  FMap.PositionLeft := TVec2f.Create(70, 230);
  FMap.PositionRight := TVec2f.Create(540, 230);
  InitClassic;
  //FShipMove := FShips[0];
  //FShipMopePosition := TVec2f.Create(0, 0);
end;

procedure TField.DelShips(IsPlayer: Boolean);
var
  i, l: Integer;
  Ship: TShip;
begin
  i := 0;
  l := Length(FShips);
  while i < l do
  begin
    if FShips[i].IsPlayer = IsPlayer then
    begin
      FShips[i].Free;
      if i < l - 1 then
        FShips[i] := FShips[l - 1];
      SetLength(FShips, l - 1);
      Dec(l);
    end
    else
      Inc(i);
  end;
end;

destructor TField.Destroy;
begin
  FreeShips;
  FMap.Free;

  if Assigned(FSide) then
    FSide.Free;

  inherited;
end;

procedure TField.FreeShips;
var
  i, Count: Integer;
begin
  Count := Length(FShips);
  for i := 0 to Count - 1 do
    FShips[i].Free;
  SetLength(FShips, 0);
end;

function TField.GetGunShotIsKill: Boolean;
var
  i: Integer;
begin
  Result := True;
  for i := 0 to GunShotCount - 1 do
    if not FGunShot[i].IsKill then
      Exit(False);
end;

function TField.GetShip(Index: Integer): TShip;
begin
  Result := FShips[Index];
end;

function TField.GetShipIsArrangement: Boolean;
var
  i, Count: Integer;
begin
  Result := True;
  Count := Length(FShips);
  for i := 0 to Count - 1 do
    if not FShips[i].IsArrangement then
      Exit(False);
end;

function TField.GetShipsAtack(IsPlayer: Boolean): TShip;
var
  i: Integer;
begin
  Result := nil;
  for i := 0 to High(FShips) do
    if (FShips[i].IsPlayer = IsPlayer) then
      if (Result = nil) or (FShips[i].HP > 0) and (SHIP_TYPE[Result.ShipType] > SHIP_TYPE[FShips[i].ShipType]) then
        Result := FShips[i];
end;

function TField.GetShips(IsPlayer: Boolean): TShip;
var
  i, Count, TotalCount: Integer;
  Ships: array of TShip;
begin
  Count := 0;
  for i := 0 to High(FShips) do
    if (FShips[i].IsPlayer = IsPlayer) then
    begin
      if not FShips[i].IsArrangement then
      begin
        SetLength(Ships, Count + 1);
        Ships[Count] := FShips[i];
        Inc(Count);
      end;
      Inc(TotalCount);
    end;

  if Count > 0 then
    Result := Ships[Random(Count)]
  else
    if TotalCount > 0 then
    begin
      ClearShips(IsPlayer);
      Result := GetShips(IsPlayer);
    end
    else
      Result := nil;
end;

procedure TField.InitClassic;
var
  i, ShipType, count, Position: Integer;
begin
  Position := 130;
  for ShipType := 3 downto 0 do
    for i := 0 to 3 - ShipType do
    begin
      count := Length(FShips);
      SetLength(FShips, count + 1);
      FShips[count] := TShip.Create(FQuad, TVec2f.Create(Position, 100), SHIP_TYPE_T[ShipType+1], True);
      Inc(Position, 50);
    end;
end;

procedure TField.NextShip;
begin
  FMode := fmShooting;
  FShipMove := GetShips(FStroke);
 // FStroke := not FStroke;
end;

procedure TField.GoToShooting;
begin
  FMode := fmShooting;
  ShipRandom(False);
  ClearShips(False);
  ClearShips(True);
  FStroke := True;
  NextShip;
end;

function TField.GunShotCount: Integer;
begin
  Result := Length(FGunShot);
end;

procedure TField.Process(const dt: Double);
begin
  if FTime < 1 then
    FTime := FTime + dt;

  if Assigned(FSide) then
  begin
    FSide.Process(dt);
    if FSide.IsOk then
    begin
      FSide.Free;
      FSide := nil;
      if not FShipMove.GetAllGunsShots then
      begin
        FSide := TSide.Create(FQuad, Self, FShipMove, FGrav);
      end
      else
      begin
        FShipMove.IsArrangement := True;
        FMode := fmFlight;
      end;
    end;
    Exit;
  end;

  ProcessMouse;
  ProcessShips(dt);
end;

procedure TField.DrawGunShot;
var
  i: Integer;
  Scale: Single;
begin
  for i := 0 to GunShotCount - 1 do
    if not FGunShot[i].IsKill then
    begin
      Scale := 0.2 + (500 - FGunShot[i].Point.Y) / 300;

      Textures.Shot.DrawRot(FGunShot[i].DrawPoint.X, FGunShot[i].DrawPoint.Y, 0, Scale);
    end;
end;

procedure TField.DrawShips;
var
  X, Y: Integer;
  Rect: T2DRect;
  i, Count: Integer;
  Point, Vector: TVec2f;
begin
  case FMode of
  fmShooting:
    if  Assigned(FShipMove) and FShipMove.IsPlayer then
    begin
      for i := 0 to FShipMove.GunCount - 1 do
      begin
        Point := FShipMove.GetGunPosition(FShipMove.Gun[i]^);
        Vector := (FMouse - Point).Normalize*532;
        Textures.Line.DrawRot(Point.X + Vector.X, Point.Y + Vector.Y, Coll.GetAngle(Point, FMouse), 1, $BBFFFFFF);
       // Textures.Line.DrawRot(Vector.X, Vector.Y, Coll.GetAngle(Point, FMouse), 1);
        //FShipMove.Gun[i].Angle := Coll.GetAngle(Point, FMouse);
      end;
    end;

  fmArrangement:
    if  Assigned(FShipMove) then
    begin
      for Y := 0 to 9 do
        for X := 0 to 9 do
          if FMap.Item[X, Y].IsBusy then
          begin
            Rect := FMap.GetRect(X, Y);
            FQuad.Rectangle(Rect.X, Rect.Y, Rect.X + Rect.W, Rect.Y + Rect.H, $55FF0000);
          end
          else if FMap.Item[X, Y].IsDraw then
          begin
            Rect := FMap.GetRect(X, Y);
            FQuad.Rectangle(Rect.X, Rect.Y, Rect.X + Rect.W, Rect.Y + Rect.H, $5500FF00);
          end;
    end;
  end;

  Count := Length(FShips);
  for i := 0 to Count - 1 do
    FShips[i].Draw;
end;

function TField.TestShot(Len: Single; Graviti: TVec2f): TGonfigComp;
var
  c: Integer;
  Point, Vector: TVec2f;
begin
  Result.Angle := Pi;
  while Result.Angle > Pi do
  begin
    Result.Force := 0;
    Result.vAngle := TVec2f.Create(cos(Result.Angle), sin(Result.Angle));
    while Result.Force < 1.5 do
    begin
      Point := TVec2f.Create(0, 480);
      Result.vForce := Result.vAngle * 250 * (Result.Force + 0.5);
      Vector := Result.vForce;
      while Point.Y < 500 do
      begin
        Point := Point + Vector * 0.1;
        Vector := Vector + Graviti * 0.1;
      end;
      if (Point.X - 30 < len) and (Point.X + 30 > len) then
        Exit;

      Result.Force := Result.Force + 0.05;
    end;
    Result.Angle := Result.Angle - Pi / 90;
  end;

       {
      FPathConfig.point := FPathConfig.point + FVectorForce * dt;
      RenderPath;
      if FPathConfig.point.Y > 500 then
      begin
        FMode := smOk;
      end;

      FVectorForce := FVectorForce + TVec2f.Create(-80, 250) * dt;


        FForce := FForce + dt;
      Radius := FGunPoint.Distance(FMouse);
      FVectorForceDraw := (FMouse - FGunPoint).Normalize * (FForce / 1.5 * Radius);
      FAngleForce := Coll.GetAngle(FGunPoint, FMouse);
      if (FForce >= 1.5) or (Input.MouseUp[mbRight]) then
      begin
        FVectorForce := FVectorForceDraw.Normalize * 250 * (FForce + 0.5);
        FField.AddGunShot(FStartPosition, FGunPoint, FStartVector / 1024, FVectorForce, TVec2f.Create(-80, 250));
        FMode := smPath;
      end;  }
//  Point := Point + Vecror * dt;
//  FGunShot[i].DrawPoint := FGunShot[i].GunPoint + FGunShot[i].Angle * (FGunShot[i].Point.X - FGunShot[i].PointStart.X);


end;

procedure TField.ProcessShips(const dt: Double);
var
  i, s, Count: Integer;
  x, y: Integer;
  Rect: T2DRect;
  Point: TVec2f;
  Items: array[1..4] of PFieldMapItem;
  Ship: TShip;
  ConfCompAtack: TGonfigComp;
begin
  case FMode of
    fmShooting:
      if Assigned(FShipMove) and FShipMove.IsPlayer then
      begin
        for i := 0 to FShipMove.GunCount - 1 do
        begin
          Point := FShipMove.GetGunPosition(FShipMove.Gun[i]^);
          FShipMove.Gun[i].Angle := Coll.GetAngle(Point, FMouse);
        end;
        if Input.MouseDown[mbLeft] and (FTime >= 1) then
        begin
          ClearGunShot;
          FGrav := TVec2f.Create(Random(300)-150, 250);
          FSide := TSide.Create(FQuad, Self, FShipMove, FGrav);
        end;
      end{
      else
      if Assigned(FShipMove) then
      begin
        Ship := GetShipsAtack(True);
        if Ship <> nil then
          for i := 0 to FShipMove.GunCount - 1 do
          begin
            Point := FShipMove.GetGunPosition(FShipMove.Gun[i]^);
        //    FShipMove.Gun[i].Angle := Coll.GetAngle(Point, Ship.Position);

        //    ConfCompAtack := TestShot(Point.Distance(Ship.Position), TVec2f.Create(0, 250));
        //    ConfCompAtack.Force := ConfCompAtack.Force;

        //    AddGunShot(Point, TVec2f.Create(0, 480), Point - Ship.Position, ConfCompAtack.vForce, TVec2f.Create(0, 250), );
          end;
        FMode := fmFlight;
      end};

    fmFlight:
    begin
      for i := 0 to GunShotCount - 1 do
        if not FGunShot[i].IsKill then
        begin
          FGunShot[i].Point := FGunShot[i].Point + FGunShot[i].Vecror * dt;
          FGunShot[i].DrawPoint := FGunShot[i].GunPoint + FGunShot[i].Angle * (FGunShot[i].Point.X - FGunShot[i].PointStart.X);

          //FGunShot[i].PointDraw := FGunShot[i].PointDraw + FGunShot[i].Angle * (FGunShot[i].Vecror.X * dt);
          if (FGunShot[i].Point.Y > 480) and (FGunShot[i].Point.Y <= 500) then
          begin
            for s := 0 to ShipsCount - 1 do
              if Coll.PointRect(FGunShot[i].DrawPoint, FShips[s].GetRect) then
              begin
                if FGunShot[i].Gun = sgtCore then
                  FShips[s].HP := FShips[s].HP - 3
                else
                  FShips[s].HP := FShips[s].HP - 1;

                FGunShot[i].IsKill := True;
              end;
            if GetGunShotIsKill then
            begin
              NextShip;
              Break;
            end;
          end
          else
            if FGunShot[i].Point.Y > 500 then
            begin
              FGunShot[i].IsKill := True;
              if GetGunShotIsKill then
              begin
                NextShip;
                Break;
              end;
            end;

          FGunShot[i].Vecror := FGunShot[i].Vecror + FGunShot[i].Gravitation * dt;
        end;
    end;

    fmArrangement:
    begin
      if Input.MouseDown[mbLeft] and Coll.PointRect(FMouse, Coll.ToRect(630, 50, 120, 32)) then
      begin
        FTime := 0;
        DelShips(True);
        ShipRandom(True);
        GoToShooting;
      end
      else
        if Assigned(FShipMove) then
        begin
          FShipMove.Position := FMouse - FShipMopePosition;
          Count := 0;
          for i := 1 to 4 do
            Items[i] := nil;
          Point := TVec2f.Create(0, 0);
          for Y := 0 to 9 do
            for X := 0 to 9 do
            begin
              Rect := FMap.GetRect(X, Y);
              FMap.Item[X, Y].IsDraw := False;
              if not Assigned(FMap.Item[X, Y].Ship) and not FMap.Item[X, Y].IsBusy and Coll.LineRect(FShipMove.GetLine, Rect) then
              begin
                FQuad.Rectangle(Rect.X, Rect.Y, Rect.X + Rect.W, Rect.Y + Rect.H, $55FF0000);
                Inc(Count);
                if Count <= SHIP_TYPE[FShipMove.ShipType] then
                begin
                  Items[Count] := FMap.Item[X, Y];
                  Point := Point + TVec2f.Create(Rect.X + 20, Rect.Y + 20);
                  FMap.Item[X, Y].IsDraw := True;
                end;
              end;
            end;

          if Input.MouseDown[mbRight] then
            FShipMove.NextAngle;

          if Input.MouseUp[mbLeft] then
          begin
            if Count = SHIP_TYPE[FShipMove.ShipType] then
            begin
              Point := Point / Count;
              FShipMove.Position := point;
              FShipMove.IsArrangement := True;
              FShipMove.StartPosition := point;
              FShipMove := nil;
              for i := 1 to 4 do
                if Items[i] <> nil then
                  FMap.SetIsBusy(Items[i]);
              if GetShipIsArrangement then
                GoToShooting;
            end
            else
            begin
              FShipMove.RefreshPosition;
              FShipMove := nil;
            end;
          end;
        end;
    end;
  end;

  Count := Length(FShips);
  for i := 0 to Count - 1 do
  begin
    if (FMode = fmArrangement) and Input.MouseDown[mbLeft] and not Assigned(FShipMove) and not FShips[i].IsArrangement and Coll.PointRect(FMouse, FShips[i].GetRect) then
    begin
      FShipMove := FShips[i];
      FShipMopePosition := FMouse - FShipMove.Position;
    end;

    FShips[i].Process(dt);
  end;
end;

procedure TField.ShipRandom(IsPlayer: Boolean);
 function GetAngle(X, Y: Integer): Integer;
  begin
    if (X = 1) and (Y = 0) then
      Result := 180
    else if (X = 0) and (Y = 1) then
      Result := 270
    else if (X = -1) and (Y = 0) then
      Result := 0
    else if (X = 0) and (Y = -1) then
      Result := 90;
  end; 
var
  N, M, i, count: Integer;
  x, y, kx, ky: Integer;
  B: Boolean; 
  Point: TVec2f; 
  Rect: T2DRect;
  p: TPoint;
begin
  for N := 3 downto 0 do
    for M := 0 to 3 - N do
      repeat
        if IsPlayer then
          x := Random(10)
        else
          x := Random(10) + 10;
        y := Random(10);
        if Random(2) = 1 then
        begin
          kx := 0;
          if Random(2) = 1 then
            ky := 1
          else
            ky := -1;
        end
        else
        begin
          ky := 0;
          if Random(2) = 1 then
            kx := 1
          else
            kx := -1;
        end;

        B := True;

        for i := 0 to N do
        begin
          p.X := x + kx * i;
          if x > 9 then
            p.X := p.X - 10;
          p.Y := y + ky * i;
          if (p.X < 0) or (p.Y < 0) or (p.X > 9) or (p.Y > 9) or FMap.Item[x + kx * i, p.Y].IsBusy then
          begin
            B := False;
            Break;
          end;
        end;
                 
        if B then
        begin
          Point := TVec2f.Create(0, 0);
          for i := 0 to N do 
          begin 
            Rect := FMap.GetRect(x + kx * i, y + ky * i);
            Point := Point + TVec2f.Create(Rect.X + 20, Rect.Y + 20);  
            FMap.SetIsBusy(FMap.Item[x + kx * i, y + ky * i]);
          end;                   
          Point := Point / (N + 1);
        
          count := Length(FShips);
          SetLength(FShips, count + 1);
          FShips[count] := TShip.Create(FQuad, TVec2f.Create(Point.X, Point.Y), SHIP_TYPE_T[N+1], IsPlayer);
          FShips[count].Angle := GetAngle(kx, ky)+90;
          FShips[count].IsArrangement := True;
        end;          
      until B;  
end;

function TField.ShipsCount: Integer;
begin
  Result := Length(FShips);
end;

procedure TField.ProcessMouse;
var
  Angle: Single;
begin
  Angle := Pi / 180 * FAngle;
  FMouse.X := (Input.Mouse.X - FPosition.X) * cos(Angle) + (Input.Mouse.Y - FPosition.Y) * sin(Angle) + FPosition.X - 12;
  FMouse.Y := -(Input.Mouse.X - FPosition.X) * sin(Angle) + (Input.Mouse.Y - FPosition.Y) * cos(Angle) + FPosition.Y - 13;

end;

procedure TField.Draw;
begin
  FQuad.SetBlendMode(qbmSrcAlpha);
  Textures.Sheet.DrawRot(FPosition.X, FPosition.Y, FAngle, 1);

  FQuad.RenderToTexture(True, Textures.SheetFields, 0, True);
  Textures.Sheet.DrawRot(FPosition.X, FPosition.Y, FAngle, 1);
  Textures.Sheet.Draw(-12, -13);

  FMap.DrawFields;

  DrawShips;

  FQuad.SetBlendMode(qbmSrcAlpha);
  if FMode = fmFlight then
    DrawGunShot;

  if FMode = fmArrangement then
    Fonts.Gost.TextOut(630, 50, 1, PAnsiChar(String1251('Раставить')));


  DrawMouse;
  FQuad.RenderToTexture(False, Textures.SheetFields);

  //FQuad.SetBlendMode(qbmSrcColor);
 // Textures.SheetFields.DrawRot(FPosition.X, FPosition.Y, FAngle, 1);


  Textures.SheetFields.DrawMapRotAxis(
     FPosition.X - 500, FPosition.Y - 370, FPosition.X + 500, FPosition.Y + 370,
     0, 0, 1000/1024, 740/768, FPosition.X, FPosition.Y, FAngle, 1
  );

  if Assigned(FSide) then
    FSide.Draw;

end;

procedure TField.DrawMouse;
begin
  FQuad.SetBlendMode(qbmSrcAlpha);
  Textures.Line1.DrawRot(FPosition.X - 12, FMouse.Y, 180, 1, $EEFFFFFF);
  Textures.Line1.DrawRot(FMouse.X, FPosition.Y - 13, 90, 1, $EEFFFFFF);
  //FQuad.Rectangle(FMouse.X - 2, FMouse.Y - 2, FMouse.X + 2, FMouse.Y + 2, $FFFFFFFF);
end;

{ TFieldMap }

constructor TFieldMap.Create(AQuad: IQuadRender; AField: TField);
begin
  FQuad := AQuad;
  FField := AField;
  Init;
end;

procedure TFieldMap.Init;
var
  X, Y: Integer;
begin
  for Y := 0 to 9 do
    for X := 0 to 19 do
    begin
      FItems[X, Y].Position.X := X;
      FItems[X, Y].Position.Y := Y;
      FItems[X, Y].Ship := nil;
      FItems[X, Y].IsDraw := False;
      FItems[X, Y].IsBusy := False;
    end;
end;

procedure TFieldMap.SetIsBusy(Item: PFieldMapItem);
var
  X, Y: Integer;
  Conf: TIsBusyConf;
begin
  Conf := GetIsBusyConf(Item.Position);
  for Y := Conf.MinY to Conf.MaxY do
    for X := Conf.MinX to Conf.MaxX do
      FItems[X, Y].IsBusy := True;  
end;

function TFieldMap.GetIsBusy(Item: PFieldMapItem): Boolean;
var
  X, Y: Integer;
  Conf: TIsBusyConf;
begin         
  Result := False;
  Conf := GetIsBusyConf(Item.Position);
  for Y := Conf.MinY to Conf.MaxY do
    for X := Conf.MinX to Conf.MaxX do
      if FItems[X, Y].IsBusy then
        Exit(True);
end;

function TFieldMap.GetIsBusyConf(P: TPoint): TIsBusyConf;
var
  k: Integer;
begin
  k := 0;
  if P.X > 9 then
    k := 10;
  Result.MinX := max(P.X-1, k);
  Result.MinY := max(P.Y-1, 0);
  Result.MaxX := min(P.X+1, 9 + k);
  Result.MaxY := min(P.Y+1, 9);
end;

procedure TFieldMap.Draw;
begin

end;


procedure TFieldMap.DrawFields;
var
  i: Integer;
begin
  Textures.GridMain.Draw(FPositionLeft.X, FPositionLeft.Y);
  Textures.GridMain.Draw(FPositionRight.X, FPositionRight.Y);

  for i := 0 to 9 do
  begin
    Textures.Num.DrawFrame(FPositionLeft.X+40*i, FPositionLeft.Y-40, i+10);
    Textures.Num.DrawFrame(FPositionLeft.X-40, FPositionLeft.Y+40*i, i);

    Textures.Num.DrawFrame(FPositionRight.X+40*i, FPositionRight.Y-40, i+10);
    Textures.Num.DrawFrame(FPositionRight.X-40, FPositionRight.Y+40*i, i);
  end;
end;

function TFieldMap.GetItem(X, Y: Integer): PFieldMapItem;
begin
  Result := @FItems[X, Y];
end;

function TFieldMap.GetRect(X, Y: Integer): T2DRect;
begin
  if X < 10 then
    Result.X := FPositionLeft.X + X * 40
  else
    Result.X := FPositionRight.X + (X - 10) * 40;
    
  Result.Y := FPositionLeft.Y + Y * 40;
  Result.W := 40;
  Result.H := 40;
end;

{ TSide }

function TSide.GetMaxPoint: Single;
var
  i: Integer;
begin
  Result := 0;
  for i := 0 to PointsCount - 1 do
  begin
    if Result < FPoints[i].EndPoint then
      Result := FPoints[i].EndPoint;
  end;
end;

function TSide.GetMinPoint: Single;
var
  i: Integer;
begin
  Result := 5000;
  for i := 0 to PointsCount - 1 do
  begin
    if Result > FPoints[i].BeginPoint then
      Result := FPoints[i].BeginPoint;
  end;
end;

procedure TSide.PointsAdd(ABegin, AEnd: Single; AItem: TShip);
var
  l: Integer;
begin
  l := PointsCount;
  SetLength(FPoints, l + 1);
  FPoints[l].BeginPoint := ABegin;
  FPoints[l].EndPoint := AEnd;
  FPoints[l].Item := AItem;
end;

function TSide.PointsCount: Integer;
begin
  Result := Length(FPoints);
end;

constructor TSide.Create(AQuad: IQuadRender; Field: TField; Ship: TShip; grav: TVec2f);
var
  i, k, l: Integer;
  Points: T2DColPoints;
begin
  FTime := 0;
  FPathConfig.Draw := True;
  FPathConfig.Num := 0;
  FMode := smSight;
  FPosition := TVec2f.Create(Settings.WindowWidth / 2, Settings.WindowHeight / 2);
  FAngle := 2;
  FQuad := AQuad;
  FField := Field;
  FShip := Ship;
  FIsOk := False;

  FGrav := grav;
  FForce := 0;
  for i := 0 to FShip.GunCount - 1 do
    if not FShip.Gun[i].IsShot then
    begin
      FGun := FShip.Gun[i];
      FGunNum := i;
      Break;
    end;

  FStartPosition := FShip.GetGunPosition(FGun^);
  FStartVector := (FField.Mouse - FStartPosition).Normalize * 1024;

  FLine := Coll.ToLine(FStartPosition - FStartVector, FStartPosition + FStartVector);
  for i := 0 to FField.ShipsCount - 1 do
    if (FField.Ship[i].HP > 0) and Coll.LineRect(FLine, FField.Ship[i].GetRect, @Points) then
      PointsAdd(Coll.PointMinDisatance(@Points, FLine.a), Coll.PointMaxDisatance(@Points, FLine.a), FShip);
  FMinX := GetMinPoint - (1024 + GetMinPoint - GetMaxPoint) / 2;

  FGunPoint := TVec2f.Create(-FMinX + FStartPosition.Distance(FLine.a), 480);
  FPathConfig.point := FGunPoint;
  FPathConfig.sPoint := FGunPoint;

  FQuad.RenderToTexture(True, Textures.SheetSidePath, 0, True);
  FQuad.Clear($FF000000);
  FQuad.RenderToTexture(False, Textures.SheetSidePath);
end;

procedure TSide.ProcessMouse;
var
  Angle: Single;
begin
  Angle := Pi / 180 * FAngle;
  FMouse.X := (Input.Mouse.X - FPosition.X) * cos(Angle) + (Input.Mouse.Y - FPosition.Y) * sin(Angle) + FPosition.X;
  FMouse.Y := -(Input.Mouse.X - FPosition.X) * sin(Angle) + (Input.Mouse.Y - FPosition.Y) * cos(Angle) + FPosition.Y;
end;

procedure TSide.Process(const dt: Double);
var
  Radius: Single;
  i: Integer;
begin
  ProcessMouse;
  if FTime < 1 then
    FTime := FTime + dt;
  case FMode of
    smSight:
    begin
      FAngleForce := Coll.GetAngle(FGunPoint, FMouse);
      if Input.MouseDown[mbLeft] and (FTime >= 1) then
      begin
        FMode := smForce;
      end;
    end;
    smForce:
    begin
      FForce := FForce + dt;
      Radius := FGunPoint.Distance(FMouse);
      FVectorForceDraw := (FMouse - FGunPoint).Normalize * (FForce / 1.5 * Radius);
      FAngleForce := Coll.GetAngle(FGunPoint, FMouse);
      if (FForce >= 1.5) or (Input.MouseUp[mbLeft]) and (FTime >= 1) then
      begin
        FVectorForce := FVectorForceDraw.Normalize * 250 * (FForce + 0.5);

        if FGun.GunType = sgtCore then
            FField.AddGunShot(FStartPosition, FGunPoint, FStartVector / 1024, FVectorForce, FGrav, FGun.GunType)
        else
          for i := 0 to 2 do
            FField.AddGunShot(FStartPosition, FGunPoint, (FStartVector / 1024) * (1 - (Random(10)-5)/50), FVectorForce, FGrav, FGun.GunType);


        FMode := smPath;
      end;
    end;
    smPath:
    begin
      FPathConfig.point := FPathConfig.point + FVectorForce * dt;
      RenderPath;
      if FPathConfig.point.Y > 500 then
      begin
        FMode := smOk;
      end;

      FVectorForce := FVectorForce + FGrav * dt;
    end;
    smOk:
      if (FGun <> nil) and Input.MouseDown[mbLeft] and Coll.PointRect(FMouse, Coll.ToRect(800, 670, 200, 32)) then
      begin
        FGun.IsShot := True;
        FIsOk := True;
      end;
  end;

end;

procedure TSide.RenderPath;
var
  i, len: Integer;
  dis: Single;
  Vector, point: TVec2f;
begin
  FQuad.RenderToTexture(True, Textures.SheetSidePath, 0, True);
  FQuad.SetBlendMode(qbmSrcAlpha);
  Vector := FPathConfig.point - FPathConfig.sPoint;
  if Vector.Length > 1 then
  begin
    len := Round(Vector.Length+0.5);
    if len > 0 then
      for i := 0 to len - 1 do
      begin
        point := FPathConfig.sPoint + Vector.Normalize;
        if (FPathConfig.Num > 10) and FPathConfig.Draw or not FPathConfig.Draw and (FPathConfig.Num > 5) then
        begin
          FPathConfig.Draw := not FPathConfig.Draw;
          FPathConfig.Num := 0;
        end;
        if FPathConfig.Draw and (point.Y < 500) then
          Textures.Point.Draw(point.X-1, point.Y-1);
        FPathConfig.Num := FPathConfig.Num + 1;
        FPathConfig.sPoint := point;
      end;
  end;

  FQuad.RenderToTexture(False, Textures.SheetSidePath);
end;

procedure TSide.DrawArrowForce;
var
  i: Integer;
  Angle, Angle1, Len: Single;
  Point: TVec2f;
begin
  Len := FVectorForceDraw.Length;
  Textures.Line1.DrawMapRotAxis(FGunPoint.X, FGunPoint.Y, Round(FGunPoint.X+Len+20), FGunPoint.y+4, 0, 0, (Len+20)/1024, 1,
    FGunPoint.X, FGunPoint.Y, FAngleForce, 1);

  Point := TVec2f.Create(FGunPoint.X + FVectorForceDraw.X + FVectorForceDraw.Normalize.X * 20, FGunPoint.Y + FVectorForceDraw.Y + FVectorForceDraw.Normalize.Y * 20);
  Textures.Arrow.DrawRot(FGunPoint.X + FVectorForceDraw.X+1, FGunPoint.Y + FVectorForceDraw.Y+1, FAngleForce, 1, $FFFFFFFF);
  Textures.Line1.DrawMap(Point.X, Point.Y, Point.X + 80, Point.Y + 4, 0, 0, 80/1024, 1);
  Fonts.Gost.TextOutAligned(Point.X + 5, Point.Y - 22, 1, PAnsiChar(AnsiString('R' + FormatFloat('##.00', Len/10))), $FFFFFFFF, qfaLeft);

  Angle := 1 / (2 * pi * Len) * 360;
  for i := -40 to 40 do
    if abs(Angle*i) < 30 then
    begin
      Angle1 := (FAngleForce + i * Angle) / 180 * Pi;
      Textures.Point1.DrawRot(FGunPoint.X + Cos(Angle1) * Len, FGunPoint.Y + Sin(Angle1) * Len, Angle, 1);
    end;
end;

procedure TSide.Draw;
var
  i: Integer;
begin
  FQuad.SetBlendMode(qbmSrcAlpha);
  Textures.Sheet.DrawRot(FPosition.X, FPosition.Y, FAngle, 1);

  FQuad.RenderToTexture(True, Textures.SheetSide, 0, True);
  //FQuad.Clear(0);
  //Textures.Sheet.DrawRot(FPosition.X, FPosition.Y, FAngle, 1);
  Textures.Sheet.Draw(-12, -13);

  //FQuad.SetBlendMode(qbmNone);
 // Textures.Line1.Draw(20, 500-2);

  Textures.Line1.DrawMap(19, 500, 980, 504, 0, 0, 961/1024, 1);

  for i := 0 to PointsCount - 1 do
  begin
    Textures.Ship1.DrawFrame(Round(-FMinX + FPoints[i].BeginPoint)-1, 480, 0);
    Textures.Ship1.DrawFrame(Round(-FMinX + FPoints[i].EndPoint)-10, 480, 2);

    if FPoints[i].EndPoint - FPoints[i].BeginPoint > 10 then
      Textures.Ship2.DrawMap(Round(-FMinX + FPoints[i].BeginPoint)+9, 480, Round(-FMinX + FPoints[i].EndPoint)-9, 512, 0, 0, 1, 1);

    Textures.Line2.Draw(Round(-FMinX + FPoints[i].BeginPoint)-1, 500-4);
    Textures.Line2.Draw(Round(-FMinX + FPoints[i].EndPoint)-1, 500-4);
  end;

  Textures.Gun.DrawRotFrame(FGunPoint.X, FGunPoint.Y, 0, 1, 0);
  Textures.Gun.DrawRotFrame(FGunPoint.X, FGunPoint.Y, FAngleForce, 1, 1);

  if FMode <> smSight then
    DrawArrowForce;

  //FQuad.Rectangle(FPathConfig.point.X-2, FPathConfig.point.Y-2, FPathConfig.point.X+2, FPathConfig.point.Y+2, $FFFF0000);

  {
  FQuad.DrawLine(FLine.a.X, FLine.a.Y, FLine.b.X, FLine.b.Y, $FFFF0000);
  for i := 0 to Length(FP) - 1 do
    FQuad.Rectangle(FP[i].X-2, FP[i].Y-2, FP[i].X+2, FP[i].Y+2, $FFFF0000);
  }

  DrawShip;
  DrawMouse;
  FQuad.SetBlendMode(qbmSrcAlpha);
  Fonts.Gost.TextOut(40, 530, 1, PAnsiChar(String1251('ПУШКА ' + IntToStr(FGunNum+1) + '/' + IntToStr(FShip.GunCount))));

  case FGun.GunType of
    sgtCore: Fonts.Gost.TextOutAligned(500, 30, 1,
      PAnsiChar(String1251('Бслистический расчет для пушки №' + IntToStr(FGunNum+1) + ' (Ядро)' )), $FFFFFFFF, qfaCenter);
    sgtBuckshot: Fonts.Gost.TextOutAligned(500, 30, 1,
      PAnsiChar(String1251('Бслистический расчет для пушки №' + IntToStr(FGunNum+1) + ' (Картечь)' )), $FFFFFFFF, qfaCenter);
  end;

  Fonts.Gost.TextOutAligned(500, 50, 1, PAnsiChar(String1251('Ветер: х = ' + IntToStr(Round(FGrav.X)+1) )), $FFFFFFFF, qfaCenter);

  if FGunNum = FShip.GunCount - 1 then
    Fonts.Gost.TextOutAligned(950, 670, 1, PAnsiChar(String1251('Стрелять')), $FFFFFFFF, qfaRight)
  else
    Fonts.Gost.TextOutAligned(950, 670, 1, PAnsiChar(String1251('Следующая пушка')), $FFFFFFFF, qfaRight);

  FQuad.RenderToTexture(False, Textures.SheetSide);

  FQuad.SetBlendMode(qbmSrcAlpha);

  Textures.SheetSide.DrawMapRotAxis(
     FPosition.X - 500, FPosition.Y - 370, FPosition.X + 500, FPosition.Y + 370,
     0, 0, 1000/1024, 740/768, FPosition.X, FPosition.Y, FAngle, 1
  );

  FQuad.SetBlendMode(qbmSrcColor);
  Textures.SheetSidePath.DrawMapRotAxis(
     FPosition.X - 500, FPosition.Y - 370, FPosition.X + 500, FPosition.Y + 370,
     0, 0, 1000/1024, 740/768, FPosition.X, FPosition.Y, FAngle, 1);

end;

procedure TSide.DrawMouse;
begin
  FQuad.SetBlendMode(qbmSrcAlpha);
  Textures.Line1.DrawRot(FPosition.X - 12, FMouse.Y, 180, 1, $EEFFFFFF);
  Textures.Line1.DrawRot(FMouse.X, FPosition.Y - 13, 90, 1, $EEFFFFFF);
  //FQuad.Rectangle(FMouse.X - 2, FMouse.Y - 2, FMouse.X + 2, FMouse.Y + 2, $FFFFFFFF);
end;

procedure TSide.DrawShip;
var
  i: Integer;
  Point: TVec2f;
begin
  FQuad.SetBlendMode(qbmSrcAlpha);
  Textures.Ship.DrawRotFrame(50, 630, 0, 1, SHIP_TYPE[FShip.ShipType] - 1);

  for i := 0 to FShip.GunCount - 1 do
  begin
    Point := FShip.GetGunPosition(FShip.Gun[i]^, 0) - FShip.Position + TVec2f.Create(50, 630);


    if FGunNum = i then
      Textures.ShipGun.DrawRotFrame(Point.X, Point.Y, 0, 1, SHIP_TYPE[FShip.ShipType] - 1, $FFFF0000)
    else
      Textures.ShipGun.DrawRotFrame(Point.X, Point.Y, 0, 1, SHIP_TYPE[FShip.ShipType] - 1);

    if FGunNum > i then
      Fonts.Gost.TextOut(Point.X+32, Point.Y-11, 1, PAnsiChar(String1251('Готов')))
    else
      if FGunNum = i then
        Fonts.Gost.TextOut(Point.X+32, Point.Y-11, 1, PAnsiChar(String1251('на расчете')))
      else
        Fonts.Gost.TextOut(Point.X+32, Point.Y-11, 1, PAnsiChar(String1251('В ожидании')));

   //   Fonts.Console.TextOut(50, 50, 1, PAnsiChar(AnsiString(IntToStr(FGunNum + 1) + ' / ' + IntToStr(FShip.GunCount))));

  end;
end;

end.
