unit UCadencer;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,Unit1,GLKeyboard, GLScene, GLCadencer;

type
  TForm4 = class(TForm)
    GLCadencer1: TGLCadencer;
    procedure FormDestroy(Sender: TObject);    
    procedure GLCadencer1Progress(Sender: TObject; const deltaTime,
      newTime: Double);
    function Jumpheight(ID:Integer):Real;
    function Jumpstrength(Speed:Real):Real;
    procedure ShowPlayers(const deltatime:double);
    procedure ShowNPC(const deltatime:double);
    procedure MovePlayer(const deltatime:double);
    procedure ModifyThrust(const deltatime:double);  
    procedure UpdateSpeed;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form4: TForm4;
  maxJumpHeight:Real;   //4-PlayerHeight[false]

  MoveDirX,MoveDirZ:Real;

  Lastjumptime:Real=0;

  LastPos:Integer;

  CameraDirection:Integer;

implementation

uses UColorByID,Math,UMoveToRoom,GLHUDObjects,UMYUtils;

{$R *.dfm}

procedure TForm4.GLCadencer1Progress(Sender: TObject; const deltaTime,
  newTime: Double);
begin
  ModifyThrust(deltaTime); //0 ms

  if (not IsKeyDown(32))
  and (not Players[MyID].jumping) then
  jumppressed:=false;

  if inMenu or Lost then begin
    Camera.Turn(20*deltatime);
  end;
  MovePlayer(deltaTime); //0,0668ms    


                               

  
  Camera.Position.Y:=Jumpheight(MyID);  //0,0003ms
  if players[MyId].CeilWalk then
  Camera.Position.Y:=-Camera.Position.Y+2;

  Players[MyID].X:=Camera.Position.X+PosX*20;
  Players[MyID].Z:=Camera.Position.Z+PosZ*20;

  ShowPlayers(deltaTime); //0,0025ms
  
//  if FrameCount>3 then
//  SW.ResetTimer;
//  for C1:=1 to 1000000 do begin
                       
  ShowNPC(deltaTime); //0,0024ms  

//  if FrameCount<=3 then Break;
//  end;
//  if FrameCount>3 then
//  showmessage(inttostr(SW.TimeElapsedmilliSecs));

  Inc(FrameCount);
end;

procedure TForm4.ShowNPC(const deltatime:double); 
var C1,C2:Integer;
begin
  for C1:=-RaumRange to RaumRange do
  for C2:=-RaumRange to RaumRange do
  if MuhNPCArr[C1,C2].Body.Visible then begin
    MuhNPCArr[C1,C2].Body.Position.X:=
    MuhNPCArr[C1,C2].Body.Position.X+
    MuhNPCArr[C1,C2].MoveX;                             
    if MuhNPCArr[C1,C2].Body.Position.X>8.5+20*C1 then begin
      MuhNPCArr[C1,C2].Body.Position.X:=8.5+20*C1
      -(MuhNPCArr[C1,C2].Body.Position.X-(8.5+20*C1));
      MuhNPCArr[C1,C2].MoveX:=-MuhNPCArr[C1,C2].MoveX;
    end;
    if MuhNPCArr[C1,C2].Body.Position.X<-8.5+20*C1 then begin
      MuhNPCArr[C1,C2].Body.Position.X:=-8.5+20*C1
      +((-8.5+20*C1)-MuhNPCArr[C1,C2].Body.Position.X);
      MuhNPCArr[C1,C2].MoveX:=-MuhNPCArr[C1,C2].MoveX;
    end;                

    MuhNPCArr[C1,C2].Body.Position.Y:=
    MuhNPCArr[C1,C2].Body.Position.Y+
    MuhNPCArr[C1,C2].MoveY;    

    if MuhNPCArr[C1,C2].Body.Position.Y>3 then begin
      MuhNPCArr[C1,C2].Body.Position.Y:=3
      -(MuhNPCArr[C1,C2].Body.Position.Y-3);
      MuhNPCArr[C1,C2].MoveY:=-MuhNPCArr[C1,C2].MoveY;
    end;
    if MuhNPCArr[C1,C2].Body.Position.Y<-1 then begin
      MuhNPCArr[C1,C2].Body.Position.Y:=-1
      +(-1-MuhNPCArr[C1,C2].Body.Position.Y);
      MuhNPCArr[C1,C2].MoveY:=-MuhNPCArr[C1,C2].MoveY;
    end;

    MuhNPCArr[C1,C2].Body.Position.Z:=
    MuhNPCArr[C1,C2].Body.Position.Z+
    MuhNPCArr[C1,C2].MoveZ;

    if MuhNPCArr[C1,C2].Body.Position.Z>8.5+20*C2 then begin
      MuhNPCArr[C1,C2].Body.Position.Z:=8.5+20*C2
      -(MuhNPCArr[C1,C2].Body.Position.Z-(8.5+20*C2));
      MuhNPCArr[C1,C2].MoveZ:=-MuhNPCArr[C1,C2].MoveZ;
    end;
    if MuhNPCArr[C1,C2].Body.Position.Z<-8.5+20*C2 then begin
      MuhNPCArr[C1,C2].Body.Position.Z:=-8.5+20*C2
      +((-8.5+20*C2)-MuhNPCArr[C1,C2].Body.Position.Z);
      MuhNPCArr[C1,C2].MoveZ:=-MuhNPCArr[C1,C2].MoveZ;
    end;
  end;
end;
         

function TForm4.Jumpstrength(Speed:Real):Real;
begin
  if Speed<=15 then
  Result:=-7/180*sqr(Players[MyID].Speed)+Players[MyID].Speed*1.15
  else Result:=Speed*0.6;
end;

function TForm4.Jumpheight(ID:Integer):Real;
var JumpStrenghtByID:Real; RT:PRoomtype;
begin
  JumpStrenghtByID:=Jumpstrength(Players[ID].Speed);
  if (Players[ID].Speed<=0)
  or (Players[ID].jumptime<-0.00001) then begin
    Players[ID].jumping:=false;
    Result:=-2+PlayerDepth[false];
    Exit;
  end;

  Result:=      
  -4.905*sqr(Players[ID].jumptime)
  +JumpStrenghtByID*Players[ID].jumptime
  -2+PlayerDepth[false];

  RT:=GetRT(Round(Players[ID].X/20),Round(Players[ID].Z/20));
  if (Result>maxJumpHeight) and not Won then begin
    if                    
    ((RT.MaterialName[Up]='Open') and not Players[ID].Ceilwalk)
    or
    ((RT.MaterialName[Down]='Open') and Players[ID].Ceilwalk) then
    Players[ID].OutOfMaze:=true;
    
    if not Players[ID].OutOfMaze then begin
      Players[ID].jumptime:=Players[ID].jumptime+
      (200*sqrt(
      sqr(JumpStrenghtByID)+(981*(-2+PlayerDepth[false]))
      /50-(981*maxJumpHeight)/50))
      /981;

      Result:=
      -4.905*sqr(Players[ID].jumptime)
      +JumpStrenghtByID*Players[ID].jumptime
      -2+PlayerDepth[false];
    end;
  end;


  if not Players[ID].OutOfMaze and (Result<-2+PlayerDepth[false]) then begin
    if
    ((RT.MaterialName[Down]='Open') and not Players[ID].Ceilwalk)
    or
    ((RT.MaterialName[Up]='Open') and Players[ID].Ceilwalk) then begin
      Players[ID].OutOfMaze:=true;
    end else begin
      Players[ID].jumping:=false;
      Result:=-2+PlayerDepth[false];
    end;
  end;

  
  Players[ID].OutOfMaze:=
  (Result<-2.001+PlayerDepth[false])
  or (Result>4.001-PlayerHeight[false]);

  if Result>200 then Result:=200;
  if Result<-200 then Result:=200;
end;

procedure TForm4.FormDestroy(Sender: TObject);
begin
  GLCadencer1.Enabled:=false;
end;

procedure TForm4.MovePlayer(const deltatime:double);
var R1:Real; MinY,MaxY:Real;
begin
  if not Lost then begin
    Form1.GLUserInterface1.MouseUpdate;
    Form1.GLUserInterface1.MouseLook;

    if Ceil(Camera.Direction.X)+2*Ceil(Camera.Direction.Z)

    <>CameraDirection then
    Form1.Reload;
  end;
  if not Players[MyID].jumping then begin
    MoveDirX:=Camera.Position.X;
    MoveDirZ:=Camera.Position.Z;

    if isKeyDown('w') then begin
      if not (isKeyDown('d'))
      and not (isKeyDown('a'))
      then R1:=Players[MyID].Speed else R1:=Players[MyID].Speed/sqrt(2);
    end else
    if isKeyDown('a') then begin
      if not (isKeyDown('w'))
      and not (isKeyDown('s'))
      then R1:=Players[MyID].Speed else R1:=Players[MyID].Speed/sqrt(2);
    end else
    if isKeyDown('s') then begin
      if not (isKeyDown('d'))
      and not (isKeyDown('a'))
      then R1:=Players[MyID].Speed else R1:=Players[MyID].Speed/sqrt(2);
    end else
    if isKeyDown('d') then begin
      if not (isKeyDown('w'))
      and not (isKeyDown('s'))
      then R1:=Players[MyID].Speed else R1:=Players[MyID].Speed/sqrt(2);
    end else R1:=0;

    if not inMenu and not Lost and
    not GetRT(PosX,PosZ).PushPlayer[THeight(Players[MyID].Ceilwalk)] then begin
      if isKeyDown('w') then Camera.Move(R1*deltatime);
      if isKeyDown('s') then Camera.Move(-R1*deltatime);
      if isKeyDown('d') then Camera.Slide(R1*deltatime);
      if isKeyDown('a') then Camera.Slide(-R1*deltatime);
    end;

    if GetRT(PosX,PosZ).PushPlayer[THeight(Players[MyID].Ceilwalk)] and
    assigned(Map[PosX,PosZ].Inhalt.Daten) then begin
      case TRichtung(Map[PosX,PosZ].Inhalt.Daten^) of
        px:Camera.Position.X:=Camera.Position.X+deltaTime*30;
        nx:Camera.Position.X:=Camera.Position.X-deltatime*30;
        pz:Camera.Position.Z:=Camera.Position.Z+deltatime*30;
        nz:Camera.Position.Z:=Camera.Position.Z-deltatime*30;
      end;

      if not
      (isKeyDown('w')        
      or isKeyDown('s')
      or isKeyDown('d')
      or isKeyDown('a')) then
      if (
        ((TRichtung(Map[PosX,PosZ].Inhalt.Daten^)=px)
      and GetRT(PosX+1,PosZ).PushPlayer[THeight(Players[MyID].Ceilwalk)]
      and (TRichtung(Map[PosX+1,PosZ].Inhalt.Daten^)=nx))
      or ((TRichtung(Map[PosX,PosZ].Inhalt.Daten^)=nx)
      and GetRT(PosX-1,PosZ).PushPlayer[THeight(Players[MyID].Ceilwalk)]
      and (TRichtung(Map[PosX-1,PosZ].Inhalt.Daten^)=px))
      or ((TRichtung(Map[PosX,PosZ].Inhalt.Daten^)=nz)
      and GetRT(PosX,PosZ-1).PushPlayer[THeight(Players[MyID].Ceilwalk)]
      and (TRichtung(Map[PosX,PosZ-1].Inhalt.Daten^)=pz))
      or ((TRichtung(Map[PosX,PosZ].Inhalt.Daten^)=pz)
      and GetRT(PosX,PosZ+1).PushPlayer[THeight(Players[MyID].Ceilwalk)]
      and (TRichtung(Map[PosX,PosZ+1].Inhalt.Daten^)=nz))
      ) then
      case TRichtung(Map[PosX,PosZ].Inhalt.Daten^) of
        px:Camera.Position.X:=Min(Camera.Position.X+deltaTime,9.99);
        nx:Camera.Position.X:=Max(Camera.Position.X-deltatime,-9.99);
        pz:Camera.Position.Z:=Min(Camera.Position.Z+deltatime,9.99);
        nz:Camera.Position.Z:=Max(Camera.Position.Z-deltatime,-9.99);
      end;
    end;
  end else begin
    Camera.Position.X:=Camera.Position.X+2*MoveDirX*deltatime;
    Camera.Position.Z:=Camera.Position.Z+2*MoveDirZ*deltatime;
  end;

  MinY:=Camera.Position.Y-PlayerDepth[players[MyId].CeilWalk];
  MaxY:=Camera.Position.Y+PlayerHeight[players[MyId].CeilWalk];
  if ((MaxY<4) and (MaxY>-2))
  or ((MinY<4) and (MinY>-2)) then begin
    if (Camera.Position.X>8.5)
    and (px in Map[posX,PosZ].Walls) then begin
      Camera.Position.X:=8.5;
      if Players[Myid].jumping then MoveDirX:=-MoveDirX;
    end;
    if (Camera.Position.Z>8.5)
    and (pz in Map[posX,PosZ].Walls) then begin
      Camera.Position.Z:=8.5;
      if Players[Myid].jumping then MoveDirZ:=-MoveDirZ;
    end;
    if (Camera.Position.X<-8.5)
    and (nx in Map[posX,PosZ].Walls) then begin
      Camera.Position.X:=-8.5;
      if Players[Myid].jumping then MoveDirX:=-MoveDirX;
    end;
    if (Camera.Position.Z<-8.5)
    and (nz in Map[posX,PosZ].Walls) then begin
      Camera.Position.Z:=-8.5;
      if Players[Myid].jumping then MoveDirZ:=-MoveDirZ;
    end;
  end;

  if ((MaxY<1) and (MaxY>-2))
  or ((MinY<1) and (MinY>-2)) then begin
    if (Camera.Position.X>8.5)
    and (px in Map[posX,PosZ].DownWalls) then begin
      Camera.Position.X:=8.5;
      if Players[Myid].jumping then MoveDirX:=-MoveDirX;
    end;
    if (Camera.Position.X<-8.5)
    and (nx in Map[posX,PosZ].DownWalls) then begin
      Camera.Position.X:=-8.5;
      if Players[Myid].jumping then MoveDirX:=-MoveDirX;
    end;
    if (Camera.Position.Z>8.5)
    and (pz in Map[posX,PosZ].DownWalls) then begin
      Camera.Position.Z:=8.5;
      if Players[Myid].jumping then MoveDirZ:=-MoveDirZ;
    end;
    if (Camera.Position.Z<-8.5)
    and (nz in Map[posX,PosZ].DownWalls) then begin
      Camera.Position.Z:=-8.5;
      if Players[Myid].jumping then MoveDirZ:=-MoveDirZ;
    end;
  end;

  if ((MaxY<4) and (MaxY>1))
  or ((MinY<4) and (MinY>1)) then begin
    if (Camera.Position.X>8.5)
    and (px in Map[posX,PosZ].UpWalls) then begin
      Camera.Position.X:=8.5;
      if Players[Myid].jumping then MoveDirX:=-MoveDirX;
    end;
    if (Camera.Position.X<-8.5)
    and (nx in Map[posX,PosZ].UpWalls) then begin
      Camera.Position.X:=-8.5;
      if Players[Myid].jumping then MoveDirX:=-MoveDirX;
    end;
    if (Camera.Position.Z>8.5)
    and (pz in Map[posX,PosZ].UpWalls) then begin
      Camera.Position.Z:=8.5;
      if Players[Myid].jumping then MoveDirZ:=-MoveDirZ;
    end;
    if (Camera.Position.Z<-8.5)
    and (nz in Map[posX,PosZ].UpWalls) then begin
      Camera.Position.Z:=-8.5;
      if Players[Myid].jumping then MoveDirZ:=-MoveDirZ;
    end;
  end;
      

  if not Players[Myid].jumping then begin
    MoveDirX:=(Camera.Position.X-MoveDirX)/deltatime;
    MoveDirZ:=(Camera.Position.Z-MoveDirZ)/deltatime;  
  end;

  repeat
    if Camera.Position.X>10 then begin
      Camera.Position.X:=Camera.Position.X-20;
      Inc(PosX);
      MoveToRoom(PosX-1,PosZ);
    end;
    if Camera.Position.Z>10 then begin
      Camera.Position.Z:=Camera.Position.Z-20;
      Inc(Posz);
      MoveToRoom(PosX,PosZ-1);
    end;
    if Camera.Position.X<-10 then begin
      Camera.Position.X:=Camera.Position.X+20;
      Dec(PosX);
      MoveToRoom(PosX+1,PosZ);
    end;
    if Camera.Position.Z<-10 then begin
      Camera.Position.Z:=Camera.Position.Z+20;
      Dec(Posz);
      MoveToRoom(PosX,PosZ+1);
    end;
  until (Camera.Position.X<=10)
  and (Camera.Position.Z<=10)
  and (Camera.Position.X>=-10)
  and (Camera.Position.Z>=-10);
end;


procedure TForm4.ShowPlayers(const deltatime:double);
var C2:Integer;  R,G,B:Real;
begin
  for C2:=0 to High(playerarr) do begin   
    Players[C2].jumptime:=Players[C2].jumptime+deltatime;

    if Cardinal(C2)<>MyID then begin
      if Players[C2].LastTimeEnd-Players[C2].LastTimeStart<>0 then
      playerarr[C2].Position.X:=Players[C2].LastX
      +(GetTickCount-Players[C2].LastTimeStart)
      /(Players[C2].LastTimeEnd-Players[C2].LastTimeStart)
      *(Players[C2].X-Players[C2].LastX);
      if Gettickcount>Players[C2].LastTimeEnd then
      playerarr[C2].Position.X:=Players[C2].X;
      playerarr[C2].Position.X:=playerarr[C2].Position.X-PosX*20;


      if players[C2].jumping then Players[C2].Y:=Jumpheight(C2)
      else Players[C2].Y:=-2+PlayerDepth[false];
      if players[C2].CeilWalk then
      Players[C2].Y:=-Players[C2].Y+2;
      Players[C2].Y:=Players[C2].Y
      -PlayerDepth[Players[C2].CeilWalk]
      +(PlayerDepth[Players[C2].CeilWalk]
      +PlayerHeight[Players[C2].CeilWalk])/2;
      playerarr[C2].Position.Y:=Players[C2].Y;

      
            
      if Players[C2].LastTimeEnd-Players[C2].LastTimeStart<>0 then
      playerarr[C2].Position.Z:=Players[C2].LastZ
      +(GetTickCount-Players[C2].LastTimeStart)
      /(Players[C2].LastTimeEnd-Players[C2].LastTimeStart)
      *(Players[C2].Z-Players[C2].LastZ);
      if Gettickcount>Players[C2].LastTimeEnd then
      playerarr[C2].Position.Z:=Players[C2].Z;
      playerarr[C2].Position.Z:=playerarr[C2].Position.Z-PosZ*20;

      if C2>High(PlayerGoalDistPanels) then
      Setlength(PlayerGoalDistPanels,C2+1);
      if not assigned(PlayerGoalDistPanels[C2]) then begin
        PlayerGoalDistPanels[C2]:=
        TGLHUDText(Form1.PlayerGoalDists.AddNewChild(TGLHUDText));
        PlayerGoalDistPanels[C2].BitmapFont:=Form1.PlayerGoalDistFont;
        RedbyID(C2,R);
        GreenbyID(C2,G);
        BluebyID(C2,B);
        PlayerGoalDistPanels[C2].ModulateColor.SetColor(R,G,B); 
        PlayerGoalDistPanels[C2].Position.SetPoint
        (0.01*self.Width,Form1.PlayerGoalDistFont.Font.Size*(C2+0.5),0);
      end;
      PlayerGoalDistPanels[C2].Text:=
      'P'+IntToStr(C2)+': '
      +FloatToStr(Round(10*sqrt
      (sqr(GoalPos.X*20-(playerarr[C2].Position.X+PosX*20))
      +sqr(GoalPos.Y*20-(playerarr[C2].Position.Z+PosZ*20))))/10);

         

      Playerarr[C2].Visible:=
      ((RaumRange+1)*20>Playerarr[C2].Position.X)
      and ((RaumRange+1)*20>Playerarr[C2].Position.Z)
      and ((-RaumRange-1)*20<Playerarr[C2].Position.X)
      and ((-RaumRange-1)*20<Playerarr[C2].Position.Z);
    end else begin    //mit C2=MYID durchführen
      if not Lost then
      Players[MyID].Dead:=false;
      playerarr[C2].Position.SetPoint(Camera.Position.DirectVector);

      if C2>High(PlayerGoalDistPanels) then
      Setlength(PlayerGoalDistPanels,C2+1);
      if not assigned(PlayerGoalDistPanels[C2]) then begin
        PlayerGoalDistPanels[C2]:=
        TGLHUDText(Form1.PlayerGoalDists.AddNewChild(TGLHUDText));
        PlayerGoalDistPanels[C2].BitmapFont:=Form1.PlayerGoalDistFont;
        RedbyID(C2,R);
        GreenbyID(C2,G);
        BluebyID(C2,B);
        PlayerGoalDistPanels[C2].ModulateColor.SetColor(R,G,B);   
        PlayerGoalDistPanels[C2].Position.SetPoint
        (0.01*self.Width,Form1.PlayerGoalDistFont.Font.Size*(C2+0.5),0);
      end;
      PlayerGoalDistPanels[C2].Text:=
      'Your ID: '+IntToStr(C2);

      Playerarr[C2].Visible:=false;

      Players[MyID].Y:=Camera.Position.Y
      -PlayerDepth[Players[MyID].CeilWalk]
      +(PlayerDepth[Players[MyID].CeilWalk]
      +PlayerHeight[Players[MyID].CeilWalk])/2;
    end;

    if Playerarr[C2].Position.X>(mapsize+10)*20 then
    Playerarr[C2].Position.X:=0;
    if Playerarr[C2].Position.Z>(mapsize+10)*20 then
    Playerarr[C2].Position.Z:=0;
    if Playerarr[C2].Position.X<-(mapsize+10)*20 then
    Playerarr[C2].Position.X:=0;
    if Playerarr[C2].Position.Z<-(mapsize+10)*20 then
    Playerarr[C2].Position.Z:=0;
  end;
end;


procedure TForm4.ModifyThrust(const deltatime:double);
begin
  if Lost or inMenu then Exit;
  if IsKeyDown('u') then Form1.ThrustBar.Position:=
  Form1.ThrustBar.Position+Round(deltatime*250) else
  if IsKeyDown('j') then Form1.ThrustBar.Position:=
  Form1.ThrustBar.Position-Round(deltatime*250) else
  Exit;
  if Form1.ThrustBar.Position<5 then Form1.ThrustBar.Position:=5;  
  UpdateSpeed;
end;

procedure TForm4.UpdateSpeed;
begin
  Players[MyID].Speed:=Players[MyID].Speed*Form1.ThrustBar.Position/LastPos;
  Form1.GLHUDText1.Text:='Speed: '
  +Floattostr(Round(100*Players[MyID].Speed)/100)+' m/s';
  if Players[MyID].Speed<0.0001 then
  Form1.GLHUDText1.Text:='Speed: 0 m/s'; 
  LastPos:=Form1.ThrustBar.Position;
end;


end.



