unit u_player;

interface

uses u_const, zglHeader, SysUtils, zglGUI, u_music;

type TPlayer = object
       public
         Pos: zglTPoint2D;
         Go:Boolean;
         Say:string;
         SayTime:Integer;
         Lives:byte;
         Diff, Score:integer;
         Angle, AngleOffset, Anim:Integer;
         PlaySpeed : single;
         procedure Render;
         procedure Update;
         procedure AddScore(i:integer);
         procedure Init(X,Y:Integer);
     end;

implementation

uses u_game;

procedure TPlayer.AddScore(i:integer);
begin
  Score:=Score+i;
end;

procedure TPlayer.Init(X,Y:Integer);
begin
  Pos.X:=X;
  Pos.Y:=Y;
  Go:=false;
  Angle:=0;
  AngleOffset:=0;
  PlaySpeed:=0;
end;


procedure TPlayer.Update;
var i:integer;
    x:zglTPoint2D;
begin
  if SayTime>0 then Dec(SayTime);
  if Go then begin
    if Pos.X<1 then Pos.X:=Map.MapW-2;
    if Pos.Y<1 then Pos.Y:=Map.MapH-2;
    if Pos.X>Map.MapW-2 then Pos.X:=2;
    if Pos.Y>Map.MapH-2 then Pos.Y:=2;
  end;
  if PlayId>=0 then begin
    if PlaySpeed>0 then begin
      PlaySpeed:=PlaySpeed-0.00002;
      snd_SetSpeed(Msc[PlayId], 0, 1+4*round(PlaySpeed*25)/100);
    end;
  end;
  if Map.InCenter(Pos.X, Pos.Y) then begin
    if (key_Down(K_W) or key_Down(K_UP)) and Map.CkeckPos(Pos.X-m_cos(90-AngleOffset)*0.9, Pos.Y-m_sin(90-AngleOffset)*0.9, 90-AngleOffset, true)  then begin
      Go:=True;
      Angle:=90-AngleOffset;
    end;
    if (key_Down(K_S) or key_Down(K_DOWN)) and Map.CkeckPos(Pos.X-m_cos(270-AngleOffset)*0.9, Pos.Y-m_sin(270-AngleOffset)*0.9, 270-AngleOffset, true)  then begin
      Go:=True;
      Angle:=270-AngleOffset;
    end;
    if (key_Down(K_A) or key_Down(K_LEFT)) and Map.CkeckPos(Pos.X-m_cos(0-AngleOffset)*0.9, Pos.Y-m_sin(0-AngleOffset)*0.9, 0-AngleOffset, true) then begin
      Go:=True;
      Angle:=0-AngleOffset;
    end;
    if (key_Down(K_D) or key_Down(K_RIGHT)) and Map.CkeckPos(Pos.X-m_cos(180-AngleOffset)*0.9, Pos.Y-m_sin(180-AngleOffset)*0.9, 180-AngleOffset, true)  then begin
      Go:=True;
      Angle:=180-AngleOffset;
    end;
  end;
  if mouse_Down(M_BLEFT) and (Portals[1].Counter<=0) then begin
    inc(PortalsFlyCount);
    with PortalsFly[PortalsFlyCount] do begin
      PortalId:=1;
      Position:=Pos;
      lookAngle:=round(m_Angle(sX div 2, sy div 2, mouse_X, mouse_Y))-AngleOffset;
    end;
    snd_Play(sndPshoot1);
    Portals[1].Counter:=portal_counter;
  end;
  if mouse_Down(M_BRIGHT) and (Portals[2].Counter<=0) then begin
    inc(PortalsFlyCount);
    with PortalsFly[PortalsFlyCount] do begin
      PortalId:=2;
      Position:=Pos;
      lookAngle:=round(m_Angle(sX div 2, sy div 2, mouse_X, mouse_Y))-AngleOffset;
    end;
    snd_Play(sndPshoot2);
    Portals[2].Counter:=portal_counter;
  end;
  if Go then begin
    
    if j mod 64 = 0 then begin
      Inc(Anim);
      if Anim>4 then Anim:=1;
    end;

    for i:=1 to portals_count do
      if (Portals[i].State=portal_opened) and (Portals[Portals[i].ExitId].State=portal_opened) then
      if (abs(Portals[i].Position.X-Pos.X)<player_speed*2) and (abs(Portals[i].Position.Y-Pos.Y)<player_speed*2) and
        (Map.InCenter(Pos.X, Pos.Y)) then begin
        if GameState=gs_choose then begin
          StopMusic;
          if Pos.X<8 then begin
            Level:=0;
            Map.LoadFromFile('Data/Maps/demo.bmp');
          end else begin
            Player.Diff:=Round(Player.Pos.Y/2);
            Level:=1;
            Map.LoadFromFile('Data/Maps/1.bmp');
          end;
          DieCounter:=0;
          DieId:=Random(die_count);
          GameState:=gs_die;

          snd_Play(sndPremenu);
        end else begin
          Pos:=Portals[Portals[i].ExitId].Position;
          Angle:=180+Portals[Portals[i].ExitId].lookAngle;
          Pos.X:=Pos.X-m_cos(Angle)*player_speed*4;
          Pos.Y:=Pos.Y-m_sin(Angle)*player_speed*4;
          if (Portals[Portals[i].ExitId].lookAngle-Portals[i].lookAngle) mod 180 = 0 then j:=180 else j:=0;
          AngleOffset:=AngleOffset+j+Portals[Portals[i].ExitId].lookAngle-Portals[i].lookAngle;
          while AngleOffset<0 do inc(AngleOffset,360);
          while AngleOffset>360 do Dec(AngleOffset,360);
          snd_Play(sndPortalExit[Random(2)+1]);
        end;
      end;
    Pos.X:=Pos.X-m_cos(Angle)*player_speed;
    Pos.Y:=Pos.Y-m_sin(Angle)*player_speed;
    if Map.InCenter(Pos.X, Pos.Y) and (not Map.CkeckPos(Pos.X-m_cos(Angle)*0.5, Pos.Y-m_sin(Angle)*0.5, Angle, true)) then begin
      Go:=false;
    end;
    if Map.InCenter(Pos.X, Pos.Y) then begin
      case Map.MapData[round(Pos.X), round(Pos.Y)].btType of
        bt_eat:begin
          Dec(Map.EatCount);
          if PlaySpeed<playspeed_max then
            PlaySpeed:=PlaySpeed+playspeed_inc;
          x.X:=Pos.X*item_size;
          x.Y:=Pos.Y*item_size;
          zgl.CreateEffect(@plus10, x, -AngleOffset-90);
          snd_Play(sndWk);
          AddScore(10);
          if Map.EatCount<=0 then begin
            StopMusic;
            if Level=0 then begin
              GameState:=gs_choose;
              Level:=1;
              Map.LoadFromFile('Data/Maps/menu.bmp');
            end else begin
              inc(level);
              Map.LoadFromFile('Data/Maps/'+inttostr(level)+'.bmp');
              DieCounter:=0;
              DieId:=Random(die_count);
              GameState:=gs_die;
              
              snd_Play(sndPremenu);
            end;
          end;
          Map.MapData[round(Pos.X), round(Pos.Y)].btType := bt_none;
        end;
        bt_enetgizer:begin
          if PlaySpeed<playspeed_max then
            PlaySpeed:=PlaySpeed+playspeed_inc*8;
          x.X:=Pos.X*item_size;
          x.Y:=Pos.Y*item_size;
          zgl.CreateEffect(@plus100, x, -AngleOffset-90);
          AddScore(100);
          snd_Play(sndEnergizer);
          for i:=1 to ghosts_count do
            if Ghosts[i].Enabled then begin
              Ghosts[i].State:=gss_back;
              Ghosts[i].ScareTime:=scare_time;
            end;
          Map.MapData[round(Pos.X), round(Pos.Y)].btType := bt_none;
        end;
        bt_wizard:begin
          inc(WizardId);
          AddMessage(Wizards[WizardId].Text, Wizards[WizardId].Times, Wizards[WizardId].CallId);
          snd_Play(sndNewMsg);
          snd_Play(Wizards[WizardId].snd);

          Map.MapData[round(Pos.X), round(Pos.Y)].btType := bt_none;
        end;
      end;
    end;
  end;
end;

procedure TPlayer.Render;
begin

  asprite2d_Draw(txPacMan, (Pos.X-0.5)*item_size, (Pos.Y-0.5)*item_size,
    item_size, item_size, Angle, Anim);
  ssprite2d_Draw(txWeapon, (Pos.X-1)*item_size, (Pos.Y-1)*item_size,
    item_size*2, item_size*2, m_Angle(sX div 2, sy div 2, mouse_x, mouse_Y)-AngleOffset);
end;

end.
