Entwickler-Ecke

Sonstiges (Delphi) - Kollisionsabfrage


Thunderbird95 - Mi 05.01.11 00:38
Titel: Kollisionsabfrage
hallo nochmal,

hab noch ne kleine Frage:

und zwar habe ich mehrere Bildelemente in einem Programm. Eines (Image 1) möchte ich mit den Pfeiltasten bewegen (funktioniert). Das andere (Image 2) bewegt sich mit einer timer prozedur (funktioniert auch). Wenn nun Image 1 das Image 2 berührt soll Image 2 "verschwinden". Jetzt weiß ich allerdings nicht wie ich das abfragen kann.

Danke im voraus
Thunderbird95

achso hier noch ein wenig quelltext:

Image 1:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin

  if Key = vk_right
    then Image1.Left := Image1.Left +10;
  if Key = vk_Left
    then Image1.Left := Image1.Left -10;
  if Key = vk_Up
    then Image1.Top := Image1.Top -10;
  if Key = vk_down
    then Image1.Top := Image1.Top +10;

end;

Image 2:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
procedure TForm1.TiImage2Timer(Sender: TObject);
begin
if Image2 = True                                          //Legende: Image2 = Boolesche Variable
  then                                                    //       ImImage2 = Bildelement       
    if ImImage2.Left > 10                                 //       TiImage2 = Timer
      then 
        ImImage2.Left := ImImage2.Left -2
      else 
        ImImage2 := False
  else
    if ImImage2.Left < Form1.ClientWidth-ImImage2.Width-15
      then 
        ImImage2.Left := ImImage2.Left+2
      else 
        Image2:=True;


bummi - Mi 05.01.11 02:01

Die Kollisionsabfrage:

Delphi-Quelltext
1:
2:
3:
4:
5:
var
  r:Trect;
begin
  if InterSectRect(r,image1.BoundsRect,image2.BoundsRect) then  TuwasWeilKollision;
end;


Thunderbird95 - Mi 05.01.11 10:28

erstmal vielen dank^^

dann hab ich noch fragen zu dem quelltext (leider :cry: ):

1. diese Rect variable melde ich doch dann ganz normal unter private an, oder??
2. was heißt InterSectRect ??
3. was ist eine Rect variable??
4. und schließlich: was bedeutet das hier:

Delphi-Quelltext
1:
(r,image1.BoundsRect,image2.BoundsRect)                    


thepaine91 - Mi 05.01.11 10:35

Es gibt so eine Taste die nennt sich F1 damit kannst du dir die Fragen doch selbst beantworten.
Falls nicht wird google die Antwort wissen. ^^

Und wieso soll die Variable private angelegt werden?
Einfach in der Funktion wo die Kollision geprüft wird eine Lokale Variable nehmen. (Steht aber auch so in seinem Codeausschnitt)


elundril - Mi 05.01.11 10:40

user profile iconThunderbird95 hat folgendes geschrieben Zum zitierten Posting springen:
erstmal vielen dank^^

dann hab ich noch fragen zu dem quelltext (leider :cry: ):

1. diese Rect variable melde ich doch dann ganz normal unter private an, oder??
2. was heißt InterSectRect ??
3. was ist eine Rect variable??
4. und schließlich: was bedeutet das hier:

Delphi-Quelltext
1:
(r,image1.BoundsRect,image2.BoundsRect)                    


1) Das kannst du sogar lokal in einer Prozedur anmelden, das rect, da du es ja nicht wirklich brauchst. Du musst es nur übergeben weil InterSectRect es haben will.

2) InterSectRect ist eine API-Funktion von Windows, welche dir, wie der Name schon sagt, den Bereich zurückliefert wo sich die 2 übergebenen Bereich überschneiden. Zusätzlich aber bekommst du noch eine Booleanvariable heraus die dir sagt OB sie sich überschneiden. Diese verwendest du auch dann in der If-Abfrage wie man sieht.

3) Ein Rect ist ein Viereck, definiert durch 4 Abstände. Oben, Links, Unten, Rechts.

4) Das sind einfach die Übergabeparameter der Funktion. Der erste ist dein Rect, vom überschneidenden Bereich, das du zurückbekommst, die 2 anderen sind Rects die aus der Größe deiner Imagekomponenten erstellt wurden.

Ich würde dir mal empfehlen das Delphi-Wikibook [http://de.wikibooks.org/wiki/Programmierkurs:_Delphi] und Christians Crashkurs [http://www.christian-stelzmann.de/index_tutorials_crashkurs.html] zu lesen. Außerdem solltest du öfter auf die Hilfefunktion zurückgreifen und ein bisschen googeln. Ein klein wenig eigeninitiative kann ja nicht schaden.

lg elundril


Fiete - Mi 05.01.11 13:16

Moin Thunderbird95,

Hinter Kollisionsabfragen steckt ein bißchen Mathematik.

Ein altes Beispiel für Rechtecke
Mensch ist ein TImage

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
function TLaby.Kollision:Boolean;
  var K:Integer;
      A1,A2,B1,B2:TPoint;
  begin
   Kollision:=False;
   A1.X:=Mensch.Left;A1.Y:=Mensch.Top; // oben links - A1
   A2.X:=Mensch.Left+Mensch.Width;
   A2.Y:=Mensch.Top+Mensch.Height;   // unten rechts - A2
   for K:=1 to 31 do
    begin
     Hindernis:=TImage(FindComponent('Image'+IntToStr(K)));
     B1.X:=Hindernis.Left;B1.Y:=Hindernis.Top; // oben links - B1
     B2.X:=Hindernis.Left+Hindernis.Width;
     B2.Y:=Hindernis.Top+Hindernis.Height;   // unten rechts - B2
     if ((A1.Y<B1.Y) and (B1.Y<A2.Y)) or ((B1.Y<A1.Y) and (A1.Y<B2.Y)) then // Kollision möglich
      if ((B1.X<=A1.X) and (A1.X<=B2.X)) or ((A1.X<=B1.X) and (B1.X<=A2.X)) then
       begin Kollision:=True;exit end;
    end;
  end;

Ein altes Beispiel für Kreise

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
function TEskiv.Kollision(Ball,Hindernis:TShape):Boolean;  // Ball mit Hindernis
  var P1,P2:TPoint;
      R1,R2:Integer;
  begin
   P1.X:=Ball.Left+Ball.Width div 2;
   P1.Y:=Ball.Top+Ball.Height div 2;
   P2.X:=Hindernis.Left+Hindernis.Width div 2;
   P2.Y:=Hindernis.Top+Hindernis.Height div 2;
   R1:=Ball.Width div 2;
   R2:=Hindernis.Width div 2;
   Result:=sqr(P1.X-P2.X)+sqr(P1.Y-P2.Y)<=sqr(R1+R2) 
  end;

Ich hoffe die Mathematik ist nicht zu kompliziert :wink:
Gruß
Fiete