![]() |
Timer.Interval<1
Hallo zusammen,
ich habe ein kleines Problem mit der Timer-Komponente. Ich möchte einen Interval haben, der kleiner 1 ist. Ist mir jedoch klar, dass das nicht klappt (oder doch?). Nun habe ich versucht, eine "eigene" Timer-Komponente mit der Procedure sleep zu simulieren. Ich habe eine eigene Procedur erstellt, die am Ende die Procedure sleep ausführt und dann sich selbst wieder aufruft. Jedoch schläft dabei das Programm ein. Kennt jemand eine Möglichkeit, kleinere Intervalle als 1ms zu realisieren? Schon mal danke für jegliche Hilfe, Martin.Ghosts |
Re: Timer.Interval<1
das macht keinen Sinn, alles unter ca. 20 ms macht keinen Sinn weil deine Windows deinem Programm in der Regel nicht viel mehr Zeit am Stück gibt. Wozu brauchst du einen so kleinen Interval? Da macht es doch eher sein das ganze in einer Schleife auszuführen ohne darin zu warten.
|
Re: Timer.Interval<1
Ich bin ein klassisches Pongspiel am programieren und will den Ball immer um einen Pixel verschieben. Mit einem Interval von 1 ist er mir aber zu langsam. Bei einer Verschiebung von mehr als einem Pixel kann es passieren, dass der Ball teilweise den Rand des Formulars überschreitet.
|
Re: Timer.Interval<1
In DelphiX soll ein schnellerer Timer drin sein.
Aber warum immer nur ein Pixel ... mach doch Mehrere Du kannst dir natürlich auch mit QueryPerformanceCounter, RealTimeStampCounter, oder ... was eigenes aufbauen. |
Re: Timer.Interval<1
Zitat:
Delphi-Quellcode:
if Ball.X <= linke_Wand then
// links else if Ball.X >= ... else if Ball.Y <= ... |
Re: Timer.Interval<1
sinnvoller wäre es wenn du die Position andauern um eins verschiebst (in einer Extra Variablen) und in geringeren Abständen dann den Ball zeichnest. Denn kleiner als 1ms macht da keinen Sinn, das sieht man nicht und die cpu wird vermutlich auch zu 100% ausgelastet sein. 25 Bilder (also 25 mal verschieben deines Balles) reicht vollkommen.
|
Re: Timer.Interval<1
esist doch auch möglich, ob bei einer Verschiebung von 20 Pixeln nach links z.b. der linke rand erreicht wird (x<=0) .. da muss man doch net jeden Pixel einzelnd prüfen.. so käme man bei größeren Computerspielen auch net weit ^^
Dann reicht ein Intervall von 20ms gut.. |
Re: Timer.Interval<1
Zitat:
Zitat:
|
Re: Timer.Interval<1
ich hab die Vermutung das du versuchst alle 1 ms ein TImage oder etwas anderes zu malen. Unter Windows dauert das malen aber von allem am längsten. Das heißt du solltest das Malen nur so häufig machen wie es wirklich nötig ist (also maximal 25 mal in der Sekunden). Ansonsten einfach nur die Position berechnen aber nichts verschieben
|
Re: Timer.Interval<1
Zitat:
|
Re: Timer.Interval<1
Zitat:
(zu SirThornberry) Hier mal mein Quelltext:
Delphi-Quellcode:
Wenn ich dich richtig versehe meinst du es so:
var
Form1: TForm1; x, y: Integer; implementation {$R *.dfm} procedure TForm1.Move; begin Form1.Shape1.Left:= Form1.Shape1.Left + (x); Form1.Shape1.Top:= Form1.Shape1.Top + (y); if (Form1.Shape1.Left <= 0) then x:= (-1) * x; if (Form1.Shape1.Top <= 0) then y:= (-1) * y; if ((Form1.Shape1.Left + Form1.Shape1.Width) >= Form1.Width) then x:= (-1) * x; if ((Form1.Shape1.Top + Form1.Shape1.Height) >= Form1.Height) then y:= (-1) * y; end; procedure TForm1.FormCreate(Sender: TObject); begin x:= -1; y:= -1; end; procedure TForm1.Timer1Timer(Sender: TObject); begin Form1.Move; end; end.
Delphi-Quellcode:
Dadurch bewegt sich der Ball jedoch nochmal deutlich langsamer.
var
Form1: TForm1; x, y, count: Integer; implementation {$R *.dfm} procedure TForm1.Move; begin Form1.Shape1.Left:= Form1.Shape1.Left + (x); Form1.Shape1.Top:= Form1.Shape1.Top + (y); if (Form1.Shape1.Left <= 0) then x:= (-1) * x; if (Form1.Shape1.Top <= 0) then y:= (-1) * y; if ((Form1.Shape1.Left + Form1.Shape1.Width) >= Form1.Width) then x:= (-1) * x; if ((Form1.Shape1.Top + Form1.Shape1.Height) >= Form1.Height) then y:= (-1) * y; end; procedure TForm1.FormCreate(Sender: TObject); begin x:= -1; y:= -1; count:= 0; end; procedure TForm1.Timer1Timer(Sender: TObject); begin if (count = 25) then begin count:= 0; Form1.Move; end else count:= count + 1; end; end. |
Re: Timer.Interval<1
hat es etwas falsch verstanden. Anstelle jedes mal vom Shape die Koordinaten zu ändern (wodurch ja das form und das darauf neu gezeichnet wird) sollst du die Koordinaten in einer extra Variablen ändern und dann nur maximal 25 mal pro sekunden diese koordinanten für das Shape übernehmen.
|
Re: Timer.Interval<1
Hab mal gerade versucht das zu realisieren, jedoch ohne Erfolg. Erlich gesagt, habe ich keine Ahnung, wie ich das umsetzen könnte.
|
Re: Timer.Interval<1
nimm einfach anstelle von shape1 ein rect. und wenn du die move-procedure eine bestimmte anzahl mal aufgerufen hast überträgst du die daten auf dein shape
|
Re: Timer.Interval<1
Ich würd das Interval vom Timer auf 20 setzen (also 50 Bilder pro Sekunde, mehr kann das menschliche Auge nicht wahrnehmen). Die Timer-Procedure änderst du dann in
Delphi-Quellcode:
var i: integer;
begin For i:=1 to 20 do Form1.Move; end; |
Re: Timer.Interval<1
Timer auf 20ms einstellen und einfach rechnen, wie weit sich der Ball seit der letzten Bewegung fortbewegt hätte. Dazu muss nur der Bewegungsvektor (dx,dy) bekannt sein. Dx gibt dabei die Anzahl der Pixel an, die sich das Objekt in einer bestimmten Zeit in X-Richtung verschiebt, und Dy eben in Y-Richtung. Als "bestimmte Zeit" kann man ja z.B. 50ms nehmen.
Delphi-Quellcode:
Das Timer-Interval ist hier egal, denn das Objekt wird sich immer mit korrekter Geschwindigkeit bewegen. Eine Auflösung von ca. 20-40 ms sollte wohl reichen.
Procedure TMyForm.MyTimer (Sender : Tobject);
Begin dt := (GetTickCount - LastTickCount); MoveInX := Muldiv (dx,dt,50); MoveInY := MulDiv (dy,dt,50); // Das Objekt bewegt sich also von seiner augenblicklichen Position aus um MoveInX Pixel // nach rechts und MoveInY Pixel nach oben. // Es ist nun ein leichtes, etwaige Kollisionen mit irgendwelchen Wänden zu berechnen // (einfache Schnittpunktberechnung zweier Geraden). // Zum Schluss merken wir uns die Zeit, nachdem das Objekt gezeichnet wurde. LastTickCount := GetTickCount; End; |
Re: Timer.Interval<1
Zitat:
x := (-1) * x;? ... wie wär es mit x := -x; :gruebel: Außerdem brauchst du in einer Klassenprozedur (z.B. TForm1) nicht nochmal die Klassenvariable (z.B. Form1) angeben.
Delphi-Quellcode:
so isses doch bestimmt auch übersichtlicher?
procedure TForm1.Move;
begin Form1.Shape1.Left := Form1.Shape1.Left + x; Form1.Shape1.Top := Form1.Shape1.Top + y; if Form1.Shape1.Left <= 0 then begin if Form1.Shape1.Left < 0 then Form1.Shape1.Left := 0; x:= -x; end else if Form1.Shape1.Left + Form1.Shape1.Width >= Form1.Width then begin if Form1.Shape1.Left > Form1.Width - Form1.Shape1.Width then Form1.Shape1.Left := Form1.Width - Form1.Shape1.Width; x:= -x; end; if Form1.Shape1.Top <= 0 then begin if Form1.Shape1.Top < 0 then Form1.Shape1.Top := 0; y:= -y; end else if Form1.Shape1.Top + Form1.Shape1.Height >= Form1.Height then begin if Form1.Shape1.Top > Form1.Height - Form1.Shape1.Height then Form1.Shape1.Top := Form1.Height - Form1.Shape1.Height; y:= -y; end; end;
Delphi-Quellcode:
Und wenn du jetzt noch erstmal über temporäre Variablen gehst, dann wird das Shap auch nich (falls es über'n Rand hinausging) zweimal verschoben, außerdem sind Variablen schneller, als die Setter-/Getterprozeduren (der Shape).
procedure TForm1.Move;
begin Shape1.Left := Shape1.Left + x; Shape1.Top := Shape1.Top + y; if Shape1.Left <= 0 then begin if Shape1.Left < 0 then Shape1.Left := 0; x:= -x; end else if Shape1.Left + Shape1.Width >= Width then begin if Shape1.Left > Width - Shape1.Width then Shape1.Left := Width - Shape1.Width; x:= -x; end; if Shape1.Top <= 0 then begin if Shape1.Top < 0 then Shape1.Top := 0; y:= -y; end else if Shape1.Top + Shape1.Height >= Height then begin if Shape1.Top < Height - Shape1.Height then Shape1.Top := Height - Shape1.Height; y:= -y; end; end;
Delphi-Quellcode:
So ging es auch noch:
procedure TForm1.Move;
var x2, y2: integer; begin x2 := Shape1.Left + x; y2 := Shape1.Top + y; if x2 <= 0 then begin if x2 < 0 then x2 := 0; x:= -x; end else if x2 + Shape1.Width >= Width then begin if x2 > Width - Shape1.Width then x2 := Width - Shape1.Width; x:= -x; end; if y2 <= 0 then begin if y2 < 0 then y2 := 0; y:= -y; end else if y2 + Shape1.Height >= Height then begin if y2 < Height - Shape1.Height then y2 := Height - Shape1.Height; y:= -y; end; Shape1.Left := x2; Shape1.Top := y2; end;
Delphi-Quellcode:
jetzt könnte man noch Fomr1.Width und Form1.Height durch Variablen ersetzen (welche in TForm1.OnCreate und eventuell noch TForm1.OnResize gesetzt werden).
procedure TForm1.Move;
var x2, y2: integer; begin x2 := Shape1.Left + x; y2 := Shape1.Top + y; if x2 <= 0 then begin x2 := 0; x:= -x; end else if x2 + Shape1.Width >= Width then begin x2 := Width - Shape1.Width; x:= -x; end; if y2 <= 0 then begin y2 := 0; y:= -y; end else if y2 + Shape1.Height >= Height then begin y2 := Height - Shape1.Height; y:= -y; end; Shape1.Left := x2; Shape1.Top := y2; end; Und aus Shape1.Width und Shape1.Height lassen sich schöne Konstanten machen. (schneller gehts dann wohl nicht mehr mit der Speicherverwaltung ... in VCL) [add] natürlich wäre es mit der von alzaimar vorgeschlagen Schnittpunktberechnung besser, weil dann ja beide Richtungen angepasst werden, aber o gehts auch (halbwegs) ... 's wird ja jeweils nur eine der Richtungen zurückgesetzt. Und das LastTickCount := GetTickCount; würde ich auch gleich mal am Anfang mit machen, damit es zu keiner Zeitverschiebung kommt, da das Zeichen/verschieben auch etwas Zeit benötigt.
Delphi-Quellcode:
procedure TForm1.Move;
var x2, y2, t: integer; dt: Cardinal; begin dt := GetTickCount - LastTickCount; LastTickCount := GetTickCount; x2 := Shape1.Left + MulDiv(x, dt, 50); y2 := Shape1.Top + MulDiv(y, dt, 50); if x2 <= 0 then begin x2 := 0; x:= -x; end else begin t := Width - Shape1.Width; if x2 >= t then begin x2 := t; x:= -x; end; end; if y2 <= 0 then begin y2 := 0; y:= -y; end else begin t := Height - Shape1.Height; if y2 >= t then begin y2 := t; y:= -y; end; end; Shape1.Left := x2; Shape1.Top := y2; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:31 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