![]() |
Berührung 2er bewegter Kreise
ersteinmal hallo bin hier schonwas länger angemeldet brauchte aber bisher noch nicht wirklich hilfe
jetzt schon^^ mein problem ist das wir für die schule ein prog schreiben sollen indem sich auf einem canvas 2 kreise bewegen die gleiche oder verschiedene geschwindigkeiten haben treffen diese auf die wände sollen sie reflektiert werden was auch klappt aller dings sollen sie auch reflecktiert werden wenn sie sich gegenseitig berühren und da liegt mein problem hier einmal den quelltext
Code:
hoffe das ihr mir helfen könnt:)
verschx := StrToInt(edit1.text);
verschy := StrToInt(edit2.text); verschx1 := StrToInt(edit3.text); verschy1 := StrToInt(edit4.text); image1.Canvas.Pen.Color := clwhite; image1.Canvas.Brush.Color := clwhite; image1.Canvas.Rectangle(x,y,x+50,y+50); image1.Canvas.Rectangle(x1,y1,x1+50,y1+50); x := x+verschx; y := y+verschy; x1 := x1+verschx1; y1 := y1+verschy1; image1.Canvas.Pen.Color := clred; image1.Canvas.Brush.Color := clred; {if (((x1 <= x+50) and (x1 >= x)) and ((y1 <= y+50) and (y1 >= y))) then begin edit1.Text := IntToStr(StrToInt(Edit1.Text)*(-1)); edit3.Text := IntToStr(StrToInt(Edit3.Text)*(-1)); edit2.Text := IntToStr(StrToInt(Edit2.Text)*(-1)); edit4.Text := IntToStr(StrToInt(Edit4.Text)*(-1)); end;} if (x1+25-x+25+y1+25-y+25) > 0 then if (Round(sqrt(x1+25-x+25+y1+25-y+25))) <= 50 then begin edit1.Text := IntToStr(StrToInt(Edit1.Text)*(-1)); edit3.Text := IntToStr(StrToInt(Edit3.Text)*(-1)); edit2.Text := IntToStr(StrToInt(Edit2.Text)*(-1)); edit4.Text := IntToStr(StrToInt(Edit4.Text)*(-1)); end ; if x <= 0 then edit1.Text := IntToStr(StrToInt(Edit1.Text)*(-1)); if x >= image1.Width-50-StrToInt(Edit1.Text) then edit1.Text := IntToStr(StrToInt(Edit1.Text)*(-1)); if y <= 0 then edit2.Text := IntToStr(StrToInt(Edit2.Text)*(-1)); if y >= image1.Height-50-StrToInt(Edit2.Text) then edit2.Text := IntToStr(StrToInt(Edit2.Text)*(-1)); image1.Canvas.Ellipse(x,y,x+50,y+50); if x1 <= 0 then edit3.Text := IntToStr(StrToInt(Edit3.Text)*(-1)); if x1 >= image1.Width-50-StrToInt(Edit3.Text) then edit3.Text := IntToStr(StrToInt(Edit3.Text)*(-1)); if y1 <= 0 then edit4.Text := IntToStr(StrToInt(Edit4.Text)*(-1)); if y1 >= image1.Height-50-StrToInt(Edit4.Text) then edit4.Text := IntToStr(StrToInt(Edit4.Text)*(-1)); image1.Canvas.Brush.Color := clblue; image1.Canvas.Pen.Color := clblue; image1.Canvas.Ellipse(x1,y1,x1+50,y1+50); |
Re: Berührung 2er bewegter Kreise
Also mal theoretisch...
Beide Kreismittelpunkte berechnen (Koordinaten umgebendes Quadrat hast Du) Entfernung der Kreismittelpunkte berechnen (Wie Diagonale eines Rechteckes) Wenn Entfernung <= Radius1 + Radius2 dann berühren sich die Kreise Sollte aus den Kreisen echte Ellipsen werde, wird es mit dem Radius haarig |
Re: Berührung 2er bewegter Kreise
nein sollen kreise bleiben
und von der theorie her ist mir auch klar wie das geht nur leider funzt das net habe bei beiden kreisen den radius 25 gewählt nun rechne ich via phytagoras aus wie weit die voneinander entfernt sind und lasse die dann ihre richtung wechseln nur wenn man das ganze startet kommt da irgendwie müll raus
Code:
if round(sqrt(sqr(x1+25-x+25)+sqr(y1+25-y+25))) <= 50
then begin edit1.Text := IntToStr(StrToInt(Edit1.Text)*(-1)); edit3.Text := IntToStr(StrToInt(Edit3.Text)*(-1)); edit2.Text := IntToStr(StrToInt(Edit2.Text)*(-1)); edit4.Text := IntToStr(StrToInt(Edit4.Text)*(-1)); end ; |
Re: Berührung 2er bewegter Kreise
Hast du schon mal was von Variablen gehört? Ein Edit ist nicht dazu da, Variablen zu speichern... Wenn du die aktuellen Werte anzeigen willst, wären Labels das richtige.
Zahlen wie "25" gehören auf keinen Fall (!) in den Code, in 2h weisst du nicht mehr, was die bedeuten, wenn du einen größeren Kreis benutzen willst, liegst du damit recht schnell auf der Nase. Das mit der Kollision ist eigentlich ziemlich einfach. Du kannst die beiden Geraden, auf denen sich die Mittelpunkte bewegen, in Parameterform angeben: g_1 : (x,y)+r*(vx,vy) g_2 : (x',y')+s*(vx',vy') Die beiden Kreise kollidieren, wenn der Abstand der geraden der Summe der Radien entspricht. In Abhängigkeit von der Position hast du einen Abstand von d_x = (x+r*vx-x'-r*vx) d_y = (y+r*vy-y'-s*vy') d(r,s)=sqrt(d_x*d_x+d_y*d_y) Dann löst du den Ausdruck d(r,s)=R_1+R_2 und hast zwei Mögliche Lösungen, wobei du die frühere Lösung wählst. Wenn du das hast, kannst du dir sorgen um das Abprallen machen, da wirds schon ein bischen schwieriger, weil noch Rotationsmatrizen ins Spiel kommen (und für Fortgeschrittene auch noch unterschiedliche Massen). @satty: Das mit Ellipsen wird SEHR unschön. Die Kollisionsberechnung dort für auf ein Polynom dritten Grades, dessen Lösung (ohne Approximative Verfahren) recht schwierig wird. @Post 3: Hast du verstanden, was dein Code macht? Du tust so, als ob die Kugeln von senkrechten Wänden abprallen und nicht voneinander... btw: Du hast schon die Variable verschx. Warum machst du diesen Murks mit den Casts in das Edit rein und wieder raus? |
Re: Berührung 2er bewegter Kreise
Zitat:
hier müsstest du mir noch einmal erklären was du mit s meinst ansonsten danke ich dir für deine hilfe werde versuchen alles umzusetzen |
Re: Berührung 2er bewegter Kreise
Zitat:
s ist eine Laufvariable (z.B. die Zeit) und x',y' ist die Anfangsposition. Zum Zeuitpubkt s=0 ist die Position also gleich der Anfangsposition. Danach bewegt sich das Objekt - du zählst s hoch und bekommst die aktuielle Position raus. |
Re: Berührung 2er bewegter Kreise
Delphi-Quellcode:
function CircleIntersect( Circle1Center, Circle2Center: TPoint;
Circle1Radius, Circle2Radius: Cardinal ): Boolean; begin Circle1Center := Point( Circle2Center.X - Circle1Center.X, Circle2Center.Y - Circle1Center.Y ); Result := SQRT( Circle1Center.X*Circle1Center.X + Circle1Center.Y*Circle1Center.Y ) <= (Circle1Radius div 2 + Circle2Radius div 2); end; procedure TForm1.FormCreate(Sender: TObject); begin M1 := Point( $80, $80 ); M1R := $80; M2 := Point( $100, $80 ); M2R := $80; end; procedure TForm1.FormPaint(Sender: TObject); begin if CircleIntersect( M1, M2, M1R, M2R ) then Canvas.Pen.Color := clRed else Canvas.Pen.Color := clLime; Canvas.Ellipse( M1.X - M1R div 2, M1.Y - M1R div 2, M1.X + M1R div 2, M1.Y + M1R div 2 ); Canvas.Ellipse( M2.X - M2R div 2, M2.Y - M2R div 2, M2.X + M2R div 2, M2.Y + M2R div 2 ); end; |
Re: Berührung 2er bewegter Kreise
Das ist aber ziemlich schlechter Stil.
Warum benutzt du in der Intersect-Funktion denn keine lokale Variable für den Abstand in x und y und überschreibst lieber einen der Parameter, wodurch die fiese Seiteneffekte auslöst und die Benennung der Variablen nichts mehr mit ihrem Inhalt zu tun hat. Was machst du bei schnellen Kreisen? (Also etwa solche, die während eines Zeitschritts durcheinander durchlaufen?) Die Lösung funktioniert zwar bei einfachen Beispielen, bei einer richtigen Anwendung bringt es dir aber gar nichts mehr... |
Re: Berührung 2er bewegter Kreise
Wie wärs mit Vektorrechnung? Hier mal eine Function die ich aufgrund eines Kollisionstest mal schrieb.
Vector ist eine Klasse die die Vektoroperationen beinhaltet.
Delphi-Quellcode:
Der Rückgabewert der Funktion beinhaltet die Zeiteinheiten bis die Kreise kollidieren. Wenn sie nicht kollidieren s=0.
TSphere=record
m :TVector;//Stützvektor, Kreismittelpunkt a :TVector;//Geschwindigkeitsvektor r :Single;//Kreisradius end; //.. function collision(k1,k2:TSphere):Single; var a,b :TVector; s,r,t:Single; begin with Vector do begin a:=Sub(k1.m,k2.m); b:=Sub(k1.a,k2.a); r:=k1.r+k2.r; t:=Skalar(b,b); if t<>0 then begin s:=sqr(Skalar(a,b)/t)-Skalar(a,a)/t+r*r/t; if s>=0 then s:=-Skalar(a,b)/t-sqrt(s) else s:=0; end else s:=0; result:=s; end; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:29 Uhr. |
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