(* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
                         -****************+.
               .-=++*+::*###############*-
           :=+##*+=-::*##**############=
        .=*#*=:    .+#*=+############+.
       =##+.      +#+-=############*-:
     :*#+.      =+-.=#############- =#*.
    -##-      -=..+#############*:.  ---.
   -##:     .: .+################= :+#*-:.
  .##-        :==========*#####= :*#*- -#*
  =##                   -####*:-*#*-   .##:
  +#+                  -###*--*#*-      *#=
  *#+                 +###==*#*:        *#=
  +#*                *##+=*#*-          ##-
  :##.             .*##*##*:           -##.
   +#*            -#####*:             *#=
    *#+          =####+:             .*#+
     +#*.       +###+.              :##=
      -##+.    *##+:              :+#*:
        =*#+..*#+:             .-*#*-
          :-:#+::.        .:-=*##+:
           -+..+*###****####*+-.
          :.      ..:::::..
        ____                   _
       / ___| _ __   __ _ _ __| | __
       \___ \| '_ \ / _` | '__| |/ /
        ___) | |_) | (_| | |  |   <
       |____/| .__/ \__,_|_|  |_|\_\
             |_|   Game Toolkit™

Copyright © 2024-present tinyBigGAMES™ LLC
         All Rights Reserved.

Website: https://tinybiggames.com
Email  : support@tinybiggames.com

See LICENSE for license information
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *)

unit UCamera01;

interface

uses
  System.SysUtils,
  SGT.Deps,
  SGT.Deps.Ext,
  SGT.OGL,
  SGT.Core,
  SGT.Lua,
  SGT.LuaDebugger,
  UCommon;

procedure Demo();

implementation

// The 'Demo' procedure demonstrates the use of a camera to move, zoom, and rotate within a window, and rendering objects with various properties.

procedure Demo();
type
  // TObj represents a drawable object with position, size, and color.
  TObj = record
    X, Y, Size: Single;       // Position and size of the object.
    Color: TColor;            // Color of the object.
  end;
var
  LWindow: TWindow;          // Represents the window for rendering.
  LFont: TFont;              // Represents the font used for displaying text.
  LPos: TPoint;              // Position on the window for text rendering.
  FCam: TCamera;            // Represents the camera for viewing and transformation.
  FObj: array[0..1000] of TObj; // Array of objects to be rendered.

  // InitObjects initializes the objects with random positions, sizes, and colors.
  procedure InitObjects();
  var
    I: Integer;
  begin
    for I := Low(FObj) to High(FObj) do
    begin
      FObj[I].X := Math.RandomRange(-10000, 10000);
      FObj[I].Y := Math.RandomRange(-10000, 10000);
      FObj[I].Size := Math.RandomRange(50, 250);
      FObj[I].Color.Red := Math.RandomRange(0, 255) / $FF;
      FObj[I].Color.Green := Math.RandomRange(0, 255) / $FF;
      FObj[I].Color.Blue := Math.RandomRange(0, 255) / $FF;
      FObj[I].Color.Alpha := 1;
    end;
  end;

  // DrawObjects renders each object to the window.
  procedure DrawObjects();
  var
    I: Integer;
  begin
    for I := Low(FObj) to High(FObj) do
    begin
      LWindow.DrawFilledRect(FObj[I].X, FObj[I].Y, FObj[I].Size, FObj[I].Size, FObj[I].Color, 0);
    end;
  end;

begin
  // Initialize the window with the title 'SGT: Camera #01'.
  LWindow := TWindow.Init('SGT: Camera #01');

  // Load the default font for text rendering.
  LFont := TFont.LoadDefault(LWindow, 10);

  // Initialize the camera with default values.
  FCam := TCamera.Create();
  FCam.X := LWindow.DEFAULT_CENTER_WIDTH;
  FCam.Y := LWindow.DEFAULT_CENTER_HEIGHT;
  FCam.Rotation := 0;
  FCam.Scale := 0.20;

  // Initialize the objects with random properties.
  InitObjects();

  // Main loop to keep the window running until the user closes it.
  while not LWindow.ShouldClose() do
  begin
    // Start processing a new frame.
    LWindow.StartFrame();

      // Check if the ESC key was pressed. If so, set the window to close.
      if LWindow.GetKey(KEY_ESCAPE, isWasPressed) then
        LWindow.SetShouldClose(True);

      // Control camera movement and transformation based on key inputs.
      if LWindow.GetKey(KEY_DOWN, isPressed) then
        FCam.Move(0, 10)
      else if LWindow.GetKey(KEY_UP, isPressed) then
        FCam.Move(0, -10);

      if LWindow.GetKey(KEY_RIGHT, isPressed) then
        FCam.Move(10, 0)
      else if LWindow.GetKey(KEY_LEFT, isPressed) then
        FCam.Move(-10, 0);

      if LWindow.GetKey(KEY_A, isPressed) then
        FCam.Rotate(-2)
      else if LWindow.GetKey(KEY_D, isPressed) then
        FCam.Rotate(3);

      if LWindow.GetKey(KEY_S, isPressed) then
        FCam.Zoom(-0.01)
      else if LWindow.GetKey(KEY_W, isPressed) then
        FCam.Zoom(0.01);

      // Reset camera to default position, rotation, and scale if R key is released.
      if LWindow.GetKey(KEY_R, isWasReleased) then
      begin
        FCam.Reset();
        FCam.X := LWindow.DEFAULT_CENTER_WIDTH;
        FCam.Y := LWindow.DEFAULT_CENTER_HEIGHT;
        FCam.Rotation := 0;
        FCam.Scale := 0.20;
      end;

      // Reinitialize objects if SPACE key is released.
      if LWindow.GetKey(KEY_SPACE, isWasReleased) then
        InitObjects();

      // Start drawing on the window.
      LWindow.StartDrawing();

        // Clear the window with a black background color.
        LWindow.Clear(BLACK);

        // Apply the camera transformation and draw objects.
        FCam.Use(LWindow);
        DrawObjects();
        FCam.Use(nil);

        // Set the initial position for text rendering.
        LPos := Math.Point(3, 3);

        // Display various HUD information and controls.
        LFont.DrawText(LWindow, LPos.X, LPos.Y, 0, WHITE, haLeft, 'fps %d', [FrameLimitTimer.FrameRate()]);
        LFont.DrawText(LWindow, LPos.X, LPos.Y, 0, GREEN, haLeft, Utils.HudTextItem('Quit', 'ESC'), [FrameLimitTimer.FrameRate()]);
        LFont.DrawText(LWindow, LPos.X, LPos.Y, 0, GREEN, haLeft, Utils.HudTextItem('Space', 'Spawn'), []);
        LFont.DrawText(LWindow, LPos.X, LPos.Y, 0, GREEN, haLeft, Utils.HudTextItem('Left/Right', 'cam move left/right'), []);
        LFont.DrawText(LWindow, LPos.X, LPos.Y, 0, GREEN, haLeft, Utils.HudTextItem('Up/Down', 'cam move up/down'), []);
        LFont.DrawText(LWindow, LPos.X, LPos.Y, 0, GREEN, haLeft, Utils.HudTextItem('W/S', 'cam zoom up/down'), []);
        LFont.DrawText(LWindow, LPos.X, LPos.Y, 0, GREEN, haLeft, Utils.HudTextItem('A/D', 'cam rotate up/down'), []);
        LFont.DrawText(LWindow, LPos.X, LPos.Y, 0, GREEN, haLeft, Utils.HudTextItem('R', 'Reset'), []);
        LFont.DrawText(LWindow, LPos.X, LPos.Y, 0, YELLOW, haLeft, Utils.HudTextItem('Pos', '%03.2f/%03.2f', 20, ' '), [FCam.X, FCam.Y]);
        LFont.DrawText(LWindow, LPos.X, LPos.Y, 0, YELLOW, haLeft, Utils.HudTextItem('Zoom', '%3.2f'), [FCam.Scale]);
        LFont.DrawText(LWindow, LPos.X, LPos.Y, 0, YELLOW, haLeft, Utils.HudTextItem('Angle', '%3.2f'), [FCam.Rotation]);

      // Finish drawing on the window.
      LWindow.EndDrawing();

    // End processing the frame.
    LWindow.EndFrame();
  end;

  // Free resources in reverse order of initialization.
  FCam.Free();
  LFont.Free();
  LWindow.Free();
end;


end.
