{code by peter mindek, 2006}
PROGRAM ca47708c07fae3935fafb1d5db8419a0_DISINFECT;
uses
  math3d in 'math3d.pas',
  types3d in 'types3d.pas',
  ogl3d in 'ogl3d.pas',
  menu in 'menu.pas',
  intro in 'intro.pas',
  credits in 'credits.pas',
  textures3d in 'textures3d.pas',
  texfont,

  Forms,
  StdCtrls,
  ComObj,
  SysUtils,

  Classes,
  Windows,
  Messages,
  Graphics,
  OpenGL,
  FMOD,
  FMODTypes,
  FMODErrors;

{$R 'ca47.res'}
{$R 'mode.dfm'}
{$R 'windowsXP.res'}

CONST AppTitle = 'Disinfect';
      TexCnt = 20; //pocet textur
      TID_Halo       = 0;
      TID_Loading    = 1;
      TID_Cursor     = 2;
      TID_Font       = 3;
      TID_MenuBack   = 4;
      TID_MenuButton = 5;
      TID_MenuCircle = 6;
      TID_Intro      = 7;
      TID_Credits    = 8;
      TID_Player0    = 9;
      TID_Player1    = 10;
      TID_Pane       = 11;
      TID_Arrow      = 12;
      TID_Logo       = 13;
      TID_StillBack  = 14;
      TID_ScrollBack = 15;
      TID_BackBegin  = 16;
      TID_BackEnd0   = 17;
      TID_BackEnd1   = 18;
      TID_Presents   = 19;

      WaterRes = 300;
      WaveRes = 5;

TYPE TPlayer = RECORD
      Pos,Spd: TCoord2d;
      Left: Boolean;
      Life,LastLife: GLfloat;
      InWater: DWORD; //odkedy je vo vode (ak je =0, tak je z vody von)
      Score: GLint;
      KillTime: DWORD;
      Falling: Boolean;
     END;
     TBrick = RECORD
      X1,X2,Fade: GLfloat;
      StartFading: DWORD;
      Deck: GLbyte;
      Jump: Boolean;
     END;
     TWater = RECORD
      Val,Vel: GLfloat;
     END;

     TRes = RECORD
      W,H,B: GLint;
     END;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    ListBox1: TListBox;
    CheckBox1: TCheckBox;
    CheckBox2: TCheckBox;
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;


VAR h_Rc: HGLRC;		                  //Rendering Context
    h_Dc: HDC;                        //private GDI Device Context
    h_Wnd: HWND;                      //handle okna
    Keys: array [0..255] of BOOL;	    //pole na ukladanie vstupu z klávesnice
    Active: BOOLean = TRUE;           //ci je okno aktivne
    FullScreen: BOOLean = TRUE;       //ci je program fullscreen
    VSync: BOOLean = TRUE;            //ci je program vsyncovany
    _W_,_H_,_B__,_Width_,_Height_: GLint;  //rozlisenie
    Done: BOOLean = FALSE;            //indikuje ci sa ma program uz skoncit

    LevelWidth: GLfloat;
    WaterLevel: Glfloat=100;

    C: GLuint;


    TM1,TM2: DWORD; FPS: GLfloat;

    T,TLast,When,START,AreClose: DWORD;                   //timing
    _X_,_Y_: GLuint;                  //suradnice mysi
    _B_: BOOLEAN=FALSE;               //stav laveho tlacitka

    //textury
    Tex: Array[0..TexCnt-1] of TTexture;

    //audio
    MusicIntro,MusicMenu,MusicMenuLoop,MusicCredits,MusicGame: PFSoundStream;
    SampleHover,SampleClick,SampleSplash: PFSoundSample;

    //mennu buttons
    Btns: GLint;

    GAME: set of (_INTRO_,_MENU_,_CREDITS_,_OPTIONS_,_BEFOREGAME_,_GAME_,_AFTERGAME_); Edit: GLbyte=0; EditStr: String;

    Pt: TPoint; //na prevod koordinatov vramci okna na koordinaty vramci obrazovky

    //hraci
    Player: Array[0..1] of TPlayer;

    //mapa
    BrickCnt: GLint;
    Map: Array of TBrick;
    //voda - clupnutia
    Waves: Array[0..WaterRes div WaveRes] of TWater;
    Water: Array[0..WaterRes] of GLfloat;





    Form1: TForm1;
    Done_,OK_: BOOL;
    Loop: GLint;
    Resolutions: Array of TRes;
    S1,S2: String;

    MusicMenuPlay: Boolean;


procedure PlayPlay(Music: PFSoundStream);
begin
 FSOUND_Stream_Stop(MusicIntro);
 FSOUND_Stream_Stop(MusicMenu);
 FSOUND_Stream_Stop(MusicMenuLoop);
 FSOUND_Stream_Stop(MusicCredits);
 FSOUND_Stream_Stop(MusicGame);

 FSOUND_Stream_Play(FSOUND_FREE, Music);
end;

procedure MoveWater;
var C,Cm,Cp: GLint;
begin

 for C:=0 to (WaterRes div WaveRes) do begin

      Cm:=C-1; Cm:=Cm mod (WaterRes div WaveRes); if Cm<0 then Cm:=(WaterRes div WaveRes)+Cm;
      Cp:=C+1; Cp:=Cp mod (WaterRes div WaveRes);

      Waves[C].Vel:=Waves[C].Vel +

              (Waves[C].Val -
              (3*(Waves[Cm].Val + Waves[Cp].Val))/5) / 8;
 end;

 for C:=1 to (WaterRes div WaveRes)-1 do begin
  Waves[C].Vel:=Waves[C].Vel+(Waves[C].Val-(Waves[C-1].Val+Waves[C+1].Val)/4)/10;

  Waves[C].Val:=Waves[C].Val-Waves[C].Vel;
  Waves[C].Vel:=Waves[C].Vel*0.97;

  if Abs(Waves[C].Val)<0.01 then Waves[C].Vel:=0;
  if Abs(Waves[C].Vel)<0.01 then Waves[C].Vel:=0;
 end;

 for C:=0 to WaterRes-1 do begin
  Water[C]:=CosIPol( Waves[C div WaveRes].Val,Waves[C div WaveRes+1].Val,(C mod WaveRes)/WaveRes );
 end;
end;

procedure InitPlayers;
var C{,E,Mx}: GLint; Tmp: GLfloat; Done: Boolean; X1,X2: GLfloat;
begin
  Randomize;
   (*for C:=0 to BrickCnt-1 do begin
    if C>5 then Tmp:=Map[C-5].X2 else Tmp:=0;

    Map[C].X1:=Tmp+100+((C mod 2)*100)+Random(200);
    Map[C].X2:=Map[C].X1+100+Random(100);
    Map[C].Deck:=C mod 5;
    Map[C].Jump:=0=Random(10);
    Map[C].Fade:=1;
    Map[C].StartFading:=0;

    //LevelWidth:=Map[C].X2+100+Random(200);
   end;*)

   LevelWidth:=_Width_*2;

   BrickCnt:=0;
   for C:=0 to 4 do begin

    Done:=FALSE; Tmp:=0;
     while not Done do begin
      X1:=((C+1) mod 2)*100+Tmp+100+Random(200);
      X2:=X1+100+Random(100); Tmp:=X2;

      if X2<=LevelWidth then begin
      Inc(BrickCnt);
      SetLength(Map,BrickCnt);
      Map[BrickCnt-1].X1:=X1;
      Map[BrickCnt-1].X2:=X2;
      Map[BrickCnt-1].Deck:=C;
      Map[BrickCnt-1].Jump:=0=Random(10);
      Map[BrickCnt-1].Fade:=1;
      Map[BrickCnt-1].StartFading:=0;
      end else Done:=TRUE;
     end;


   end;


{ Mx:=(BrickCnt div 5)-1;
 for E:=0 to 4 do
   for C:=0 to Mx do begin
    if C>0 then Tmp:=Map[E*Mx+C-1].X2 else Tmp:=0;

    Map[E*Mx+C].X1:=Tmp+50+Random(150);
    Map[E*Mx+C].X2:=Map[E*Mx+C].X1+100+Random(100);
    Map[E*Mx+C].Deck:=E;
   end;}

 C:=0;
 While Map[C].Deck<>4 do Inc(C);
 Player[0].Pos.X:=(Map[C].X1+Map[C].X2)/2;
 Player[0].Pos.Y:=(Map[C].Deck+1)*80+150;
 Player[0].Spd.X:=0;
 Player[0].Spd.Y:=0;
 Player[0].Life:=1;
 Player[0].Left:=FALSE;
 Player[0].InWater:=0;
 Player[0].KillTime:=0;
 Player[0].Falling:=FALSE;

 C:=BrickCnt-1;
 While Map[C].Deck<>4 do Dec(C);
 Player[1].Pos.X:=(Map[C].X1+Map[C].X2)/2;
 Player[1].Pos.Y:=(Map[C].Deck+1)*80+150;
 Player[1].Spd.X:=0;
 Player[1].Spd.Y:=0;
 Player[1].Life:=1;
 Player[1].Left:=TRUE;
 Player[1].InWater:=0;
 Player[1].KillTime:=0;
 Player[1].Falling:=FALSE;

 Start:=GetTickCount;
end;

function OnGround(PlayerID: GLbyte): GLint;
var C: GLuint; Yef: GLint;
begin
 Yef:=-2;
 if Player[PlayerID].Pos.Y<=32 then Yef:=-1;

 if not Player[PlayerID].Falling then
 for C:=0 to BrickCnt-1 do begin
  if
      (Player[PlayerID].Pos.X+5>=Map[C].X1)
  and (Player[PlayerID].Pos.X-5<=Map[C].X2)
  and (Player[PlayerID].Pos.Y-32<=(Map[C].Deck+1)*80+5)
  and (Player[PlayerID].Pos.Y-32>=(Map[C].Deck+1)*80-5)
  and (Map[C].Fade>0.9)
  then begin Yef:=C; end;
 end;
 Result:=Yef;
end;

function InWater(PlayerID,HowMuch: GLbyte): BOOLEAN;
begin
 if Player[PlayerID].Pos.Y-32<WaterLevel-HowMuch then begin Result:=TRUE; if Player[PlayerID].Falling=TRUE then Player[PlayerID].Falling:=FALSE; end else Result:=FALSE;
end;

procedure MovePlayers;
var C: GLbyte; Warp: DWORD; Sp: GLfloat; Tmp: TCoord2D; OnGrnd: Array[0..1] of GLint;
begin

//nefunkcne odrazanie panakov
if SQR(Player[0].Pos.X-Player[1].Pos.X)+SQR(Player[0].Pos.Y-Player[1].Pos.Y)<SQR(32) then begin
 Tmp:=Player[0].Spd;
 Player[0].Spd:=Player[1].Spd;
 Player[1].Spd:=Tmp;

 if Player[0].Pos.Y<Player[1].Pos.Y then Player[0].Falling:=TRUE;
 if Player[1].Pos.Y<Player[0].Pos.Y then Player[1].Falling:=TRUE;

 if AreClose=0 then AreClose:=GetTickCount;
end;

//fading tehliciek
 for C:=0 to BrickCnt-1 do begin
  if Map[C].StartFading>0 then Map[C].Fade:=Cos( (GetTickCount-Map[C].StartFading)/1500*2*PI );
  if GetTickCOunt-Map[C].StartFading>1500 then begin Map[C].Fade:=1; Map[C].StartFading:=0; end;
 end;

Warp:=T-TLast; if Warp>1000 then Warp:=1;

 for C:=0 to 1 do begin


    if AreClose<>0 then begin
       if SQR(Player[0].Pos.X-Player[1].Pos.X)+SQR(Player[0].Pos.Y-Player[1].Pos.Y)>=SQR(32) then begin
        AreClose:=0; //ak su uz od seba, je to ok
       end else begin
        if (GetTickCount-AreClose)>50 then begin
          {Player[C].Pos.X:=Player[C].Pos.X+ (Player[C].Pos.X-Player[1-C].Pos.X)*4;
          Player[C].Pos.Y:=Player[C].Pos.Y+ (Player[C].Pos.Y-Player[1-C].Pos.Y)*4;}
          Player[C].Spd.X:=Player[C].Spd.X+(Player[C].Pos.X-Player[1-C].Pos.X)*0.17;
          Player[C].Spd.Y:=Player[C].Spd.Y+(Player[C].Pos.Y-Player[1-C].Pos.Y)*0.17;
        end;
       end;
     end;



  if InWater(C,12) then begin
   Sp:=50;
   if Player[C].InWater=0 then begin
    FSOUND_PlaySound(FSOUND_FREE,SampleSplash);
    Player[C].InWater:=GetTickCount;
    Player[C].LastLife:=Player[C].Life;
    Waves[ ROUND((Player[C].Pos.X/LevelWidth)*(WaterRes div WaveRes)) ].Vel:=-7;
   end;

   Player[C].Life:=Player[C].LastLife- (GetTickCount-Player[C].InWater)/Btn[1].Value; //UBERANI ZIVOTA PLAYEROVI

   if Player[C].Life<0 then Player[C].Life:=0;
  end else begin
   Sp:=20;
   if Player[C].InWater>0 then Player[C].InWater:=0;
  end;

  Player[C].Pos.X:=Player[C].Pos.X+Warp/Sp*Player[C].Spd.X;
  Player[C].Pos.Y:=Player[C].Pos.Y+Warp/Sp*Player[C].Spd.Y;

  OnGrnd[C]:=OnGround(C);

  //if OnGround(C)=FALSE then Player[C].Spd.Y:=Player[C].Spd.Y-0.2 else Player[C].Spd.Y:=-Player[C].Spd.Y*0.3;
  IF NOT InWater(C,12) THEN BEGIN
    if OnGrnd[C]=-2 then Player[C].Spd.Y:=Player[C].Spd.Y-0.2 else
     if Player[C].Spd.Y<0 then begin Player[C].Spd.Y:=0;//-Player[C].Spd.Y*0.3;

     if OnGrnd[C]=-1 then Player[C].Pos.Y:=32 else Player[C].Pos.Y:=(Map[OnGrnd[C]].Deck+1)*80+5+32;

     end;

    if OnGrnd[C]>=0 then if Map[OnGrnd[C]].Jump then begin Player[C].Spd.Y:=12; end;
  END ELSE BEGIN
    if OnGrnd[C]=-2 then Player[C].Spd.Y:=Player[C].Spd.Y-0.02 else
     if Player[C].Spd.Y<0 then Player[C].Spd.Y:=-Player[C].Spd.Y*0.1;
  END;



  if Abs(Player[C].Spd.X)>0 then Player[C].Spd.X:=Player[C].Spd.X*0.87;

  if Abs(Player[C].Spd.Y)<0.001 then Player[C].Spd.Y:=0;
  if Abs(Player[C].Spd.X)<0.001 then Player[C].Spd.X:=0;

  if Player[C].Pos.X<16 then begin Player[C].Pos.X:=16; Player[C].Spd.X:=0; end;
  if Player[C].Pos.X>LevelWidth-16 then begin Player[C].Pos.X:=LevelWidth-16; Player[C].Spd.X:=0; end;
 end;










//bacha nato ze kym su ongrnd 0 a 1 rovnake, startfading je vzdy gettickcount, cize plosina zacne miznut az ked sa znova nerovnaju



 if (OnGrnd[0]=OnGrnd[1]) and (OnGrnd[0]>=0) then Map[OnGrnd[1]].StartFading:=GetTickCount;
 TLast:=T;
end;





procedure Resize(Width,Height: GLsizei);
begin
  _W_:=Width; _H_:=Height;

  glViewPort(0,0,Width,Height);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0,_Width_,_Height_,0,-1,1);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
end;

function InitGL: BOOL;
//funkcia nastavi kopec veci
begin
//VSEOBECNE
  glShadeModel(GL_SMOOTH);                                //povoli jemne tienovanie
  glClearColor(1,1,1, 0.5); //color buffer sa bude vyplnat farbou hmly
  glPolygonMode(GL_BACK, GL_FILL);
  glPolygonMode(GL_FRONT, GL_FILL);

  glDisable(GL_LIGHTING);
  glEnable(GL_COLOR_MATERIAL);

//BLENDING
  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

//TEXTURY
  glEnable(GL_TEXTURE_2D);

//CIARKY
  glEnable(GL_LINE_SMOOTH);
  glLineWidth(2.1);

  Result:=TRUE;
end;


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///opengl draw/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

function DrawGLScene(): BOOL; {vykreslenie 3d sceny}
var _,C,Q: GLint; S,TStr1: String; Tmp: GLfloat; TT: DWORD; F: GLbyte;
begin
 TM1:=GetTickCount;
 FPS:=1/(TM1-TM2)*1000;
 TM2:=TM1;

 if T mod 1000<50 then begin
 Str(FPS:0:3,TStr1); SetWindowText(h_Wnd,PChar('FPS: '+TStr1));
 end;

//ZISTENIE CASU
  T:=GetTickCount-Start;

  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

  glLoadIdentity();

                                                    IF GAME=[_INTRO_] THEN BEGIN
////////////////////////////////////////////////////////////////////////////////
   IntroAnim(T,Tex[TID_Intro].ID,Tex[TID_Presents].ID,Tex[TID_Logo].ID,Tex[TID_Halo].ID,_Width_,_Height_);
   if T>43200 then begin
     GAME:=[_MENU_]; Start:=GetTickCount; T:=GetTickCOunt-Start;

     PlayPlay(MusicMenu); MusicMenuPlay:=TRUE;
   end;
////////////////////////////////////////////////////////////////////////////////
                                                                            END;
                                                  IF GAME=[_CREDITS_] THEN BEGIN
////////////////////////////////////////////////////////////////////////////////
   CreditsAnim(T,Tex[TID_Credits].ID,_Width_,_Height_);
////////////////////////////////////////////////////////////////////////////////
                                                                            END;
                             IF (GAME=[_MENU_]) OR (GAME=[_OPTIONS_]) THEN BEGIN
////////////////////////////////////////////////////////////////////////////////
  MenuAnim(T,Tex[TID_Cursor].ID,Tex[TID_MenuBack].ID,Tex[TID_MenuCircle].ID,Tex[TID_MenuButton].ID,Tex[TID_Halo].ID,Tex[TID_Font].ID,_Width_,_Height_,_X_,_Y_,When,Btns);

  For C:=0 to BtnCnt-1 do begin

  if (Btns>0) and (T-When>2000) then begin

  if GAME=[_MENU_] then begin
   case Btns of
    1: begin
        GAME:=[_BEFOREGAME_]; Player[0].Score:=0; Player[1].Score:=0; Start:=GetTickCount; InitPlayers; T:=0; PlayPlay(MusicGame);
       end;
    2: begin
        GAME:=[_INTRO_]; Start:=GetTickCount; PlayPlay(MusicIntro);
       end;
    3: begin
        GAME:=[_OPTIONS_]; InitButtonsOpti(_Width_,_Height_); Start:=GetTickCount-4000;
       end;
    4: begin
        GAME:=[_CREDITS_]; Start:=GetTickCount; PlayPlay(MusicCredits);
       end;
    5: begin
        Done:=True;
       end;
   end;
  end else
   case Btns of
    1: begin
        Edit:=1; Str(Btn[0].Value,EditStr);
       end;
    2: begin
        Edit:=2; Str(Btn[1].Value,EditStr);
       end;
    3: begin
        Edit:=3; Str(Btn[2].Value,EditStr);
       end;
    4: begin

       end;
    5: begin
        GAME:=[_MENU_]; InitButtonsMenu(_Width_,_Height_); Start:=GetTickCount-4000;
       end;
   end;


   Btns:=0;When:=0;
   //zabranenie bliknutiu menu (fadeout sa nevykresluje, ked je btns nula)
   glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  end;

  if Btn[C].MouseInFirst then begin
   FSOUND_PlaySound(FSOUND_FREE,SampleHover);
   Btn[C].MouseInFirst:=FALSE;
  end;

  end;


  if Edit>0 then begin
   glDisable(GL_TEXTURE_2D);

   glColor4f(0,0,0,0.81);

   glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

   glBegin(GL_QUADS);
    glVertex2f(_Width_ shr 1-300,_Height_ shr 1-120);
    glVertex2f(_Width_ shr 1+300,_Height_ shr 1-120);
    glVertex2f(_Width_ shr 1+300,_Height_ shr 1+70);
    glVertex2f(_Width_ shr 1-300,_Height_ shr 1+70);
   glEnd();

   glBlendFunc(GL_SRC_ALPHA,GL_ONE);

   glColor4f(1,1,1,1);
   WantWriteNow(Tex[TID_Font].ID);

   S:=Btn[Edit-1].Caption+':';
   Txt(S,_Width_ shr 1-Length(S)*20,_Height_ shr 1-100,40,40);
   if Btn[Edit-1].Units<>'' then begin
   S:='('+Btn[Edit-1].Units+')';
   Txt(S,_Width_ shr 1-Length(S)*20,_Height_ shr 1-60,40,40);
   end;

   glColor4f(1,0,0,1);
   S:=EditStr;
   {Str(Btn[Edit-1].Value,S);} S:=S+' ';
   Txt(S,_Width_ shr 1-Length(S)*25,_Height_ shr 1,50,50);

   glColor4f(1,0,0,1-Cos((T mod 1000)/1000*2*PI));
   TStr1:=S; S:='';
   For C:=1 to Length(TStr1)-1 do S:=S+' '; S:=S+'*';
   Txt(S,_Width_ shr 1-Length(S)*25,_Height_ shr 1,50,50);


  end;


////////////////////////////////////////////////////////////////////////////////
                                                                            END;
                                               IF GAME=[_BEFOREGAME_] THEN BEGIN
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
glEnable(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D,Tex[TID_BackBegin].ID);
glColor4f(1,1,1,1);
glBegin(GL_QUADS);
 glTexCoord2f(0,0);glVertex2f(0,0);
 glTexCoord2f(1,0);glVertex2f(_Width_,0);
 glTexCoord2f(1,1);glVertex2f(_Width_,_Height_);
 glTexCoord2f(0,1);glVertex2f(0,_Height_);
glEnd();

glDisable(GL_TEXTURE_2D); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
if T<1000 then glColor4f(0,0,0,1-T/1000) else if T>3000 then glColor4f(0,0,0,(T-3000)/1000) else glColor4f(0,0,0,0);
glBegin(GL_QUADS);
 glVertex2f(0,0);
 glVertex2f(_Width_,0);
 glVertex2f(_Width_,_Height_);
 glVertex2f(0,_Height_);
glEnd();


if T>4000 then begin GAME:=[_GAME_]; Start:=GetTickCount; end;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                            END;
                                               IF GAME=[_AFTERGAME_] THEN BEGIN
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
glEnable(GL_TEXTURE_2D);

if Player[0].Score>Player[1].Score then glBindTexture(GL_TEXTURE_2D,Tex[TID_BackEnd0].ID) else
if Player[0].Score<Player[1].Score then glBindTexture(GL_TEXTURE_2D,Tex[TID_BackEnd1].ID) else glBindTexture(GL_TEXTURE_2D,Tex[TID_BackBegin].ID);

glColor4f(1,1,1,1);
glBegin(GL_QUADS);
 glTexCoord2f(0,0);glVertex2f(0,0);
 glTexCoord2f(1,0);glVertex2f(_Width_,0);
 glTexCoord2f(1,1);glVertex2f(_Width_,_Height_);
 glTexCoord2f(0,1);glVertex2f(0,_Height_);
glEnd();

glDisable(GL_TEXTURE_2D); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
if T<1000 then glColor4f(0,0,0,1-T/1000) else if T>4000 then glColor4f(0,0,0,(T-4000)/1000) else glColor4f(0,0,0,0);
glBegin(GL_QUADS);
 glVertex2f(0,0);
 glVertex2f(_Width_,0);
 glVertex2f(_Width_,_Height_);
 glVertex2f(0,_Height_);
glEnd();


if T>5000 then begin GAME:=[_MENU_]; InitButtonsMenu(_Width_,_Height_); Start:=GetTickCount-4000; PlayPlay(MusicMenuLoop); end;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                            END;
                                                     IF GAME=[_GAME_] THEN BEGIN
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FOR _:=0 TO 1 DO BEGIN

if _=0 then begin
 glViewPort(0,0,_W_ div 2,_H_);
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 gluOrtho2D(0, _Width_ div 2, _Height_, 0);
end else begin
 glViewPort(_W_ div 2,0,_W_ div 2,_H_);
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 gluOrtho2D(0, _Width_ div 2, _Height_, 0);
end;
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();






 glTranslatef(-Player[_].Pos.X+_Width_/4,Player[_].Pos.Y-_Height_/2,0);



 glEnable(GL_BLEND);glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
 glEnable(GL_TEXTURE_2D);

 {glEnable(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D,Tex[TID_MenuBack].ID);
 glBegin(GL_QUADS);
  glColor4f(1,1,1,1);
  glTexCoord2f(0,0);glVertex2f(0,-100);
  glTexCoord2f(1,0);glVertex2f(LevelWidth,-100);
  glTexCoord2f(1,1);glVertex2f(LevelWidth,_Height_);
  glTexCoord2f(0,1);glVertex2f(0,_Height_);
 glEnd();}

 glPushMatrix(); glLoadIdentity();
 glTranslatef(0,Player[_].Pos.Y-_Height_/2,0);

 glBindTexture(GL_TEXTURE_2D,Tex[TID_ScrollBack].ID);
 glBegin(GL_QUADS);
  glColor4f(1,1,1,1);
  glTexCoord2f(0+(Player[_].Pos.X/_Width_/2),     0+(Player[_].Pos.Y/_Height_/2));glVertex2f(0,            -100);
  glTexCoord2f(0.5+(Player[_].Pos.X/_Width_/2),   0+(Player[_].Pos.Y/_Height_/2));glVertex2f(_Width_ div 2,-100);
  glTexCoord2f(0.5+(Player[_].Pos.X/_Width_/2),   1+(Player[_].Pos.Y/_Height_/2));glVertex2f(_Width_ div 2,_Height_);
  glTexCoord2f(0+(Player[_].Pos.X/_Width_/2),     1+(Player[_].Pos.Y/_Height_/2));glVertex2f(0,            _Height_);
 glEnd();


 glBindTexture(GL_TEXTURE_2D,Tex[TID_StillBack].ID);
 glBegin(GL_QUADS);
  glColor4f(1,1,1,1);
  glTexCoord2f(0+(Player[_].Pos.X/_Width_),     0);glVertex2f(0,            -100);
  glTexCoord2f(0.5+(Player[_].Pos.X/_Width_),   0);glVertex2f(_Width_ div 2,-100);
  glTexCoord2f(0.5+(Player[_].Pos.X/_Width_),   1);glVertex2f(_Width_ div 2,_Height_);
  glTexCoord2f(0+(Player[_].Pos.X/_Width_),     1);glVertex2f(0,            _Height_);
 glEnd();

 glPopMatrix();

 glBindTexture(GL_TEXTURE_2D,Tex[TID_MenuBack].ID);
 glBegin(GL_QUADS);
glColor4f(1,1,1,0);
  glTexCoord2f(0,0);glVertex2f(-300,-100);
glColor4f(1,1,1,1);
  glTexCoord2f(1,0);glVertex2f(0,-100);
glColor4f(1,1,1,1);
  glTexCoord2f(1,1);glVertex2f(0,_Height_);
glColor4f(1,1,1,0);
  glTexCoord2f(0,1);glVertex2f(-300,_Height_);


glColor4f(1,1,1,1);
  glTexCoord2f(0,0);glVertex2f(LevelWidth,-100);
glColor4f(1,1,1,0);
  glTexCoord2f(1,0);glVertex2f(LevelWidth+300,-100);
glColor4f(1,1,1,0);
  glTexCoord2f(1,1);glVertex2f(LevelWidth+300,_Height_);
glColor4f(1,1,1,1);
  glTexCoord2f(0,1);glVertex2f(LevelWidth,_Height_);
 glEnd();



//VECI PRED POZADIM



 //glDisable(GL_TEXTURE_2D);

 glBindTexture(GL_TEXTURE_2D,Tex[TID_Pane].ID);

  glBegin(GL_QUADS);
FOR C:=0 TO BRICKCNT-1 DO BEGIN
  //glColor4f(0.4,0.5,0.8,1);
  if Map[C].Jump=FALSE then glColor4f(1,1,1,Map[C].Fade) else glColor4f(1,Cos((T mod 2000)/2000*2*PI),Cos((T mod 2000)/2000*2*PI),Map[C].Fade);

  glTexCoord2f(0  ,0);glVertex2f(Map[C].X1,_Height_-(Map[C].Deck+1)*80-5);
  glTexCoord2f(0.5,0);glVertex2f(Map[C].X1+5,_Height_-(Map[C].Deck+1)*80-5);
  glTexCoord2f(0.5,1);glVertex2f(Map[C].X1+5,_Height_-(Map[C].Deck+1)*80+5);
  glTexCoord2f(0  ,1);glVertex2f(Map[C].X1,_Height_-(Map[C].Deck+1)*80+5);

  glTexCoord2f(0.5,0);glVertex2f(Map[C].X1+5,_Height_-(Map[C].Deck+1)*80-5);
  glTexCoord2f(1  ,0);glVertex2f(Map[C].X2-5,_Height_-(Map[C].Deck+1)*80-5);
  glTexCoord2f(1  ,1);glVertex2f(Map[C].X2-5,_Height_-(Map[C].Deck+1)*80+5);
  glTexCoord2f(0.5,1);glVertex2f(Map[C].X1+5,_Height_-(Map[C].Deck+1)*80+5);

  glTexCoord2f(0.5,0);glVertex2f(Map[C].X2-5,_Height_-(Map[C].Deck+1)*80-5);
  glTexCoord2f(0  ,0);glVertex2f(Map[C].X2,_Height_-(Map[C].Deck+1)*80-5);
  glTexCoord2f(0  ,1);glVertex2f(Map[C].X2,_Height_-(Map[C].Deck+1)*80+5);
  glTexCoord2f(0.5,1);glVertex2f(Map[C].X2-5,_Height_-(Map[C].Deck+1)*80+5);
END;
 glEnd();

//nakreslenie hracov
 glEnable(GL_TEXTURE_2D);

FOR C:=0 TO 1 DO BEGIN
 if C=0 then glBindTexture(GL_TEXTURE_2D,Tex[TID_Player0].ID) else glBindTexture(GL_TEXTURE_2D,Tex[TID_Player1].ID);
 glBegin(GL_QUADS);
 glColor4f(1,1,1,1);
 if OnGround(C)=-2 then F:=3 else begin

   if Abs(Player[C].Spd.X)<0.3 then F:=0 else begin
    Q:=T mod 400;
    {if (Q>=000) and (Q<100) then} F:=0;
    if (Q>=100) and (Q<200) then F:=1;
    if (Q>=200) and (Q<300) then F:=0;
    if (Q>=300) and (Q<400) then F:=2;
   end;

 end;

  if Player[C].Left=FALSE then begin
   glTexCoord2f(0.00+F*0.25,0);glVertex2f(Player[C].Pos.X-16,_Height_-Player[C].Pos.Y-32);
   glTexCoord2f(0.25+F*0.25,0);glVertex2f(Player[C].Pos.X+16,_Height_-Player[C].Pos.Y-32);
   glTexCoord2f(0.25+F*0.25,1);glVertex2f(Player[C].Pos.X+16,_Height_-Player[C].Pos.Y+32);
   glTexCoord2f(0.00+F*0.25,1);glVertex2f(Player[C].Pos.X-16,_Height_-Player[C].Pos.Y+32);
  end else begin
   glTexCoord2f(0.25+F*0.25,0);glVertex2f(Player[C].Pos.X-16,_Height_-Player[C].Pos.Y-32);
   glTexCoord2f(0.00+F*0.25,0);glVertex2f(Player[C].Pos.X+16,_Height_-Player[C].Pos.Y-32);
   glTexCoord2f(0.00+F*0.25,1);glVertex2f(Player[C].Pos.X+16,_Height_-Player[C].Pos.Y+32);
   glTexCoord2f(0.25+F*0.25,1);glVertex2f(Player[C].Pos.X-16,_Height_-Player[C].Pos.Y+32);
  end;
 glEnd();
END;

//nakreslenie sipiek nad playermi

 glPushMatrix();

 glTranslatef(+Player[_].Pos.X,_Height_-Player[_].Pos.Y-75,0);

  Tmp:=(Player[_].Pos.X-Player[1-_].Pos.X);
  if (Tmp)=0 then Tmp:=1;//zabranime deleniu nulou
  if (Tmp)<0 then glRotatef(180,0,0,1);
  glRotatef(-ArcTan((Player[_].Pos.Y-Player[1-_].Pos.Y)/Tmp)/2/PI*360+270,0,0,1);


 glBindTexture(GL_TEXTURE_2D,Tex[TID_Arrow].ID);
 glBegin(GL_QUADS);
 glColor4f(0.5,0,0,0.6);
   glTexCoord2f(0,0);glVertex2f(-20,-20);
   glTexCoord2f(1,0);glVertex2f(+20,-20);
   glTexCoord2f(1,1);glVertex2f(+20,+20);
   glTexCoord2f(0,1);glVertex2f(-20,+20);
 glEnd();

 glPopMatrix();

 MoveWater;

 glDisable(GL_TEXTURE_2D);
 glBegin(GL_QUADS);
for C:=0 to WaterRes-1 do begin
glColor4f(0.5,0.6,0.8,0.5);
  glVertex2f((C+0)/WaterRes*LevelWidth, _Height_-WaterLevel  -  Sin(2*PI*(T mod 1800)/1800 + (C+0)/WaterRes*2*PI*5)*3 + Cos(-2*PI*(T mod 1000)/1000 + (C+0)/WaterRes*2*PI*12)*2 +Water[C+0]*2.7);
  glVertex2f((C+1)/WaterRes*LevelWidth, _Height_-WaterLevel  -  Sin(2*PI*(T mod 1800)/1800 + (C+1)/WaterRes*2*PI*5)*3 + Cos(-2*PI*(T mod 1000)/1000 + (C+1)/WaterRes*2*PI*12)*2 +Water[C+1]*2.7);
glColor4f(0.125,0.15,0.2,0.9);
  glVertex2f((C+1)/WaterRes*LevelWidth, _Height_);
  glVertex2f((C+0)/WaterRes*LevelWidth, _Height_);
end;
glEnd();

glLineWidth(3);
glBegin(GL_LINE_STRIP);
glColor4f(0.55,0.66,0.88,0.5);
for C:=0 to WaterRes do begin
  glVertex2f((C+0)/WaterRes*LevelWidth, _Height_-WaterLevel  -  Sin(2*PI*(T mod 1800)/1800 + (C+0)/WaterRes*2*PI*5)*3 + Cos(-2*PI*(T mod 1000)/1000 + (C+0)/WaterRes*2*PI*12)*2 +Water[C+0]*2.7  );
end;
glEnd();


 glLoadIdentity();

 glDisable(GL_TEXTURE_2D);
 glBegin(GL_QUADS);
if _=0 then begin
  glColor4f(1,1,1,0);glVertex2f(_Width_/2-5,0);
  glColor4f(1,1,1,1);glVertex2f(_Width_/2  ,0);
  glColor4f(1,1,1,1);glVertex2f(_Width_/2  ,_Height_);
  glColor4f(1,1,1,0);glVertex2f(_Width_/2-5,_Height_);
end else begin
  glColor4f(1,1,1,1);glVertex2f(0,0);
  glColor4f(1,1,1,0);glVertex2f(5,0);
  glColor4f(1,1,1,0);glVertex2f(5,_Height_);
  glColor4f(1,1,1,1);glVertex2f(0,_Height_);
end;

 glColor4f(0.7,0,0,0.22);
 glVertex2f(50,10);
 glVertex2f(_Width_/2-50,10);
 glVertex2f(_Width_/2-50,20);
 glVertex2f(50,20);

 glColor4f(0.7,0,0,0.92);
 glVertex2f(50,10);
 glVertex2f(50+(_Width_/2-100)*Player[_].Life,10);
 glVertex2f(50+(_Width_/2-100)*Player[_].Life,20);
 glVertex2f(50,20);

 glEnd();


 if Player[_].KillTime>0 then begin
  glDisable(GL_TEXTURE_2D);glColor4f(0.67,0,0,(GetTickCount-Player[_].KillTime)/1000);
  glBegin(GL_QUADS);
   glVertex2f(0,0);
   glVertex2f(_Width_ div 2,0);
   glVertex2f(_Width_ div 2,_Height_);
   glVertex2f(0,_Height_);
  glEnd();
 end;

END;

 glViewPort(0,0,_W_,_H_);
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 gluOrtho2D(0, _Width_, _Height_, 0);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();

 glDisable(GL_TEXTURE_2D);
 glColor4f(0,0,0,0.7);
 glBegin(GL_QUADS);
  {glVertex2f(_Width_ div 2-140,_Height_-40);
  glVertex2f(_Width_ div 2+140,_Height_-40);
  glVertex2f(_Width_ div 2+140,_Height_);
  glVertex2f(_Width_ div 2-140,_Height_);}
  glVertex2f(0,_Height_-40);
  glVertex2f(_Width_,_Height_-40);
  glVertex2f(_Width_,_Height_);
  glVertex2f(0,_Height_);
 glEnd();

 WantWriteNow(Tex[TID_Font].ID);

 if T>=2000 then begin TT:=T-2000; S:=''; glColor4f(1,1,1,1); end else begin TT:=2000-T; S:='-'; glColor4f(1,0,0,1);end;

 Str(TT div 1000 div 60,TStr1);S:=S+TStr1;
 Str(TT div 1000 mod 60:2,TStr1);S:=S+':'+TStr1;
 Str(TT div 100 mod 10,TStr1);S:=S+'.'+TStr1;

 Txt(S,_Width_ div 2-Length(S)*15,_Height_-32,30,30);

 glColor4f(1,1,1,1);
 Str(Player[0].Score{OnGround(0)},S);
 Txt(S,20,_Height_-32,30,30);
 Str(Player[1].Score{OnGround(1)},S);
 Txt(S,_Width_-Length(S)*30-20,_Height_-32,30,30);


 if T<2000 then begin
 glDisable(GL_TEXTURE_2D);
 if T<1000 then glColor4f(0,0,0,0.5) else glColor4f(0,0,0,(1-(T-1000)/1000)*0.5);
 glBegin(GL_QUADS);
  glVertex2f(_Width_ div 2-330,_Height_ div 2-100);
  glVertex2f(_Width_ div 2+330,_Height_ div 2-100);
  glVertex2f(_Width_ div 2+330,_Height_ div 2+100);
  glVertex2f(_Width_ div 2-330,_Height_ div 2+100);
 glEnd();

 WantWriteNow(Tex[TID_Font].ID);
 if T<1000 then glColor4f(1,0,0,1) else glColor4f(1,0,0,1-(T-1000)/1000);
 Txt('Get Ready!',_Width_ div 2-10*30,_Height_ div 2-30,60,60);
 end;

 WaterLevel:=T/(Btn[0].Value*1000)*80*5;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                            END;

if ((GAME=[_MENU_]) or (GAME=[_OPTIONS_])) and (MusicMenuPlay) then
 if (FSOUND_Stream_GetTime(MusicMenu)>61800) then begin
  PlayPlay(MusicMenuLoop); MusicMenuPlay:=FALSE;
 end;

if VSync then begin
//TOTO BY PODLA VSETKEHO MALO SPRAVIT VSYNC
  glFlush();glFinish();
end;

//AK SA FUNKCIA DOSTALA AZ SEM, VSETKO JE OK
  Result:=TRUE;
end;





///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///winapi stuff////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

function WndProc(hWnd: HWND; Message: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
//funkcia odbavuje message
var C: GLint;
begin
  IF Message=WM_SYSCOMMAND THEN BEGIN
    case wParam of SC_SCREENSAVE,SC_MONITORPOWER:
        begin Result:=0; Exit; end; //odpali setric obrazovky a usporny rezim
    end;
  END;

  CASE Message OF
//zmena aktivity okna
    WM_ACTIVATE:   begin
                      if (Hiword(wParam)=0) then Active:=TRUE else Active:=FALSE; Result:=0; //cekne ci nieje okno minimalizovane
                    end;
//ukoncenie programu
    WM_CLOSE:       begin
                      PostQuitMessage(0); Result:=0;
                    end;
//stlacenie klavesy
    WM_KEYDOWN:     begin
                      Keys[wParam]:=TRUE;
                      if ((GAME=[_MENU_]) or (GAME=[_OPTIONS_])) and (T<10000) then begin Keys[wParam]:=FALSE; Start:=Start-10000; end;
                      if GAME=[_INTRO_] then begin Keys[wParam]:=FALSE; GAME:=[_MENU_]; Start:=GetTickCount; PlayPlay(MusicMenu); MusicMenuPlay:=TRUE; end;
                      if GAME=[_CREDITS_] then begin Keys[wParam]:=FALSE; GAME:=[_MENU_]; Start:=GetTickCount-10000; PlayPlay(MusicMenuLoop); end;
                      Result:=0;
                    end;
//pustenie klavesy
    WM_KEYUP:      begin
                      Keys[wParam]:=FALSE; Result:=0;
                    end;
//zmena velkosti
    WM_SIZE:        begin
                      Resize(LOWORD(lParam),HIWORD(lParam)); Result:=0;
                    end;
//mys
    WM_MOUSEMOVE:   begin
                      _X_:=ROUND(LOWORD(lParam)/_W_*_Width_);
                      _Y_:=ROUND(HIWORD(lParam)/_H_*_Height_);
                      Result:=0;
                    end;
    WM_LBUTTONDOWN: begin
                      _B_:=TRUE;

                      if (GAME=[_MENU_]) or (GAME=[_OPTIONS_]) then
                      for C:=0 to BtnCnt-1 do begin
                        if (Btn[C].MouseIn) and (Btn[C].Shape<>[BT_INVISIBLE]) then begin
                         FSOUND_PlaySound(FSOUND_FREE,SampleClick);
                         Btns:=1+C; When:=T;
                         Break;
                        end;
                      end;
                       Result:=0;
                    end;
    WM_LBUTTONUP:   begin
                      _B_:=FALSE;  Result:=0;
                    end
//ostatne spravy idu systemu
    else            begin
                      Result:=DefWindowProc(hWnd, Message, wParam, lParam);
                    end;
  END;
end;


procedure KillGLWindow;
//procedura zabija gl okno
begin
  if FullScreen then begin
      ChangeDisplaySettings(devmode(nil^),0); //prepnutie do systemu
      ShowCursor(TRUE);
  end;

  if h_Rc<>0 then begin
    if (not wglMakeCurrent(h_Dc,0)) then MessageBox(0,'Release of DC and RC failed.','Error',MB_OK or MB_ICONERROR);
    if (not wglDeleteContext(h_Rc)) then begin
      MessageBox(0,'Could not relase RC.','Error',MB_OK or MB_ICONERROR);
      h_Rc:=0;
    end;
  end;

  if (h_Dc=1) and (ReleaseDC(h_Wnd,h_Dc)<>0) then begin
    MessageBox(0,'Could not relase DC.','Error',MB_OK or MB_ICONERROR);
    h_Dc:=0;
  end;

  if (h_Wnd<>0) and (not DestroyWindow(h_Wnd)) then begin
    MessageBox(0,'Could not release hWnd.','Error',MB_OK or MB_ICONERROR);
    h_Wnd:=0;
  end;

  if (not UnregisterClass('OpenGL',hInstance)) then begin
    MessageBox(0,'Could not unregister class.','Error',MB_OK or MB_ICONERROR);
  end;
end;


function CreateGlWindow(Title: Pchar; Width,Height,BPP: Integer; FullScreenFlag: BOOL): BOOL stdcall;
//funkcia porodi gl okno
var Pixelformat: GLuint;
    WC: TWndClass;
    dwExStyle: DWord;
    dwStyle: DWord;
    PFD: PixelFormatDescriptor;
    dmScreenSettings: Devmode;
    h_Instance: HInst;
    WindowRect: TRect;
begin
  WindowRect.Left:=0;
  WindowRect.Top:=0;
  WindowRect.Right:=width;
  WindowRect.Bottom:=height;

  h_Instance:=GetModuleHandle(nil); //ulozime si instance okna
  FullScreen:=FullScreenFlag;

  with WC do begin
    Style:=CS_HREDRAW or CS_VREDRAW or CS_OWNDC;    //okno sa prekresli pri zmene velkosti a dc
    lpfnWndProc:=@WndProc;                          //definicia hlavnej procedury okna
    cbClsExtra:=0;                                  //bez extra dat
    cbWndExtra:=0;
    hInstance:=h_Instance;                          //instance
    hIcon:=LoadIcon(0,IDI_WINLOGO);                 //ikona
    hCursor:=LoadCursor(0,IDC_ARROW);               //kurzor mysi
    hbrBackground:=0;                               //bez pozadia
    lpszMenuName:=nil;                              //bez menu
    lpszClassName:='OpenGl';                        //meno triedy okna
  end;

  if  RegisterClass(WC)=0 then begin
    MessageBox(0,'Could not register the window class.','Error',MB_OK or MB_ICONERROR);
    Result:=FALSE;
    Exit;
  end;

  if FullScreen then begin
    ZeroMemory(@dmScreenSettings,SizeOf(dmScreenSettings));
      with dmScreenSettings do begin
        dmSize:=SizeOf(dmScreenSettings);
        dmPelsWidth:=Width; //vyska
	      dmPelsHeight:=Height; //sirka
        dmBitsPerPel:=BPP; //bitova hlbka
        dmFields:=DM_BITSPERPEL or DM_PELSWIDTH or DM_PELSHEIGHT;
      end;

      if (ChangeDisplaySettings(dmScreenSettings, CDS_FULLSCREEN))<>DISP_CHANGE_SUCCESSFUL then Begin
        if MessageBox(0,'This fullscreen mode is not supported. Do you want me to use windowed mode instead?',
                      AppTitle,MB_YESNO or MB_ICONEXCLAMATION)=IDYES then FullScreen:=FALSE
        else begin
          MessageBox(0,'Nothing lasts, but nothing is lost.',AppTitle,MB_OK or MB_ICONERROR);
          Result:=FALSE; Exit;
        end;
      end;
  end;

  if FullScreen then begin
    dwExStyle:=WS_EX_APPWINDOW;
    dwStyle:=WS_POPUP or WS_CLIPSIBLINGS or WS_CLIPCHILDREN;
    ShowCursor(FALSE);
  end else begin
    dwExStyle:=WS_EX_APPWINDOW or WS_EX_WINDOWEDGE;
    dwStyle:=WS_OVERLAPPEDWINDOW or WS_CLIPSIBLINGS or WS_CLIPCHILDREN;
    ShowCursor(FALSE);
  end;

  AdjustWindowRectEx(WindowRect,dwStyle,FALSE,dwExStyle); //prisposobenie velkosti okna

  H_wnd:=CreateWindowEx(dwExStyle,                    //rozsireny styl
                               'OpenGl',              //meno triedy
                               Title,                 //titulok
                               dwStyle,               //styl okna
                               0,0,                   //pozicia okna
                               WindowRect.Right-WindowRect.Left, //sirka
                               WindowRect.Bottom-WindowRect.Top, //vyska
                               0,                     //bez rodicovskeho okna
                               0,                     //bez menu
                               hinstance,             //instance
                               nil);                  //do WM_CREATE nejde nic

  if h_Wnd=0 then begin
    KillGlWindow();
    MessageBox(0,'Okno sa nemohlo narodiť :(',AppTitle,MB_OK or MB_ICONEXCLAMATION);
    Result:=FALSE;
    Exit;
  end;

  with PFD do begin                          //pixelformat
    nSize:=SizeOf(PIXELFORMATDESCRIPTOR);
    nVersion:=1;                             //verzia
    dwFlags:=PFD_DRAW_TO_WINDOW              //podpora okna
             or PFD_SUPPORT_OPENGL           //podpora opengl
             or PFD_DOUBLEBUFFER;            //podpora doublebufferingu
    iPixelType:=PFD_TYPE_RGBA;               //format rgba
    cColorBits:=BPP;                         //farebna hlbka
    cRedBits:=0;                             //ignorovat bity farieb
    cRedShift:=0;
    cGreenBits:=0;
    cBlueBits:=0;
    cBlueShift:=0;
    cAlphaBits:=0;                           //bez alpha buffera
    cAlphaShift:=0;                          //ignorovat shift bit
    cAccumBits:=0;                           //bez akumulacneho buffera
    cAccumRedBits:=0;                        //ignorovat akumulacne bity
    cAccumGreenBits:=0;
    cAccumBlueBits:=0;
    cAccumAlphaBits:=0;
    cDepthBits:=16;                          //16 bitovy z-buffer
    cStencilBits:=0;                         //bez stencil buffera
    cAuxBuffers:=0;                          //bez auxiliary buffera
    iLayerType:=PFD_MAIN_PLANE;              //hlavna vykreslovacia vrstva
    bReserved:=0;                            //rezervovane
    dwLayerMask:=0;                          //ignorovat masku vrstvy
    dwVisibleMask:=0;
    dwDamageMask:=0;
  end;

  h_Dc:=GetDC(h_Wnd); //pripoji device context
  if h_Dc=0 then begin
    KillGLWindow();
    MessageBox(0,'Cant''t create a GL device context :( Have a nice day.',AppTitle,MB_OK or MB_ICONEXCLAMATION);
    Result:=FALSE;
    Exit;
  end;

  PixelFormat:=ChoosePixelFormat(h_Dc, @PFD);
  if (PixelFormat=0) then begin
    KillGLWindow();
    MessageBox(0,'Cant''t find a suitable PixelFormat :( Have a nice day.',AppTitle,MB_OK or MB_ICONEXCLAMATION);
    Result:=False;
    Exit;
  end;
  if (not SetPixelFormat(h_Dc,PixelFormat,@PFD)) then begin
    KillGLWindow();
    MessageBox(0,'Cant''t set PixelFormat :( Have a nice day.',AppTitle,MB_OK or MB_ICONEXCLAMATION);
    Result:=FALSE;
    Exit;
  end;

  h_Rc:=wglCreateContext(h_Dc);
  if (h_Rc=0) then begin
    KillGLWindow();
    MessageBox(0,'Cant''t create a GL rendering context :( Have a nice day.',AppTitle,MB_OK or MB_ICONEXCLAMATION);
    Result:=FALSE;
    Exit;
  end;
  if (not wglMakeCurrent(h_Dc,h_Rc)) then begin
    KillGLWindow();
    MessageBox(0,'Cant''t activate the GL rendering context :( Have a nice day.',AppTitle,MB_OK or MB_ICONEXCLAMATION);
    Result:=FALSE;
    Exit;
  end;

  ShowWindow(h_Wnd,SW_SHOW); //zobrazi okno
  SetForegroundWindow(h_Wnd); //okno do popredia
  SetFocus(h_Wnd); //fokus na okno
  Resize(Width,Height); //nastavi novu velkost gl scene
    if (not InitGl()) then begin //inicializacia opengl
      KillGLWindow();
      MessageBox(0,'Inicializácia sa nezdarila :(',AppTitle,MB_OK or MB_ICONEXCLAMATION);
      Result:=FALSE;
      Exit;
    end;

  Result:=TRUE;
end;

procedure DrawLogo(Kolko,Zkolko: GLint; Show: Boolean);
begin
    glDisable(GL_BLEND);
    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
    glEnable(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D,Tex[TID_Loading].ID);glColor4f(1,1,1,1);
    glBegin(GL_QUADS);
     glTexCoord2f(0,0);glVertex2i(_Width_ shr 1-360,_Height_ shr 1-90);
     glTexCoord2f(1,0);glVertex2i(_Width_ shr 1+360,_Height_ shr 1-90);
     glTexCoord2f(1,1);glVertex2i(_Width_ shr 1+360,_Height_ shr 1+90);
     glTexCoord2f(0,1);glVertex2i(_Width_ shr 1-360,_Height_ shr 1+90);
    glEnd();
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE);
    glDisable(GL_TEXTURE_2D);

    glColor4f(1,0.3,0,0.5);

    glBegin(GL_QUADS);
     glVertex2f(_Width_ shr 1-360                   ,_Height_ shr 1-90);
     glVertex2f(_Width_ shr 1-360+720/Zkolko*Kolko  ,_Height_ shr 1-90);
     glVertex2f(_Width_ shr 1-360+720/Zkolko*Kolko  ,_Height_ shr 1+90);
     glVertex2f(_Width_ shr 1-360                   ,_Height_ shr 1+90);


    glColor4f(1,0.3,0,0.5);
     glVertex2f(_Width_ shr 1-360+720/Zkolko*Kolko   ,_Height_ shr 1-90);
    glColor4f(1,0.3,0,0.0);
     glVertex2f(_Width_ shr 1-360+720/Zkolko*Kolko+18,_Height_ shr 1-90);
    glColor4f(1,0.3,0,0.0);
     glVertex2f(_Width_ shr 1-360+720/Zkolko*Kolko+18,_Height_ shr 1+90);
    glColor4f(1,0.3,0,0.5);
     glVertex2f(_Width_ shr 1-360+720/Zkolko*Kolko   ,_Height_ shr 1+90);

    glEnd();

    if Show then SwapBuffers(h_Dc);
end;

function WinMain(hInstance: HINST; hPrevInstance: HINST; lpCmdLine: PChar; nCmdShow: Integer): integer; stdcall;
var Msg: TMsg; //spravy
    C{,I}: GLint;
begin
  Done:=FALSE;

  //FMOD INIT
  if FMOD_VERSION > FSOUND_GetVersion then begin
    MessageBox(0,'FMOD error: wrong dll version',AppTitle,MB_OK or MB_ICONERROR);
    Result:=1; Exit;
  end;

  if not FSOUND_Init(44100, 32, 0) then begin
    MessageBox(0,PChar('Error initializing FMOD: '+FMOD_ErrorString(FSOUND_GetError())),AppTitle,MB_OK or MB_ICONERROR);
    FSOUND_Close();
    Result:=1; Exit;
  end;

//CREATE WINDOW
  {_W_:=800;
  _H_:=600;}

  _Width_:=800;
  _Height_:=600;

  {I:=MessageBox(0,'Fullscreen?',AppTitle,
                MB_YESNOCANCEL or MB_ICONQUESTION);

  if I=IDNO     then FullScreen:=FALSE;
  if I=IDYES    then FullScreen:=TRUE;
  if I=IDCANCEL then begin Result:=0; Exit; end;}

  if not CreateGLWindow(AppTitle,_W_,_H_,_B__,FullScreen) then begin
   Result:=0; Exit;
  end;

  SetCursorPos(_W_ shr 1,90);_X_:=ROUND((_W_ shr 1)/_W_*_Width_);_Y_:=ROUND(90/_H_*_Height_);


  ViewOrtho(_Width_,_Height_);

  //nacitanie textur
  glEnable(GL_BLEND);
    LoadTextureFromResources         (02,     Tex[TID_Loading],TRUE);        DrawLogo(01,18,TRUE);
    LoadTextureAlphaFromResources    (03,-1,  Tex[TID_Cursor],TRUE);         DrawLogo(02,18,TRUE);
    LoadTextureAlphaFromResources    (04,-1,  Tex[TID_Font],TRUE);           DrawLogo(03,18,TRUE);
    LoadTextureFromResources         (05,     Tex[TID_MenuBack],TRUE);       DrawLogo(04,18,TRUE);
    LoadTextureAlphaFromResources    (06,-1,  Tex[TID_MenuButton],TRUE);     DrawLogo(05,18,TRUE);
    LoadTextureAlphaFromResources    (07,-1,  Tex[TID_MenuCircle],TRUE);     DrawLogo(06,18,TRUE);
    LoadTextureAlphaFromResources    (08,09,  Tex[TID_Intro],TRUE);          DrawLogo(07,18,TRUE);
    LoadTextureAlphaFromResources    (10,-1,  Tex[TID_Credits],TRUE);        DrawLogo(08,18,TRUE);
    LoadTextureAlphaFromResources    (11,12,  Tex[TID_Player0],TRUE);        DrawLogo(09,18,TRUE);
    LoadTextureAlphaFromResources    (20,12,  Tex[TID_Player1],TRUE);        DrawLogo(10,18,TRUE);
    LoadTextureAlphaFromResources    (13,14,  Tex[TID_Pane],TRUE);           DrawLogo(11,18,TRUE);
    LoadTextureAlphaFromResources    (15,-1,  Tex[TID_Arrow],TRUE);          DrawLogo(12,18,TRUE);
    LoadTextureFromResources         (16,     Tex[TID_Logo],TRUE);           DrawLogo(13,18,TRUE);
    LoadTextureAlphaFromResources    (17,18,  Tex[TID_StillBack],FALSE);     DrawLogo(14,18,TRUE);
    LoadTextureFromResources         (19,     Tex[TID_ScrollBack],FALSE);    DrawLogo(15,18,TRUE);
    LoadTextureFromResources         (21,     Tex[TID_BackBegin],FALSE);     DrawLogo(16,18,TRUE);
    LoadTextureFromResources         (22,     Tex[TID_BackEnd0],FALSE);      DrawLogo(17,18,TRUE);
    LoadTextureFromResources         (23,     Tex[TID_BackEnd1],FALSE);      DrawLogo(18,18,TRUE);
    LoadTextureAlphaFromResources    (24,-1,  Tex[TID_Presents],TRUE);


  Tex[TID_Halo].Width:=64; Tex[TID_Halo].Height:=64; Tex[TID_Halo].BPP:=4; SetLength(Tex[TID_Halo].Data,Tex[TID_Halo].Width*Tex[TID_Halo].Height*Tex[TID_Halo].BPP);
  GenHalo(Tex[TID_Halo],FALSE);
  CreateTextureAlpha(Tex[TID_Halo],TRUE);

  InitButtonsOpti(_Width_,_Height_);
  InitButtonsMenu(_Width_,_Height_); Btns:=0;

  SampleHover:=FSOUND_Sample_Load(0,'hover.mp3',0,0,0);
  SampleClick:=FSOUND_Sample_Load(1,'click.mp3',0,0,0);
  SampleSplash:=FSOUND_Sample_Load(2,'splash.mp3',0,0,0);

  MusicIntro:=FSOUND_Stream_Open('intro.mp3', FSOUND_NORMAL or FSOUND_LOOP_OFF, 0, 0);
  MusicMenu:=FSOUND_Stream_Open('menu.mp3', FSOUND_NORMAL or FSOUND_LOOP_OFF, 0, 0);
  MusicMenuLoop:=FSOUND_Stream_Open('menuloop.mp3', FSOUND_NORMAL or FSOUND_LOOP_NORMAL, 0, 0);
  MusicCredits:=FSOUND_Stream_Open('credits.mp3', FSOUND_NORMAL or FSOUND_LOOP_NORMAL, 0, 0);
  MusicGame:=FSOUND_Stream_Open('morphine.mp3', FSOUND_NORMAL or FSOUND_LOOP_NORMAL, 0, 0);

  {if (MusicIntro=nil) then begin
   MessageBox(0,FMOD_ErrorString(FSOUND_GetError), 'Load error', MB_OK or MB_ICONHAND);
   FSOUND_Close();
   Result:=1; Exit;
  end;}


  FSOUND_SetVolume(FSOUND_ALL,255);
  GAME:=[_INTRO_];
  stuffinit(_Width_,_Height_);

  //fadeout
  Start:=GetTickCount;
  Repeat
   DrawLogo(7,7,FALSE);
   glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);glEnable(GL_BLEND);glDisable(GL_TEXTURE_2D);glColor4f(1,1,1,(GetTickCount-Start)/1000);
   glBegin(GL_QUADS);
    glVertex2i(0,0);
    glVertex2i(_Width_,0);
    glVertex2i(_Width_,_Height_);
    glVertex2i(0,_Height_);
   glEnd();

   SwapBuffers(h_Dc);
  Until GetTickCount-Start>1000;


  glDisable(GL_BLEND);
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  SwapBuffers(h_Dc);
  Sleep(300);


  FSOUND_Stream_Play(FSOUND_FREE, MusicIntro);

  START:=GetTickCount;
  WHILE NOT DONE DO BEGIN //v tejto slucke program zije
      if (PeekMessage(Msg, 0, 0, 0, PM_REMOVE)) then  begin //cekne ci prisla sprava
          if Msg.message=WM_QUIT then Done:=TRUE
          else begin
	          TranslateMessage(Msg); //prelozi spravu
	          DispatchMessage(Msg);  //odosle spravu
	        end;
      end else begin
          //ak je program aktivny a nejde kreslit, pripadne bol stlaceny esc, tak sa program ukonci
          if (Active and not(DrawGLScene()) {or Keys[VK_ESCAPE]}) then begin Done:=TRUE end
          else SwapBuffers(h_Dc); //prehodi buffery (doublebuffering);
        end;

      {if Keys[VK_ESCAPE] then begin
       Keys[VK_ESCAPE]:=FALSE;
       GAME:=[_MENU_]; Start:=GetTickCount-10000;
      end;}







      if GAME=[_GAME_] then begin
        MovePlayers;

        if (Keys[VK_ESCAPE]) then begin
         Keys[VK_ESCAPE]:=FALSE;
         GAME:=[_MENU_]; InitButtonsMenu(_Width_,_Height_); Start:=GetTickCount-4000; PlayPlay(MusicMenuLoop);
        end;


        if (Player[0].Life=0) and (Player[0].KillTime=0) then begin Player[0].KillTime:=GetTickCount; end;
        if (Player[0].KillTime>0) and (GetTickCount-Player[0].KillTime>=1000) then begin
          if Player[1].KillTime=0 then Inc(Player[1].Score);
          InitPlayers;
          if (Player[0].Score>=Btn[2].Value) or (Player[1].Score>=Btn[2].Value) then begin GAME:=[_AFTERGAME_]; Start:=GetTickCount; end;
        end;

        if (Player[1].Life=0) and (Player[1].KillTime=0) then begin Player[1].KillTime:=GetTickCount; end;
        if (Player[1].KillTime>0) and (GetTickCount-Player[1].KillTime>=1000) then begin
          if Player[0].KillTime=0 then Inc(Player[0].Score);
          InitPlayers;
          if (Player[0].Score>=Btn[2].Value) or (Player[1].Score>=Btn[2].Value) then begin GAME:=[_AFTERGAME_]; Start:=GetTickCount; end;
        end;

{        if Keys[VK_RETURN] then begin
         Keys[VK_RETURN]:=FALSE;
         Waves[5].Vel:=-10;
        end;}

        if (T>2000) then BEGIN

        if (Player[0].Life>0) then begin
        if Keys[Ord('W')] then begin
         if (OnGround(0)<>-2) or (InWater(0,50)) then if Player[0].Spd.Y<8 then Player[0].Spd.Y:=8;
        end;
        if Keys[Ord('S')] then begin
         if (OnGround(0)<>-2) or (InWater(0,50)) then Player[0].Spd.Y:=-5;
        end;
        if Keys[Ord('A')] then begin
         Player[0].Spd.X:=-3;
         Player[0].Left:=TRUE;
        end;
        if Keys[Ord('D')] then begin
         Player[0].Spd.X:=+3;
         Player[0].Left:=FALSE;
        end;
        end;

        if (Player[1].Life>0) then begin
        if Keys[VK_UP] then begin
         if ((OnGround(1)<>-2) and (Player[1].Spd.Y<8)) or (InWater(1,50)) then Player[1].Spd.Y:=8;
        end;
        if Keys[VK_DOWN] then begin
         if (OnGround(1)<>-2) or (InWater(1,50)) then Player[1].Spd.Y:=-5;
        end;
        if Keys[VK_LEFT] then begin
         Player[1].Spd.X:=-3;
         Player[1].Left:=TRUE;
        end;
        if Keys[VK_RIGHT] then begin
         Player[1].Spd.X:=+3;
         Player[1].Left:=FALSE;
        end;
        end;

        END;

      end;









      if GAME=[_OPTIONS_] then begin

       if Edit>0 then begin

       for C:=Ord('0') to Ord('9') do if Keys[C] then begin Keys[C]:=FALSE; EditStr:=EditStr+Chr(C); end;
       if Keys[VK_BACK] then begin Keys[VK_BACK]:=FALSE; Delete(EditStr,Length(EditStr),1); end;
       if Keys[VK_RETURN] then begin Keys[VK_RETURN]:=FALSE; Val(EditStr,Btn[Edit-1].Value,C); Edit:=0; end;

       end;


      end;


      if (GAME=[_MENU_]) or (GAME=[_OPTIONS_]) then begin
        if KeyMenu<>[] then begin
         KeyMenu:=[];
         Pt:=Point(ROUND(TmpX/_Width_*_W_),ROUND(TmpY/_Height_*_H_));
         ClientToScreen(h_Wnd,Pt);
         SetCursorPos(Pt.X,Pt.Y);_X_:=ROUND(TmpX);_Y_:=ROUND(TmpY);
        end;

        if (Keys[VK_DOWN]) or (Keys[VK_RIGHT]) then begin
          Keys[VK_DOWN]:=FALSE;
          Keys[VK_RIGHT]:=FALSE;
          KeyMenu:=[MoveDown];
        end;
        if (Keys[VK_UP]) or (Keys[VK_LEFT]) then begin
          Keys[VK_UP]:=FALSE;
          Keys[VK_LEFT]:=FALSE;
          KeyMenu:=[MoveUp];
        end;

        if (Keys[VK_RETURN]) then begin
         Keys[VK_RETURN]:=FALSE;
         Mouse_Event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTDOWN, 0,0,0,0);
         Mouse_Event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTUP, 0,0,0,0);
        end;
      end;
  END;

  {FSOUND_Stream_Stop(Music);
  FSOUND_Stream_Close(Music);}

  FSOUND_Sample_Free(SampleHover);
  FSOUND_Sample_Free(SampleClick);
  FSOUND_Sample_Free(SampleSplash);

  FSOUND_Stream_Close(MusicIntro);
  FSOUND_Stream_Close(MusicMenu);
  FSOUND_Stream_Close(MusicGame);
  FSOUND_Stream_Close(MusicMenuLoop);
  FSOUND_Stream_Close(MusicCredits);

  //deinit fmod
  FSOUND_Close();
  KillGLwindow(); //zavrazdi okno

  Result:=Msg.wParam; //ukoncenie programu
end;



procedure TForm1.Button1Click(Sender: TObject);
begin
 OK_:=TRUE;
 Done_:=TRUE;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
 Done_:=TRUE;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 if Done_=FALSE then Action:=caNone;
 Done_:=TRUE;
end;

BEGIN
  Form1:=TForm1.Create(nil);
  TRY

   Form1.Caption:=AppTitle;

   Form1.OnClose:=Form1.FormClose;
   Form1.Button1.OnClick:=Form1.Button1Click;
   Form1.Button2.OnClick:=Form1.Button2Click;

   SetLength(Resolutions,10);
   Resolutions[ 0].W:= 320; Resolutions[0].H:= 240; Resolutions[0].B:=32;
   Resolutions[ 1].W:= 640; Resolutions[1].H:= 480; Resolutions[1].B:=32;
   Resolutions[ 2].W:= 800; Resolutions[2].H:= 600; Resolutions[2].B:=32;
   Resolutions[ 3].W:=1024; Resolutions[3].H:= 768; Resolutions[3].B:=32;
   Resolutions[ 4].W:=1280; Resolutions[4].H:=1024; Resolutions[4].B:=32;

   Resolutions[ 5].W:= 320; Resolutions[ 5].H:= 240; Resolutions[ 5].B:=16{24};
   Resolutions[ 6].W:= 640; Resolutions[ 6].H:= 480; Resolutions[ 6].B:=16{24};
   Resolutions[ 7].W:= 800; Resolutions[ 7].H:= 600; Resolutions[ 7].B:=16{24};
   Resolutions[ 8].W:=1024; Resolutions[ 8].H:= 768; Resolutions[ 8].B:=16{24};
   Resolutions[ 9].W:=1280; Resolutions[ 9].H:=1024; Resolutions[ 9].B:=16{24};

{   Resolutions[10].W:= 320; Resolutions[10].H:= 240; Resolutions[10].B:=16;
   Resolutions[11].W:= 640; Resolutions[11].H:= 480; Resolutions[11].B:=16;
   Resolutions[12].W:= 800; Resolutions[12].H:= 600; Resolutions[12].B:=16;
   Resolutions[13].W:=1024; Resolutions[13].H:= 768; Resolutions[13].B:=16;
   Resolutions[14].W:=1280; Resolutions[14].H:=1024; Resolutions[14].B:=16;}

   for Loop:=0 to 9 do begin
    Form1.ListBox1.Items.Add(Format('%dx%d, %dbit',[Resolutions[Loop].W,Resolutions[Loop].H,Resolutions[Loop].B]));
   end;
   Form1.ListBox1.ItemIndex:=2;

   Form1.Show;
   ShowWindow(Application.Handle, SW_HIDE);

   Done_:=FALSE; OK_:=FALSE;
   Repeat
    Application.ProcessMessages;
   Until Done_;

   _W_:=Resolutions[Form1.ListBox1.ItemIndex].W;
   _H_:=Resolutions[Form1.ListBox1.ItemIndex].H;
   _B__:=Resolutions[Form1.ListBox1.ItemIndex].B;
   Fullscreen:=Form1.CheckBox1.Checked;
   VSync:=Form1.CheckBox2.Checked;


  FINALLY
   Form1.Close;
   Form1.Free;
  END;



  if OK_ then begin
  WinMain( hInstance, hPrevInst, CmdLine, CmdShow );
  ShowCursor(TRUE);
  For C:=0 to TexCnt-1 do SetLength(Tex[C].Data,0);
  end;

END.
