unit USilnik;

interface

Uses
	Windows,
   Classes,
   SysUtils,

   UKlasy;

Type

Silnik = class(TObject)
private
	Lista : TList;

public
	procedure Add(wsk : Figura);
   procedure Show();
   procedure Move();
   procedure Sprawdz_kolizje(const nazwa : String; x1, y1, x2, y2 : Integer);
   procedure Przestaw_te_w_kolizji(const nazwa : String; x1, y1, x2, y2 : Integer);

	function  Spr_czy_jest_kolizja(x1, y1, x2, y2,
                                  x1b, y1b, x2b, y2b : Integer) : Boolean;

	constructor Create(); virtual;
   destructor  Destroy(); override;
end;

implementation

constructor Silnik.Create();
begin
	Lista := TList.Create();
end;

destructor Silnik.Destroy();
var
	wsk : Figura;
   lp  : Integer;

begin
	if not Assigned(Lista) then
   begin
   	exit;
   end;

	lp := 0;
   for lp := 0 to Lista.Count - 1 do
   begin
   	wsk := Figura(Lista.Items[lp]);
      wsk.Free();
   end;

   Lista.Clear();
	FreeAndNil(Lista);
end;

procedure Silnik.Show();
var
	wsk : Figura;
   lp  : Integer;

begin
   if not Assigned(Lista) then
   begin
		exit;
   end;

   for lp := 0 to Lista.Count-1 do
   begin
   	wsk := Figura(Lista.Items[lp]);
      wsk.Show();
   end;
end;

procedure Silnik.Move();
var
	nazwa : String;
	wsk   : Figura;
   il    : Integer;
   lp    : Integer;
   x1    : Integer;
   y1    : Integer;
   x2    : Integer;
   y2    : Integer;

begin
   if not Assigned(Lista) then
   begin
		exit;
   end;

	nazwa := '';
	wsk   := Nil;
   il    := 0;
   lp    := 0;
   x1    := 0;
   y1    := 0;
   x2    := 0;
   y2    := 0;

	for lp := 0 to Lista.Count - 1 do
   begin
   	wsk := Figura(Lista.Items[lp]);
      x1 := wsk.Get_x1();
      y1 := wsk.Get_y1();
      x2 := wsk.Get_x2();
      y2 := wsk.Get_y2();

      wsk.Get_etykieta(nazwa);

      wsk.Move();

      Sprawdz_kolizje(nazwa, x1, y1, x2, y2);

      wsk.Show();
   end;
end;

procedure Silnik.Add(wsk : Figura);
begin
	Lista.Add(wsk);
end;

procedure Silnik.Sprawdz_kolizje(const nazwa: String; x1, y1, x2, y2: Integer);
var
	nazwa2 : String;
	wsk    : Figura;
   lp     : Integer;

begin
	nazwa2 := '';
   wsk    := Nil;
   lp     := 0;

   // dla każdej figury poza samą sobą
   for lp := 0 to Lista.Count - 1 do
   begin
   	wsk := Figura(Lista.Items[lp]);
      wsk.Get_etykieta(nazwa2);

      if nazwa <> nazwa2 then
      begin
      	Przestaw_te_w_kolizji(nazwa, x1, y1, x2, y2);
      end;
   end;
end;

procedure Silnik.Przestaw_te_w_kolizji(const nazwa: String; x1, y1, x2, y2: Integer);
var
   jest_w_kolizji        : Boolean;
   zmien_wlasny_kierunek : Boolean;
   w_gore                : Boolean;
   w_lewo                : Boolean;
   w_gore_b              : Boolean;
   w_lewo_b              : Boolean;
   lp                    : Integer;
   wsk                   : Figura;
   nazwa2                : String;
   x1b                   : Integer;
   y1b                   : Integer;
   x2b                   : Integer;
   y2b                   : Integer;

begin
   // sprawdzam które figury znajdują się w kolizji z badaną figurą
   // i zmieniam im kierunek
   jest_w_kolizji        := false;
   zmien_wlasny_kierunek := false;
   w_gore                := false;
   w_lewo                := false;
   w_gore_b              := false;
   w_lewo_b              := false;
   lp                    := 0;
	wsk                   := Nil;
   nazwa2                := '';
   x1b                   := 0;
   y1b                   := 0;
   x2b                   := 0;
   y2b                   := 0;

   // dla każdej figury tylko nie dla samej siebie
   for lp := 0 to Lista.Count - 1 do
   begin
   	wsk := Figura(Lista.Items[lp]);

      wsk.Get_etykieta(nazwa2);

      if nazwa <> nazwa2 then
      begin
         // współrzędne drugiej figury
	      x1b := wsk.Get_x1();
   	   y1b := wsk.Get_y1();
	      x2b := wsk.Get_x2();
   	   y2b := wsk.Get_y2();

			jest_w_kolizji := Spr_czy_jest_kolizja(x1 , y1 , x2 , y2 ,
                                                x1b, y1b, x2b, y2b);

			if jest_w_kolizji then
         begin
				if(zmien_wlasny_kierunek = false) then
            begin
            	zmien_wlasny_kierunek := true;
            end;

				w_gore_b := wsk.Get_w_gore();
            w_lewo_b := wsk.Get_w_lewo();

            wsk.Set_w_gore(not w_gore_b);
            wsk.Set_w_lewo(not w_lewo_b);
         end;
      end;
   end;

	if zmien_wlasny_kierunek then
   begin
   	// znajdz samą siebie
      for lp := 0 to Lista.Count - 1 do
      begin
         wsk := Figura(Lista.Items[lp]);
         wsk.Get_etykieta(nazwa2);

         if nazwa = nazwa2 then
         begin
         	w_gore := wsk.Get_w_gore();
            w_lewo := wsk.Get_w_lewo();

            wsk.Set_w_gore(not w_gore);
            wsk.Set_w_lewo(not w_lewo);
         end;
      end;
   end;
end;

function Silnik.Spr_czy_jest_kolizja(x1, y1, x2, y2,
                                     x1b, y1b, x2b, y2b : Integer): Boolean;
var
	jest_kolizja : Boolean;
   war1         : Boolean;
   war2         : Boolean;
   war3         : Boolean;
   war4         : Boolean;
   war5         : Boolean;
   war6         : Boolean;
   war7         : Boolean;
   war8         : Boolean;

begin
	jest_kolizja := false;
   war1         := false;
   war2         := false;
   war3         := false;
   war4         := false;
   war5         := false;
   war6         := false;
   war7         := false;
   war8         := false;
	
   // wierzchołek (x1,y1)
   war1 := ((x1 >= x1b) and (x1 <= x2b) and (y1 >= y1b) and (y1 <= y2b));
   // wierzchołek (x2,y1)
   war2 := ((x2 >= x1b) and (x2 <= x2b) and (y1 >= y1b) and (y1 <= y2b));
   // wierzchołek (x1,y2)
   war3 := ((x1 >= x1b) and (x1 <= x2b) and (y2 >= y1b) and (y2 <= y2b));
   // wierzchołek (x2,y2)
   war4 := ((x2 >= x1b) and (x2 <= x2b) and (y2 >= y1b) and (y2 <= y2b));
   // wierzchołek (x1b, y1b)
   war5 := ((x1b >= x1) and (x1b <= x2) and (y1b >= y1) and (y1b <= y2));
   // wierzchołek (x2b, y1b)
   war6 := ((x2b >= x1) and (x2b <= x2) and (y1b >= y1) and (y1b <= y2));
	// wierzchołek (x2b, y1b)
   war7 := ((x2b >= x1) and (x2b <= x2) and (y1b >= y1) and (y1b <= y2));
   // wierzchołek (x2b, y2b)
   war8 := ((x2b >= x1) and (x2b <= x2) and (y2b >= y1) and (y2b <= y2));
	
   if(war1 or war2 or war3 or war4 or war5 or war6 or war7 or war8) then
   begin
      jest_kolizja := true;
   end;

	Result := jest_kolizja;
end;


end.


