unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  OmegaTimer, OmegaFont, OmegaInput, OmegaImageList, OmegaScreen,
  OmegaSprite, ExtCtrls, OmegaSurface, OmegaPrimitives;

type
  PPunkt=^TPunkt;
  TPunkt=class
    fOmegaPrimitives:TOmegaPrimitives;
    fOmegaScreen:TOmegaScreen;
    fX,             //współrzędna X
    fY     :single; //współrzędna Y
    fZ     :integer;//współrzędna Z
    fH     :single;//poziom wysokości
    fRed,
    fGreen,
    fBlue  :integer;
  protected
    property X:single  read fX write fX;
    property Y:single  read fY write fY;
    property Z:integer read fZ write fZ;
    property H:single read fH write fH;
    property Red   :integer read fRed   write fRed;
    property Green :integer read fGreen write fGreen;
    property Blue  :integer read fBlue  write fBlue;
  public
    procedure Draw(const Xk,Yk,XKPion,YKPion:single);
    constructor Create(const AX,AY:single;const AZ:integer;
                       const AR,AG,AB:integer;
                       const AOmegaScreen:TOmegaScreen);
  end;
  TWspolrzedna=record
       x,
       y,
       h:single;
  end;
  PKafel=^TKafel;
  TKafel=class(TSimpleAnimSprite)
    fA,  //wspol. kolejnych rogow prostokata
    fB,                  //A------------B
    fC,                  //|            |
    FD   :TWspolrzedna;  //D------------C
    fIdObraz,
    fIdKlatka:integer;
    fOmegaImageList:TOmegaImageList;
   protected
    property OmegaImageList:TOmegaImageList read fOmegaImageList write fOmegaImageList;
    property IdObraz  :integer      read fIdObraz  write fIdObraz;
    property IdKlatka :integer      read fIdKlatka write fIdKlatka;
    property A        :TWspolrzedna read fA write fA;
    property B        :TWspolrzedna read fB write fB;
    property C        :TWspolrzedna read fC write fC;
    property D        :TWspolrzedna read fD write fD;
   public
    constructor Create(const AParent: TOmegaSprite;
                       const AOmegaImageList:TOmegaImageList;
                       const AIdObraz,AIdKlatka:integer;
                       Const AA,Ab,Ac,Ad:TWspolrzedna);
    procedure Draw;override;
    procedure UaktualniWspolrzedne(Const AA,Ab,Ac,Ad:TWspolrzedna);
  end;


  TForm1 = class(TForm)
    OmegaScreen1: TOmegaScreen;
    OmegaImageList1: TOmegaImageList;
    OmegaInput1: TOmegaInput;
    OmegaFont1: TOmegaFont;
    OmegaTimer1: TOmegaTimer;
    OmegaSprite1: TOmegaSprite;
    procedure OmegaTimer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormShow(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word;
                          Shift: TShiftState);
    procedure FormDestroy(Sender: TObject);
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

procedure TworzPunkty(const RogX,RogY:integer);//tworzy punkty siatki mapy
procedure PokazPunkty;//pokazuje punkty siatki mapy
procedure TworzKafle;
//procedure RysujKafle;
procedure UaktualnijWspolrzedneKafli;

var
  kafel:TKafel;
  idAktywny:integer=-1;
  Form1: TForm1;
  ListaKafli,
  Lista:TList;
  fPunkty:boolean=false;
  fLinie :boolean=false;
const

  RozmiarKfla:TPoint=(x:64;y:48);
  SiatkaMapy :TPoint=(x:14;y:14);
  pedzel0:array[0..11,0..1]of integer=((0,0),(1,0),(1,1),(0,1),
                                        (0,-1),(1,-1),(2,0),(2,1),(1,2),(0,2),(-1,1),(-1,0));

implementation

{$R *.DFM}
procedure szczyt(const n:integer;const h:single);
var
 wiersz,kol,i,j:integer;
begin
 if n=0 then exit;
 wiersz:=n div SiatkaMapy.x;
 kol:=n-wiersz*siatkaMapy.x;
 for i:=0 to high(pedzel0) do
     if kol+pedzel0[i,0]<SiatkaMapy.x then
     begin
       j:=kol+pedzel0[i,0]+(wiersz+pedzel0[i,1])*siatkaMapy.x;
       if (j>-1)and(j<Lista.Count)then
       begin
         if i<4 then PPunkt(Lista.items[j])^.fh:=PPunkt(Lista.items[j])^.fh+h
         else PPunkt(Lista.items[j])^.fh:=PPunkt(Lista.items[j])^.fh+h/2;
       end;
     end;
end;

procedure TPunkt.Draw(const Xk,Yk,XKPion,YKPion:single);
begin
 //rysuj linie
 if fLinie then begin
    //poziomy
    fOmegaPrimitives.Line(fx,fy+fh,xk,yk,OmegaColor(125,125,125));
    //piony
    fOmegaPrimitives.Line(fx,fy+fh,xkPion,ykpion,OmegaColor(125,125,125));
 end;
 //rysuj punkty
 if fPunkty then
 fOmegaScreen.SetPixel(Round(fX),Round(fY+fh),fRed,fGreen,fBlue,0);

end;
constructor TPunkt.Create(const AX,AY:single;const AZ:integer;
                          const AR,AG,AB:integer;
                          const AOmegaScreen:TOmegaScreen);
begin
  fX:=AX;
  fY:=AY;
  fZ:=AZ;
  fH:=0;
  fRed  :=AR;
  fGreen:=AG;
  fBlue :=AB;
  fOmegaScreen:=AOmegaScreen;
  fOmegaPrimitives:=TOmegaPrimitives.Create(AOmegaScreen);
  fOmegaPrimitives.OmegaScreen:=AOmegaScreen;

end;
procedure TworzPunkty(const RogX,RogY:integer);
var
 w,k:integer;
 APunkt:PPunkt;
begin

 for w:=0 to SiatkaMapy.y-1 do
  for k:=0 to SiatkaMapy.x-1 do begin
      New(APunkt);
      APunkt^:=TPunkt.Create(RogX+k*RozmiarKfla.x,RogY+w*RozmiarKfla.y,0,0,255,0,Form1.OmegaScreen1);
      Lista.Add(APunkt);
  end;
end;

procedure PokazPunkty;
var
  i:integer;
  xk,yk,XKPion,YKPion:single;
begin
  for i:=1 to Lista.Count-1 do
  begin
    if i mod SiatkaMapy.x<>0 then begin
    xk:=PPunkt(Lista.Items[i-1])^.x;
    yk:=PPunkt(Lista.Items[i-1])^.y+PPunkt(Lista.Items[i-1])^.fh;
    end else begin
        xk:=PPunkt(Lista.Items[i])^.x;
        yk:=PPunkt(Lista.Items[i])^.y+PPunkt(Lista.Items[i])^.fh;
    end;
    if i> SiatkaMapy.x then begin
     xkpion:=PPunkt(Lista.Items[i-SiatkaMapy.x])^.x;
     ykpion:=PPunkt(Lista.Items[i-SiatkaMapy.x])^.y+PPunkt(Lista.Items[i-SiatkaMapy.x])^.fh;
    end else begin
     xkpion:=PPunkt(Lista.Items[i mod SiatkaMapy.x])^.x;
     ykpion:=PPunkt(Lista.Items[i mod SiatkaMapy.x])^.y+PPunkt(Lista.Items[i mod SiatkaMapy.x])^.fh;
    end;
    PPunkt(Lista.Items[i])^.Draw(xk,yk,XKPion,YKPion);
  end;
end;

procedure TForm1.OmegaTimer1Timer(Sender: TObject);
var
 i:integer;
begin
 OmegaInput1.Update;
 if not omegascreen1.CanDraw then exit;

 OmegaScreen1.ClearScreen(0,0,128,0);
 OmegaScreen1.BeginRender;

 OmegaSprite1.Collision;
 OmegaSprite1.Draw;
 OmegaSprite1.Dead;
 OmegaSprite1.Move(OmegaTimer1.DeltaSecs);
 PokazPunkty;
 //rysuj drzewa- bardzo prymitywne podejście
 //jakiego nie należy stosować :)
   OmegaImageList1.ImageList.Items[1].Draw(Round(PPunkt(Lista.Items[60])^.x-64),
                                           Round(PPunkt(Lista.Items[60])^.y+PPunkt(Lista.Items[60])^.fh-128),
                                           3);
   OmegaImageList1.ImageList.Items[1].Draw(Round(PPunkt(Lista.Items[75])^.x-64),
                                           Round(PPunkt(Lista.Items[75])^.y+PPunkt(Lista.Items[75])^.fh-128),
                                           12);
   OmegaImageList1.ImageList.Items[1].Draw(Round(PPunkt(Lista.Items[95])^.x-64),
                                           Round(PPunkt(Lista.Items[95])^.y+PPunkt(Lista.Items[95])^.fh-128),
                                           11);
   OmegaImageList1.ImageList.Items[1].Draw(Round(PPunkt(Lista.Items[105])^.x-64),
                                           Round(PPunkt(Lista.Items[105])^.y+PPunkt(Lista.Items[105])^.fh-128),
                                           8);
   OmegaImageList1.ImageList.Items[1].Draw(Round(PPunkt(Lista.Items[115])^.x-64),
                                           Round(PPunkt(Lista.Items[115])^.y+PPunkt(Lista.Items[115])^.fh-128),
                                           8);
   OmegaImageList1.ImageList.Items[1].Draw(Round(PPunkt(Lista.Items[122])^.x-64),
                                           Round(PPunkt(Lista.Items[122])^.y+PPunkt(Lista.Items[122])^.fh-128),
                                           7);
   OmegaImageList1.ImageList.Items[1].Draw(Round(PPunkt(Lista.Items[127])^.x-64),
                                           Round(PPunkt(Lista.Items[127])^.y+PPunkt(Lista.Items[127])^.fh-128),
                                           2);
   OmegaImageList1.ImageList.Items[1].Draw(Round(PPunkt(Lista.Items[137])^.x-64),
                                           Round(PPunkt(Lista.Items[137])^.y+PPunkt(Lista.Items[137])^.fh-128),
                                           6);
   OmegaImageList1.ImageList.Items[1].Draw(Round(PPunkt(Lista.Items[147])^.x-64),
                                           Round(PPunkt(Lista.Items[147])^.y+PPunkt(Lista.Items[147])^.fh-128),
                                           5);
   OmegaImageList1.ImageList.Items[1].Draw(Round(PPunkt(Lista.Items[157])^.x-64),
                                           Round(PPunkt(Lista.Items[157])^.y+PPunkt(Lista.Items[157])^.fh-128),
                                           1);

 OmegaFont1.Print(0,0,'FPS: '+IntToStr(OmegaTimer1.FPS));
 OmegaFont1.Print(0,20,'LKM- podnieś teren');
 OmegaFont1.Print(0,40,'PKM- obniż teren');
 OmegaFont1.Print(0,60,'SPACJA- pokaż/ukryj siatkę');


 OmegaScreen1.EndRender;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Lista:=TList.Create;
  TworzPunkty(0,0);

  ListaKafli:=TList.Create;
  TworzKafle;

  OmegaScreen1.Init;
  OmegaScreen1.SetHWnd(self.handle);
  OmegaFont1.Init;
  OmegaFont1.CreateFont('Arial',10,[]);
  OmegaFont1.Color:=OmegaColor(255,255,255);

end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  OmegaTimer1.Enabled:=false;
  OmegaSprite1.Dead;
  OmegaScreen1.FreeOnRelease;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
 OmegaTimer1.Enabled:=true;
end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  //ESC
  if key=27 then close;
  //spacja
  if key=32 then fLinie:=not fLinie;
  //klawisz P
  if key=80 then fPunkty:=not fPunkty;
end;

procedure TForm1.FormDestroy(Sender: TObject);
var
  i:integer;
begin
  for i:=0 to Lista.Count-1 do Dispose(PPunkt(Lista.Items[i]));
  Lista.Free;
  for i:=0 to ListaKafli.Count-1 do Dispose(PKafel(ListaKafli.Items[i]));
  ListaKafli.Free;
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if idAktywny>-1 then
  //Anuluj aktywny punkt
  //ustaw stare
  with PPunkt(Lista.Items[idAktywny])^ do begin
       Red:=0;
       Green:=255;
       Blue:=0;
  end;
  //Wyznacz nowy aktywny punkt
  idAktywny:=x div RozmiarKfla.x+ (y div RozmiarKfla.y)*SiatkaMapy.x;
  //ustaw nowe
  with PPunkt(Lista.Items[idAktywny])^ do begin
       Red:=255;
       Green:=0;
       Blue:=0;
  end;
  //szczyty i doliny
  if Button=mbLeft  then szczyt(idAktywny,-8);
  if Button=mbRight then szczyt(idAktywny, 8);
  UaktualnijWspolrzedneKafli;
end;
//*************KAFEL*****************
constructor tkAFEL.Create(const AParent: TOmegaSprite;
                          const AOmegaImageList:TOmegaImageList;
                          const AIdObraz,AIdKlatka:integer;
                          const AA,Ab,Ac,Ad:TWspolrzedna);
begin
 inherited Create(AParent);
 fOmegaImageList:=AOmegaImageList;
 fIdObraz:=AIdObraz;
 fIdKlatka:=AIdKlatka;
 fA:=AA;
 fB:=AB;
 fC:=AC;
 fD:=AD;
 Z:=Round(fA.Y)div SiatkaMapy.x;
 DoCollision := false;
 DoPixelCheck := false;
end;
procedure TworzKafle;
var
 idPunkt,    //indeks Punktu tworzącego gorny lewy rog Kafla;
 w,k:integer;
 AKafel:PKafel;
 AA,AB,AC,AD:TWspolrzedna;
begin
 for w:=0 to SiatkaMapy.y-2 do
  for k:=0 to SiatkaMapy.x-2 do begin
      idPunkt:=k+w*SiatkaMapy.x;

      AA.x:=PPunkt(Lista.Items[idPunkt])^.x;
      AA.y:=PPunkt(Lista.Items[idPunkt])^.y+PPunkt(Lista.Items[idPunkt])^.fh;
      AA.h:=PPunkt(Lista.Items[idPunkt])^.fh;

      AB.x:=PPunkt(Lista.Items[idPunkt+1])^.x;
      AB.y:=PPunkt(Lista.Items[idPunkt+1])^.y+PPunkt(Lista.Items[idPunkt+1])^.fh;
      AB.h:=PPunkt(Lista.Items[idPunkt+1])^.fh;

      AC.x:=PPunkt(Lista.Items[idPunkt+1+SiatkaMapy.x])^.x;
      AC.y:=PPunkt(Lista.Items[idPunkt+1+SiatkaMapy.x])^.y+PPunkt(Lista.Items[idPunkt+1+SiatkaMapy.x])^.fh;
      AC.h:=PPunkt(Lista.Items[idPunkt+1+SiatkaMapy.x])^.fh;

      AD.x:=PPunkt(Lista.Items[idPunkt+SiatkaMapy.x])^.x;
      AD.y:=PPunkt(Lista.Items[idPunkt+SiatkaMapy.x])^.y+PPunkt(Lista.Items[idPunkt+SiatkaMapy.x])^.fh;
      AD.h:=PPunkt(Lista.Items[idPunkt+SiatkaMapy.x])^.fh;

      New(AKafel);
      AKafel^:=TKafel.Create(Form1.OmegaSprite1,Form1.OmegaImageList1,0,1,AA,AB,AC,AD);
      ListaKafli.Add(AKafel);
  end;
end;

procedure TKafel.Draw;
begin
  fomegaImageList.ImageList.Items[fIdobraz].Draw4Col(Round(fA.X),
                                                     Round(fA.Y),
                                                     Round(fB.X),
                                                     Round(fB.Y),
                                                     Round(fC.X),
                                                     Round(fC.Y),
                                                     Round(fD.X),
                                                     Round(fD.Y),
                                                     0,0,0,1,1,
                                                     OmegaColor(Round(255+fA.h),Round(255+fA.h),Round(255+fA.h),255),
                                                     OmegaColor(Round(255+fB.h),Round(255+fB.h),Round(255+fB.h),255),
                                                     OmegaColor(Round(255+fC.h),Round(255+fC.h),Round(255+fC.h),255),
                                                     OmegaColor(Round(255+fD.h),Round(255+fD.h),Round(255+fD.h),255),
                                                     fIdKlatka,0);
end;

procedure TKafel.UaktualniWspolrzedne(Const AA,Ab,Ac,Ad:TWspolrzedna);
begin
  fA:=AA;
  fB:=AB;
  fC:=AC;
  fD:=AD;
end;

procedure RysujKafle;
var
 i:integer;
begin
 for i:=0 to ListaKafli.Count-1 do
 PKafel(ListaKafli.Items[i])^.Draw;
end;
procedure UaktualnijWspolrzedneKafli;
var
 i,
 idPunkt:integer;    //indeks Punktu tworzącego gorny lewy rog Kafla;
 w,k:integer;
 AA,AB,AC,AD:TWspolrzedna;
begin
 i:=0;
 for w:=0 to SiatkaMapy.y-2 do
  for k:=0 to SiatkaMapy.x-2 do begin
      idPunkt:=k+w*SiatkaMapy.x;

      AA.x:=PPunkt(Lista.Items[idPunkt])^.x;
      AA.y:=PPunkt(Lista.Items[idPunkt])^.y+PPunkt(Lista.Items[idPunkt])^.fh;
      AA.h:=PPunkt(Lista.Items[idPunkt])^.fh;

      AB.x:=PPunkt(Lista.Items[idPunkt+1])^.x;
      AB.y:=PPunkt(Lista.Items[idPunkt+1])^.y+PPunkt(Lista.Items[idPunkt+1])^.fh;
      AB.h:=PPunkt(Lista.Items[idPunkt+1])^.fh;

      AC.x:=PPunkt(Lista.Items[idPunkt+1+SiatkaMapy.x])^.x;
      AC.y:=PPunkt(Lista.Items[idPunkt+1+SiatkaMapy.x])^.y+PPunkt(Lista.Items[idPunkt+1+SiatkaMapy.x])^.fh;
      AC.h:=PPunkt(Lista.Items[idPunkt+1+SiatkaMapy.x])^.fh;

      AD.x:=PPunkt(Lista.Items[idPunkt+SiatkaMapy.x])^.x;
      AD.y:=PPunkt(Lista.Items[idPunkt+SiatkaMapy.x])^.y+PPunkt(Lista.Items[idPunkt+SiatkaMapy.x])^.fh;
      AD.h:=PPunkt(Lista.Items[idPunkt+SiatkaMapy.x])^.fh;

      PKafel(ListaKafli.Items[i])^.UaktualniWspolrzedne(AA,AB,AC,AD);
      inc(i);
 end;
end;
end.
