Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi OnIdle-Timer (https://www.delphipraxis.net/77014-onidle-timer.html)

Cöster 13. Sep 2006 14:52


OnIdle-Timer
 
Hi!

Mein Spiel arbeitet bisher mit einem normalen Timer mit dem Intervall 13. Bei jedem Timer-Aufruf wird ein Ball auf dem Bildschirm um eine bestimmte Anzahl Pixel in eine bestimmte Richtung (abhängig von der gedrückten Pfeiltaste) verschoben.

Nun wollte diesen durch einen OnIdle-Timer ersetzen, damit die Positionen so oft wie möglich neu berechnet werden und neu gezeichnet wird.
Wie sollte ich das dann am besten machen?

Ich hab es mir so gedacht:
Ich habe 2 Variablen: Start und End vom Typ Integer. Ich speicher zu Beginn jedes Aufrufs der OnIdle-procedure GetTickCount unter End, ermittle mittels End - Start die vergangene Zeit seit dem letzten Aufruf und multipliziere diese mit einem Geschwindigkeitsfaktor (der kleiner als 1 ist). Daraus ergibt sich die aktuelle Position, die unter einer Variablen gespeichert wird. Zum Zeichnen muss diese durch Trunc() noch auf einen Integer gerundet werden. Start wird irgendwann während der procedure auf End gesetzt, aber erst nachdem die Zeitdifferenz berechnet wurde.

Ist die Überlegung gut? Wäre es schneller, statt mit einer Zahl kleiner als 1 zu multiplizieren durch eine Zahl größer als 1 zu teilen? Wird die ganze procedure vielleicht dadurch ausgebremst, dass mit Floats gerechnet wird? Das war ja bei dem Standard-Timer nicht so. Da hab ich einfach nur (wenn VK_Right gedrückt ist) PositionX + 5 gerechnet um die neue Position zu ermitteln. Sollte ich statt GetTickCount TimeGetTime benutzen? Es ist genauer, aber ist es auch schneller ermittelt?

Ich hoffe, ich könnt mir sagen, wie ich das möglichst performant hinkriege.

Der_Unwissende 13. Sep 2006 15:09

Re: OnIdle-Timer
 
Hi,
ich denke mal alle 13 Sek. (das wären doch so ziemlich 75Hz ist mehr als ausreichend. Das menschliche Auge dürfte hier schon wieder langsamer auflösen und Flachbildschirme werden z.B. auch nur mit 60 Hz betrieben (viele zumindest). Das reicht also für Bewegungen schon aus. Die Frage ist also, warum brauchst du einen anderen Timer?
Ich denke mal, dass du eher wieder ein Problem mit dem Zeichnen hast, flimmert es oder springt dir der Ball zu sehr?

Nebenbei bemerkt, das ermitteln der vergangenen Zeit dürfte kaum ins Gewicht fallen. Die Unterschiede hier werden schon völlig durch dein Zeichnen dominiert, da muss deutlich mehr gemacht werden. Auch die Floatingpoint-Einheiten heutiger CPUs werden für deinen Fall keinen (ernsthaften) Flaschenhals darstellen.


Gruß Der Unwissende

Cöster 13. Sep 2006 15:37

Re: OnIdle-Timer
 
Naja, es ruckelt schon ein bisschen. DoubleBuffered ist True. Die Zeichnen-procedure (nested procedure, weil ich hier gelesen hab, dass das schneller ist) sieht so aus:

(Wert ist ein Array[1..7, 1..4], in dem Daten wie z.B. X-, Y-Position, Radius, Geschwindigkeit usw von Spieler 1 und 2 sowie von 2 Beamlöchern gespeichert sind. X, Y, Radius sind Integer-Konstanten.

Delphi-Quellcode:
procedure Zeichnen(Cvs: TCanvas; Spieler: Byte);
begin
  with Cvs do begin
    Pen.Color  := Farbe[Spieler];
    Brush.Color := Farbe[Spieler];
    Ellipse(Wert[X, Spieler] - Wert[Radius, Spieler],
      Wert[Y, Spieler] - Wert[Radius, Spieler],
      Wert[X, Spieler] + Wert[Radius, Spieler],
      Wert[Y, Spieler] + Wert[Radius, Spieler]);
  end;
end;
Es wird nicht direkt auf das Image gezeichnet, sondern erst aufs Canvas einer globalen Variablen von Typ TBitmap. Ich erzeuge das Bitmap nicht immer neu, weil ich mir dachte, dass wichtige Zeit verloren geht, wenn ich jedesmal Bmp.Width und Height anpassen müsste und immer wieder Bmp := TBitmap.Create und Bmp.Free aufgerufen wird. Ist dieser Zeitgewinn kleiner als der Zeitverlust, der entsteht, weil Bmp global statt lokal ist?

Delphi-Quellcode:
with Bmp.Canvas do
begin
  Pen.Color  := $00D8E9EC;
  Brush.Color := $00D8E9EC;
  Rectangle(0, 0, Bmp.Width, Bmp.Height);
end;
Zeichnen(Bmp.Canvas, Loch1);
Zeichnen(Bmp.Canvas, Loch2);
Zeichnen(Bmp.Canvas, 1);
Zeichnen(Bmp.Canvas, 2);
ImSpiel.Picture.Bitmap := Bmp;

Cöster 14. Sep 2006 15:47

Re: OnIdle-Timer
 
*push*


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:57 Uhr.

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