Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi fortlaufende Animationen - ohne Freeze (https://www.delphipraxis.net/166415-fortlaufende-animationen-ohne-freeze.html)

Muellermilchtrinker 12. Feb 2012 16:43

fortlaufende Animationen - ohne Freeze
 
Hallo alle miteinander,

ich programmiere gerade (mal wieder?) einen LED Cube Simulator mit OpenGL. Dies soll einfach dazu da sein um ein paar Animation auf einem großen LED Cube (12³) darzustellen. Diese sollen dann später mal auf einem echten LED Cube in der Größe dargestellt werden.

Nun habe ich bis jetzt folgendes: OpenGL Ausgabe steht und der LED Cube steht selber in einem Array dar. Nun geht es aber darum die Animation drauf abzuspielen. Diese sollten natürlich auch pausierbar sein. Nun wollte ich einen Timer verwenden und dann, je nachdem welche Animation ausgewählt ist, eine procedure aufrufen. Der Timer sollte dafür da sein, um die Animationen fortlaufend zu haben.

Jetzt ist aber das Problem, dass wenn ich Sleep anwenden möchte sich das ganze Programm festhängt. Ich habe nun ein einfaches Blinken hinbekommen in dem ich in der Prozedur eine Variable hochzähle und dann je nach dem ob an oder aus den LED Cube aus oder an schalte. Dies müsste dann mit globalen Variablen geschehen, weil man ja Variablen nicht so direkt in einem Timer initialisieren kann.

Meine Frage nun, wie ich das am elegantesten lösen kann, dass ich eine fortlaufende Animation habe, die den das Programm nicht festhängen lasse und gleichzeitig auch Sleep unterstützen und am besten mit wenig globalen Variablen auskommt.

MGC 12. Feb 2012 17:10

AW: fortlaufende Animationen - ohne Freeze
 
Wozu benötigst Du denn Sleep, etwa zum Pausieren der Animation?
Wenn Du die Animation angehalten hast, kannst Du ja entweder den Timer anhalten oder falls dieser noch weitere Aufgaben erfüllt eine Bool'sche Variable verwenden die bei jedem Timer-Ereignis abgefragt wird und entsprechend die Animation dargestellt wird oder auch nicht.

Muellermilchtrinker 12. Feb 2012 17:59

AW: fortlaufende Animationen - ohne Freeze
 
Sleep dafür, um das aktuelle Bild anzuzeigen.
Beispiel:
Delphi-Quellcode:
LED Cube an
500ms warten
LED Cube aus
500ms warten
Und das halt im Timer, und damit dann pausieren oder fortsetzen.

MGC 13. Feb 2012 08:32

AW: fortlaufende Animationen - ohne Freeze
 
und warum stellst Du den Timer nicht auf 500 ms und verwendest ein Flag das Dir angibt ob die LED an, bzw. aus ist oder ob die Animation pausiert ist?

Sir Rufo 13. Feb 2012 09:33

AW: fortlaufende Animationen - ohne Freeze
 
Es ist schon komisch, dass Delphi-Referenz durchsuchenSleep den aktuellen Thread schlafen legt :mrgreen:

MGC 13. Feb 2012 11:22

AW: fortlaufende Animationen - ohne Freeze
 
Zitat:

Zitat von Sir Rufo (Beitrag 1150708)
Es ist schon komisch, dass Delphi-Referenz durchsuchenSleep den aktuellen Thread schlafen legt :mrgreen:

Diese Doppeldeutigkeit ist herrlich. :-)

//Edit:
Eigentlich wollte ich an dieser Stelle noch einen Vorschlag zu den oben von mir vorgeschlagenen Flags machen. Bitte jetzt nicht alles in wilden globalen Variablen unübersichtöich anlegen, sondern lieber eine gut durchdachte Bitmaske nutzen. Wie's geht findet man hier.

Muellermilchtrinker 13. Feb 2012 15:44

AW: fortlaufende Animationen - ohne Freeze
 
Naja ich will den Timer auch für andere Animationen haben.

Deshalb gibt es eine andere Möglichkeit eine bestimmte Zeit zu warten oder soll ich dann den Timer für die Animationen in einem eigenen Thread laufen lassen?

himitsu 13. Feb 2012 16:31

AW: fortlaufende Animationen - ohne Freeze
 
Zitat:

Zitat von Muellermilchtrinker (Beitrag 1150842)
oder soll ich dann den Timer für die Animationen in einem eigenen Thread laufen lassen?

Da ja wohl alles, bis auf das "Warten" in/mit der GUI arbeitet, bringt ein Thread überhaupt nichts.
Ein Thread, welcher nur wartet und sich sonst mit der VCL synchronisieren muß, wird ein kleines bissl unterfordert sein. (schließlich sind Threads dafür da, um etwas zu machen)
Ein Timer wäre also genau die ideale Lösung.

TTimer laufen immer im Hauptthread es wird innerhalb der TThreadklasse eine unsichtbare Form erstellt, welche mit dem Haupthtread verbunden wird
und ein Thread, dessen "Arbeit" nur aus Sleep besteht, ist halt nutzlos.


DelayDelay (aber dennoch eher einen Timer verwenden)

MGC 13. Feb 2012 18:01

AW: fortlaufende Animationen - ohne Freeze
 
Zitat:

Zitat von Muellermilchtrinker (Beitrag 1150842)
Naja ich will den Timer auch für andere Animationen haben.

Hier stellt sich mir die Frage: Laufen diese Animationen parallel ab? Ansonsten kannst Du ja andere Timer-Zeiten verwenden und benutzt dennoch nur einen Timer. Ähnlich hättest Du es ja auch mit Sleep machen müssen. Ob Du nun dem Sleep oder dem Timer eine Variable übergibst ist doch im Grunde egal.
Willst Du allerdings mehrere Animationen parallel ablaufen lassen würde ich ggf. mehrere Timer einsetzen oder schöner eine Objekt-Behandlungsroutine im Timer-Event hinterlegen und die Animationsobjekte z.B. über eine TObjectList verwalten und abarbeiten.

Um besser auf Deine Problematik eingehen zu können, wie gestaltest Du eigentlich Deine Animation, wie sieht das entsprechende Objekt zur Zeit aus und wie gestaltest Du den Aufruf? Und auch ganz wichtig welche Arten und wie viele Animationen möchtest Du gleichzeitig darstellen können?

@himitsu: Deine Variante mit Delay im Timer ist auch recht interessant. Damit werde ich auch mal experimentieren.

EWeiss 13. Feb 2012 18:33

AW: fortlaufende Animationen - ohne Freeze
 
Gesetz der Fall du würdest deine Animationen in einem AVIStream wiedergeben können.
Dann benötigst du kein Sleep sondern könntest direkt das Frame_XX (Bild) anzeigen lassen.

gruss

Muellermilchtrinker 13. Feb 2012 18:48

AW: fortlaufende Animationen - ohne Freeze
 
So ich hab mal ein wenig rumexperimentiert. Jedoch freezt sich mein Programm immer noch.
Also auf dem Hauptformular gibt es einen Timer, der für die Animation ausführern soll und danach auch wiederholen. Diese Animationen sind einzelne Prozeduren in einer anderen Unit. Nun habe ich in der anderen Unit einen Timer erstellt um eine gewisse Zeit warten zu können, ohne jeglichen Erfolg.

Also der Timer auf meinem Hauptformular ganz billig (wird mit 2 Buttons gestartet/gestoppt):
Delphi-Quellcode:
//Effekte Timer
procedure TfrmMain.effectTimer(Sender: TObject);
begin
  //Blinken Animation
  if blinken1.Checked then
  begin
    ani_blinken();
  end
  //mittlere Ebene rotieren
  else if rotierendeEbene1.Checked then
  begin

  end;
end;
Die rotierende Ebene ist noch nicht programmiert, da ich die eine Animation ja noch nicht ganz hab. ;)
Und dann in der Unit animations:
Delphi-Quellcode:
unit animations;

interface

uses
  ExtCtrls;

type
  TMyTimer = class(TTimer)
    procedure TimerProc(Sender: TObject);
  end;

  procedure waitpertimer(msec: Integer);
  procedure ani_blinken();

var
  timetoend: Integer;
  timestriked: Integer = 0;
  timeend: Boolean;

implementation

uses
  windows, Forms, draw;

procedure TMyTimer.TimerProc(Sender: TObject);
begin
  inc(timestriked);
  if timestriked = timetoend then
  begin
    timestriked := 0;
    timeend := true;
  end;
end;

procedure waitpertimer(msec: Integer);
  var Timer: TMyTimer;
begin
  Timer := TMyTimer.Create(nil);
  Timer.Enabled := False;
  Timer.Interval := 10;
  Timer.OnTimer := Timer.TimerProc;

  timetoend := round(msec/10);
  timeend := false;
  Timer.Enabled := True;

  repeat
    Application.ProcessMessages;
  until (timeend);

  Timer.Enabled := False;
  Timer.Free;
end;

//Lässt den LED Cube blinken
procedure ani_blinken();
begin
  //Cube an
  set_cube();

  waitpertimer(500);

  //Cube aus
  clear_cube();

  waitpertimer(500);
end;

end.
Die clear_cube und set_cube Funktionen sind in einer anderen Unit. Dort sollen später 0815-Zeichen-Routinen rein, damit man zum Beispiel eine Ebene nicht imemr mit Schleifen füllen muss.

MGC 13. Feb 2012 19:22

AW: fortlaufende Animationen - ohne Freeze
 
Warum zählst Du extra eine globale Variable hoch, anstatt die Systemuhr für Dich die vergangene Zeit angeben zu lassen?
Abgesehen davon finde ich Deinen Ansatz recht verworren.:? Warum organisierst Du die Blinkattacken Deiens Würfels nicht in einem eigenen Objekt und später die Rotation in einem anderen. Dann kannst Du diese Animationen als Objekte in eine Liste erzeugen und Deinen Timer in regelmäßigen kurzen Abständen diese Liste abarbeiten lassen.
Deinen Timer hat doch nicht zu interessieren was Deine Objekte anzeigen, er hat nur dafür sorge zu tragen, dass die Objekte immer wider mal angestuppst werden um den Bildschirm zu aktualisieren.
Wenn Du noch die Parentform an Deine Objekte übergibst, kannst Du direkt aus den Objekten heraus das Neuzeichnen der Form oder besser Übergabe der Zeichenfläche udn refresh der Zeichenfläche auslösen.

Tut mir leid, dass ich gerade eher den Eindruck habe als ob Du dabei bist Dein Projekt ein wenig zu einem Nudelgericht zu verdrehen.

Muellermilchtrinker 13. Feb 2012 19:54

AW: fortlaufende Animationen - ohne Freeze
 
Naja die Delayfunktionen die himitsu verlinkt hat, die produzieren auch freezes.

Sir Rufo 13. Feb 2012 21:42

AW: fortlaufende Animationen - ohne Freeze
 
So schwer kann das doch nicht sein ...

Nimm den Timer als Taktgeber und das Intervall stellst du auf den ggT aller Animationsintervalle.

Code:
Animation1 1000ms
Animation2 1500ms
Animation3 2000ms
Animation4 2500ms

ggT => 500ms

Animation1 => 2 Zyklen
Animation2 => 3 Zyklen
Animation3 => 4 Zyklen
Animation4 => 5 Zyklen
Für die Animation kannst du ja Klassen erstellen, die z.B. wie folgt aufgebaut sind:
Delphi-Quellcode:
TCustomAnimation = class
private
  FTaktCount : integer;
  FZyklen : integer;
protected
  procedure DoAnimation; virtual; abstract;
public
  procedure Taktung;
  property Zyklen : integer read FZyklen write FZyklen;
end;

procedure TCustomAnimation.Taktung;
begin
  Inc( FTaktCount );
  if FTaktCount >= FZyklen then
    begin
      FZyklen := 0;
      DoAnimation;
    end;
end;
und bei TimerEvent
Delphi-Quellcode:
procedure TForm1.Timer1Timer( Sender : TObject );
var
  idx : integer;
begin
  for idx := 0 to AnimationList.Count - 1 do
    TCustomAnimation( AnimationList[ idx ] ).Taktung;
end;
Ein Timer, kein Sleep, kein Freeze, alles schick

himitsu 13. Feb 2012 22:09

AW: fortlaufende Animationen - ohne Freeze
 
Zitat:

Deine Variante mit Delay im Timer ist auch recht interessant. Damit werde ich auch mal experimentieren.
Falsch verstanden.

Timer oder Sleep

bzw. Delay statt Sleep

MGC 13. Feb 2012 22:55

AW: fortlaufende Animationen - ohne Freeze
 
@Sir Rufo: Ja, so ungefähr habe ich mir das auch vorgestellt. Dann ist es sauberer Code der am Ende auch leicht erweiterbar ist. War selbst heute nur zu faul dies in Code zu packen, da ich nebenher an einem anderen Projekt gearbeitet habe.

@himitsu: Äh, nein nicht falsch verstanden, sorry, nur falsch geschrieben...:pale: meinte Delay statt Timer, bzw. Sleep anstatt von Delay mit Timer oder so... Ansonsten wäre ich ja selbst auf genau das reingefallen was ich vorher auch bemeckert hatte... klar soweit? :gruebel:


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:15 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