Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Eigene einfache 2D Grafik Engine (https://www.delphipraxis.net/78558-eigene-einfache-2d-grafik-engine.html)

ferby 6. Okt 2006 23:01


Eigene einfache 2D Grafik Engine
 
Hallo


Ich habe ein Problem mit Grafiken.

Ich programmiere gerade ein Spiel bei den auf der ganzen Form ständig bis zu 50 Images bewegt und vergrößer/verkleinert werden.

Leider geht das nicht ruckelfrei.

Ich habe schon mehrmals gelesen das TImage einfach nicht dafür gedacht ist,
deshalb möchte ich mir jetzt selbst eine ganz einfache Engine schreiben.

Delphix und andere Engines hab ich schon ausprobiert,
die sind aber zu komplex, bzw. zu aufwendig für meine Programme.
Vor allem möchte ich die Engine selbst schreiben.


Mein Ansatz ist simple:
Ich zeichne die 50 Objekte, die alle Rechtecke sind und meist einfärbig, auf einen TBitmap und mit
Delphi-Quellcode:
 BitBlt(paintbox1.Canvas.Handle, 0, 0, bm.Width, bm.Height, bm.Canvas.Handle, 0, 0, SrcCopy);
bring ich es dann auf ein TPaintBox.

Die Paintbox wird dann alle 50ms neu gezeichnet.

Jetzt meine eigentlich Frage:
Wenn ich bei meiner jetztigen Programmierung, bei dder ich 50 TImages verwende, doublebufferd auf true stelle,
dann ruckelt zwar nichts mehr, nur es wird alles um ca. das 10 Fache verlangsamt und die CPU springt sofort auf 100%.

Doublebufferd mach aber genau das selbe was ich machen will:
Es zeichnet intern auf ein Bitmap und bringt es dann auf einmal auf die Form.


Daher frage ich nun:
Hat meine Engine, so wie ich sie mir vorstelle, überhaupt einen Sinn?
Ist da ein Unterschied wen ich alle Objekte auf ein TBitmap Zeichne und dann auf eine PaintBox kopiere,
oder ob ich 50 Images habe und mit DoubleBufferd auf ein TBitmap intern zeichnen lasse?

Kann mich wer aufklären???


Bin auch dankbar für Ideen für die Engine,
sollt hal sehr einfach sein.

xaromz 6. Okt 2006 23:20

Re: Eigene einfache 2D Grafik Engine
 
Hallo,
Zitat:

Zitat von ferby
Hat meine Engine, so wie ich sie mir vorstelle, überhaupt einen Sinn?

Nein, siehe nächste Frage.
Zitat:

Zitat von ferby
Ist da ein Unterschied wen ich alle Objekte auf ein TBitmap Zeichne und dann auf eine PaintBox kopiere,
oder ob ich 50 Images habe und mit DoubleBufferd auf ein TBitmap intern zeichnen lasse?

Wie Du schon sagtest, DoubleBuffered macht genau das gleiche, nur mit geringfügig weniger Overhead.

Ändern sich denn immer alle Images? Wenn sich immer nur Teile ändern, dann kannst Du Windows mitteilen, auch nur diese Bereiche neu zu zeichnen. Dadurch lassen sich Performanceverbesserungen erreichen, die geradezu obszön sind.

Das eigentliche Problem ist aber: Du möchtest eine Framerate von 20 fps erreichen, dafür aber das GDI verwenden. Leider ist dieses nicht für so etwas ausgelegt. Genau dafür wurde DirectX (damals noch WinG) entwickelt. Wenn Du also flackerfreie grafikintensive Programme schreiben willst, rate ich Dir dringend zu einer hardwarebeschleunigten Graphikschnittstelle (DirectX/OpenGl).

Gruß
xaromz

Cöster 6. Okt 2006 23:24

Re: Eigene einfache 2D Grafik Engine
 
Ich weiß nicht, ob es was hilft, aber du könntest es ja mal versuchen:

Gar keine Images benutzen! Die Bitmaps, die sich unter den Images verbergen könntest du in Variablen im Hauptspeicher einlesen, um die Images nachher freigeben zu können. Ein Bitmap im Speicher braucht sicherlich weniger Platz als ein Image auf der Form und der Zugriff ist auch schneller. Dann kopierst du diese Bitmaps einfach mit BitBlt, wie du's beschrieben hast auf die PaintBox.

PS: Ein Timer-Intervall von 50 halte ich für zu langsam. Das sind gerade mal 20 Bilder pro Sekunde. Das menschliche Auge hat eine Reaktionszeit von einer 50tel Sekunde. Lieber ein 20er-Intervall.

Namenloser 6. Okt 2006 23:32

Re: Eigene einfache 2D Grafik Engine
 
Imho nimmt man ab 16 bildern pro sekunde schon eine bewegung wahr. :gruebel:

Auf jeden Fall sollte BitBlt schneller sein als tausend images. Einen Versuch wäre es also Wert. Ich würde aber für das Intervall keinen Timer nehmen, weil der sehr Ungenau ist und je nach Rechner/Betriebssystem unterschiedlich schnell laufen kann. Besser wäre eine Schleife mit selbstgebastelten Delays.

ferby 6. Okt 2006 23:40

Re: Eigene einfache 2D Grafik Engine
 
Hi,

Phuuu, verschiedene Antworten, verschiedene Vorschläge.



Zitat:

Das sind gerade mal 20 Bilder pro Sekunde.
Glaub mir für das spiel was ich mache reicht es. Du kannst mein Spiel mit Nokia Snake vergleichen,
bei solchen Spielen reichen 20 Bilder die Sekunde locker.


Zitat:

Ändern sich denn immer alle Images?
Nein nicht alles, aber sehr viel.
Nur ich glaub das wird mir dann schon wieder zu viel Aufwand, immer die Berieche zu suchen die neu gezeichnet werden sollen,
ich will das ganze so einfach und leicht wie möglich halten....



Ich hoff es hat jemand noch eine richtig guten Vorschlag der mich dazu bringt die Engine einfach zu schreiben oder das ganze zu lassen.

Cöster 7. Okt 2006 00:04

Re: Eigene einfache 2D Grafik Engine
 
Zitat:

Zitat von NamenLozer
Imho nimmt man ab 16 bildern pro sekunde schon eine bewegung wahr.

Natürlich, man sollte auch bei einem Bild pro Sekunde eine Bewegung wahrnehmen, sonst ist man ja blind. :P Es kommt nur darauf an, wann es ruckelt und wann nicht.


Zitat:

Zitat von ferby
Glaub mir für das spiel was ich mache reicht es. Du kannst mein Spiel mit Nokia Snake vergleichen,
bei solchen Spielen reichen 20 Bilder die Sekunde locker.

Nagut :wink:

Zitat:

Zitat von ferby
Ich hoff es hat jemand noch eine richtig guten Vorschlag der mich dazu bringt die Engine einfach zu schreiben oder das ganze zu lassen.

Kannst ja erstmal das mit den 50 Bitmaps im Speicher versuchen, sodass du die Images freigeben kannst. Wirst dann ja sehen, in wie weit Verbesserungen dann noch nötig sind.

ferby 7. Okt 2006 00:08

Re: Eigene einfache 2D Grafik Engine
 
Hallo,

Zitat:

Kannst ja erstmal das mit den 50 Bitmaps im Speicher versuchen
Wiso 50? Ich brauche nur ein Bitmap, auf den 50 Objekte gezeichnet werden^^



Zitat:

Wirst dann ja sehen, in wie weit Verbesserungen dann noch nötig sind.

Ich hoffe ja das mir jemand aus der Delphi-Praxis sagen kann ob meine Idee ein schwachsinn ist oder ob sie zimlich sicher bessere Performance bringt als mit DoubleBuffered.....

Cöster 7. Okt 2006 01:22

Re: Eigene einfache 2D Grafik Engine
 
Zitat:

Zitat von ferby
Hallo,

Zitat:

Kannst ja erstmal das mit den 50 Bitmaps im Speicher versuchen
Wiso 50? Ich brauche nur ein Bitmap, auf den 50 Objekte gezeichnet werden^^

Ja, statt der 50 Images auf der Form hast du dann 50 Bitmaps im Speicher. Also insgesamt 51 Bitmaps im Speicher. Es ist sicher schneller, von den 50 Bitmaps im Speicher auf das 51te zu kopieren als 50 mal Image1.Picture.Bitmap auf ein Bitmap im Speicher zu kopieren. Nachdem du die Bitmaps der 50 Images im Speicher hast solltest du für jedes Image nochmal Free aufrufen, um den Speicher etwas zu entlehren.

Sunlight7 7. Okt 2006 05:52

Re: Eigene einfache 2D Grafik Engine
 
Moin ferby!

Wenn ich das richtig verstehe, und Du so etwas das hier programmieren möchtest, muß es nicht DirectX sein.
In der schnellsten Stufe (Turbo, 10 KM/H) läuft mein Spiel mit 20 fps und die CPU langweilt sich dabei sowas von zwischen 0 und 3 Prozent bei 2.40 Ghz.

Wenn Du jetzt nicht die größten ansprüche auf die Framerate stellst, für 20 fps reicht GDI.

ferby 7. Okt 2006 10:26

Re: Eigene einfache 2D Grafik Engine
 
Hallo,

eigentlich sollte das reichen,
der große Unterschied bei meinen Spiel ist es, das sich nicht nur die Spielfigur bewegt (also bei dir der Wurm),
sondern auch das Spielfeld.

Ich werde mir einfach mal eine Engine basteln und dann hier rein posten ob es schneller ist oder ob es für die Katz war.

Cöster 7. Okt 2006 10:34

Re: Eigene einfache 2D Grafik Engine
 
Naja, was soll deine Engine denn leisten? Nur, dass sie nicht direkt auf die PaintBox zeichnet, sondern erst auf ein Bitmap? Dafür brauchst du keine Engine

SirThornberry 7. Okt 2006 10:37

Re: Eigene einfache 2D Grafik Engine
 
Also ich hab mir vor kurzem (für meine Firma) eine recht performante Engine gebastelt die wie folgt funktioniert.

Ich habe eine Anzeigefläsche (Display) worauf später das fertige Bild kommt.
Wenn irgend ein Object neu gezeichnet werden muss teilt dieses Object dem Display mit das es neu gezeichnet werden müsste.
Das Display hat einen Timer in dem geprüft wird ob seit dem letzten malen 40ms vergangen sind und prüft ob überhaupt ein neuemalen erforderlich ist (ob also irgend ein Object das malen Flag gesetzt hat).
Nur wenn mindestens 40ms vergangen sind und das Malenflag gesetzt ist ruft das Display von allen Objekten die Malen-Methode auf und übergibt ein Bitmap worauf gemalt werden muss.
Wenn also kein Object ein neu malen braucht bleibt das Display auch unverändert und die cpu-last sinkt auf 0%.
Zusätzlich wird im Paint des Displays noch das Bitmap (worauf die Objecte gemalt haben) ausgegeben.
Auf diese Art und Weise habe ich locker über 100 Frames pro Sekunde geschaft (die 40ms heruntergesetzt zum test).

Das war jetzt nur grob umrissen wie man sowas machen kann. In meinem speziellen Fall sorgt das Display auch dafür das ebenen welche auf der Z-Achse weiter hinten leigen als erstes gemalt werden etc.

arbu man 7. Okt 2006 10:41

Re: Eigene einfache 2D Grafik Engine
 
Image32 ist auch noch ein bissel schneller, gab hier in Forum schon ein paar Anwenungen die das benutzt hattenund gut liefen :)

mfg, Björn

Cöster 7. Okt 2006 11:44

Re: Eigene einfache 2D Grafik Engine
 
Zitat:

Zitat von SirThornberry
Das Display hat einen Timer in dem geprüft wird ob seit dem letzten malen 40ms vergangen sind

Wie machst du denn so einen Timer? Nach Standard-Timer hört es sich nicht an und du hörst dich auch nicht gerade wie ein Fan von OnIdle an.

Zitat:

Zitat von SirThornberry
Auf diese Art und Weise habe ich locker über 100 Frames pro Sekunde geschaft (die 40ms heruntergesetzt zum test).

Hm? Versteh ich nicht. Wenn nur alle 40 ms was passiert kannst du doch keine 100 fps erhalten :?:

SirThornberry 7. Okt 2006 12:47

Re: Eigene einfache 2D Grafik Engine
 
[quote="Cöster"]
Zitat:

Zitat von SirThornberry
Zitat:

Zitat von SirThornberry
Auf diese Art und Weise habe ich locker über 100 Frames pro Sekunde geschaft (die 40ms heruntergesetzt zum test).

Hm? Versteh ich nicht. Wenn nur alle 40 ms was passiert kannst du doch keine 100 fps erhalten :?:

Deswegen hatte ich ja geschrieben
Zitat:

(die 40ms heruntergesetzt zum test)
Das Problem was die meisten haben ist das sobald sich ein Object ändert sie das Bild auf die Canvas ausgeben. Wenn man jetzt mehrere Objecte hat welche alle 40 ms ein neuzeischnen auslösen wird nicht alle 40 ms ein neue Zeischnen ausgelöst sondern jedes Object löst ein neu zeischnen aus was das ganze so langsam macht.
Es geht also nur darum das man die Ausgabe auf den Bildschirm aufs nötigste begrenzt und nicht bei jeder miniänderung gleich das gesammte Bild ändert.

Sunlight7 7. Okt 2006 13:08

Re: Eigene einfache 2D Grafik Engine
 
Zitat:

Zitat von ferby
der große Unterschied bei meinen Spiel ist es, das sich nicht nur die Spielfigur bewegt (also bei dir der Wurm),
sondern auch das Spielfeld.

Das sieht nur so aus, als ob nur das Würmchen neu gezeichnet wird...
Da sich die CPU ohnehin so gelangweilt hat, war ich damals zu faul, da eine Optimierung einzubauen :???:

mimi 7. Okt 2006 13:09

Re: Eigene einfache 2D Grafik Engine
 
ich mache das so:
ich habe eine paintbox und eine liste alle objekte die ich zeichnen muss/möchte nun habe ich eine draw procedure die in zwei hälfe aufgeteilt ist:
isdraw auf drue wird alle komplet neu gezeichnet.

ist istDraw auf false wird nur noch das neugezeichet was sich geändert hat.

und ich verwende nur noch windows botschaften und habe dort eine zeitschleife eingebaut so habe ich es geschaft das die listbox die ich gezeichnet habe fast in "echtzeit" reagiert und das bei minimaler cpu auslastung*freu*.

atreju2oo0 7. Okt 2006 13:57

Re: Eigene einfache 2D Grafik Engine
 
Ansonsten ist es auch möglich mit der Scanline Eigenschaft zu arbeiten.
Da kriegst Du die Speicheradresse des Canvas Objektes und kannst dort direkt zeichnen.
Is meiner Erfahrung nach die schnellste Methode...

Sunlight7 7. Okt 2006 14:06

Re: Eigene einfache 2D Grafik Engine
 
Zitat:

Zitat von atreju2oo0
Ansonsten ist es auch möglich mit der Scanline Eigenschaft zu arbeiten.
Da kriegst Du die Speicheradresse des Canvas Objektes und kannst dort direkt zeichnen.
Is meiner Erfahrung nach die schnellste Methode...

Äh? Du meinst die Speicheradresse der DIB Bitmap.

ferby 12. Nov 2006 16:00

Re: Eigene einfache 2D Grafik Engine
 
Liste der Anhänge anzeigen (Anzahl: 3)
Hallo,

Also nach euren Antworten habe ich mich entschieden einfach mal meine eingene kleine Engine zu Basteln und schaun was rauskommt.

Das Ergebniss war super :-)


Die eigene Engine funktioniert ganz simpel:
Auf einen Bitmap wird im Hintergrund alles gemalt und dann wird alles auf eine PaintBox kopiert.

Ich habe euch alle 3 Versionen zum Testen bereitgestellt.

Achtung: Das Spiel Ferby-Speed Version 8 ist noch eine Alpha Version,
ich hab es nur zum Testen der Grafikengine raufgestellt, das Spiel selbst ist noch nicht fertig und kann noch Bugs haben.
Ich bitte nur um Kritik zur Grafik Leistung nicht zum Eigentlichen Spiel.


Version 8 Alpha 1:
Diese Version funktionirt mit Images, ohne Double Buffered

Version 8 Alpha 1.1
Diese Version funktioniert mit Images, mit Double Buffered

Version 8 Alpha 2
Diese Version funktioniert mit einen Bitmap und PaintBox


EDIT: Entzipt die Datei, öffnet die Exe, geht auf LEVEL LADEN, wählt Level 10. Da sieht man am besten den Unterschied.

Fazit:
Die eigene Engine hat sich gelohnt, fast kein Geschwindigkeitsverlust und die Grafiken ruckeln nicht mehr.

Cöster 13. Nov 2006 12:23

Re: Eigene einfache 2D Grafik Engine
 
Also um ehrlich zu sein: Es ruckelt bei mir! Ich hab mir Version 8 Alpha 2 runtergeladen. Es ruckelt sowohl im Spiel, als auch im Menü: einerseits das Raumschiff, andererseits die roten Linien die sich um die Menübox aufbauen.

igel457 15. Nov 2006 17:36

Re: Eigene einfache 2D Grafik Engine
 
Also bei mir läuft es ohne Probleme.

Ich finde es ganz nett.

Wenn du eine "richtige" 2D Engine suchst, nimm Andorra 2D :-).

Cöster 15. Nov 2006 18:22

Re: Eigene einfache 2D Grafik Engine
 
Zitat:

Zitat von igel457
Also bei mir läuft es ohne Probleme.

Hm, komisch. Also am deutlichsten ist es, wenn sich der rote Kasten aufbaut, nachdem man auf "Level laden" klickt. Die roten Linien werden immer wieder (vielleicht 4mal pro Sekunde) an manchen Stellen kurzzeitig (schätzungsweise ne 10tel Sekunde) blau (wie die Hintergrundfarbe).

Was ich mich immer wieder frage: Wie kriegen es die großen Spielefirmen hin, dass deren Spiele (egal wie aufwändig, detailreich, 3D sowieso) problemlos laufen, aber ein im Vergleich dazu graphisch eher anspruchsloses mit Delphi geschriebenes 2D-Spiel dagegen flackert bis zum geht nicht mehr (bei mir zumindest). Woran liegt das? Nicht genug optimiert? Wenn ja, wo kann man denn noch mehr optimieren? Mit etwa Delphi gar nicht? Womit dann? Was haben denn deren Engines, was ferbys Engine nicht hat?
Ich wär schon froh, wenn mir jemand auch nur eine dieser Fragen beantworten könnte.

xaromz 15. Nov 2006 19:08

Re: Eigene einfache 2D Grafik Engine
 
Hallo,
Zitat:

Zitat von Cöster
Was ich mich immer wieder frage: Was haben denn deren Engines, was ferbys Engine nicht hat?

Hardware-Beschleunigung.

Gruß
xaromz


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