![]() |
AW: FMX = Spiele-Engine in schlecht?
Zitat:
Zitat:
Seit Vista übernimmt das Rendern (inkl. Überlappungen usw.) die Grafikkarte statt der CPU, sofern das möglich und Aero aktiv ist. |
AW: FMX = Spiele-Engine in schlecht?
Liste der Anhänge anzeigen (Anzahl: 1)
@Daniel
Ich würde gern noch hier bleiben, weil ich noch bei der Idee der gepufferten Bitmaps bleiben will. Wenn Du das verschieben willst ist das natürlich auch ok (in meinen neuen OpenGL-Thread passt es aber auch nicht besser). @all Anbei nochmal eine neue Testversion. Die GUI wird im Mainthread gezeichnet. Die Businesslogik läuft in einem eigenen Thread. Dort erfolgen die Positionsänderungen usw. Die Geschwindigkeit des Threads kann über den Sleepwert geändert werden. Eine echte Anwendung würde man natürlich ohne Sleep laufen lassen. Da würden ja normalerweise keine Controls verschoben. Wenn man die VCL-Schleife startet, dann hängt die Anwendung natürlich so lange. Die Test-Schleife vom unteren Button läuft im Business-Thread. Die Geschwindigkeit ist vom Sleepwert abhängig. Der Zahlenwert in den Controls zeigt den Schleifenzähler an. Die Controls zeichnen sich jetzt bei jedem Frame neu. Es gibt also keine Bitmaps zum puffern mehr. Das Ganze läuft trotzdem sehr schnell (bei der einfachen Grafik). Bis 10.000 Panels läuft das flüssig, danach wird es hakelig. Der Flaschenhals bei FMX dürfte also wohl nicht mit Bitmappuffern zu verbessern sein, wie ich ursprünglich meinte. Was aber wichtig ist, ist bei Controländerungen nicht rings herum ständige Neuzeichnungen auszulösen. Ich habe drei neue Controls gebastelt: AniIndicator, Progressbar, Edit. Die sind natürlich nur mal schnell angetestet. :-) Der AniIndicator läuft ständig vor sich hin. Die Geschwindigkeit ist einstellbar. Die Progressbar kann mit der Maus eingestellt werden und läuft dann automatisch auf null zurück. Beide sind verbunden (ist natürlich hier kein echtes Binding ;-)) Die Edits können einen Fokus erhalten und Zeichen annehmen (sonst geht da noch nix - also kein Cursor, kein Select, kein Löschen usw!). Um das weiter auszubauen wäre natürlich einige Arbeit notwendig. Die VCL-Controls sind natürlich hier nur für Testzwecke. Real könnte man auf VCL-Controls verzichten (wenn es ausreichend Alternativen gäbe). Warum nun das Ganze? So richtig habe ich keine Ahnung! ;-) Die VCL und FMX will ich nicht mehr gern verwenden. Die sind einfach nicht angenehm, stabil und flüssig zu händeln. Die Demo gefällt mir vom Handling schon ganz gut. Man hat eine flüssige GUI, die unabhängig vom Businessthread läuft, der in einem Objekt gekapselt ist. Die Windowsereignisse spielen dann eigentlich keine Rolle mehr, außer dass das Formular diese abfängt und an die GUI übergibt. Die GUI-Controls können direkt in die Businesslogik gebunden werden. Ich habe jetzt m.E. einen Ablauf, wie er auch mit OpenGL o.ä. funktionieren würde - natürlich auf ganz anderem Niveau. ;-) Wenn ich das Projekt schrittweise debugge, dann werden Änderungen natürlich wie bei der VCL auch nicht sichtbar, da die Formularaktualisierung im Mainthread läuft. Evtl. könnte man den Formularcanvas einer fremden Anwendung kapern, so dass man Formularaktualisierungen so beim Debuggen erkennen könnte. PS: Jetzt gehe ich erst mal ins´ Bettchen - vielleicht bin ich morgen schon schlauer. :stupid: |
AW: FMX = Spiele-Engine in schlecht?
Zitat:
|
AW: FMX = Spiele-Engine in schlecht?
Vollkommen wegkommen von den Windows Events wirst du nicht, wenn du deine Zeichenvorgänge korrekt umsetzen willst. Dazu musst du nunmal zwangsweise auf die WM_PAINT reagieren (wenn du nicht auf gut Glück periodisch alles neu Zeichnen willst).
Dass alle Windows Messages in einem einzigen Message Loop (bei Delphi im "Main-Thread") empfangen werden, kann man als Vor- oder auch als Nachteil sehen. Klar blockiert eine Schleife von 1..10000 dann natürlich erstmal den Empfang weiterer Nachrichten, weshalb dann auch die GUI nicht mehr aktualisiert wird, oder Button Click Ereignisse nicht sofort umgesetzt werden. Auf der anderen Seite kannst du dieses Verhalten recht einfach beeinflussen, indem du (wie von jaenicke schon erwähnt) ein Paar
Delphi-Quellcode:
Aufrufe einstreust (oder System-nah direkt
Application.ProcessMessages
![]() ![]() ![]() Zu den Neuzeichnungen .. nehmen wir an ich habe folgende Hierachie:
Gehe ich hier mal generell von der Möglichkeit aus, dass eine Komponente semitransparent ist, so muss in jedem Falle alles was darunter liegt neu gezeichnet werden. Im "schlimmsten" Falle würde eine Änderung von Button3 also ebenfalls das Panel und das Formular neu zeichnen. Analog dazu muss natürlich bei einer Änderung des Panels sowohl das Formular (falls das Panel z.b. semintransparent ist oder einen AlphaChannel hat), als auch die darüberliegenden Buttons 3 und 4 (in jedem Falle; da diese ggfls. durch das Neuzeichnen des Panels teilweise überdeckt werden) neu gezeichnet werden. Man sieht also recht schnell, dass diese Zeichenlogik keine triviale Sache ist und dass man in gewissen Fällen halt einfach nicht um ein Neuzeichnen herumkommt. Optimieren kann man hier z.b. indem man jedem Control ein Flag zuweist, welches angibt, ob die Komponente semitransparent ist oder nicht. Dann spart man sich ein paar Zeichenoperationen von darunterliegenden Controls (macht die VCL soweit ich gesehen habe auch so). Falls das Zeichnen ansich wirklich ein Flaschenhals sein sollte, kann man natürlich auch das "Bitmap Caching" (mindestens GDI+, weil hier zwingend Transparenz / AlphaChannel benötigt wird) verwenden. Ich wage allerdings mal zu behaupten, dass die Zeichenoperationen in der Regel schneller sind, als die ganze Cache Geschichte. Auch wichtig ist, dass man exzessiven Gebrauch von Clipping macht und somit wirklich immer nur die Teile aktualisiert, die sich wirklich geändert haben und nicht wild drauf los das komplette Control. Im Hintergrund gehe ich zwar davon aus, dass sich ein Control IMMER komplett neu zeichnet, aber die GDI (oder zumindest mal DirectX, OpenGL) sollten die Zeichenoperationen entsprechend des Clippings optimieren, was sich dann wohl in einer kleinen Performancesteigerung sichtbar macht. |
AW: FMX = Spiele-Engine in schlecht?
So, nun nehme ich mir mal ein paar Minuten um das Konzept meiner selbst gezeichneten Komponenten zu erklären. Das ist vor FireMonkey entstanden. Im Moment sieht es allerdings so aus als ob das in der Praxis wegen FireMonkey nie zum Einsatz kommen wird und wir stattdessen FireMonkey einsetzen werden.
Deshalb kommt das ganze größtenteils aus der Erinnerung und einem kurzen Blick in den Quelltext, denn das ist schon eine Weile her... Das Grundprinzip: Beim Zeichnen bekommt die Komponente eine Zeichenfläche mit übergeben. Dort zeichnet sie sich selbst einfach drauf. Ob die Zeichenfläche der Bildschirm oder eine Bitmap ist, interessiert die Komponente nicht. Jede Komponente besitzt eine Methode, die eine Region erstellt, die die Grenzen der Komponente festlegt. Vor dem Zeichnen wird die Zeichenfläche mit ExtSelectClipRgn auf diese Region in Kombination der Region der Elternkomponente beschränkt. Man kann also z.B. günstige Gradientmethoden usw. nutzen, die eigentlich über die Komponente hinaus zeichnen würden, statt diese manuell auf die konkrete Region anzupassen. Muss eine Komponente neu gezeichnet werden und ist Transparenz aktiv, wird ein umgebendes Rechteck der Region benutzt um alle Komponenten, die im selben Bereich liegen, zu finden und ebenfalls neu zu zeichnen. Der Vergleich der Regionen kostete bei vielen Komponenten zu viel Zeit, ebenso die Sichtbarkeitsprüfung um nur nicht verdeckte und somit sichtbare Teile neu zu zeichnen. Dazu kommt nun, dass eine Komponente gedreht, gezerrt, gedrückt usw. werden kann. Dies weiß die Komponente selbst aber nicht, sondern wird über eine Matrixtransformation der Zeichenfläche realisiert. Die Komponente zeichnet sich selbst also ganz normal, sieht aber auf der realen Zeichenfläche entsprechend transformiert aus. Die Transformation geschieht mit SetWorldTransform, die reine Versetzung um einen gedrückten Zustand darzustellen mit SetViewportOrgEx (womit dies vor die weitere Transformation gesetzt wird ohne dass das normale Zeichnen diesen Extraoffset kennt), Transparenz kommt am Ende mit AlphaBlend dazu. Für den Designmodus wird ebenfalls das umgebende Rechteck verwendet und daran die Henkel zum Anfassen, drehen, zerren usw. gezeichnet. Das funktioniert natürlich direkt in Delphi wie man es gewohnt ist. Für den Objektinspektor war ein wenig Tools API Trickserei nötig, aber es funktioniert gut und war nicht weiter kompliziert. Quelltext kann ich wie gesagt nicht viel zeigen, daher nur in sehr groben Ausschnitten:
Delphi-Quellcode:
Auf diese Weise kann man das Bild z.B. drehen und versetzen. Mehr zu diesen Berechnungen findest du hier in der Doku zu SetWorldTransform:
var
TransForm: TXForm; TransForm.eM11 := Cos(RadAngle); TransForm.eM12 := Sin(RadAngle); TransForm.eM21 := -Sin(RadAngle); TransForm.eM22 := Cos(RadAngle); TransForm.eDx := OffsetX; TransForm.eDy := OffsetY; ![]() bzw. in der Doku zu ExtCreateRegion, mit der Funktion lässt sich eine Region analog transformieren: ![]() Das Zeichnen selbst ist daher sehr gradlinig:
Delphi-Quellcode:
Sprich es wird immer entsprechend geclipped und auch bei Fehlern das alte Clipping wiederhergestellt. Das try..finally ist hier sehr wichtig.
procedure T...Element.Paint(ACanvas: TCanvas);
var RegionRect: TRect; DisplayRegion, OldRegion: HRGN; begin DisplayRegion := AutoClipElement(ACanvas, RegionRect, OldRegion); try PaintTo(ACanvas, RegionRect); finally SelectClipRgn(ACanvas.Handle, OldRegion); DeleteObject(OldRegion); DeleteObject(DisplayRegion); end; end; Das mal als kurze Übersicht... |
AW: FMX = Spiele-Engine in schlecht?
Schade, dass sich solche Entwicklungen bisher nicht durchgesetzt hatten.
Ich hätte Dir auf jeden Fall mehr Qualität zugetraut als (nach leidlicher Erfahrung) Emba. |
AW: FMX = Spiele-Engine in schlecht?
Liste der Anhänge anzeigen (Anzahl: 4)
Nur mal am Rande: Transparente Controls bzw. Formulare habe ich jetzt auch mal versucht (normale Grafik, also kein OpenGL o.ä.).
Für Farbverläufe, Drehungen usw. wäre sicher die Nutzung von OpenGL o.ä. sinnvoll. Wenn man unter OpenGL eine Ausgabe drehen würde wäre mir nur unklar, ob man später Mausereignisse direkt auf die das Ergebnis der gedrehten Region umrechnen kann. Kann es sein, dass SDL so etwas unterstützt? |
AW: FMX = Spiele-Engine in schlecht?
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Wenn man den Anhang betrachtet, könnte man im ersten Falle ja einfach
Delphi-Quellcode:
verwenden, um zu prüfen, ob das Control "getroffen" wurde. Im zweiten Falle sieht das schon anders aus, da das BoundsRect nicht mehr der gezeichneten Darstellung entspricht.
BoundsRect.Contains(ClickPoint)
|
AW: FMX = Spiele-Engine in schlecht?
Liste der Anhänge anzeigen (Anzahl: 2)
Beim Aufräumen ist mir jetzt nochmal eine etwas überarbeitete Version "in die Hände gefallen". ;-)
Falls es jemanden interessiert: Man kann jetzt "Edits" und "ListBoxen" ein- und ausblenden und die Controls auf Wunsch transparent schalten. Bei den "Edits" kann man nur Zeichen eingeben und rückwärts wieder löschen. Die Listboxen kann man mit der Maus scrollen. Den Wert der "Progressbar" kann man mit der Maus einstellen und er geht nach dem Loslassen langsam wieder auf 0. Die Panels kann man mit der Maus einfangen und von Hand verschieben. Bis 10.000 Panels läuft das bei mir flüssig. Ziel war es, mal eine flüssige, kleine, aber funktionsfähige GUI selbst aufzubauen. Diese soll von der BL unabhängig lauffähig, allerdings auch leicht an die BL bindbar sein. (Das Projekt ist natürlich recht provisorisch und mit möglichst wenig Aufwand umgesetzt.) |
AW: FMX = Spiele-Engine in schlecht?
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe die Quellen von dem letzten Testprojekt leider nicht mehr, aber jetzt mal ein neueres Testprojekt etwas ausgebaut.
Das neue Projekt ist langsamer als das alte aber dafür mit geskinten Controls und einfachen 3D-Effekten. Das Programm kombiniert Daten, die es von einem Server abholt (der Drehwinkel des "Pulsars" wird laufend nur auf dem Server weiter berechnet) und den Positionsberechnungen der Controls, die eigenständig auf den Clients erfolgt (so wie ein ein- oder ausfliegendes Control oder ein AniIndicator individuell im Formular eines Anwenders). Das Projekt selbst kann ich nicht veröffentlichen aber hier mal ein kleines Video: ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:27 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