![]() |
Kreise sollen von Wänden abprallen, tun sie aber nicht
Hey Leute,
ich versuche mich die ganze Zeit schon an einem Projekt. Und zwar sollen bei klick auf einen Button Kreise erstellt werden die sich bewegen und von den Wänden (Ränder der Form) abprallen. Das erstellen klappt super nur nicht das bewegen. Hier mal das was ich bis jetzt habe:
Delphi-Quellcode:
Wieso bewegen sich die Kreise denn erst garnicht ? Was mache ich falsch ??
TKreis = class(TShape)
private { Private-Deklarationen } public { Public-Deklarationen } radius,speedx,speedy,right,bottom:integer; Abprallseite: String; end; var Form1: TForm1; kreis: array of TKreis; procedure TForm1.Button1Click(Sender: TObject); var arraylaenge:integer; begin arraylaenge := length(kreis); setLength(kreis,length(kreis)+1); kreis[arraylaenge]:= TKreis.Create(self); With kreis[arraylaenge] do begin parent:= Form1; Shape:=stCircle; radius:=10+random(30); width:=radius*2; height:=radius*2; top:=random(Form1.Clientheight-Kreis[arraylaenge].height-20); left:=random(Form1.Clientwidth-Kreis[arraylaenge].width-20); end; end; procedure TForm1.Timer1Timer(Sender: TObject); var arraylaenge,k : integer; begin arraylaenge := length(kreis); For k:= 0 to arraylaenge-1 do begin //Kreis[k].right:=Kreis[k].Left+Kreis[k].Width; //Kreis[k].bottom:=Kreis[k].top+Kreis[k].Height; Form1.right:=Form1.Left+Form1.ClientWidth; Form1.bottom:=Form1.top+Form1.ClientHeight; Kreis[k].speedx:=Random(20)+1; Kreis[k].speedy:=Random(20)+1; if Kreis[k].Top > Form1.clientheight then begin Kreis[k].AbprallSeite := 'Unten'; end; if Kreis[k].Top < 0 then begin Kreis[k].AbprallSeite := 'Oben'; end; if Kreis[k].AbprallSeite = 'Unten' then begin Kreis[k].Top := Kreis[k].Top + Kreis[k].speedy; end; if Kreis[k].AbprallSeite = 'Oben' then begin Kreis[k].Top := Kreis[k].Top - Kreis[k].speedy; end; if Kreis[k].left > Form1.clientwidth then begin Kreis[k].AbprallSeite := 'Rechts'; end; if Kreis[k].left < 0 then begin Kreis[k].AbprallSeite := 'Links'; end; if Kreis[k].AbprallSeite = 'Unten' then begin Kreis[k].Top := Kreis[k].Top + Kreis[k].speedx; end; if Kreis[k].AbprallSeite = 'Oben' then begin Kreis[k].Top := Kreis[k].Top - Kreis[k].speedx; end; end; end; |
AW: Kreise sollen von Wänden abprallen, tun sie aber nicht
Hallo!
Bewegen tust du die Shapes so
Delphi-Quellcode:
lg
Kreis[Position].Left := Kreis[Position].Left + Speed;
Kreis[Position].Top := Kreis[Position].Top + Speed; |
AW: Kreise sollen von Wänden abprallen, tun sie aber nicht
Zitat:
|
AW: Kreise sollen von Wänden abprallen, tun sie aber nicht
Zitat:
Aber da gibt es noch einiges im Code was suboptimal ist:
Zudem wenn der Kreis einen Weg von 20 zurücklegen soll, dieser aber nach 18 schon den Rand trifft, dann lässt du den Kreis von der aktuellen Position 20 in die entgegengesetzte Richtung wandern. Irgendwie nicht so wirklich ;) |
AW: Kreise sollen von Wänden abprallen, tun sie aber nicht
Zitat:
Besser wäre es, die Bewegung immer auszuführen und beim Abprallen das Vorzeichen des entsprechenden Speed-Wertes zu ändern. |
AW: Kreise sollen von Wänden abprallen, tun sie aber nicht
Deine Klasse TKreis ist auch mit überflüssigen Informationen gespickt. Das reicht schon:
Delphi-Quellcode:
Allerdings solltest du diese Werte auch beim Erstellen des Kreises mit vorgeben:
TKreis = class(TShape)
private { Private-Deklarationen } public { Public-Deklarationen } speedx,speedy :integer; end;
Delphi-Quellcode:
Das mit dem
procedure TForm1.Button1Click(Sender: TObject);
var arraylaenge, radius : integer; begin arraylaenge := length(kreis); setLength( kreis, arraylaenge + 1); kreis[arraylaenge]:= TKreis.Create(self); With kreis[arraylaenge] do begin Parent := Self; Shape := stCircle; radius := 10+random(30); // 10 .. 39 Width := radius*2; Height := radius*2; Top := random( Self.ClientHeight - Height ); Left := random( Self.ClientWidth - Width ); speedx := random( 41 ) - 20; // -20 .. 20 speedy := random( 41 ) - 20; // -20 .. 20 end; end;
Delphi-Quellcode:
kann einen manchmal in Teufels Küche bringen, von daher sollte man es eigentlich vermeiden, wenn hier der Kontext nicht eindeutig ist. Hier sollte es zwar funktionieren, fraglich ist aber nur, wie lange.
with
Nun zum Bewegen:
Delphi-Quellcode:
procedure TForm1.Timer1Timer(Sender: TObject);
var kidx, ntop, nleft : integer; k : TKreis; begin for kidx := Low( Kreis ) to High( Kreis ) do begin k := Kreis[kidx]; ntop := k.top + k.speedy; nleft := k.left + k.speedx; // Untere Grenze prüfen if ntop > ( Self.ClientHeight - k.Height ) then begin ntop := 2 * ( Self.ClientHeight - k.Height ) - ntop; // Abprallen berücksichtigen k.speedy := - k.speedy; // Richtung umdrehen end; // analog mit oben, links, rechts verfahren ... // Position zuweisen k.top := ntop; k.left := nleft; end; end; |
AW: Kreise sollen von Wänden abprallen, tun sie aber nicht
Zitat:
Delphi-Quellcode:
// Untere Grenze prüfen
if ntop > ( Self.ClientHeight - k.Height ) then begin ntop := 2 * ( Self.ClientHeight - k.Height ) - ntop; // Abprallen berücksichtigen k.speedy := - k.speedy; // Richtung umdrehen end; // Rechte Grenze prüfen if nleft > ( Self.ClientWidth - k.Width ) then begin nleft := 2 * ( Self.ClientWidth - k.Width ) - nleft; // Abprallen berücksichtigen k.speedx := - k.speedx; // Richtung umdrehen end; // Obere Grenze prüfen if ntop > ( 0 + k.Height ) then begin ntop := 2 * ( k.Height ) + ntop; // Abprallen berücksichtigen k.speedy := - k.speedy; // Richtung umdrehen end; // Linke Grenze prüfen if nleft < ( 0 + k.Width ) then begin nleft := 2 * ( k.Width ) + nleft; // Abprallen berücksichtigen k.speedx := - k.speedx; // Richtung umdrehen end; |
AW: Kreise sollen von Wänden abprallen, tun sie aber nicht
Kann mir das denn niemand beantworten ??
|
AW: Kreise sollen von Wänden abprallen, tun sie aber nicht
Zitat:
|
AW: Kreise sollen von Wänden abprallen, tun sie aber nicht
Zitat:
|
AW: Kreise sollen von Wänden abprallen, tun sie aber nicht
ntop und nleft sind die Positionen, die nach einer ungeprüften Bewegung angenommen würden. Und was sind denn wohl die Minimalwerte für Left und Top, die Deine Kreise annehmen dürfen? Kleiner Tipp: das ist bei beiden das Gleiche und könnte als Konstante mit Namen ZERO deklariert werden.
|
AW: Kreise sollen von Wänden abprallen, tun sie aber nicht
Zitat:
|
AW: Kreise sollen von Wänden abprallen, tun sie aber nicht
Wenn Left < 0 oder (Left + Width) > Form.ClientWidth wird, Richtung umkehren, das Gleiche analog für die Y-Achse.
|
AW: Kreise sollen von Wänden abprallen, tun sie aber nicht
Zitat:
Delphi-Quellcode:
Weil jetzt bewegt es sich nurnoch in x richtung und wackelt hin und her.
// Obere Grenze prüfen
if ntop > ( 0 + k.Height ) then begin k.speedy := - k.speedy; // Richtung umdrehen end; // Linke Grenze prüfen if nleft < ( 0 + k.Width ) then begin k.speedx := - k.speedx; // Richtung umdrehen end; |
AW: Kreise sollen von Wänden abprallen, tun sie aber nicht
Und so?
Delphi-Quellcode:
if (ntop < 0) or (ntop + k.Height > ClientHeight) then
k.speedy := - k.speedy; if (nleft < 0) or (nleft + kWidth > ClientWidth) then k.speedx := -k.speedx; |
AW: Kreise sollen von Wänden abprallen, tun sie aber nicht
Mal dir das doch einfach mal auf, dann sieht man das auch besser.
Hier mal ein paar Hinweise: Mit Top und Left ist die linke, obere Ecke beschrieben. Über die Informationen Width und Height ist es möglich auch die untere und rechte Kante zu bestimmen. Rechte Kante = Left + Width Untere Kante = Top + Height Man kann sich das aber auch anders vorstellen: Der Bereich, indem sich die linke obere Ecke sich befinden darf ist:
Code:
also
0 <= Kreis.Top < Form.ClientWidth - Kreis.Width
0 <= Kreis.Left < Form.ClientHeight - Kreis.Height
Delphi-Quellcode:
if ntop >= Self.ClientHeight - k.Height then
... if ntop < 0 then ... if nleft >= Self.ClientWidth - k.Width then ... if nleft < 0 then ... Zitat:
|
AW: Kreise sollen von Wänden abprallen, tun sie aber nicht
danke so geht es
|
AW: Kreise sollen von Wänden abprallen, tun sie aber nicht
Abfrage falsch!
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:47 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 by Thomas Breitkreuz