![]() |
Schreiben einer kleinen 3D-Engine - Timer
Ich habe mir seit Anfang des Jahres eine Menge Wissen über 3D-Engines angelesen und kleine Tests gemacht (insbesondere zu Netzwerk). Nun möchte ich testweise eine eigene, kleine Engine schreiben. Dies auf Basis der VCL, für Grafik verwende ich OpenGL, für Sound OpenAL, und für den Netzwerkteil die klassischen Komponenten TServerSocket und TClientSocket. Dann benötige ich aber noch einen Timer! Der normale von Delphi ist mir zu ungenau. Den von DelphiX möchte ich so in dieser Form nicht verwenden, weil ich diese ganze Komponenten-Sammlung nicht installieren möchte/kann (macht bei mir in der Schule Probleme mit dem Delphi6 PE, liegt laut Lehrer am Schulnetzwerk weil Delphi nicht lokal installiert ist und auf dem Server liegt). Also bräuchte ich einen Timer, den ich über eine einfache Unit einbinden kann. Gibt es das schon vorgefertigt? Wie kann ich es im Zweifelsfalle realisieren? Ich kann zwar eigene Komponenten schreiben bzw ableiten, aber ich habe keinen Schimmer, wie ich ein 'OnTimer'-Ereignis selber schreibe.
Wer kann mir helfen? MfG |
Re: Schreiben einer kleinen 3D-Engine - Timer
Also folgende Hilfe könnte ich geben:
Delphi besitzt eine OnIdle Routine, die die Applikation (die Winmain-Routine quasi) aufruft, wenn keine Nachrichten (WM_PAINT etc.) zu verarbeiten sind. Sie ist ziemlich hochauflösend. Schau mal unter OnIdle in der Online-Hilfe. Ansonsten einfach mit einem Thread machen. Es gibt da glaube ich einen DXTimer, der ziemlich gute Auflösungen schaffen soll. |
Re: Schreiben einer kleinen 3D-Engine - Timer
Dieser DXTimer ist der von DelphiX. Dann kenn ich auch noch den SanosTimer, der hat aber keine .pas und ich hab daher keine Ahnung wie ich den verwenden kann. Dann kenn ich noch den HighResTimer, den kann ich installieren und so, aber der hat nur einen Prozedur zum einmaligen warten und keine Schleife mit OnTimer-Ereignis. Könnte das aber mit einer boolean-Variable mache und einer Repeat-until-Schleife die solange ausgeführt wird bis ich die Variable auf false setze. Andere Vorschläge?
|
Re: Schreiben einer kleinen 3D-Engine - Timer
Ich habe dieses Problem mit einem Thread und CreateWaitableTimer realisiert.
Das Ereignis kann man durch eine CallBack
Delphi-Quellcode:
oder
type
T??? = class fOnTimer : TNotifyEvent; property OnTimer : TNotifyEvent read fOnTimer write fOnTimer; if Assigned(fOnTimer) then fOnTimer(Self); eine Botschaft auslösen PostMessage(hwndMain, WM_APP + ????, 0, 0); |
Re: Schreiben einer kleinen 3D-Engine - Timer
Die Möglichkeit gefällt mir wirklich gut! Aber ich habe da 3 Fragen:
MfG EDIT: Wenn ich die Hilfe richtig verstehe, muss ich das TNotifyEvent da verändern. Da muss dieses Warten rein. Und wenn ich dann auch noch richtig liege, das ich auf die property OnTimer in dieser Prozedur schreibend zugreifen kann und auf true setze, wird das Event ausgelöst oder wie?? |
Re: Schreiben einer kleinen 3D-Engine - Timer
Das war natürlich nur eine Skizze.
Für den kompletten Timer braucht man schon etwas mehr Code. Ich wollte dir da nur ein paar Stichworte gegeben, die die Idee formen könnten. Na gut, etwas mehr:
Delphi-Quellcode:
Das Teil ist noch nicht FERTIG!
type
TExTimer = class (TThread) private fOnTimer : TNotifyEvent; hClose : Cardinal; protected procedure Execute; override; public Hinweis: in Destroy muss der Thread über das hClose-Event beendet werden!!! property OnTimer : TNotifyEvent read fOnTimer write fOnTimer; end; procedure TExTimer.Execute; var hTimer : Cardinal; lQuit : Boolean; aObjs : array [0..1] of Cardinal; begin hClose := CreateEvent( ??? ); // Event damit der Thread sauber beendet werden kann hTimer := CreateWaitableTimer(nil, false, nil); SetWaitableTimer(hTimer, ???); aObjs[0] := hTimer; aObjs[1] := hClose; lQuit := false; repeat case WaitForMultipleObjects(2, @aObjs, false, INFINITE, false) of WAIT_OBJECT_0: if Assigned(fOnTimer) then fOnTimer(Self); WAIT_OBJECT_0 + 1: lQuit := true; else // Fehler end; end; until not lQuit; CloseHandle(hTimer); end; |
Re: Schreiben einer kleinen 3D-Engine - Timer
Ja das hilft meinem Verständnis schon sehr. Vielen Dank erstmal, ich werde mir das mal genauer ansehen.
MfG |
Re: Schreiben einer kleinen 3D-Engine - Timer
Möchtest du den Timer haben, um eine bestimmte Zeit abzuwarten und dann benachrichtigt zu werden, oder möchtest du über den Timer die gesamte Engine laufen lassen?
In letzterem Fall rate ich dir davon ab, schreib' schön deine Gameloop selbst und verwende zur Zeitmessung zum Beispiel den PerformanceCounter (QueryPerformanceCounter). Es gibt da einen Artikel zu dem Thema. In dem wird ausführlich erklärt, warum weder OnIdle noch ein beliebiger Timer verwendet werden sollten, um eine Game Engine am laufen zu halten. ![]() Achtung: Der Artikel beschreibt die Hintergründe, den Code am Ende würde ich allerdings so nicht empfehlen (Framebegrenzung sollte man nur dann implementieren, wenn es wirklich notwendig ist und wenn man weiß warum). Der Code unter "Keeping Awake" ist aber ein optimaler Ausgangspunkt. [Addendum] ![]() [/Addendum] |
Re: Schreiben einer kleinen 3D-Engine - Timer
OregonGhost, hab mir das aufmerksam durchgelesen. Die Idee dahinter ist zwar in einem kommerziellen Spiel o.ä. sinnvoll, da meine Engine aber im Großen und Ganzen nur zum Testen und lernen da sein wird, werde ich auf Timer und OnIdle zurückgreifen. Und die Zeitmessung zwischen Frames mache ich schon über den PerformanceCounter der CPU. Daraus ergibt sich bei einem leeren OpenGL-Vollbild bei 1024x768x32 auf einem Athlon TBird mit 256 MB RAM und einer Radeon9600 bisher stolze 1400 FPS. Also wird die Leistung auch bei etwas komplexeren Szenen ausreichen... Trotzdem vielen Dank!
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:32 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