| Autor |
Beitrag |
Waldkauz
      
Beiträge: 102
|
Verfasst: Do 28.05.09 22:52
Hallo
Wie bereits beschrieben, mach ich ein Spiel.
Auf einem Image bewegen sich zwei Images.
Wenn Image2 auf Image3 trifft, bzw. umgekehrt, soll der Timer angehalten werden.
Ich hab da zwar eine Ahnung, wie ich das machen könnte, und zwar, dass er ihn ausschaltet, sobald mindestens ein Pixel des jeweiligen Image den gleichen Abstand (Left, Top) hat, wie das andere - aber das wird ja 'ne ziemlich umständliche Schleife...
Gehts auch einfacher?
mfg
Markus
|
|
jaenicke
      
Beiträge: 19336
Erhaltene Danke: 1751
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 29.05.09 00:28
Prüfe einfach für alle vier Ecken des zweiten Images, ob der Punkt im Rechteck des ersten Images ist... Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| var FirstImgRect, SecondImgRect: TRect; begin FirstImgRect := FirstImage.BoundsRect; SecondImgRect := SecondImage.BoundsRect; if PtInRect(SecondImgRect.TopLeft, FirstImgRect) or PtInRect(Point(SecondImgRect.Right, SecondImgRect.Top), FirstImgRect) or ... then | Wenn die Kollision schon vor dem Überlappen ausgelöst werden soll, füge vor der Abfrage noch ein OffsetRect(FirstImage, -1, -1); hinzu, damit das erste Rechteck ein Pixel in jeder Richtung größer ist.
|
|
Waldkauz 
      
Beiträge: 102
|
Verfasst: Sa 30.05.09 11:01
jaenicke hat folgendes geschrieben : | Prüfe einfach für alle vier Ecken des zweiten Images, ob der Punkt im Rechteck des ersten Images ist... Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| var FirstImgRect, SecondImgRect: TRect; begin FirstImgRect := FirstImage.BoundsRect; SecondImgRect := SecondImage.BoundsRect; if PtInRect(SecondImgRect.TopLeft, FirstImgRect) or PtInRect(Point(SecondImgRect.Right, SecondImgRect.Top), FirstImgRect) or ... then | Wenn die Kollision schon vor dem Überlappen ausgelöst werden soll, füge vor der Abfrage noch ein OffsetRect(FirstImage, -1, -1); hinzu, damit das erste Rechteck ein Pixel in jeder Richtung größer ist. |
mein Gott, stell ich mich jetzt blöd an, aber was sind die anderen zwei Parameter? 
|
|
Marc.
      
Beiträge: 1876
Erhaltene Danke: 129
Win 8.1, Xubuntu 15.10
|
Verfasst: Sa 30.05.09 11:08
Alle vier Ecken, zwei bleiben also noch übrig: Bottom Left und Bottom Right. 
|
|
Waldkauz 
      
Beiträge: 102
|
Verfasst: Sa 30.05.09 11:16
|
|
Marc.
      
Beiträge: 1876
Erhaltene Danke: 129
Win 8.1, Xubuntu 15.10
|
Verfasst: Sa 30.05.09 11:37
|
|
ffgorcky
      
Beiträge: 573
WIN XP/2000 & 7Prof (Familie:Win95,Win98)
|
Verfasst: Sa 30.05.09 11:42
Also wenn ich das gerade richtig überblicke, dann möchtest Du sowas schreiben:
Delphi-Quelltext 1: 2: 3:
| if PruefeObKollision(Image2,Image3) or PruefeObKollision(Image3,Image2) then ShowMessage('Ja! Sie haben sich getroffen!'); |
Und die Abfrage wäre dann so:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| function PruefeObKollision(erstesImage,zweitesImage:TImage):boolean begin if erstesImage.Left<zweitesImage.Left+zweitesImage.width and zweitesImage.Left<erstesImage.Left+erstesImage.width and zweitesImage.top<erstesImage.top+erstesImage.height then PruefeObKollision:=true; if erstesImage.Left<zweitesImage.Left+zweitesImage.width and zweitesImage.Top>erstesImage.Top+erstesImage.Height and erstesImage.top>zweitesImage.top+zweitesImage.height then PruefeObKollision:=true; end; |
- Oder?
Ich kann jetzt leider so spontan nicht sagen, ob ich da jetzt alles richtig geschrieben habe (da ich das hier momentan leider schlecht überprüfen kann) und:
Ich weiß leider im Moment auch keine einfachere, prozessorsparendere Lösung.
Zuletzt bearbeitet von ffgorcky am Sa 30.05.09 12:02, insgesamt 1-mal bearbeitet
|
|
Marc.
      
Beiträge: 1876
Erhaltene Danke: 129
Win 8.1, Xubuntu 15.10
|
Verfasst: Sa 30.05.09 12:00
Ich hab auch noch schnell etwas gebastelt. Es funktioniert jedenfalls.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| if (FirstImage.Left + FirstImage.Width <= SecondImage.Left) and (FirstImage.Left >= (SecondImage.Left + SecondImage.Width)) or (FirstImage.Left <= SecondImage.Left + SecondImage.Width) and (FirstImage.Left + FirstImage.Width >= SecondImage.Left) and ((FirstImage.Top <= SecondImage.Top + SecondImage.Height) and (FirstImage.Top + FirstImage.Height >= SecondImage.Top) or (FirstImage.Top + FirstImage.Height >= SecondImage.Top) and (FirstImage.Top <= SecondImage.Top + SecondImage.Height)) then ... |
Grüße,
Marc
|
|
ffgorcky
      
Beiträge: 573
WIN XP/2000 & 7Prof (Familie:Win95,Win98)
|
Verfasst: Sa 30.05.09 12:09
Ja Marc, ich denke nur, dass meine Lösung (so sie denn funktioniert - was ich ja hoffe) dadurch, dass ich die Abfragen auf jeweils nur von links und oben beschränkt habe und das ganze dann einfach nur noch einmal mit vertauschten Parametern (also Image2 und Image3 umgedreht) abfrage, das ganze doch übersichtlicher und schneller mal wieder zu ändern macht - oder?
Siehst Du das nicht so?
|
|
Marc.
      
Beiträge: 1876
Erhaltene Danke: 129
Win 8.1, Xubuntu 15.10
|
Verfasst: Sa 30.05.09 12:16
Das mag sein. Ich muss zugeben den Source relativ flott und ohne Gedanken runtergetippt zu haben. Ich muss jetzt auch leider direkt los, werd mir später nochmal den Kopf darüber zerbrechen.
Edit: Bei meinem Beispiel ließen sich auch die Parameter austauschen, vorrausgesetzt du verwendest ein entsprechendes Funktionsgerüst, wie bei dir.
Zudem, performanter wird dein Beispiel, wenn du statt den IF-Abfragen direkt den Boolschen-Wert als Rückgabe verwendest.
Timer1.Enabled := (A and B) or ..
Grüße,
Marc
|
|
Waldkauz 
      
Beiträge: 102
|
Verfasst: Sa 30.05.09 12:42
hab jetzt mal alle durchprobiert...
Sind zwar frei von Fehlermeldungen, aber funktionieren tun sie nicht...die Images "fliegen" trotzdem weiter
|
|
SvenAbeln
      
Beiträge: 334
Erhaltene Danke: 3
|
Verfasst: Sa 30.05.09 14:10
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| function CheckCollision(FirstImage, SecondImage: TImage): boolean; var FirstImgRect, SecondImgRect: TRect; begin FirstImgRect := FirstImage.BoundsRect; SecondImgRect := SecondImage.BoundsRect;
Result := (FirstImgRect.Left <= SecondImageRect.Right) and (FirstImgRect.Right>= SecondImageRect.Left) and (FirstImgRect.Top) <= SecondImageRect.Bottom) and (FirstImgRect.Bottom >= SecondImageRect.Top); end; |
@ ffgorcky
In deiner Funktion prüfst du einige Bedingungen unötigerweise doppelt, ausserdem mußt du die beiden Abfragen noch miteinander verküpfen. Im Moment können die beiden Images sich über bzw untereinander befinden und du meldest trotzdem eine Kollision, da deine erste Bedingung schon erfüllt ist. z.B. Image2.Top = 5 und Image2.Top = 500
Ausserdem hast du noch einen groben Fehler:
Sollte es keine Kollision geben, wird bei dir gar kein Ergebnis geliefert, Result ist dann also undefiniert.
Delphi-Quelltext 1:
| if PruefeObKollision(Image2,Image3) or PruefeObKollision(Image3,Image2) then |
So ein Aufruf ist auch unnötig und eher verwirrent, denn wenn zwei Images kollidieren ist es egal in welcher Reihenfolge ich dies prüfe.
@ Marc.
Delphi-Quelltext 1: 2:
| if (FirstImage.Left + FirstImage.Width <= SecondImage.Left) and (FirstImage.Left >= (SecondImage.Left + SecondImage.Width)) |
Das wird nur Wahr für folgende Bedingungen:
Delphi-Quelltext 1: 2:
| FirstImage.Left = SecondImage.Left und FirstImage.Width = SecondImage.Width = 0 | da ein Bild nicht gleichzeitig Links und Rechts von einem anderen sein kann.
|
|
jaenicke
      
Beiträge: 19336
Erhaltene Danke: 1751
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 30.05.09 15:19
Ja, die Parameter für PtInRect habe ich vertauscht, aber ansonsten klappt das so wie ich anfangs geschrieben habe... Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| var FirstImgRect, SecondImgRect: TRect; begin FirstImgRect := FirstImage.BoundsRect; SecondImgRect := SecondImage.BoundsRect; if PtInRect(FirstImgRect, SecondImgRect.TopLeft) or PtInRect(FirstImgRect, Point(SecondImgRect.Right, SecondImgRect.Top)) or PtInRect(FirstImgRect, Point(SecondImgRect.Left, SecondImgRect.Bottom)) or PtInRect(FirstImgRect, SecondImgRect.BottomRight) then | Marc. hat folgendes geschrieben : | Das wird aber so nur funktionieren, wenn das zweite Image kleiner-gleich groß dem Ersten ist.  |
Das verstehe ich nicht, warum?
Einloggen, um Attachments anzusehen!
|
|
Waldkauz 
      
Beiträge: 102
|
Verfasst: Sa 30.05.09 15:50
es geht immer noch nicht...
hier mal der quelltext:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| procedure TForm2.Button5Click(Sender: TObject); var FirstImgRect, SecondImgRect: TRect; begin FirstImgRect := Image2.BoundsRect; SecondImgRect := Image4.BoundsRect; if PtInRect(FirstImgRect, SecondImgRect.TopLeft) or PtInRect(FirstImgRect, Point(SecondImgRect.Right, SecondImgRect.Top)) or PtInRect(FirstImgRect, Point(SecondImgRect.Left, SecondImgRect.Bottom)) or PtInRect(FirstImgRect, SecondImgRect.BottomRight) then Timer4.Enabled:=false; |
|
|
jaenicke
      
Beiträge: 19336
Erhaltene Danke: 1751
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 30.05.09 15:53
Das gehört ja wohl eher in den Timer und nicht in den ButtonClick, oder?
Dass es prinzipiell funktioniert, siehst du ja an der Demo, ich weiß ja nicht was du anders machst. Ich vermute der ButtonClick passiert nur nicht im richtigen Moment...
|
|
Waldkauz 
      
Beiträge: 102
|
Verfasst: Sa 30.05.09 15:56
jaenicke hat folgendes geschrieben : | Das gehört ja wohl eher in den Timer und nicht in den ButtonClick, oder?
Dass es prinzipiell funktioniert, siehst du ja an der Demo, ich weiß ja nicht was du anders machst. Ich vermute der ButtonClick passiert nur nicht im richtigen Moment... |
upps  , hast recht, das kommt in den Timer...
jetzt funktionierts!
Vielen Dank an alle!
|
|
Marc.
      
Beiträge: 1876
Erhaltene Danke: 129
Win 8.1, Xubuntu 15.10
|
Verfasst: Sa 30.05.09 17:55
|
|
Waldkauz 
      
Beiträge: 102
|
Verfasst: Mi 03.06.09 19:52
Marc. hat folgendes geschrieben : | | Angenommen, du willst wissen, ob eine größeres Rect ein kleineres schluckt und testest dabei nur die äußerden Punkte des größeren Rects... dann kann's durchrutschen. |
Und wie kann ich das verhindern, dass es "durchrutscht" ?
Denn genau das Problem habe ich jetzt.
Wenn das größere Image nun auf dem kleineren liegt (da das größere eine Zufallsposition hat) und es praktisch verdeckt, treten nicht die Paramter einer Kollision ein.
Moderiert von Narses: Zitat gekürzt.
|
|
Waldkauz 
      
Beiträge: 102
|
Verfasst: Do 18.06.09 00:33
push (sorry, aber das Problem mit dem Durchrutschen hab ich nach wie vor).
Und wird das nicht ein wenig zu aufwendig für eine Art Arkanoid-Spiel?
|
|
SvenAbeln
      
Beiträge: 334
Erhaltene Danke: 3
|
Verfasst: Do 18.06.09 09:37
|
|
|