unit _World;

interface

Uses
  QuadEngine,
  _Scene,
  _Geometry,
  _Resources,
  _Forms,
  _SysUtils,
  pngImage,
  Classes;

const
  BULLET_SPEED = 850;
  RELOAD_TIME = 0.1;
  CL_BLUE  = $ff0000ff;
  CL_GREEN = $ff00ff00;
  CL_WHITE = $ffeeeeee;

type

TObjList = class;   
THero = class;

TObj = class
  private
    class var FParent: TObjList;
    class var FQuad: IQuadRender;
    class var FCamera: TVector2;     
    class var FHero: THero;
  private        
    FFluctuation: Single;
    FAngle: Single;
    FScale: Single;
    FPosition: TVector2;
    FColor: Cardinal;
  public             
    Visible: Boolean;
    constructor Create(Position: TVector2; Angle: Single; Scale: Single = 0.6; Color: Cardinal = $ffffffff);
    procedure Draw; virtual;
    procedure Act(dt: Single); virtual;
    class procedure SetRender(Quad: IQuadRender);
    property Scale: Single read FScale;
    property Position: TVector2 read FPosition;
end;

TBullet = class(TObj)
    FVelocity: TVector2;
  public               
    constructor Create(Position: TVector2; Angle: Single);
    procedure Draw; override;
    procedure Act(dt: Single); override;
end;

TGreenBullet = class(TObj)
    FVelocity: TVector2;
  public               
    constructor Create(Position: TVector2; Angle: Single);
    procedure Draw; override;
    procedure Act(dt: Single); override;
end;

TBlueBullet = class(TObj)
    FVelocity: TVector2;
  public               
    constructor Create(Position: TVector2; Angle: Single);
    procedure Draw; override;
    procedure Act(dt: Single); override;
end;

TPortal = class(TObj)
    FRing: Single;
    FParts: Single;
  public               
    constructor Create(Position: TVector2);
    procedure Draw; override;
    procedure Act(dt: Single); override;
end;

TCrystal = class(TObj)
  public
    constructor Create(Position: TVector2);
    procedure Draw; override;
    procedure Act(dt: Single); override;
end;


THero = class(TObj)
    FVelocity: TVector2;
    FReload: Single;
  public
    Crystals: Byte;
    CrystalsVis: Byte;
    procedure Die;
    procedure Draw; override;
    procedure Act(dt: Single); override;
    procedure Fire(FirePoint: TVector2; Tip: Byte);
end; 

TBug = class(TObj)
    FVelocity: TVector2;
    FStep: Single;
    FLife: Byte;
    FNeedAngle: Single;
  public
    constructor Create(Position: TVector2; Angle: Single);
    procedure Hit(Tip: Byte); virtual;
    procedure Draw; override;
    procedure Act(dt: Single); override;
end;

TWhiteBug = class(TBug)   
  public
    constructor Create(Position: TVector2; Angle: Single);
    procedure Hit(Tip: Byte); override;
end;

TGreenBug = class(TBug)   
  public
    constructor Create(Position: TVector2; Angle: Single);
    procedure Hit(Tip: Byte); override;
end;

TBigBug = class(TBug)
  public
    constructor Create(Position: TVector2; Angle: Single);
    procedure Hit(Tip: Byte); override;
end;

TObjList = class(TList)
    function GetObj(Index: Integer): TObj;
  public                                 
    destructor Destroy; override;        
    procedure Delete(Obj: TObj);
    function Add(NewObject: TObj): TObj;
    property Items[Index: Integer]: TObj read GetObj; default;
end;

TWorld = class(TBasicScene)
  private
    FQuad: IQuadRender;
    Music: Byte;
    FObject: TObjList;
    FHero: THero;
    FCamera: TVector2;
    FMap: TPoint;
    procedure PutTree(Position: TVector2; Angle: Single; Level: Byte);  
    procedure FindVisibleObjects;
  public
    constructor Create(QuadEngine: IQuadRender);
    destructor Destroy; override;
    procedure Render; override;
    procedure Update(dt: single); override;
    procedure Control; override;
  end;

var
  World:TWorld;

implementation

{$REGION 'TObjList'}
function TObjList.Add(NewObject: TObj): TObj;
begin
  inherited Add(NewObject);
  Result:= NewObject;
end;

destructor TObjList.Destroy;
var
  i: integer;
begin
  for i := 0 to Count - 1 do
    TObj(Items[i]).Free;
  inherited;
end;

function TObjList.GetObj(Index: Integer): TObj;
begin
  Result := TObj(inherited Get(Index));
end;  

procedure TObjList.Delete(Obj: TObj);
var
  i: Word;
begin
  Self.Remove(Obj);
  Obj.Free;
end;
{$ENDREGION}

{$REGION 'TObj'}
constructor TObj.Create(Position: TVector2; Angle: Single; Scale: Single = 0.6; Color: Cardinal = $ffffffff);
begin
  FPosition:= Position;
  FScale:= Scale;
  FAngle:= Angle;
  FColor:= Color;
  FFluctuation:= Random(360); 
  Visible:= true;
end;

procedure TObj.Draw;
var
  Position: TVector2;
begin
  Position:= FPosition + GetVector(FFluctuation, FScale * 10) - FCamera;
  Resources.TileTexture.DrawRot(Position.X, Position.Y, FAngle, FScale * 1.2, $53000000);
  Resources.TileTexture.DrawRot(Position.X, Position.Y, FAngle, FScale, FColor);
end;

procedure TObj.Act;
begin
  FFluctuation:= GetRound(FFluctuation + 0.4);
end;

class procedure TObj.SetRender(Quad: IQuadRender);
begin
  FQuad:= Quad;
end;
{$ENDREGION}
//Bullet
{$REGION 'TBullet'}
constructor TBullet.Create(Position: TVector2; Angle: Single);
begin                 
  Visible:= true;
  FPosition:= Position;
  FAngle:= Angle;
  FVelocity.GetVector(Angle, BULLET_SPEED);
  Act(0.02);
end;

procedure TBullet.Draw;   
var
  Position: TVector2;
begin                    
  Position:= FPosition - FCamera;
  Resources.BulletTexture.DrawRot(Position.X, Position.Y, FAngle + 180, 0.5, $f0ffffff, 0);
end;

procedure TBullet.Act(dt: Single);
begin
  FPosition:= FPosition + FVelocity * dt;
  if not FPosition.InRectangle(FCamera - Vector2( 50, 50), FCamera + Vector2(Window.Width + 50, Window.Height + 50)) then
    FParent.Delete(Self);
end;
{$ENDREGION}

{$REGION 'TGreenBullet'}
constructor TGreenBullet.Create(Position: TVector2; Angle: Single);
begin     
  Visible:= true;
  FPosition:= Position;
  FAngle:= Angle;
  FVelocity.GetVector(Angle, BULLET_SPEED);
  Act(0.02);
end;

procedure TGreenBullet.Draw;
var
  Position: TVector2;
begin                    
  Position:= FPosition - FCamera;
  Resources.BulletTexture.DrawRot(Position.X, Position.Y, FAngle + 180, 0.5, $f000ff00, 0);
end;

procedure TGreenBullet.Act(dt: Single);
begin
  FPosition:= FPosition + FVelocity * dt;
  if not FPosition.InRectangle(FCamera - Vector2( 50, 50), FCamera + Vector2(Window.Width + 50, Window.Height + 50)) then
    FParent.Delete(Self);
end;
{$ENDREGION}   

{$REGION 'TBlueBullet'}
constructor TBlueBullet.Create(Position: TVector2; Angle: Single);
begin   
  Visible:= true;
  FPosition:= Position;
  FAngle:= Angle;
  FVelocity.GetVector(Angle, BULLET_SPEED);
  Act(0.02);
end;

procedure TBlueBullet.Draw;
var
  Position: TVector2;
begin                    
  Position:= FPosition - FCamera;
  Resources.BulletTexture.DrawRot(Position.X, Position.Y, FAngle + 180, 0.5, $f00000ff, 0);
end;

procedure TBlueBullet.Act(dt: Single);
begin
  FPosition:= FPosition + FVelocity * dt;
  if not FPosition.InRectangle(FCamera - Vector2( 50, 50), FCamera + Vector2(Window.Width + 50, Window.Height + 50)) then
    FParent.Delete(Self);
end;
{$ENDREGION}
//Portal
{$REGION 'TPortal'}
constructor TPortal.Create(Position: TVector2);
begin  
  Visible:= true;
  FPosition:= Position;
  FAngle:= Random(360);    
  FRing:= Random(360);
  FParts:= Random(360);
end;

procedure TPortal.Draw;   
var
  Position: TVector2;
begin                    
  Position:= FPosition - FCamera;
  Resources.PortalTexture.DrawRot(Position.X, Position.Y, FAngle, 0.5, $ffffffff, 0);
  Resources.PortalTexture.DrawRot(Position.X, Position.Y, FRing, 0.5, $ffffffff, 2);
  Resources.PortalTexture.DrawRot(Position.X, Position.Y, FParts, 0.5, $ffffffff, 1);
end;

procedure TPortal.Act(dt: Single);
begin
  FRing:= GetRound(FRing - 0.5);
  FParts:= GetRound(FParts + 0.7);
end;
{$ENDREGION}
//Crystal
{$REGION 'TCrystal'}
constructor TCrystal.Create(Position: TVector2);
begin  
  Visible:= true;
  FPosition:= Position;
  FAngle:= Random(360);
end;

procedure TCrystal.Draw;
var
  Position: TVector2;
begin                    
  Position:= FPosition - FCamera;
  Resources.CrystalTexture.DrawRot(Position.X, Position.Y, FAngle, 0.14, $fff8f00d);
end;

procedure TCrystal.Act(dt: Single);
begin
  FAngle:= GetRound(FAngle - 0.5);
  if FHero.FPosition.Distance(FPosition) < 15 * FScale + 17 then
    begin
      FHero.CrystalsVis:= 200;     
      Inc(FHero.Crystals);
      FParent.Delete(Self);
    end;
end;
{$ENDREGION}
//Hero
{$REGION 'THero'}
procedure THero.Die;
begin
  Self.FPosition:= Vector2(Window.Width / 2, Window.Height / 2);
end;

procedure THero.Draw;
var
  EyeVector: TVector2;
  Position: TVector2;
begin
  Position:= FPosition - FCamera;
  EyeVector:= GetVector(FAngle, 10);
  Resources.TileTexture.DrawRot(Position.X, Position.Y, 0, 0.2, $53000000);
  Resources.TileTexture.DrawRot(Position.X, Position.Y, 0, 0.15, $ffcccccc);
  Position:= Position + EyeVector;
  Resources.TileTexture.DrawRot(Position.X, Position.Y, FAngle, 0.03, $ffffffff);
end;

procedure THero.Act;
begin
  if FReload > 0 then
    FReload:= FReload - dt;

  FPosition:= FPosition + FVelocity * dt;
  FAngle:= RotateToAngle(FAngle, FPosition.GetAngle(Vector2(Window.Mouse.x, Window.Mouse.y) + FCamera), 3);
end;

procedure THero.Fire(FirePoint: TVector2; Tip: Byte);
begin
  if FReload > 0 then
    exit;
  FReload:= RELOAD_TIME;
  case Tip of
    0:FParent.Add(TBullet.Create(Self.FPosition, GetAngle(FPosition - FirePoint)));
    1:FParent.Add(TGreenBullet.Create(Self.FPosition, GetAngle(FPosition - FirePoint)));
    2:FParent.Add(TBlueBullet.Create(Self.FPosition, GetAngle(FPosition - FirePoint)));
  end;
end;
{$ENDREGION}
//TBug
{$REGION 'TBug'}
constructor TBug.Create(Position: TVector2; Angle: Single);
begin
  Visible:= true;
  FPosition:= Position;
  FAngle:= Angle;    
  FNeedAngle:= Angle;
  FScale:= 1;
  FColor:= CL_BLUE;
end;

procedure TBug.Draw;   
var
  i: Byte;
  Position: TVector2;
  LegsPos: TVector2;
begin                
  Position:= FPosition - FCamera;
  LegsPos:= Position + GetVector(FAngle + 50 + Abs(FStep - 10) - 5 + 0 * 40, 16 * FScale);
  Resources.TileTexture.DrawRot(LegsPos.X, LegsPos.Y, FAngle + 180, 0.045 * FScale, FColor - $2f000000);
  LegsPos:= Position + GetVector(FAngle - 50 - Abs(FStep - 10) + 5 - 0 * 40, 16 * FScale);
  Resources.TileTexture.DrawRot(LegsPos.X, LegsPos.Y, FAngle + 180, 0.045 * FScale, FColor - $2f000000);

  LegsPos:= Position + GetVector(FAngle + 50 - Abs(FStep - 10) + 5 + 1 * 40, 16 * FScale);
  Resources.TileTexture.DrawRot(LegsPos.X, LegsPos.Y, FAngle + 180, 0.045 * FScale, FColor - $2f000000);
  LegsPos:= Position + GetVector(FAngle - 50 + Abs(FStep - 10) - 5 - 1 * 40, 16 * FScale);
  Resources.TileTexture.DrawRot(LegsPos.X, LegsPos.Y, FAngle + 180, 0.045 * FScale, FColor - $2f000000);

  LegsPos:= Position + GetVector(FAngle + 50 + Abs(FStep - 10) - 5 + 2 * 40, 16 * FScale);
  Resources.TileTexture.DrawRot(LegsPos.X, LegsPos.Y, FAngle + 180, 0.045 * FScale, FColor - $2f000000);
  LegsPos:= Position + GetVector(FAngle - 50 - Abs(FStep - 10) + 5 - 2 *  40, 16 * FScale);
  Resources.TileTexture.DrawRot(LegsPos.X, LegsPos.Y, FAngle + 180, 0.045 * FScale, FColor - $2f000000);

  Resources.TileTexture.DrawRot(Position.X, Position.Y, FAngle + 180, 0.13 * FScale, FColor);

  LegsPos:= Position + GetVector(FAngle, 8 * FScale);
  Resources.TileTexture.DrawRot(LegsPos.X, LegsPos.Y, FAngle + 180, 0.025 * FScale, $ffffffff);
end;

procedure TBug.Act(dt: Single);
begin
  if FVelocity.Length > 0 then
    FStep:= FStep + 30 * dt;
  if FStep > 20 then
    FStep:= 0;
  FAngle:= RotateToAngle(FAngle, FNeedAngle, 100 * dt);
  if Random(30) = 0 then
      Self.FVelocity:= Vector2(0,0);
  if FHero.FPosition.Distance(FPosition) < 400 then
    begin
      FNeedAngle:= FPosition.GetAngle(FHero.FPosition);
      Self.FVelocity:= GetVector(FAngle, 150);
    end
  else
    begin
      if Random(20) = 0 then
        Self.FVelocity:= GetVector(FAngle, 150);
      if Random(100) = 0 then
        Self.FNeedAngle:= Random(360);
    end;        
  if FHero.FPosition.Distance(FPosition) < 15 * FScale + 17 then
    FHero.Die;

  FPosition:= FPosition + FVelocity * dt;

end;

procedure TBug.Hit(Tip: Byte);
begin
  case Tip of
    0:;
    1:FParent.Delete(Self);
    2:;
  end;
end;
{$ENDREGION}
//Green Bug
{$REGION 'TGreenBug'}
constructor TGreenBug.Create(Position: TVector2; Angle: Single);
begin
  inherited;
  FColor:= CL_GREEN;
end;

procedure TGreenBug.Hit(Tip: Byte);
begin
  case Tip of
    0:;
    1:;
    2:FLife:= FLife + 1;
  end;
  if FLife > 8 then
    FParent.Delete(Self)
end;
{$ENDREGION}

{$REGION 'TWhiteBug'}
constructor TWhiteBug.Create(Position: TVector2; Angle: Single);
begin
  inherited;
  FScale:= 0.8;
  FColor:= CL_WHITE;
end;

procedure TWhiteBug.Hit(Tip: Byte);
begin
  case Tip of
    0:FLife:= FLife + 1;
    1:;
    2:;
  end;
  if FLife > 12 then
    FParent.Delete(Self)
end;
{$ENDREGION}

{$REGION 'TBigBug'}
constructor TBigBug.Create(Position: TVector2; Angle: Single);
begin
  inherited;
  FColor:= CL_BLUE;
  FScale:= 2;
end;

procedure TBigBug.Hit(Tip: Byte);
begin
  if FColor = CL_BLUE then      
    case Tip of
      0:;
      1:FColor:= CL_WHITE;
      2:;
    end
  else
  if FColor = CL_WHITE then
    case Tip of
      0:FLife:= FLife + 1;
      1:FColor:= CL_BLUE;
      2:;
    end;  
  if FLife > 2 then
    FParent.Delete(Self)
end;
{$ENDREGION}
//World
{$REGION 'World'}
procedure TWorld.PutTree(Position: TVector2; Angle: Single; Level: Byte);
begin

end;

constructor TWorld.Create;
Var
  i, j: Word;
  Pos: TVector2;
begin
  FMap.Create(0, 0);
  FQuad:= QuadEngine;
  FQuad.SetBlendMode(qbmSrcAlpha);
  FObject:= TObjList.Create;
  TObj.FParent:= FObject;    
  TObj.SetRender(QuadEngine);  
  FHero:= THero.Create(Vector2(Window.Width / 2, Window.Height / 2),0,1);
  for i:=0 to 2580 do
//    PutTree(Vector2(Random(950)+50, Random(600)+50), Random(2), 2);
    FObject.Add(TObj.Create(Vector2((Random(950)+50), Random(600)+50) + Vector2((Random(12) - 6) * Window.Width, (Random(12) - 6) * Window.Height), 0, 0.1 + Random(500) * 0.001, $ff000000 + (Random($2f) + $bb)*$10000 + Random($2f) + (Random($3f) + $50) * $100 * Random(2)));
  for j:=0 to 40 do
    begin
      Pos:= Vector2((Random(950)+50), Random(600)+50) + Vector2((Random(12) - 6) * Window.Width, (Random(12) - 6) * Window.Height);
      FObject.Add(TCrystal.Create(Pos));

      i:= 0;
      while i < FObject.Count do
      begin
        if (FObject[i] is TObj) and not (FObject[i] is TCrystal) then
          if FObject[i].FPosition.InRectangle(Pos + Vector2( - 100, - 100), Pos + Vector2(100, 100)) then
            FObject.Delete(FObject[i]);
        Inc(i);               
      end;
    end;
  for i:=0 to 600 do
    FObject.Add(TBug.Create(Vector2((Random(950)+50), Random(600)+50) + Vector2((Random(12) - 6) * Window.Width, (Random(12) - 6) * Window.Height), Random(260)));
  for i:=0 to 300 do
    FObject.Add(TGreenBug.Create(Vector2((Random(950)+50), Random(600)+50) + Vector2((Random(12) - 6) * Window.Width, (Random(12) - 6) * Window.Height), Random(260)));
  for i:=0 to 100 do
    FObject.Add(TWhiteBug.Create(Vector2((Random(950)+50), Random(600)+50) + Vector2((Random(12) - 6) * Window.Width, (Random(12) - 6) * Window.Height), Random(260)));
  for i:=0 to 50 do
    FObject.Add(TBigBug.Create(Vector2((Random(950)+50), Random(600)+50) + Vector2((Random(12) - 6) * Window.Width, (Random(12) - 6) * Window.Height), Random(260)));

  i:= 0;
  while i < FObject.Count do
  begin
    if FObject[i] is TObj then
      if FObject[i].FPosition.InRectangle(Vector2(Window.Width / 2 - 200, Window.Height / 2 - 200), Vector2(Window.Width / 2 + 200, Window.Height / 2 + 200)) then
        FObject.Delete(FObject[i]);
    if (FObject[i] is TBug) or (FObject[i] is TGreenBug) or (FObject[i] is TBigBug) then
      if FObject[i].FPosition.InRectangle(
        Vector2(Window.Width / 2 - Window.Width, Window.Height / 2 - Window.Height),
        Vector2(Window.Width / 2 + Window.Width, Window.Height / 2 + Window.Height)) then
        FObject.Delete(FObject[i]);
    Inc(i);
  end;
  FObject.Add(FHero);
  FObject.Add(TPortal.Create(Vector2(Window.Width / 2, Window.Height / 2)));
  FindVisibleObjects;
end;

destructor TWorld.Destroy;
begin
  FObject.Destroy;
  Inherited;
end;

procedure TWorld.Control;
var
  Speed: Single;
begin
  FHero.FVelocity.Vector2(0, 0);
  Speed:= 180;
  if (Window.key[KEY_D] or Window.key[KEY_RIGHT]) then begin FHero.FVelocity:= FHero.FVelocity + Vector2( Speed, 0); end;
  if (Window.key[KEY_A] or Window.key[KEY_LEFT ]) then begin FHero.FVelocity:= FHero.FVelocity + Vector2(-Speed, 0); end;
  if (Window.key[KEY_S] or Window.key[KEY_DOWN ]) then begin FHero.FVelocity:= FHero.FVelocity + Vector2(0,  Speed); end;
  if (Window.key[KEY_W] or Window.key[KEY_UP   ]) then begin FHero.FVelocity:= FHero.FVelocity + Vector2(0, -Speed); end;
// hero fire
  if Window.Mouse.mbl then
    if Window.Mouse.mbr then
      FHero.Fire(Vector2(Window.Mouse.x, Window.Mouse.y) + FCamera, 0)
    else
      FHero.Fire(Vector2(Window.Mouse.x, Window.Mouse.y) + FCamera, 2)
  else         
    if Window.Mouse.mbr then
      FHero.Fire(Vector2(Window.Mouse.x, Window.Mouse.y) + FCamera, 1);
// Functional
  if Window.key[KEY_TILDA] or Window.key[KEY_ESC] then  //esc
  begin
    Window.key[KEY_TILDA]:= false;
    Window.key[KEY_ESC]:= false;
    Window.Close;
    //Manager.SetScene(Menu);
  end;
end;


procedure TWorld.Render;
var
  i:Word;
begin
  //Clear
  FQuad.Clear($ff000000);
  for i:=  FObject.Count - 1 downto 0 do
    if FObject[i] <> nil then             
      if FObject[i].Visible then
        FObject[i].Draw;
  //Cursor
//  Resources.TileTexture.DrawRot(Window.Mouse.X, Window.Mouse.Y, 0, 0.05);
  Resources.Font.TextOutAligned(
    Window.Width - 100, 50, 1,
    PAnsiChar(IntToStr(FHero.Crystals)),
    $ffffff + Round(FHero.CrystalsVis / 200 * $ff) * $1000000,
    qfaRight);
  if FHero.Crystals > 10 then
    begin
      Resources.Font.TextOutAligned(
        Window.Width / 2, Window.Height / 2, 1.2,
        PAnsiChar('You win!'),
        $ffffffff,
        qfaCenter);
      FHero.Die;
    end;
end;
                      
procedure TWorld.FindVisibleObjects;
var
  i:Word;
  TLCorner, DRCorner: TVector2;
begin
  TLCorner:= Vector2(FMap.X * (Window.Width - 100), FMap.Y * (Window.Height - 100)) - Vector2(Window.Width, Window.Height);
  DRCorner:= Vector2(FMap.X * (Window.Width - 100), FMap.Y * (Window.Height - 100)) + Vector2(Window.Width * 2, Window.Height * 2);
  for i:=  FObject.Count - 1 downto 0 do
    if FObject[i] <> nil then
      if FObject[i].FPosition.InRectangle(TLCorner, DRCorner) then
        FObject[i].Visible:= true
      else
        FObject[i].Visible:= false;
end;

procedure TWorld.Update(dt: Single);
var
  i, j, t: Word;
begin
  Resources.PlayMusic(Music);
  

  FCamera:= FCamera * 0.95 + Vector2(FMap.X * (Window.Width - 100), FMap.Y * (Window.Height - 100)) * 0.05;
  TObj.FCamera:= FCamera;
  TObj.FHero:= FHero;
  if (FHero.CrystalsVis > 0) then
    Dec(FHero.CrystalsVis);

  if FHero.FPosition.X - TObj.FCamera.X < 30 then
    begin
      FMap.X:= FMap.X - 1;
      FindVisibleObjects;
    end;
  if FHero.FPosition.X - TObj.FCamera.X > Window.Width - 30  then
    begin
      FMap.X:= FMap.X + 1;
      FindVisibleObjects;
    end;

  if FHero.FPosition.Y - TObj.FCamera.Y < 30 then
    begin
      FMap.Y:= FMap.Y - 1;  
      FindVisibleObjects;
    end;
  if FHero.FPosition.Y - TObj.FCamera.Y > Window.Height - 30  then
    begin
      FMap.Y:= FMap.Y + 1;  
      FindVisibleObjects;
    end;

  i:= 0;
  while i < FObject.Count do
    begin
      if FObject[i] <> nil then
        if FObject[i].Visible then
          FObject[i].Act(dt);
      inc(i);
    end;   

  i:= 0;
  while i < FObject.Count do
    begin
      if (FObject[i] is TBullet) then
        t:= 0;
      if (FObject[i] is TBlueBullet) then
        t:= 1;                 
      if (FObject[i] is TGreenBullet) then
        t:= 2;
      if (FObject[i] is TBullet) or
         (FObject[i] is TBlueBullet) or
         (FObject[i] is TGreenBullet) then
        if FObject[i].Visible then
          begin
            j:=0;        
            while j < FObject.Count do
              begin
                if FObject[j] is TBug then
                  if FObject[j].Visible then
                    if FObject[j].Position.Distance(FObject[i].FPosition) < 15 * FObject[j].FScale then
                      begin
                        TBug(FObject[j]).Hit(t);
                        Break;
                      end;
                Inc(j);
              end;
          end;
      inc(i);
    end;     
  if FHero.FPosition = Vector2(Window.Width / 2, Window.Height / 2) then
    begin
      FMap.Create(0, 0);  
      FCamera:= FCamera * 0.95 + Vector2(FMap.X * (Window.Width - 100), FMap.Y * (Window.Height - 100)) * 0.05;  
      TObj.FCamera:= FCamera;
      FindVisibleObjects;
    end;
end;
{$ENDREGION}
end.
