unit u_lvl;

interface

uses
  zglHeader, u_Menu;

Type
  TBezierPoint = record
    X, Y, Xl, Yl, Xr, Yr: SmallInt;
  end;

  TMapPoint = record
    X, Y: Single;
  end;

Const
  MapPointBezier: array[0..10] of TBezierPoint = (
    (X: 144; Y: 92;  Xl: 90;  Yl: 37;  Xr: 196; Yr: 146),
    (X: 483; Y: 139; Xl: 408; Yl: 156; Xr: 558; Yr: 123),
    (X: 826; Y: 190; Xl: 816; Yl: 25;  Xr: 835; Yr: 354),
    (X: 881; Y: 439; Xl: 847; Yl: 372; Xr: 910; Yr: 508),
    (X: 772; Y: 653; Xl: 954; Yl: 703; Xr: 585; Yr: 603),
    (X: 432; Y: 590; Xl: 551; Yl: 548; Xr: 313; Yr: 628),
    (X: 402; Y: 435; Xl: 213; Yl: 465; Xr: 589; Yr: 405),
    (X: 710; Y: 410; Xl: 750; Yl: 559; Xr: 671; Yr: 264),
    (X: 456; Y: 285; Xl: 642; Yl: 227; Xr: 274; Yr: 340),
    (X: 132; Y: 387; Xl: 133; Yl: 245; Xr: 129; Yr: 531),
    (X: 196; Y: 668; Xl: 137; Yl: 629; Xr: 253; Yr: 708)
  );

Type
  Tlvl = class
    Bg, But, Tex_Point: zglPTexture;
    lvl: Byte;
    Point: Word;
    Volna: Word;
    Rect: zglTRect;
    Move: Byte;
    MapPoint: array of TMapPoint;
    Constructor Create;
    Destructor Destroy;
    Procedure Process;
    Procedure Draw;
    Procedure RefreshRect;
    Procedure lvlStart;
    Procedure Next;

    Procedure PointsInit;
    procedure BezierValue(P1, P2: TBezierPoint; t: Single; var X, Y: single);
    Function WidthBezier(p1, p2: TBezierPoint): single;
  end;

Var
  lvl: Tlvl;

implementation

uses u_Game, u_Main, u_Sound, u_Player, u_Map, u_Puli, u_Mutant, u_lvlAtack;

{ Tlvl }

constructor Tlvl.Create;
begin
  PointsInit;
  lvl := 0;
  Point := 0;
  Move := 1;
  Tex_Point := tex_LoadFromFile('Data\MapPoint.png');
  Bg := tex_LoadFromFile('Data\Map.jpg');
  But := tex_LoadFromFile('Data\Player1.png');
  tex_SetFrameSize(But, 64, 64);
  RefreshRect;
end;

destructor Tlvl.Destroy;
begin
  Tex_Del(Bg);
  Tex_Del(But);
  Tex_Del(Tex_Point);
end;

procedure Tlvl.Draw;
Var
  i: word;
begin
  ssprite2d_Draw(Bg, 0, 0, 1024, 768, 0);

 if Point > 0 then
    for i := 0 to Point-1 do begin
      ssprite2d_Draw(Tex_Point, MapPoint[i].X-16, MapPoint[i].Y-16, 32, 32, 0, 180);
                {
      pr2d_Circle(MapPoint[i].X, MapPoint[i].Y, 4, $FF0000, 150, 32, PR2D_FILL);
      pr2d_Circle(MapPoint[i].X, MapPoint[i].Y, 4, $000000, 255);  }
    end;

  asprite2d_Draw(But, Rect.X, Rect.Y, Rect.W, Rect.H, 0, Move);

  ssprite2d_Draw(Menu.Arrow, Mouse_X, Mouse_Y, 32, 32, 0);
end;

procedure Tlvl.lvlStart;
begin
  Game.lvl := lvl;
  Game.Refresh;
  gm := gmGame;
end;

procedure Tlvl.Next;
begin
  Inc(lvl);
  Inc(Point, 28);
  RefreshRect;
end;

procedure Tlvl.Process;
begin
  if col2d_PointInRect(Mouse_X, Mouse_Y, Rect) then begin
    if Move = 1 then
      Sound.Play(Sound.Move);
    Move := 2;
    if (lvl <= CountVolnaAtack) and mouse_Click(M_BLEFT) then begin
      Sound.Play(Sound.Click);
      lvlStart;
    end;
  end else
    Move := 1;
end;

procedure Tlvl.RefreshRect;
begin
  Rect.X := MapPoint[Point].X-32;
  Rect.Y := MapPoint[Point].Y-60;
  Rect.H := 64;
  Rect.W := 64;
end;

Procedure Tlvl.PointsInit;
Const
  LinPoint = 20;
Var
  l, i, c: Word;
  W, cW: Single;
  X, Y, X1, Y1: single;
begin
  l := 1;
  W := 0;
  cW := WidthBezier(MapPointBezier[0], MapPointBezier[1]);
  while true do begin
    if W > cW then begin
      W := W - cW;
      Inc(l);
    end;
    if l = 11 then
      Exit;
    c := length(MapPoint);
    SetLength(MapPoint, c+1);
    cW := WidthBezier(MapPointBezier[l-1], MapPointBezier[l]);

    BezierValue(MapPointBezier[l-1], MapPointBezier[l], W/cW,  X, Y);
    MapPoint[c].X := X;
    MapPoint[c].Y := Y;
    W := W + LinPoint;
  end;
end;

Function Tlvl.WidthBezier(p1, p2: TBezierPoint): single;
var
  i, Num: integer;
  X, Y, X1, Y1: single;
begin
  result := 0;
  Num := 50;
  X1 := P1.X;
  Y1 := P1.Y;
  for i := 1 to Num - 1 do begin
    BezierValue(p1, p2, i / Num, x, y);
    result := result + m_Distance(X1, Y1, X, Y);
    X1 := X;
    Y1 := Y;
  end;
result := result + m_Distance(P2.X, P2.Y, X, Y);
end;

procedure Tlvl.BezierValue(P1, P2: TBezierPoint; t: Single; var X, Y: single);
var
  t_sq, t_cb, r1, r2, r3, r4: double;
begin
  t_sq := t * t;
  t_cb := t * t_sq;
  r1 := (1 - 3 * t + 3 * t_sq - t_cb) * P1.X;
  r2 := (3 * t - 6 * t_sq + 3 * t_cb) * P1.Xr;
  r3 := (3 * t_sq - 3 * t_cb) * P2.Xl;
  r4 := (t_cb) * P2.X;
  X := r1 + r2 + r3 + r4;
  r1 := (1 - 3 * t + 3 * t_sq - t_cb) * P1.Y;
  r2 := (3 * t - 6 * t_sq + 3 * t_cb) * P1.Yr;
  r3 := (3 * t_sq - 3 * t_cb) * P2.Yl;
  r4 := (t_cb) * P2.Y;
  Y := r1 + r2 + r3 + r4;
end;

end.
