program Tactic;

uses
  Windows,
  Messages,
  QuadEngine in 'QuadEngine.pas',
  Direct3d9 in 'DirectX\Direct3d9.pas',
  DXTypes in 'DirectX\DXTypes.pas',
  _Forms in '_Forms.pas',
  _World in '_World.pas',
  _SysUtils in '_SysUtils.pas',
  _Geometry in '_Geometry.pas',
  _Units in '_Units.pas',
  _Render in '_Render.pas';

const
  LogoTime = 150;
  //game states
  gs_exit = 0;
  gs_logo = 1;
  gs_menu = 2;
  gs_game = 3;

type
  TManager = record
   Game_State:byte;
   Anim:integer;
   Logo:IQuadTexture;
   menu_screen:byte;
  end;

// {$R *.res}
Var
  World:TWorld;
  Manager:TManager;

{$REGION 'Logo'}
procedure Show_Logo;
begin
  Quad.Clear($FF000000);
  Manager.Logo.DrawRot(Win.ScreenWidth div 2,Win.ScreenHeight div 2,0,1,$ffffffff);
  Manager.Anim:=Manager.Anim+1;
  if (Manager.Anim>LogoTime*0.75) then
  Quad.Rectangle(0,0,Win.ScreenWidth,Win.ScreenHeight,trunc((Manager.Anim)/(LogoTime*0.25)*255)*$1000000);
  if (Manager.Anim>=LogoTime) then Manager.Game_State:=gs_game;
end;
{$ENDREGION}

{$REGION 'Keys'}
procedure Check_Keys;       //key press proc
Var Speed:Single;
begin
 //mouse wheel move
 If Win.MW>0 then World.Need_Scale:=World.Need_Scale+(World.Need_Scale)*0.1;
 If Win.MW<0 then World.Need_Scale:=World.Need_Scale-(World.Need_Scale)*0.1;
 Win.MW:=0;
 Speed:=0.15*Tile_Size/World.Scale;
 //move
  if (Win.key[__d] or Win.key[__right]) then begin World.Camera:=plus(World.Camera,Vector(0,-Speed));{KY:=KY+1;Win.key[87]:=false;Win.key[38]:=false;}end;
  if (Win.key[__a] or Win.key[__left ]) then begin World.Camera:=plus(World.Camera,Vector(0, Speed));{KY:=KY-1;Win.key[83]:=false;Win.key[40]:=false;}end;
  if (Win.key[__s] or Win.key[__down ]) then begin World.Camera:=plus(World.Camera,Vector(-Speed,0));{KX:=KX-1;Win.key[65]:=false;Win.key[37]:=false;}end;
  if (Win.key[__w] or Win.key[__up   ]) then begin World.Camera:=plus(World.Camera,Vector( Speed,0));{KX:=KX+1;Win.key[68]:=false;Win.key[39]:=false;}end;
 if Win.my<40 then World.Camera:=plus(World.Camera,Vector(0,-Speed));
 if Win.mx<40 then World.Camera:=plus(World.Camera,Vector(-Speed,0));
 if Win.my>Win.ScreenHeight-40 then World.Camera:=plus(World.Camera,Vector(0,Speed));
 if Win.mx>Win.ScreenWidth-40 then World.Camera:=plus(World.Camera,Vector(Speed,0));

 //mouse left click
 if Win.mbl then //left mouse button - selection
  begin
   World.Mouse_Selection(Coord(Win.mx,Win.my));
  end;
 //mouse left click
 if Win.mbr then //left mouse button - selection
  begin
   World.Mouse_Send(Coord(Win.mx,Win.my));
   Win.mbr:=false;
  end;
 //alt - show all health
 World.Show_Add_info:=Win.key[__ctrl];
 if Win.key[__space] then //space
  begin
   World.Change_Selected_State;
   Win.key[__space]:=false;
  end;
 if Win.key[__esc] then  //esc
  begin
   if Manager.Game_State=gs_logo then
   begin
    Manager.Game_State:=gs_menu;
    exit;
   end;
   if (Manager.Game_State=gs_game) then Manager.Game_State:=gs_menu
   else
   if World.Num_level>0 then
     Manager.Game_State:=gs_game else Kill_Window;
   Win.key[__esc]:=false;
  end;
end;
{$ENDREGION}

{$REGION 'Show Menu'}
procedure Show_Menu;
begin
 Font.TextOut(100,100,2,'Осада',$FFFFFFFF);
 case Manager.menu_screen of
  0:Begin
     if Point_In_Rect(Vector(Win.mx,Win.my),Vector(120,180),Vector(300,220)) then
       Font.TextOut(120,180,1,'Новая игра',$FF4444aa) else
       Font.TextOut(120,180,1,'Новая игра',$FFFFFFFF);
     if Point_In_Rect(Vector(Win.mx,Win.my),Vector(120,220),Vector(300,260)) then
       Font.TextOut(120,220,1,'Автор',$FF4444aa) else
       Font.TextOut(120,220,1,'Автор',$FFFFFFFF);
     if Point_In_Rect(Vector(Win.mx,Win.my),Vector(120,260),Vector(300,300)) then
       Font.TextOut(120,260,1,'Выход',$FF4444aa) else
       Font.TextOut(120,260,1,'Выход',$FFFFFFFF);
     if Win.Key[49] or (win.mbl and Point_In_Rect(Vector(Win.mx,Win.my),Vector(120,180),Vector(300,220))) then
      begin
        Manager.menu_screen:=1;
        Win.Key[49]:=false;
        win.mbl:=false;
      end;
     if Win.Key[50] or (win.mbl and Point_In_Rect(Vector(Win.mx,Win.my),Vector(120,220),Vector(300,260))) then
      begin
        Manager.menu_screen:=2;
        Win.Key[50]:=false;
        win.mbl:=false;
      end;
     if Win.Key[51] or (win.mbl and Point_In_Rect(Vector(Win.mx,Win.my),Vector(120,260),Vector(300,300))) then
      begin
        Kill_Window;
        Win.Key[51]:=false;
        win.mbl:=false;
      end;
    end;
  1:Begin
     if Point_In_Rect(Vector(Win.mx,Win.my),Vector(120,180),Vector(300,220)) then
      Font.TextOut(120,180,1,'1. Засада',$FF4444aa) else
      Font.TextOut(120,180,1,'1. Засада',$FFFFFFFF);
     if Point_In_Rect(Vector(Win.mx,Win.my),Vector(120,220),Vector(300,260)) then
      Font.TextOut(120,220,1,'2. Тихой сапой',$FF4444aa) else
      Font.TextOut(120,220,1,'2. Тихой сапой',$FFFFFFFF);
     if Point_In_Rect(Vector(Win.mx,Win.my),Vector(120,260),Vector(300,300)) then
     Font.TextOut(120,260,1,'3. До последней капли',$FF4444aa) else
     Font.TextOut(120,260,1,'3. До последней капли',$FFFFFFFF);
     if Win.Key[49] or (win.mbl and Point_In_Rect(Vector(Win.mx,Win.my),Vector(120,180),Vector(300,220))) then
      begin
        Manager.menu_screen:=0;
        Manager.Game_State:=gs_game;
        World.Load_level(1);
        Win.Key[49]:=false;
        win.mbl:=false;
      end;
     if Win.Key[50] or (win.mbl and Point_In_Rect(Vector(Win.mx,Win.my),Vector(120,220),Vector(300,260))) then
      begin
        Manager.menu_screen:=0;
        Manager.Game_State:=gs_game;
        World.Load_level(2);
        Win.Key[50]:=false;
        win.mbl:=false;
      end;
     if Win.Key[51] or (win.mbl and Point_In_Rect(Vector(Win.mx,Win.my),Vector(120,260),Vector(300,300))) then
      begin
        Manager.menu_screen:=0;
        Manager.Game_State:=gs_game;
        World.Load_level(3);
        Win.Key[51]:=false;
        win.mbl:=false;
      end;
    end;
  2:Begin
     Font.TextOut(120,180,1,'Специально для 74 конкурса (Tower Defense III ) на IGDC.ru ',$FFFFFFFF);
     Font.TextOut(120,220,1,'Игра Осада.',$FFFFFFFF);
     Font.TextOut(120,260,1,'Автор: Mefistofel ',$FFFFFFFF);
     Font.TextOut(120,300,1,'       17.10.2011 г. ',$FFFFFFFF);
     if Win.Key[50] or  Win.Key[49] or Win.Key[51] or (win.mbl and Point_In_Rect(Vector(Win.mx,Win.my),Vector(120,220),Vector(300,300))) then
      begin
        Manager.menu_screen:=0;
        Win.Key[49]:=false;
        Win.Key[50]:=false;
        Win.Key[51]:=false;
        win.mbl:=false;
      end;
    end;
 end;
end;
{$ENDREGION}

{$REGION 'Timer'}
procedure OnTimer( var delta: Double );
begin
 if not Win.Focus then exit; //do something only if window in focus
 Check_Keys;     
 Quad.BeginRender;
 case Manager.Game_State of
  gs_exit:Kill_Window;
  gs_logo:Show_Logo;
  gs_menu:
  begin
   if World.Num_level=0 then
    World.Move;
   World.Render;
   Show_Menu;
  end;
  gs_game:
   begin
    if World.Num_level=0 then Manager.Game_State:=gs_menu;    
    World.Move;        //world tact
    World.Render;
   end;
 end;
 Quad.EndRender;
end;
{$ENDREGION}

{$REGION 'Create_prog'}
procedure Create_prog;//creation initialization
begin
 Randomize;
{$REGION '  Engine'}
 Quad := CreateQR;
 Quad.Initialize(
       Win.Handle,
       Win.ScreenWidth,Win.ScreenHeight,
       false);//fullscreen

 Timer := Quad.CreateTimer;
 Timer.SetInterval( 16 );
 Timer.SetCallBack( @OnTimer );
{$ENDREGION}
 Manager.menu_screen:=0;             
 Manager.Logo:=Quad.CreateTexture;
 Manager.Logo.LoadFromFile(0,'data/quad.png');  
 Quad.SetBlendMode(qbmSrcAlpha);

 World:=TWorld.CreateWorld;

 Manager.Game_State:=gs_logo;
 Manager.menu_screen:=0;

 Timer.SetState( True );
end;
{$ENDREGION}   

{$REGION 'Kill_program'}
procedure Kill_prog;
begin
 World.Free();
end;
{$ENDREGION}

{$REGION 'Change_state'}
procedure Change_State;
begin

end;
{$ENDREGION}

begin
 Win.Top:=0;//top/left value
 Win.Left:=0;
 Win.Width:=GetSystemMetrics(SM_CXSCREEN);//get desktop resolution
 Win.Height:=GetSystemMetrics(SM_CYSCREEN);
 //tmp
{ Win.Top:=(Win.Width-1024) div 2;
 Win.Left:=(Win.Height-768) div 2;  
 Win.Width:=1024;
 Win.Height:=768;   }

 Main_Proc('Besinger',@Create_prog,@kill_prog,@Change_State,Win.Top,Win.Left,Win.Width,Win.Height);
end.
