Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Kollision mit Farbe (https://www.delphipraxis.net/142634-kollision-mit-farbe.html)

Notxor 31. Okt 2009 16:47


Kollision mit Farbe
 
Tag auch, hoffe die Frage ist nicht zu trivial, aber wie schafft man es, dass eine Kugel (hab ich schon) mit einem Shape kollidiert?
Wenn ich es so mache, dass ich die Distanz zwischen Shape und Kugel prüfe klappt auch alles wunderbar, nur wäre es besser, wenn er nicht auf das shape direkt reagiert, sondern eher auf die farbe.
Am besten wäre die Farbe "unter" der Kugel (mx,my). Kann man die irgendwie abrufen wenn die kugel sich selbst darüber befindet?

Ach ja, kann man einfach ein Rechteck mit canvas auf die Form zeichnen OHNE image/paint Feld? Ein Error kommt zwar nicht wenn ich es versuche, aber das Rechteck auch nicht.

Hoffe mein WirrWarr an Fragen war einigermaßen verständlich und es erbarmt sich jemand, mir zu helfen .

:thumb:

implementation 31. Okt 2009 17:13

Re: Kollision mit Farbe
 
Durch die erste Frage bin ich jetzt nicht ganz durchgestiegen.

Zur zweiten Frage:
Auf OnPaint reagieren und dann mit Rectangle(X1,Y1,X2,Y2) zeichnen.

Medium 31. Okt 2009 17:16

Re: Kollision mit Farbe
 
Zitat:

Zitat von Notxor
nur wäre es besser, wenn er nicht auf das shape direkt reagiert, sondern eher auf die farbe.

Nein, der geometrische Ansatz ist definitiv überlegen. Wenn du das schon hast, wäre eine Pixelprüfung ein Rückschritt. Lass es besser wie es ist.

Zitat:

Ach ja, kann man einfach ein Rechteck mit canvas auf die Form zeichnen OHNE image/paint Feld? Ein Error kommt zwar nicht wenn ich es versuche, aber das Rechteck auch nicht.
Du kannst natürlich mit Form.Canvas.Rectangle() z.B. direkt auf's Formular zeichnen, allerdings musst du dies dann im Ereignis TForm.OnPaint tun, da es sonst nicht neu gezeichnet wird nachdem irgend etwas dazu geführt hat dass es verdeckt bzw. nicht sichtbar war.
Eine PaintBox zeichnet letztlich auch auf den Canvas des Formulars (hat also keinen eigenen).

Notxor 31. Okt 2009 17:32

Re: Kollision mit Farbe
 
Ok, das mit OnPaint habe ich jetzt.

Auch wenn es ein Rückschritt ist, habe ich sonst keine Idee wie ich es sonst machen sollte.
Es geht um den Tascheneinlauf beim Snooker/Billard. Und den kann ich mit Shapes nicht sonderlich gut darstellen, weshalb ich ihn als Bild etc einfügen/zeichnen wollte und die Kollision dann mit den Pixeln machen.

:gruebel: Irgendwie habe ich mich darauf festgebissen, komme einfach auf keine andere Idee als die Pixelkollision.

himitsu 31. Okt 2009 17:43

Re: Kollision mit Farbe
 
Pixelabfragen sind aber seh unperformant und man kann auch schnell mal was übersehn.

Abgesehn davon ist es nicht einfach von einem Canvas die Pixelfarbe abzufragen, wenn wenn mal irgendwas über dem Pixel ist, dann gibt es diese Farbe nicht mehr.

Nimm den Mittelpunkt der Kugel und einen oder mehrere Punkte innerhalb der Taschen und rechne dir die Abständer der Punkte aus.
Ist einer der Abständer kleiner als die entsprechenden Radien, dann ist der "Ball" drinnen.

Notxor 31. Okt 2009 18:23

Re: Kollision mit Farbe
 
Gut, werde das mal so versuchen. Bringt mich aber zur nächsten Frage, wie/ob man die Stärke der Rundung der gerundeten Rechtecke abfragen/verändern kann.

Edit: ok, ich glaube, diese Frage hat sich erledigt.
Edit: oder auch nicht :(. Mit canvas kein Problem, aber kann man das auch bei Shapes direkt einstellen?

omata 31. Okt 2009 18:32

Re: Kollision mit Farbe
 
Ist der Punkt im Kreis: x² + y² < r²

Notxor 31. Okt 2009 21:15

Re: Kollision mit Farbe
 
Hmm, neues Problem.
Wenn ich versuche, einen Ball von einer beliebigen Seite eines Shapes (Rechteck) zurückzuwerfen, verfangen sich die Bälle am Shape und "zappeln" hin und her.

Code:
if (x-(shape1.Left+shape1.width)<=r) and (y>=shape1.top)and(y<=shape1.top+shape1.height)and (vx<0)
then vx := -vx*reibungbande;           //von rechts nach links

if (Y-(shape1.top+shape1.height)<=R) and (x>=shape1.left)and(x<=shape1.Left+shape1.Width) and (vy<0)
then vy := -vy*reibungbande;         //unten oben

if ((shape1.left)-x <= r)and(y>=shape1.top)and(y<=shape1.top+shape1.height)and (vx>0)
then vx := -vx*reibungbande;                      //links rechts

if (shape1.Top-y<=r) and (x>=shape1.left)and(x<=shape1.Left+shape1.Width) and (vy>0)
then vy := -vy*reibungbande;                       //oben unten
V sind die Geschwindigkeiten, r der Radius, x/y der Mittelpunkt des Balls.
Wenn ich beide horizontalen oder vertikalen Abfragen gleichzeitig aktiviere kommt das Problem, und ich hab leider keine Idee, wie ich das verhindern kann.

olee 31. Okt 2009 23:12

Re: Kollision mit Farbe
 
Es gibt die möglichkeit mit Vektorrechnung herauszufinden, ob der Ball sich denn momentan auch wirklich
auf das Objekt zubewegt, mit dem er wohl kollidiert.
Ich hab das selbst mal so gemacht.

Dazu nimmt man das Punkt-Produkt aus Abstand(Ball <-> Mittelpunkt des Objektes) und dem Geschwindigkeitsvektor
des Balles

Delphi-Quellcode:
  If VectorDotProduct(VectorSub(Ball.Pos, Object.Pos), Ball.vel) < 0 then
  begin
    [...]
  end;
ANMERKUNG: Weil ich das jetzt nicht nachgeprüft hab, könnte es auch sein das da anstatt "< 0" stattdessen
"> 0" stehen muss.

MFG

Medium 1. Nov 2009 01:48

Re: Kollision mit Farbe
 
Du kannst als sehr einfache Lösung den Ball bei Kollision einfach manuell an den Rand des Shapes zurechtschieben. Einfach in Richtung des neuen Vektors um die Länge (R1+R2)-||M2-M1||+e von seiner Position aus, oder von M1 aus um die Länge R1+R2+e verschieben. (M1=Mittelpunkt des Kollisionspartners; M2=Mittelpunkt des Balls; R1=Radius des Kollisionspartners; R2=Radius des Balls; e=epsilon, sehr kleiner Wert um zu umgehen, dass kleinste Rechenungenauigkeiten bei Floats dazu führen, dass die Verschiebung ganz knapp zu kurz ausfällt; ||x||=Länge von x)

Der ganz korrekte Weg wäre es festzustellen ob eine Kollision passieren wird, bevor du die Verschiebung ausführst. Durch Berechnung des Schnittpunktes weisst du genau wo (bzw. wann) die Kollision zwischen den Schritten auftritt, und du kannst den Restvektor zum Shape-Rand (V1) sowie den verbleibenden Anteil des reflektierten Vektors (V2) berechnen. Dann verschiebst du nachher um V1+V2, gibst aber dem Ball die Geschwindigkeit Norm(V2)*(||V1||+||V2||)*k (k=Konstante die den Energieverlust beim Stoß beschreibt), bzw. Norm(V2)*||V0||*k (V0=Geschwindigkeit des Balls vor der Kollision).


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:12 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz