Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - shape problem - randdefinierung schlägt fehl


suga2001 - Di 06.01.09 14:30
Titel: shape problem - randdefinierung schlägt fehl
Hallo ^^
Ich soll einen Ball von einem shape abprallen lassen. Die Seiten und Eckpunkte habe ich defniniert, aber der ball "fliegt" bis zur Hälfte einfach durch. Woran liegt das?
alles habe ich in einen Timer gepackt :


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
procedure TForm1.Timer1Timer(Sender: TObject);
var Mittelpunkt:TPoint;
Punkte:integer;
begin
Punkte:=0;
//Image(Ball) um Schrittweite bewegen
Image1.Left:=Image1.Left +vx;
Image1.Top:=Image1.Top +vy;
if (Image1.Left <= Panel1.Left) OR (Image1.Left >= Panel1.Width - Image1.Width -1)
then vx:=vx*-1// links und rechts
Mittelpunkt:=Image1.BoundsRect.BottomRight;
Mittelpunkt.x:=Mittelpunkt.X-Image1.Width DIV 2;

if PtInRect(Shape1.BoundsRect,Mittelpunkt) THEN vy:=vy*-1;
Mittelpunkt:=Image1.BoundsRect.BottomRight;
Mittelpunkt:=Image1.BoundsRect.TopLeft;
Mittelpunkt.x:=Mittelpunkt.X-Image1.Width DIV 2;

if PtInRect(Shape2.BoundsRect,Mittelpunkt) THEN vy:=vy*-1;
Mittelpunkt:=Image1.BoundsRect.BottomRight;
Mittelpunkt:=Image1.BoundsRect.TopLeft;

Mittelpunkt.x:=Mittelpunkt.X-Image1.Width DIV 2;


if (Image1.Top <= Panel1.Top) OR (Image1.Top >= Panel1.Height -Image1.Height -1)
then vy:= vy*-1//oben und unten

if (image1.Top >=Panel1.Height - Image1.Height-1)then inc(Punkte);
Label2.Caption:=inttostr(Punkte);


end;


Sieht jemand, wo mein Fehler ist oder was ich vergessen habe?`
Danke schon mal im Voraus ^^


Marc. - Di 06.01.09 14:48
Titel: Re: shape problem - randdefinierung schlägt fehl
Du musst den Radius bzw. die Seitenlängen in deiner Berechnung berücksichtigen. ;)
So in etwa sollte es gehen - hab es jetzt nicht getestet. Muss jetzt auch schnell weg.
user profile iconsuga2001 hat folgendes geschrieben Zum zitierten Posting springen:
if ((Image1.Left + Radius) => Panel1.Left) and (Image1.Left <= Panel1.Left + Panel1.Width)


Grüße,
Marc

PS: Deine Formatierung ist ein Graus.


jaenicke - Di 06.01.09 15:48
Titel: Re: shape problem - randdefinierung schlägt fehl
user profile iconsuga2001 hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
if PtInRect(Shape1.BoundsRect,Mittelpunkt) THEN vy:=vy*-1;
Mittelpunkt:=Image1.BoundsRect.BottomRight;
Mittelpunkt:=Image1.BoundsRect.TopLeft;
Mittelpunkt.x:=Mittelpunkt.X-Image1.Width DIV 2;

if PtInRect(Shape2.BoundsRect,Mittelpunkt) THEN vy:=vy*-1;
Mittelpunkt:=Image1.BoundsRect.BottomRight;
Mittelpunkt:=Image1.BoundsRect.TopLeft;

Mittelpunkt.x:=Mittelpunkt.X-Image1.Width DIV 2;
Kann es sein, dass du denkst, dass zu dem if alles danach gehört? Das stimmt nicht. Die korrekte Einrückung:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
if PtInRect(Shape1.BoundsRect,Mittelpunkt) then
  vy := vy * -1;

Mittelpunkt := Image1.BoundsRect.BottomRight;
Mittelpunkt := Image1.BoundsRect.TopLeft;
Mittelpunkt.x := Mittelpunkt.X - Image1.Width div 2;

if PtInRect(Shape2.BoundsRect,Mittelpunkt) then
  vy := vy * -1;

Mittelpunkt : =Image1.BoundsRect.BottomRight;
Mittelpunkt := Image1.BoundsRect.TopLeft;
Mittelpunkt.x := Mittelpunkt.X - Image1.Width div 2;
Die if-Abfragen habe ich einzeln geschrieben um zu zeigen, dass die mir den folgenen Zeilen jeweils nix zu tun haben. Du weist also Mittelpunkt und vy immer wieder neu zu. Auch in diesen Zeilen bereits:

Delphi-Quelltext
1:
2:
Mittelpunkt := Image1.BoundsRect.BottomRight;
Mittelpunkt := Image1.BoundsRect.TopLeft;
In der zweiten Zeile überschreibst du den Wert der ersten.

Wenn du mehrere Befehle in if schreiben willst, dann musst du begin..end benutzen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
if PtInRect(Shape1.BoundsRect,Mittelpunkt) then
begin
  vy := vy * -1;
  Mittelpunkt := Image1.BoundsRect.BottomRight;
  Mittelpunkt := Image1.BoundsRect.TopLeft;
  Mittelpunkt.x := Mittelpunkt.X - Image1.Width div 2;
end;
Da hier aber die Befehle ohnehin wiederholt werden, lässt sich dein aktueller Quelltext auch stark kürzen, die auskommentierten Zeilen haben keine Wirkung, was dir eigentlich auch der Compiler sagen sollte...

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
procedure TForm1.Timer1Timer(Sender: TObject);
var
  Mittelpunkt: TPoint;
  Punkte: Integer;
begin
  Punkte := 0;
  // Image(Ball) um Schrittweite bewegen
  Image1.Left := Image1.Left + vx;
  Image1.Top := Image1.Top + vy;
  if (Image1.Left <= Panel1.Left) or (Image1.Left >= Panel1.Width - Image1.Width -1then
    vx := vx * -1// links und rechts
  //Mittelpunkt := Image1.BoundsRect.BottomRight;
  //Mittelpunkt.x := Mittelpunkt.X - Image1.Width div 2;

  if PtInRect(Shape1.BoundsRect,Mittelpunkt) then
    vy := vy * -1;
  //Mittelpunkt := Image1.BoundsRect.BottomRight;
  //Mittelpunkt := Image1.BoundsRect.TopLeft;
  //Mittelpunkt.x := Mittelpunkt.X - Image1.Width div 2;

  if PtInRect(Shape2.BoundsRect,Mittelpunkt) then
    vy := vy * -1;
  //Mittelpunkt := Image1.BoundsRect.BottomRight;
  Mittelpunkt := Image1.BoundsRect.TopLeft; // <-- HIER weist du Mittelpunkt zuletzt zu, dies ist der benutzte Wert!
  Mittelpunkt.x := Mittelpunkt.X - Image1.Width div 2;

  if (Image1.Top <= Panel1.Top) or (Image1.Top >= Panel1.Height -Image1.Height -1then
    vy := vy * -1//oben und unten

  if (image1.Top >= Panel1.Height - Image1.Height-1then
    Inc(Punkte);
  Label2.Caption := IntToStr(Punkte);
end;


suga2001 - Mo 12.01.09 20:46

Danke für die schnelle und informative Antwort.
Ich habe den Quelltext nun übernommen und ausprobiert. Leider hat das nun den Effekt, dass mein image1 einfach durch meine shapes durchfliegt, als wenn sie gar nicht da wären.
Vorher ist image1 noch am oberen rand des shapes abgeprallt, was nun nicht mehr so ist. ich bin echt ratlos...


Marc. - Mo 12.01.09 21:43

user profile iconsuga2001 hat folgendes geschrieben Zum zitierten Posting springen:
Danke für die schnelle und informative Antwort.

Habe ich dir nicht auch geantwortet? :roll:
Nochmal: Du musst zur Position die Breite dazurechnen!

Delphi-Quelltext
1:
2:
 if ((Image1.Left + Image1.Width) >= Panel1.Left) and (Image1.Left <= Panel1.Left + Panel1.Width)  then
  vx:=vx*-1;

Funktioniert bei mir tadellos...

Warum die Breite wichtig ist:

Delphi-Quelltext
1:
2:
3:
4:
5:
    A-------B
   // A gibt die linke Kante deines Images an und befindet sich an der Stelle "Left". 
   // Das Image besteht jedoch nicht nur aus einer Kante, sondern bildet ein ganzes Rechteck,
   // dargestellt durch die Striche. Mit A+Width kommst du zur rechten Kante, die du bei der Kollision von Links mit dem Panel prüfst.
   // und vice versa...


Grüße,
Marc.


suga2001 - Mo 12.01.09 21:46

doch, hast du ^^ . das war ernst gemeint :roll: . ich fand alles informativ :idea: , aber nun ist mir aufgefallen,dass ich mir die ganze Zeit falsch ausgedrückt habe. von meinen panelseiten prallt der ball wunderbar ab. :wink:

wenn der aber auf mein shap1 trifft, bleibt er hängen oder stottert, fliegt sogar manchmal einfach ein stücks ins shape, wobei ich auch da die grenzen definiert habe.


jaenicke - Di 13.01.09 13:31

Ich hab jetzt nochmal geschaut. Die auskommentierten Zeilen haben doch teilweise eine Wirkung, weil du prüfst, ob der Punkt in dem Rechteck liegt und da verschiedene Punkte des Rechtecks angibst. :oops:
Aber was das bewirken soll ist mir nicht so klar.

Wie wäre es, wenn du eine Funktion schreibst, die dir zurückgibt, ob es eine Kollision gibt, wenn du zwei Rechtecke der Komponenten und die aktuelle Bewegung übergibst. Dann prüfst du eine Kollision bei der aktuellen Bewegung in x-Richtung und y-Richtung und kehrst ggf. die entsprechende Bewegung um.