Genau da liegt nämlich der Hase im Pfeffer. Wenn du das so ruckelfrei wie nur möglich hinbekommen möchtest, dann wirst du nicht darum herumkommen, die Bilder alle im Speicher vorzuhalten.
Ach, ich würd mal die Kirche im Dorf lassen. Es geht vermutlich eher um einfache 2D-Animationen. Meine Physiklehrerin in der Schule hat übrigens damals auch gerne mal für bestimmte Dinge solche kleinen Simulationsprogramme mit Delphi geschrieben. TCanvas hat locker ausgereicht.
@DerHaushaltsProfi
Lest euch mal die Dokumentation und die Beispiele zu
TCanvas bzw.
TPaintBox. Wenn ihr ein Bild zeichnen könnt, könnt ihr auch eine Animation zeichnen. Dazu müsst ihr nur in regelmäßigen Abständen immer wieder ein neues Bild über das alte zeichnen.
Damit das ganze flüssig läuft, noch ein paar Tips. Es gibt nämlich verschiedene Möglichkeiten, wie man die Simulation/Animation umsetzen kann.
1. Feste Schritte
Das ist vielleicht der naheliegenste Ansatz. Wenn man z.B. ein Objekt mit konstanter Geschwindigkeit von links nach rechts über den Bildschirm wandern lassen will, könnte man das naiv so bewerkstelligen (Pseudocode):
Delphi-Quellcode:
// Animationsschleife
while True do
begin
Objekt.X := Objekt.X + 5;
Objekt zeichnen;
// 10ms Pause zwischen Frames = 100 FPS
Sleep(16);
end;
Nachteil ist, dass durch verschiedene Faktoren wie Prozess-Scheduling und Rechnergeschwindigkeit die tatsächliche Zeit zwischen zwei Frames schwanken kann, was sich dann in Rucklern oder ungewolltem Zeitlupentempo bemerkbar macht.
2. Zeitabhängig
Besser ist es, direkt die Position des Objekts in Abhängigkeit von der Zeit zu berechnen:
Delphi-Quellcode:
var t0, t: integer;
t0 := GetCurrentTimestamp;
while True do
begin
t := GetCurrentTimestamp;
// Geschwindigkeit des Objekts = 500 Pixel in 1000 ms
Objekt.X := 500 * (t-t0)/1000;
Objekt zeichnen;
Sleep(10);
end;
Das ist für einfache Bewegungen wie Bewegungen mit konstanter Geschwindigkeit oder konstanter Beschleunigung eigentlich die optimale Lösung. Der Nachteil ist, dass man oft vorher mit Stift und Papier erst mal einige Umformungen machen muss, um auf die richtige Formel zu kommen.
3. Zeitabhängige Zwischenschritte
Bei komplexeren Simulationen wird dieser Ansatz deswegen leider schnell sehr schwierig bis unmöglich. In dem Fall kann man aber immer noch bei den Bewegung zwischen den Frames die verstrichene Zeit berücksichtigen:
Delphi-Quellcode:
var t0, t: integer;
t0 := GetCurrentTimestamp;
while True do
begin
t := GetCurrentTimestamp;
// 500 * (t-t0)/1000 = Wie weit müsste sich das Objekt mit seiner aktuellen Geschwindigkeit seit dem letzten Frame bewegt haben?
Objekt.X := Objekt.X + 500 * (t-t0)/1000;
Objekt zeichnen;
Sleep(10);
// Alte Zeit merken
t0 := t;
end;
Hier noch ein
Link dazu.
Auch dieser Ansatz hat aber einen Nachteil, nämlich dass die Simulation u.U. nicht mehr deterministisch ist. D.h. durch die bereits erwähnten, kleinen Zeitschwankungen zwischen Frames, läuft die Simulation immer ein kleines bisschen anders ab (wirkt dafür aber flüssig), und hat u.U. auch ein etwas anderes Ergebnis. Im Extremfall könnte es z.B. in einem Computerspiel passieren, dass du auf einem schnellen Rechner von einer Kugel getroffen wirst, aber auf einem langsameren Rechner mit niedrigerer FPS-Zahl die gleiche Kugel einfach berührungslos durch dich durchfliegt, weil die Simulationsabstände zu groß sind. Das sollte für euch aber unerheblich sein (und das zu lösen ist ein ziemlich schwieriges Problem).
Ich würde euch also wenn möglich zum 2. Ansatz raten (sollte bei euren Wellen vermutlich gehen), und falls das nicht geht zum 3.
Ich hoffe, das war einigermaßen verständlich und ich habe euch nicht mit zu viel Information erschlagen.