unit USprite;

interface

uses
  Classes,
  JEN_Header,
  JEN_Math;

type
  TSprite = class
    constructor Create(FrameList: IInterfaceList; FrameSpeed: Single); overload;
    constructor Create(Tex: ITexture);  overload;
    private
    public
      Frame      : Single;
      FrameSpeed : Single;
      FTex       : ITexture;
      Pos        : TVec2f;
      Angle      : Single;
      PlayAction : Boolean;
      ScaleX     : Single;
      ScaleY     : Single;
      FlipX, FlipY: Boolean;
      AnchorPoint: TVec2f;
      Color      : TVec4f;
      FrameList  : IInterfaceList;
      function GetHeight: Single;
      function GetWidth: Single;
      function GetTexure: ITexture;
      function GetRect: TRecti;
      procedure SetScale(Value: Single);
      procedure Draw;
      procedure Update(dt: LongInt);
      property Height: Single read GetHeight;
      property Width: Single read GetWidth;
      property Texture: ITexture read GetTexure;
      property Scale: Single write SetScale;

  end;

implementation

uses
  Main;


constructor TSprite.Create(FrameList: IInterfaceList; FrameSpeed: Single);
begin
  Assert(FrameList.Count > 0, 'Frame List must consist more than one frame');
  self.FrameList := FrameList;
  PlayAction := True;
  Scale := 1;
  self.FrameSpeed := FrameSpeed;
  Color := clWhite;
end;

constructor TSprite.Create(Tex: ITexture);
begin
  PlayAction := False;
  FTex := Tex;
  Scale := 1;
end;

procedure TSprite.SetScale(Value: Single);
begin
  ScaleX := Value;
  ScaleY := Value;
end;

function TSprite.GetTexure: ITexture;
begin
  if Assigned(FrameList) then
    Result := ITexture(FrameList.Items[Trunc(Frame)])
  else
    Result := FTex;
end;

function TSprite.GetRect: TRecti;
var
  ap     : TVec2f;
  Tex    : ITexture;
begin
  Tex := Texture;
  ap := AnchorPoint * Vec2f(Tex.Width, Tex.Height) * Vec2f(ScaleX, ScaleY);
  Result := Recti(Round(Pos.x - ap.x), Round(Pos.y - ap.y), Round(Tex.Width * ScaleX), Round(Tex.Height * ScaleY));
end;

procedure TSprite.Draw;
var
  iFrame : Integer;
  flags  : Cardinal;
  ap     : TVec2f;
  Tex    : ITexture;
begin
  iFrame := Trunc(Frame);
  flags := 0;
  if FlipX then
    flags := FX_FLIPX;

  if FlipY then
    flags := flags and FX_FLIPY;

  Tex := Texture;
  ap := AnchorPoint * Vec2f(Tex.Width, Tex.Height) * Vec2f(ScaleX, ScaleY);
  Render2d.RotCenter := AnchorPoint;
  Render2d.DrawSprite(Tex.Frame, Pos.x - ap.x, Pos.y - ap.y, Tex.Width * ScaleX, Tex.Height * ScaleY, Color, Angle, flags);
  Render2d.RotCenter := Vec2f(0.5, 0.5);
end;

function TSprite.GetHeight;
begin
  Result := Texture.Height * ScaleY;
end;

function TSprite.GetWidth;
begin
  Result := Texture.Width * ScaleX;
end;

procedure TSprite.Update(dt: LongInt);
begin
  if not PlayAction then
    Exit;

  Frame := Frame + FrameSpeed * (dt/1000);
  if Frame >= FrameList.Count then
    Frame:= Frame - FrameList.Count;
end;

end.
