program game;
uses
  Windows,
  Messages,
  OpenGL,
  SysUtils,
  Bass in 'Bass.pas',
  MyUnit in 'MyUnit.pas',
  FontUnit in 'FontUnit.pas',
  ParticleUnit in 'ParticleUnit.pas';

type
  TBullet = record
    x1,y1:Single;
    dx,dy:Single;
    AmmoType:integer;
    fraction:integer;
  end;
  TEnemy = record
    x1,y1:Single;
    dx,dy:Single;
    Eclass,Weapon,Health,ShotDelay:integer;
  end;
  TPlayer = record
    x1,y1:Single;
    Weapon,Power,Health:Smallint;
  end;
  TStar = record
    x1,y1,speed:Single;
  end;

var
  H_Wnd:HWND;
  H_DC:HDC;
  H_RC:HGLRC;
  msg:TMsg;
  Mpos:TPoint;
  Mouse:Boolean;
  Finished,FullScr,Active:Boolean;
  newCount,frameCount,lastCount,time:LongInt;
  keys:array[0..255] of Boolean;
  FpsRate:Integer;
  State: Smallint =1;{1Menu, 2 game, -1 score, -2 option, 0 exit}
  Bullets: array of TBullet;
  Enemies: array of TEnemy;
  HeavyEnemy:TEnemy;
  player: TPlayer;
  Bonus,BonusWeapon: TEnemy;
  star: array[1..50] of TStar;
  HeavyShot,shotDelay,enemyDelay,HeavyDelay,FastDelay:Integer;
  BulletCount,EnemyCount,StarCount:integer;
  EnemyTex, BulletTex, PlayerTex:TextureImage;
  BacgroundTex:TextureImage;
  Score:Integer=0;
  GameOver:Boolean=False;
  SelectedOption:Shortint=0;
  BestScore:array[1..10] of Integer;
  BestPlace:Shortint=10;
  ScoreFile:Text;
  Level:Shortint=0;
  LVLUP:Integer=300;
  Started:Boolean=False;
  ShotSound1,ShotSound2,ShotSound3,ExplosionSound:Cardinal;
  InputType:Shortint=1;
  UpKey,DownKey,LeftKey,RightKey,ShotKey: Byte;


function NewBullet: Integer;
begin
  Result := BulletCount;
  if BulletCount >= (Length(Bullets)) then
  SetLength(Bullets, BulletCount + 100);
  Inc(BulletCount);
end;

procedure KillBullet(const BulletID: Integer);
  var i: Integer;
begin
  for i := BulletID + 1 to BulletCount - 1 do
  Bullets[i - 1] := Bullets[i];
  Dec(BulletCount);
end;

function NewEnemy: Integer;
begin
  Result := EnemyCount;
  if EnemyCount >= (Length(Enemies)) then
  SetLength(Enemies, EnemyCount + 100);
  Inc(EnemyCount);
end;

procedure KillEnemy(const EnemyID: Integer);
  var i: Integer;
begin
  for i := EnemyID + 1 to EnemyCount - 1 do
  Enemies[i - 1] := Enemies[i];
  Dec(EnemyCount);
end;

procedure SetupBullet(var Cnt:integer; Ammo,frct,delta_x:Integer; pos_x,pos_y:Single);
begin
  Cnt:= NewBullet;
  with Bullets[Cnt] do
    begin
      fraction:=frct;
      AmmoType:=Ammo;
      x1:=pos_x;
      y1:=pos_y;
      dx:=delta_x;
      if fraction>0 then
      dy:=4+AmmoType
      else
      dy:=-4-AmmoType;
    end;
  Inc(Cnt);
end;

procedure SetupEnemy(var Cnt:integer; delta_x,currClass,currWeapon:integer; pos_x,pos_y:Single);
begin
  Cnt:= NewEnemy;
  with Enemies[Cnt] do
    begin
      x1:=pos_x;
      y1:=pos_y;
      dx:=delta_x;
      dy:=currWeapon;
      Eclass:=currClass;
      Weapon:=currWeapon;
      health:=currClass;
    end;
  Inc(Cnt);
end;

procedure Init;
var i:Integer;
  s:string;
begin
  Assign(ScoreFile,'score.txt');
  {$I-}
  Reset(ScoreFile);
  {$I+}
  if IOResult<> 0 then
  Rewrite(ScoreFile);
  Reset(ScoreFile);
  for i:=1 to 10 do
    begin
      Readln(ScoreFile,s);
      if s<>'' then
      BestScore[i]:=StrToInt(s);
    end;
  lastCount:=GetTickCount;
  frameCount:=0;
  BuildFont;
  shotdelay:=16;
  player.x1:=round(WndWidth/2)+10;
  player.y1:=WndHeight-200;
  player.Weapon:=1;
  player.Power:=1;
  player.health:=10;
  Bonus.x1:=-100;
  Bonus.y1:=-100;
  BonusWeapon.x1:=-100;
  BonusWeapon.y1:=-100;
  HeavyEnemy.x1:=-100;
  HeavyEnemy.y1:=-100;
  UpKey:=VK_UP;
  DownKey:=VK_DOWN;
  LeftKey:=VK_LEFT;
  RightKey:=VK_RIGHT;
  ShotKey:=32;
    for i :=1 to Length(star) do
    begin
      star[i].x1:=10+random(WndWidth-10);
      star[i].y1:=5+random(WndHeight-150);
      star[i].speed:=random(3)+1;
    end;
  LoadTGA(BacgroundTex, 'picture\background.tga');
  LoadTGA(PlayerTex, 'picture\player.tga');
  LoadTGA(EnemyTex, 'picture\enemy.tga');
  LoadTGA(BulletTex, 'picture\bullet.tga');
  LoadTGA(FontTex, 'picture\font.tga');
  LoadTGA(ParticleTex, 'picture\spark.tga');
  InitParticle;
  BASS_Init(-1, 44100, 0, H_Wnd, nil);
  ShotSound1:=BASS_StreamCreateFile(FALSE, PChar('sound\Blast.wav'), 0, 0, 0);
  ShotSound2:=BASS_StreamCreateFile(FALSE, PChar('sound\Blast.wav'), 0, 0, 0);
  ShotSound3:=BASS_StreamCreateFile(FALSE, PChar('sound\Blast.wav'), 0, 0, 0);
  ExplosionSound:=BASS_StreamCreateFile(FALSE, PChar('sound\Explosion.wav'), 0, 0, 0);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
end;

procedure glResizeWnd(Width, Height : Integer);
begin
  if (Height = 0) then
    Height := 1;
  WndWidth:=Width;
  WndHeight:=Height;
  glViewport(0, 0, width, Height);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0.0,Width,Height,0.0,-1.0,1.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
end;

procedure DrawBackground;
begin
  glEnable(GL_TEXTURE_2D);
  glCallList(BacgroundTex.texID);
  glBegin(GL_QUADS);
  glTexCoord2f(0,0); glVertex2f(0,0);
  glTexCoord2f(1,0); glVertex2f(WndWidth,0);
  glTexCoord2f(1,1); glVertex2f(WndWidth,WndHeight);
  glTexCoord2f(0,1); glVertex2f(0,WndHeight);
  glEnd;
  glDisable(GL_TEXTURE_2D);
end;

function MyButton(pos_x,pos_y,whth,hght:Single; SetState:integer):Boolean;
begin
  Result:=False;
  If (Mpos.x>pos_x) and (Mpos.y>pos_y) and (Mpos.x<pos_x+whth) and (Mpos.y<pos_y+hght) Then
  begin
    glColor3f(0, 0, 0.5);
    if Mouse then
    begin
    State:=SetState;
    Result:=True;
    end;
    Mouse:=False;
  end
  else
  glColor3f(0, 0.2, 0.9);
  glBegin(GL_QUADS);
    glVertex2f(pos_x,pos_y);
    glVertex2f(pos_x,pos_y+hght);
    glVertex2f(pos_x+whth,pos_y+hght);
    glVertex2f(pos_x+whth,pos_y);
  glEnd;
end;

procedure Menu_Proc;
begin
  glClearColor(0.0, 0.5, 0.0, 1.0);
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  glLoadIdentity;

  if (Level<>0) then MyButton(550,100,200,60,2);
  glPrint(620,135,'game');

  MyButton(550,180,200,60,-1);
  glPrint(615,215,'score');

  MyButton(550,260,200,60,-2);
  glPrint(605,295,'options');

  MyButton(550,340,200,60,0);
  glPrint(620,380,'exit');

  DrawBackground;
  if (level=0) then
    glPrint(200,100,'please select difficult in options');
end;

procedure Score_show;
var i,j,buf:Integer;
begin
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

  MyButton(550,180,200,60,1);
  glPrint(580,215,'back to menu');

  DrawBackground;
  glPrint(320,90,'BEST SCORE');

  for i:=1 to 9 do
    for j:=i+1 to 10 do
    begin
      if BestScore[j]>BestScore[i] then
      begin
        buf:=BestScore[i];
        BestScore[i]:=BestScore[j];
        BestScore[j]:=buf;
      end;
    end;

  glPrint(320,400,'You Score: '+ IntToStr(Score));

  Rewrite(ScoreFile);
  for i:=1 to 10 do
    begin
      glPrint(350,100+i*25,IntToStr(BestScore[i]));
      Writeln(Scorefile,BestScore[i]);
    end;
end;

procedure DrawCircle(x,y,size:integer; red,green,blue:Single);
var i:integer;
begin
  glColor3f (red,green,blue{1,0.7,0.1});
  glBegin (GL_TRIANGLE_STRIP);
  For i := 0 to 20 do
    begin
      glVertex2f (x+(size * cos ((2*Pi) * i / 20)),
                  y+(size * sin ((2*Pi) * i / 20)));
      glVertex2f (x, y);
    end;
  glEnd;
end;

procedure Options_Proc;
begin
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  glLoadIdentity;

  if not Started then
  case SelectedOption of
    1:begin
        DrawCircle(410,230,20, 0.1,0.7,0.1);
        Level:=1;
      end;
    2:begin
        DrawCircle(410,310,20, 0.1,0.7,0.1);
        Level:=2;
      end;
    3:begin
        DrawCircle(410,390,20, 0.1,0.7,0.1);
        Level:=3;
      end;
  end;

  if MyButton(380,200,150,60,-2) then
    SelectedOption:=1;
  glPrint(440,235,'Easy');

  if MyButton(380,280,150,60,-2) then
    SelectedOption:=2;
  glPrint(435,315,'Normal');

  if MyButton(380,360,150,60,-2) then
    SelectedOption:=3;
  glPrint(435,395,'Hard');

  if MyButton(380,360,150,60,-2) then

  glPrint(435,395,'Hard');

  MyButton(550,180,200,60,1);
  glPrint(580,215,'back to menu');

  DrawBackground;
  glPrint(340,100,'OPTIONS');
end;

procedure GameUpdate;
var i,j:integer;
begin
  if (keys[VK_ESCAPE]) then
  begin
    keys[VK_ESCAPE] := False;
    State:=1;
  end;

  if enemydelay>25 then
    begin
      enemydelay:=0;
      SetupEnemy(EnemyCount,0,Random(6)+Level,Level,Random(WndWidth-20)+10,-5);
    end
  else inc(enemydelay);


  if (HeavyEnemy.x1>0) then
    begin
      HeavyEnemy.y1:=HeavyEnemy.y1+HeavyEnemy.Weapon;
      if HeavyShot>70 then
      begin
        HeavyShot:=0;
        SetupBullet(BulletCount,Level,-9,-1,HeavyEnemy.x1-5,HeavyEnemy.y1);
        SetupBullet(BulletCount,Level,-9,1,HeavyEnemy.x1+5,HeavyEnemy.y1);
      end
      else Inc(HeavyShot);
    end;
  if (HeavyEnemy.y1>WndHeight-120) then
    HeavyEnemy.x1:=-100;
  if((HeavyEnemy.y1>=player.y1-15) and (HeavyEnemy.y1<=player.y1+15)) and
       ((HeavyEnemy.x1>=player.x1-30) and (HeavyEnemy.x1<=player.x1+30)) then
    begin
      HeavyEnemy.x1:=-100;
      HeavyEnemy.y1:=-100;
      player.Health:=player.Health-Level;
    end;
  if (HeavyDelay>2000-100*Level) and (HeavyEnemy.x1<0) then
    begin
      HeavyDelay:=0;
      HeavyEnemy.x1:=Random(WndWidth-60)+30;
      HeavyEnemy.y1:=-15;
      HeavyEnemy.dy:=Level;
      HeavyEnemy.Eclass:=20*Level;
      HeavyEnemy.Weapon:=Level;
      HeavyEnemy.health:=20*Level;
    end
  else inc(HeavyDelay);

  if (Bonus.x1>0) then
    Bonus.y1:=Bonus.y1+2;
  if (Bonus.y1>WndHeight-120) then
    Bonus.x1:=-100;
  if((Bonus.y1>=player.y1-15) and (Bonus.y1<=player.y1+15)) and
       ((Bonus.x1>=player.x1-15) and (Bonus.x1<=player.x1+15)) then
    begin
      Bonus.x1:=-100;
      Bonus.y1:=-100;
      Score:=Score+10;
      if player.Power<3 then player.Power:=player.Power+1;
    end;

  if (BonusWeapon.x1>0) then
    BonusWeapon.y1:=BonusWeapon.y1+2;
  if (BonusWeapon.y1>WndHeight-120) then
    BonusWeapon.x1:=-100;
  if((BonusWeapon.y1>=player.y1-15) and (BonusWeapon.y1<=player.y1+15)) and
       ((BonusWeapon.x1>=player.x1-15) and (BonusWeapon.x1<=player.x1+15)) then
    begin
      BonusWeapon.x1:=-100;
      BonusWeapon.y1:=-100;
      Score:=Score+30;
      if (player.Weapon<3) then
      begin
        player.Weapon:=player.Weapon+1;
        player.Power:=1;
      end
      else if (player.Health<10) then player.Health:=player.Health+1;
    end;

  if (keys[Ord('B')]) and (keys[Ord('P')]) then
	  begin
      keys[Ord('B')]:=False;
      keys[Ord('P')]:=False;
      if player.Weapon<3 then player.Weapon:=player.Weapon+1;;
	  end;
	if (keys[RightKey]) and (player.x1<WndWidth-10) then
    begin
      player.x1:=player.x1+5;
    end;
  if (keys[LeftKey]) and (player.x1>10) then
    begin
      player.x1:=player.x1-5;
    end;
  if (keys[UpKey]) and (player.y1>10) then
	  begin
      player.y1:=player.y1-5;
        end;
  if (keys[DownKey]) and (player.y1<WndHeight-150) then
    begin
      player.y1:=player.y1+5;
    end;

  if (keys[ShotKey])and (shotdelay>15) then
    begin
      shotdelay := 0;
      BASS_ChannelPlay(ShotSound1, False);
      case player.Weapon of
        1:SetupBullet(BulletCount,player.Power,9,0,player.x1,player.y1);
        2:begin
            BASS_ChannelPlay(ShotSound2,False);
            SetupBullet(BulletCount,player.Power,9,-1,player.x1,player.y1);
            SetupBullet(BulletCount,player.Power,9,1,player.x1,player.y1);
          end;
        3:begin
            BASS_ChannelPlay(ShotSound3,False);
            SetupBullet(BulletCount,player.Power,9,0,player.x1,player.y1);
            SetupBullet(BulletCount,player.Power,9,1,player.x1,player.y1);
            SetupBullet(BulletCount,player.Power,9,-1,player.x1,player.y1);
          end;
      end;
    end
    else
      Inc(shotdelay);

  for i := BulletCount - 1 downto 0 do
  begin
    Bullets[i].x1 := Bullets[i].x1 - Bullets[i].dx;
    Bullets[i].y1 := Bullets[i].y1 - Bullets[i].dy;
      if (Bullets[i].y1<0) or (Bullets[i].y1>WndHeight-120) then
        KillBullet(i)
      else
        if Bullets[i].fraction>0 then
        begin
        for j := EnemyCount  - 1 downto 0 do
          if((Bullets[i].y1>=Enemies[j].y1-10) and (Bullets[i].y1<=Enemies[j].y1+10)) and
            ((Bullets[i].x1>=Enemies[j].x1-15) and (Bullets[i].x1<=Enemies[j].x1+15)) then
            begin
              KillBullet(i);
              Enemies[j].health:=Enemies[j].health-Bullets[i].AmmoType;
              if Enemies[j].health<=0 then
                begin
                  BASS_ChannelPlay(ExplosionSound, False);
                  If (Random(200)>170) and (Bonus.x1<0) Then
                  begin
                    Bonus.x1:=Enemies[j].x1;
                    Bonus.y1:=Enemies[j].y1;
                  end;
                  If (Random(200)<10) and (BonusWeapon.x1<0) Then
                  begin
                    BonusWeapon.x1:=Enemies[j].x1;
                    BonusWeapon.y1:=Enemies[j].y1;
                  end;
                  KillEnemy(j);
                  Score:=score+Enemies[j].Eclass;
                end;
            end;

        if((Bullets[i].y1>=HeavyEnemy.y1-15) and (Bullets[i].y1<=HeavyEnemy.y1+15)) and
          ((Bullets[i].x1>HeavyEnemy.x1-30) and (Bullets[i].x1<=HeavyEnemy.x1+30)) then
          begin
            KillBullet(i);
            HeavyEnemy.Health:=HeavyEnemy.Health-bullets[i].AmmoType;
            if HeavyEnemy.Health<=0 then
              begin
                HeavyEnemy.x1:=-100;
                Score:=Score+HeavyEnemy.Eclass;
              end;
          end;
        end;

     if Bullets[i].fraction<0 then
     if((Bullets[i].y1>=player.y1-5) and (Bullets[i].y1<=player.y1+15)) and
       ((Bullets[i].x1>=player.x1-15) and (Bullets[i].x1<=player.x1+15)) then
       begin
         KillBullet(i);
         if player.Power>1 then  player.Power:=player.Power-1;
         player.health:=player.health-Bullets[i].AmmoType;
       end;
  end;

  for i := EnemyCount - 1 downto 0 do
  begin
    Enemies[i].x1 := Enemies[i].x1 + Enemies[i].dx;
    Enemies[i].y1 := Enemies[i].y1 + Enemies[i].dy;
    if (Enemies[i].ShotDelay>Random(300-Level*50)+150) then
      begin
        Enemies[i].ShotDelay:=0;
        SetupBullet(BulletCount,Level,-9,0,Enemies[i].x1,Enemies[i].y1+10);
      end
    else Inc(Enemies[i].ShotDelay);
    if Enemies[i].y1 > WndHeight-110 then
      KillEnemy(i)
    else
      if ((Enemies[i].y1>=player.y1-20) and (Enemies[i].y1<=player.y1+20)) and
         ((Enemies[i].x1>player.x1-30) and (Enemies[i].x1<player.x1+30)) then
        begin
          KillEnemy(i);
          player.health:=player.health-Enemies[i].Weapon;
        end;
  end;

  for i:=Length(star) downto 1 do
    begin
      star[i].y1:=star[i].y1+star[i].speed;
      if star[i].y1>WndHeight-110 then
        begin
          star[i].y1:=0;
          star[i].x1:=Random(WndWidth-10)+10;
          star[i].speed:=random(3)+1;
        end;
    end;

  if player.health <=0 then
    begin
      if BestScore[10]<Score then BestScore[10]:=Score;
      GameOver:=True;
    end;
  if score>LVLUP then
  begin
    Level:=Level+1;
    LVLUP:=LVLUP+300;
  end;
end;

procedure GameDraw;
var i,j:integer;
begin
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  glLoadIdentity;

  glColor3f(1.0,0.0,0.0);
  glBegin(GL_QUADS);
    glVertex2f(Bonus.x1-15,Bonus.y1);
    glVertex2f(Bonus.x1+15,Bonus.y1);
    glVertex2f(Bonus.x1+15,Bonus.y1+30);
    glVertex2f(Bonus.x1-15,Bonus.y1+30);
  glEnd;
  glPrint(Round(Bonus.x1)-10,Round(Bonus.y1)+25,'P');

  glColor3f(1.0,0.0,1.0);
  glBegin(GL_QUADS);
    glVertex2f(BonusWeapon.x1-15,BonusWeapon.y1);
    glVertex2f(BonusWeapon.x1+15,BonusWeapon.y1);
    glVertex2f(BonusWeapon.x1+15,BonusWeapon.y1+30);
    glVertex2f(BonusWeapon.x1-15,BonusWeapon.y1+30);
  glEnd;
  glPrint(Round(BonusWeapon.x1)-10,Round(BonusWeapon.y1)+25,'W');

  glColor3f(0.0,1.0,0.0);
  glBegin(GL_QUADS);
    glVertex2f(5,WndHeight-40);
    glVertex2f(10*player.health+5,WndHeight-40);
    glVertex2f(10*player.health+5,WndHeight-30);
    glVertex2f(5,WndHeight-30);
  glEnd;

  if player.Weapon>0 then DrawCircle(200,WndHeight-30,15,1.0,0.1,0.7);
  if player.Weapon>1 then DrawCircle(250,WndHeight-30,15,1.0,0.1,0.7);
  if player.Weapon>2 then DrawCircle(300,WndHeight-30,15,1.0,0.1,0.7);

  if player.Power>0 then DrawCircle(400,WndHeight-30,15,1.0,0.1,0.1);
  if player.Power>1 then DrawCircle(450,WndHeight-30,15,1.0,0.1,0.1);
  if player.Power>2 then DrawCircle(500,WndHeight-30,15,1.0,0.1,0.1);

  for i :=EnemyCount - 1 downto 0 do
  begin
    glColor3f(0.1*Enemies[i].Health,0.3,0.2);
    glBegin(GL_QUADS);
      glVertex2f(enemies[i].x1-15,enemies[i].y1);
      glVertex2f(enemies[i].x1-15,enemies[i].y1+5);
      glVertex2f(enemies[i].x1+15,enemies[i].y1+5);
      glVertex2f(enemies[i].x1+15,enemies[i].y1);
    glEnd;
  end;

  glColor3f(0.0,0.0,1.0);
  glEnable(GL_TEXTURE_2D);
  glCallList(BulletTex.texID);
  for i :=BulletCount - 1 downto 0 do
  begin
    glBegin(GL_QUADS);
      glTexCoord2f(0.0, 0.0); glVertex2f(bullets[i].x1-5,bullets[i].y1);
      glTexCoord2f(0.0, 1.0); glVertex2f(bullets[i].x1-5,bullets[i].y1+10);
      glTexCoord2f(1.0, 1.0); glVertex2f(bullets[i].x1+5,bullets[i].y1+10);
      glTexCoord2f(1.0, 0.0); glVertex2f(bullets[i].x1+5,bullets[i].y1);
    glEnd;
    end;

  glColor3f(1.0,1.0,1.0);
  glCallList(PlayerTex.texID);

  glBegin(GL_QUADS);
      glTexCoord2f(0.0, 0.0); glVertex2f(HeavyEnemy.x1-30,HeavyEnemy.y1);
      glTexCoord2f(0.0, 1.0); glVertex2f(HeavyEnemy.x1-30,HeavyEnemy.y1+30);
      glTexCoord2f(1.0, 1.0); glVertex2f(HeavyEnemy.x1+30,HeavyEnemy.y1+30);
      glTexCoord2f(1.0, 0.0); glVertex2f(HeavyEnemy.x1+30,HeavyEnemy.y1);
    glEnd;

  glCallList(EnemyTex.texID);
  for i :=EnemyCount - 1 downto 0 do
  begin
    glBegin(GL_QUADS);
      glTexCoord2f(0.0, 0.0); glVertex2f(enemies[i].x1-15,enemies[i].y1);
      glTexCoord2f(0.0, 1.0); glVertex2f(enemies[i].x1-15,enemies[i].y1+30);
      glTexCoord2f(1.0, 1.0); glVertex2f(enemies[i].x1+15,enemies[i].y1+30);
      glTexCoord2f(1.0, 0.0); glVertex2f(enemies[i].x1+15,enemies[i].y1);
    glEnd;
  end;

  MakeParticle(player.x1,player.y1+25);
  glColor3f(1.0,1.0,1.0);
  glCallList(PlayerTex.texID);
  glBegin(GL_QUADS);
    glTexCoord2f(0.0, 1.0); glVertex2f(player.x1-15,player.y1);
    glTexCoord2f(0.0, 0.0); glVertex2f(player.x1-15,player.y1+30);
    glTexCoord2f(1.0, 0.0); glVertex2f(player.x1+15,player.y1+30);
    glTexCoord2f(1.0, 1.0); glVertex2f(player.x1+15,player.y1);
  glEnd;
  glDisable(GL_TEXTURE_2D);
  glPrint(600,WndHeight-40,'Score: '+IntToStr(Score));
  glPrint(15,WndHeight-50,'Life');
  glPrint(400,WndHeight-50,'Power');
  glPrint(200,WndHeight-50,'Weapon');

  glColor3f(1.0,1.0,1.0);
  for i :=Length(star) downto 1 do
    begin
      glBegin(GL_POINTS);
        glVertex2f(star[i].x1,star[i].y1);
      glEnd;
    end;

  if GameOver then
    State:=-1;
end;

procedure Game_Proc;
begin
  glClearColor(0,0,0,0);
  GameUpdate;
  GameDraw;

//******** draw text **********
  //glPrint(10,15,'player '+IntToStr(igrok1.x)+', '+IntToStr(igrok1.y)+' grv '+IntToStr(Gravity));
  //glPrint(10,30,'mouse coord '+IntToStr(mousecoordX)+', '+IntToStr(mousecoordY));
end;

function WndProc(hWnd: HWND;
				 Msg: UINT;
				 wParam: WPARAM;
				 lParam: LPARAM): LRESULT; stdcall;
begin
  Result :=0;
  case (Msg) of
    WM_CLOSE:
        PostQuitMessage(0);
    WM_ACTIVATEAPP:
      If (wParam=WA_ACTIVE) or (wParam=WA_CLICKACTIVE)
         then Active:=True
         else Active:=False;
	  WM_KEYDOWN:
        keys[wParam] := True;
    WM_KEYUP:
        keys[wParam] := False;
    WM_LBUTTONDOWN:
        mouse:=True;
    WM_LBUTTONUP:
        mouse:=False;
	  //WM_LBUTTONDBLCLK:
    WM_MOUSEMOVE:
      begin
        Mpos.x:= LoWord ( LParam );
        Mpos.y:= HiWord ( LParam );
      end;
    WM_SIZE:
        glResizeWnd(LOWORD(lParam),HIWORD(lParam));
  else
    Result := DefWindowProc(hWnd, Msg, wParam, lParam);
  end;
end;

procedure glKillWnd(Fullscreen : Boolean);
begin
  DeleteFont;
  CloseFile(ScoreFile);
  if Fullscreen then            
      begin
        //dmFields := DM_PELSWIDTH or DM_PELSHEIGHT or DM_BITSPERPEL;
        ChangeDisplaySettings({DefDM}devmode(nil^), CDS_FULLSCREEN);
        ShowCursor(True);
      end;
  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, 'Release of rendering context failed!', 'Error', MB_OK or MB_ICONERROR);
    h_RC := 0;
  end;
  if ((h_DC > 0) and (ReleaseDC(h_Wnd, h_DC) = 0)) then
  begin
    MessageBox(0, 'Release of device context failed!', 'Error', MB_OK or MB_ICONERROR);
    h_DC := 0;
  end;
  if ((h_Wnd <> 0) and (not DestroyWindow(h_Wnd))) then
  begin
    MessageBox(0, 'Unable to destroy window!', 'Error', MB_OK or MB_ICONERROR);
    h_Wnd := 0;
  end;
  if (not UnRegisterClass('OpenGL', hInstance)) then
  begin
    MessageBox(0, 'Unable to unregister window class!', 'Error', MB_OK or MB_ICONERROR);
    hInstance := 0;
  end;
end;

function glCreateWnd(Width, Height : Integer; Fullscreen : Boolean; PixelDepth : Integer) : Boolean;
var
  wndClass : TWndClass;         // Window class
  dwStyle : DWORD;              // Window styles
  dwExStyle : DWORD;            // Extended window styles
  dmScreenSettings : TDEVMODE;  // Screen settings (fullscreen, etc...)
  PixelFormat : GLuint;         // Settings for the OpenGL rendering
  h_Instance : HINST;           // Current instance
  pfd : TPIXELFORMATDESCRIPTOR; // Settings for the OpenGL window
  WindowRect: TRect;
begin
  h_Instance := GetModuleHandle(nil);       //Grab An Instance For Our Window
  ZeroMemory(@wndClass, SizeOf(TwndClass)); // Clear the window class structure
  WindowRect.Left := 0;                              
  WindowRect.Top := 0;
  WindowRect.Right := width;
  WindowRect.Bottom := height;

  with wndClass do                    // Set up the window class
  begin
  style     := CS_HREDRAW or
              CS_VREDRAW or
              CS_OWNDC;
	lpfnWndProc:= @WndProc;
	cbClsExtra:=0;
	cbWndExtra:=0;
  hInstance:= h_Instance;
	hIcon:=LoadIcon(0,IDI_WINLOGO);
	hCursor:= LoadCursor(0, IDC_ARROW);
	hbrBackground:=0;
	lpszMenuName:=nil;
  lpszClassName:= 'OpenGL';
  end;

  if (RegisterClass(wndClass) = 0) then  // Attemp to register the window class
  begin
    MessageBox(0, 'Failed to register the window class!', 'Error', MB_OK or MB_ICONERROR);
    Result := False;
    Exit;
  end;

  if Fullscreen then
  begin
	ZeroMemory( @dmScreenSettings, sizeof(TDEVMODE{dmScreenSettings}) );
    with dmScreenSettings do begin              // Set parameters for the screen setting
      dmSize       := SizeOf(TDEVMODE{dmScreenSettings});
      dmPelsWidth  := Width;                   
      dmPelsHeight := Height;
      dmBitsPerPel := PixelDepth;
      dmFields     := DM_PELSWIDTH or DM_PELSHEIGHT or DM_BITSPERPEL;
    end;

    if (ChangeDisplaySettings(dmScreenSettings, CDS_FULLSCREEN))<> DISP_CHANGE_SUCCESSFUL then
    begin
      MessageBox(0, 'Unable to switch to fullscreen!', 'Error', MB_OK or MB_ICONERROR);
      Fullscreen := False;
    end;
  end;
  if Fullscreen then
  begin
    dwStyle := WS_POPUP or                
               WS_CLIPCHILDREN or         
               WS_CLIPSIBLINGS;
    dwExStyle := WS_EX_APPWINDOW;
    //ShowCursor(False);                 
  end
  else
  begin
    dwStyle := WS_OVERLAPPEDWINDOW or    
               WS_CLIPCHILDREN or        
               WS_CLIPSIBLINGS;           
    dwExStyle := WS_EX_APPWINDOW or       
                 WS_EX_WINDOWEDGE;        
  end;

  AdjustWindowRectEx(WindowRect,dwStyle,false,dwExStyle);
  h_Wnd := CreateWindowEx(dwExStyle,
                          'OpenGL',     
                          'frost',      
                          dwStyle,        
                          0, 0,           
                          WindowRect.Right-WindowRect.Left,
                          WindowRect.Bottom-WindowRect.Top,
                          0,              
                          0,
                          h_Instance,
                          nil);           
  if h_Wnd = 0 then
  begin
    glKillWnd(Fullscreen);               
    MessageBox(0, 'Unable to create window!', 'Error', MB_OK or MB_ICONERROR);
    Result := False;
    Exit;
  end;

  h_DC := GetDC(h_Wnd);
  if (h_DC = 0) then
  begin
    glKillWnd(Fullscreen);
    MessageBox(0, 'Unable to get a device context!', 'Error', MB_OK or MB_ICONERROR);
    Result := False;
    Exit;
  end;

  with pfd do
  begin
    nSize           := SizeOf(TPIXELFORMATDESCRIPTOR);
    nVersion        := 1;
    dwFlags         := PFD_DRAW_TO_WINDOW
                       or PFD_SUPPORT_OPENGL
                       or PFD_DOUBLEBUFFER;
    iPixelType      := PFD_TYPE_RGBA;
    cColorBits      := PixelDepth;
    iLayerType      := PFD_MAIN_PLANE;
    cDepthBits      := 16;
  end;

  PixelFormat := ChoosePixelFormat(h_DC, @pfd);
  if (PixelFormat = 0) then
  begin
    glKillWnd(Fullscreen);
    MessageBox(0, 'Unable to find a suitable pixel format', 'Error', MB_OK or MB_ICONERROR);
    Result := False;
    Exit;
  end;

  if (not SetPixelFormat(h_DC, PixelFormat, @pfd)) then
  begin
    glKillWnd(Fullscreen);
    MessageBox(0, 'Unable to set the pixel format', 'Error', MB_OK or MB_ICONERROR);
    Result := False;
    Exit;
  end;

  h_RC := wglCreateContext(h_DC);
  if (h_RC = 0) then
  begin
    glKillWnd(Fullscreen);
    MessageBox(0, 'Unable to create an OpenGL rendering context', 'Error', MB_OK or MB_ICONERROR);
    Result := False;
    Exit;
  end;

  if (not wglMakeCurrent(h_DC, h_RC)) then
  begin
    glKillWnd(Fullscreen);
    MessageBox(0, 'Unable to activate OpenGL rendering context', 'Error', MB_OK or MB_ICONERROR);
    Result := False;
    Exit;
  end;

  SetForegroundWindow(h_Wnd);
  SetFocus(h_Wnd);
  ShowWindow(h_Wnd, SW_SHOW);
  glResizeWnd(Width,Height);

  Init;
  Result := True;
end;

begin
  finished:= False;
  FullScr:=False;
  time:=0;

  {with defDM do
  try
    DeskDC := GetDC(0);
    dmSize := SizeOf(TDEVMODE);
    dmPelsWidth := GetDeviceCaps(DeskDC,HORZRES);
    dmPelsHeight := GetDeviceCaps(DeskDC,VERTRES);
    dmBitsPerPel := GetDeviceCaps(DeskDC,BITSPIXEL);
  finally
    ReleaseDC(0, DeskDC);
  end; }
  if not glCreateWnd(WndWidth, WndHeight, FullScr, 32) then
    Exit;
  while not finished do
    if (PeekMessage(msg, 0, 0, 0, PM_REMOVE)) then
        if (msg.message = WM_QUIT) then
          finished := True
        else
        begin
  	      TranslateMessage(msg);
          DispatchMessage(msg);
        end
    else
    If Active then
    begin
      if (GetTickCount - time)>10 then
      begin
	    newCount := GetTickCount;
	    Inc(frameCount);
       case State of
         0:Finished:=True;
         1:Menu_Proc;
         -1:Score_show;
         -2:Options_Proc;
         2:Game_Proc;
       end;
      SwapBuffers(h_DC);
	    If (newCount - lastCount) > 1000 then
	   	 begin
	  	 fpsRate:=Trunc(frameCount * 1000 / (newCount - lastCount));
	  	 SetWindowText(h_Wnd, PChar(' [ FPS - '+IntToStr (fpsRate)+' ] '));
	  	 lastCount:= newCount;
	  	 frameCount:= 0;
	  	 end;
      time:=GetTickCount;
      end;
	    if keys[VK_F1] then
        begin
         Keys[VK_F1] := false;
         glKillWnd(FullScr);
         FullScr := not FullScr;
         if not glCreateWnd(WndWidth,WndHeight, FullScr, 32) then
           Exit;
        end;
    end;
  glKillWnd(FullScr);
end.
