Anfängerfrage zu Sprites und DoubleBuffering
- CptGreenwood
- Beiträge: 125
- Registriert: 12.07.2007 10:40
Anfängerfrage zu Sprites und DoubleBuffering
Hallo,
ich versuche seit Stunden verzweifelt ein eigentlich ganz einfaches Szenario hinzubekommen. Ich habe mit OpenScreen einen Grafikbildschirm geöffnet, mit LoadImage und DrawImage ein Hintergrundbild angezeigt und das Ganze mit FlipBuffer und ClearScreen in eine Schleife gelegt, die das Prog beendet, wenn man Escape drückt.
Das klappt auch gut.
Nun möchte ich bei einem Mausklick in der Mitte des Bildschirms eine Art Fenster anzeigen (die Grafik für das Fenster ist ein Sprite) und dann innerhalb einer Schleife mit 2 Sek. Abstand (Delay(2000)) einige weitere Sprites auf diesem Fenstersprite anzeigen und anschließend warten, bis eine Taste gedrückt wird, dann soll Fenstersprite samt allen anderen Sprites verschwinden und nur noch das Hintergrundbild sichtbar sein.
Ich habe es bisher mit keinem einzigen Versuch hinbekommen, was vielleicht daran liegt, dass ich das DoubleBuffering nicht 100%ig durchblicke. Entweder das Hintergrundbild ist weg, wenn ich die Maustaste drücke oder beim Anzeigen der Sprites auf dem Fenster (innerhalb Schleife) wird immer nur das aktuelle angezeigt, alle davor verschwinden oder ich sehe nur das Fenster mit dem allerletzen Sprite oder überhaupt nichts (kein Fenster, keine Sprites) und erst wenn ich Escape drücke sehe ich alles ganz kurz. bevor es verschwindet. Ich bekomme es einfach nicht hin!
Kann mir jemand, der mehr Erfahrung mit der 2D-Grafik hat kurz skizzieren, wann ich was machen muss? Wo brauche ich welche Schleifen? Wo muss ClearScreen und wo FlipBuffer stehen?
Wäre echt dankbar für Hilfe...
Greetz,
Cpt
ich versuche seit Stunden verzweifelt ein eigentlich ganz einfaches Szenario hinzubekommen. Ich habe mit OpenScreen einen Grafikbildschirm geöffnet, mit LoadImage und DrawImage ein Hintergrundbild angezeigt und das Ganze mit FlipBuffer und ClearScreen in eine Schleife gelegt, die das Prog beendet, wenn man Escape drückt.
Das klappt auch gut.
Nun möchte ich bei einem Mausklick in der Mitte des Bildschirms eine Art Fenster anzeigen (die Grafik für das Fenster ist ein Sprite) und dann innerhalb einer Schleife mit 2 Sek. Abstand (Delay(2000)) einige weitere Sprites auf diesem Fenstersprite anzeigen und anschließend warten, bis eine Taste gedrückt wird, dann soll Fenstersprite samt allen anderen Sprites verschwinden und nur noch das Hintergrundbild sichtbar sein.
Ich habe es bisher mit keinem einzigen Versuch hinbekommen, was vielleicht daran liegt, dass ich das DoubleBuffering nicht 100%ig durchblicke. Entweder das Hintergrundbild ist weg, wenn ich die Maustaste drücke oder beim Anzeigen der Sprites auf dem Fenster (innerhalb Schleife) wird immer nur das aktuelle angezeigt, alle davor verschwinden oder ich sehe nur das Fenster mit dem allerletzen Sprite oder überhaupt nichts (kein Fenster, keine Sprites) und erst wenn ich Escape drücke sehe ich alles ganz kurz. bevor es verschwindet. Ich bekomme es einfach nicht hin!
Kann mir jemand, der mehr Erfahrung mit der 2D-Grafik hat kurz skizzieren, wann ich was machen muss? Wo brauche ich welche Schleifen? Wo muss ClearScreen und wo FlipBuffer stehen?
Wäre echt dankbar für Hilfe...
Greetz,
Cpt
-
- Beiträge: 17389
- Registriert: 10.11.2004 03:22
eine Display-Schleife für nen Screen sollte IMMER permanent durchlaufen.
also, wenn du zwei sekunden lang was anzeigen willst, musst du
a) deine Frames mitzählen, bis zwei sekunden rum sind.
b) nen timer mitlaufen lassen.
du kanst für den anfang SetFrameRate() verwenden, oder du baust gleich nen timer ein.
hier mal zwei alte beispiele, wie screenhändling aussehen kann:
http://www.purebasic.fr/german/viewtopi ... 539#136539
http://www.purebasic.fr/german/viewtopi ... 634#116634
die sind auch etwas älter, also vielleicht musst du auch noch was anpassen...
also, wenn du zwei sekunden lang was anzeigen willst, musst du
a) deine Frames mitzählen, bis zwei sekunden rum sind.
b) nen timer mitlaufen lassen.
du kanst für den anfang SetFrameRate() verwenden, oder du baust gleich nen timer ein.
hier mal zwei alte beispiele, wie screenhändling aussehen kann:
http://www.purebasic.fr/german/viewtopi ... 539#136539
http://www.purebasic.fr/german/viewtopi ... 634#116634
die sind auch etwas älter, also vielleicht musst du auch noch was anpassen...
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Der Weise weiß, dass er ein Narr ist.
Code: Alles auswählen
InitSprite()
InitKeyboard()
InitMouse()
fa.l ;F(enster)A(ktiv)
OpenScreen(1024,768,32,"Screenhandling")
CreateSprite(0,1024,768) ;Hintergund
StartDrawing(SpriteOutput(0))
For y = 1 To 768
Line(0,y,1024,0,RGB(255*y/768,0,0))
Next
StopDrawing()
CreateSprite(1,400,400) ;Fenster
StartDrawing(SpriteOutput(1))
Box(0,0,400,400,RGB(132, 212, 232))
StopDrawing()
CreateSprite(2,32,32) ; Button1
StartDrawing(SpriteOutput(2))
Box(0,0,32,32,RGB(100,200,100))
StopDrawing()
CreateSprite(3,32,32) ; Button2
StartDrawing(SpriteOutput(3))
Box(0,0,32,32,RGB(100,100,100))
StopDrawing()
CreateSprite(4,4,4) ; Maus
StartDrawing(SpriteOutput(4))
Circle(2,2,2,RGB(0,255,0))
StopDrawing()
TransparentSpriteColor(4,0)
Repeat
ExamineKeyboard()
ExamineMouse()
ClearScreen(0)
DisplaySprite(0,0,0) ; hintergrund
If MouseButton(#PB_MouseButton_Left) And mp = 0; mp = mouse pressed
fa = 1
timer = ElapsedMilliseconds()
mp = 1
EndIf
If fa = 1
DisplaySprite(1,312,159) ; Fenster anzeigen
If (ElapsedMilliseconds() - timer)/1000 = 2 ; nach zwei Sekunden
ds = 1
EndIf
If (ElapsedMilliseconds() - timer)/1000 = 4 ; nach vier Sekunden
ds = 2
EndIf
If ds = 1
DisplaySprite(2,322,169) ; nach zwei sekunden ds = 1 wird nur das erste angezeigt
EndIf
If ds = 2 ; Nach vier sekunden das zweite zusammen mit dem ersten
DisplaySprite(2,322,169)
DisplaySprite(3,364,169)
EndIf
EndIf
DisplayTransparentSprite(4,MouseX(),MouseY()) ; Maus
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
Schlagt mich nicht, wenn es eigentlich besser geht, es ist halb drei morgens und ich penn schon vorm Pc.

Ich verkaufe Rechtschreibfehler und jede menge GROßBUCHSTABEN. Alles unbegrenzt zu haben.
- CptGreenwood
- Beiträge: 125
- Registriert: 12.07.2007 10:40
Drei Uhr am PC? Arghh.
Vielen Dank für die Antworten. Ich hab mir die Codeschnipsel mal angeschaut und bin zur Erkenntnis gekommen, dass ich es grundsätzlich falsch anpacke. Ich habe die Sprites auf dem Fenster in einer For-Schleife angezeigt, in der ich jeweils ein FlipBuffers untergebracht habe, die zwei Sekunden habe ich in der Schleife mit Delay realisiert. Ich werde es mal mit einer permanenten Schleife und dem Timer versuchen.
Zum Verständnis:
DoubleBuffering nimmt man dann, wenn sich Dinge auf dem Bildschirm bewegen sollen, damit Flackern vermieden wird, gell? Da sich bei mir aber nichts bewegt, sondern lediglich neue Elemente auf das aktuelle Bild drauf gezeichnet werden, könnte man da nicht sagen, dass man für diese Routine auf DoubleBuffering verzichtet und seinen Kram direkt in den FrontBuffer schreibt? Gab es da nicht eine Möglichkeit, zu bestimmen, ob die Ausgabe auf dem Front- oder dem BackBuffer gemacht werden soll?

Vielen Dank für die Antworten. Ich hab mir die Codeschnipsel mal angeschaut und bin zur Erkenntnis gekommen, dass ich es grundsätzlich falsch anpacke. Ich habe die Sprites auf dem Fenster in einer For-Schleife angezeigt, in der ich jeweils ein FlipBuffers untergebracht habe, die zwei Sekunden habe ich in der Schleife mit Delay realisiert. Ich werde es mal mit einer permanenten Schleife und dem Timer versuchen.
Zum Verständnis:
DoubleBuffering nimmt man dann, wenn sich Dinge auf dem Bildschirm bewegen sollen, damit Flackern vermieden wird, gell? Da sich bei mir aber nichts bewegt, sondern lediglich neue Elemente auf das aktuelle Bild drauf gezeichnet werden, könnte man da nicht sagen, dass man für diese Routine auf DoubleBuffering verzichtet und seinen Kram direkt in den FrontBuffer schreibt? Gab es da nicht eine Möglichkeit, zu bestimmen, ob die Ausgabe auf dem Front- oder dem BackBuffer gemacht werden soll?
-
- Beiträge: 167
- Registriert: 29.12.2005 09:58
- Computerausstattung: Intel Core2 Quad (4x2,4 GHz), 4096 MB RAM, GForce 8800GTX 786 MB
Windows XP 32 Bit, PureBasic 4.40 (x86)
Doublebuffering ist auch bei unbeweglichen Grafikausgaben zu empfehlen.
Nehmen wir an deine Hauptschleife sieht so aus:
- Bildschirm löschen, damit wäre z.B. alles schwarz
- Hintergrund zeichnen
- verschiedene Objekte zeichnen
- evtl. noch Benutzereingaben abfragen und darauf reagieren
Wenn du das jetzt ohne Doublebuffering machst, dann kann das bei wenigen Elementen noch klappen ohne das du was siehst, aber je mehr Elemente du anzeigst, desto mehr flimmert dein Programm, auch wenn sich nichts bewegt.
Der Grund:
Alles was du direkt auf den sichtbaren Bereich zeichnest ist sofort zu sehen. D.h. für den Bruchteil einer Sekunde ist der Bildschirm schwarz, dann ist nur das Hintergrundbild zu sehen, dann der Hintergrund und das erste Element, dann Hintergrund und die ersten beiden Elemente, usw. bis die ganze Grafikausgabe fertig ist. Danach beginnt alles wieder mit dem schwarzen Bildschirm.
Die zuletzt gezeichneten Elemente sind damit am kürzesten zu sehen und flimmern irgendwann. Sehr deutlich kann man das z.B. bei Spielen sehen, deren Hintergrund aus Tiles aufgebaut ist.
Beim Doublebuffering zeichnest du zuerst alles auf einen nicht sichtbaren Bereich und kopierst diesen dann auf einmal in den sichtbaren Bereich. Jetzt kannst du im nicht sichtbaren Bereich das Bild neu aufbauen, während sich der sichtbare Bereich in der Zwischenzeit nicht verändert.
Doublebuffering kann sogar sinnvoll sein wenn du auf ganz normale Fenster zeichnest (egal ob in einer Schleife oder im Repaint-Event), nur das du es dir da selber bauen musst, da FlipBuffers() nur mit Screens funktioniert.
Nehmen wir an deine Hauptschleife sieht so aus:
- Bildschirm löschen, damit wäre z.B. alles schwarz
- Hintergrund zeichnen
- verschiedene Objekte zeichnen
- evtl. noch Benutzereingaben abfragen und darauf reagieren
Wenn du das jetzt ohne Doublebuffering machst, dann kann das bei wenigen Elementen noch klappen ohne das du was siehst, aber je mehr Elemente du anzeigst, desto mehr flimmert dein Programm, auch wenn sich nichts bewegt.
Der Grund:
Alles was du direkt auf den sichtbaren Bereich zeichnest ist sofort zu sehen. D.h. für den Bruchteil einer Sekunde ist der Bildschirm schwarz, dann ist nur das Hintergrundbild zu sehen, dann der Hintergrund und das erste Element, dann Hintergrund und die ersten beiden Elemente, usw. bis die ganze Grafikausgabe fertig ist. Danach beginnt alles wieder mit dem schwarzen Bildschirm.
Die zuletzt gezeichneten Elemente sind damit am kürzesten zu sehen und flimmern irgendwann. Sehr deutlich kann man das z.B. bei Spielen sehen, deren Hintergrund aus Tiles aufgebaut ist.
Beim Doublebuffering zeichnest du zuerst alles auf einen nicht sichtbaren Bereich und kopierst diesen dann auf einmal in den sichtbaren Bereich. Jetzt kannst du im nicht sichtbaren Bereich das Bild neu aufbauen, während sich der sichtbare Bereich in der Zwischenzeit nicht verändert.
Doublebuffering kann sogar sinnvoll sein wenn du auf ganz normale Fenster zeichnest (egal ob in einer Schleife oder im Repaint-Event), nur das du es dir da selber bauen musst, da FlipBuffers() nur mit Screens funktioniert.
- CptGreenwood
- Beiträge: 125
- Registriert: 12.07.2007 10:40
Hmm... soweit verstanden. Aber was ist, wenn ich gar keine Hauptschleife habe und den Bildschirm damit auch nicht ständig lösche. Also etwa so (Ausgaben immer direkt auf den FrontBuffer):
1. Bildschirm löschen
2. Hintergrundbild anzeigen
3. Fenster anzeigen
4. For-Scheife
4a. Sprite n ins Fenster zeichnen
4b. Next
5. Repeat
5a. Until Tastendruck
6. Return
Habe ich denn korrekt in Erinnerung, dass es einen Befehl gibt, die Ausgabe direkt auf den FrontBuffer zu machen?
1. Bildschirm löschen
2. Hintergrundbild anzeigen
3. Fenster anzeigen
4. For-Scheife
4a. Sprite n ins Fenster zeichnen
4b. Next
5. Repeat
5a. Until Tastendruck
6. Return
Habe ich denn korrekt in Erinnerung, dass es einen Befehl gibt, die Ausgabe direkt auf den FrontBuffer zu machen?
-
- Beiträge: 167
- Registriert: 29.12.2005 09:58
- Computerausstattung: Intel Core2 Quad (4x2,4 GHz), 4096 MB RAM, GForce 8800GTX 786 MB
Windows XP 32 Bit, PureBasic 4.40 (x86)
Bezogen auf dein Beispiel sollte das dann so aussehen:
Code: Alles auswählen
Repeat
Delay(1) ;wegen CPU-Auslastung
FlipBuffers()
ClearScreen(#Black)
;Hintergrundbild zeichnen
;Fenster zeichnen
For n = 0 To anzahlSprites -1
;Sprite n zeichnen
Next n
ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape)
Dieses permanente Neuzeichnen des Screens in einer Schleife habe ich als alter Amiga-Rentner auch nicht auf Anhieb begreifen (wollen).
Ökologisch ist das nicht, PC und Grafikkarte sind ständig am rödeln, auch wenn nur statische Grafik angezeigt wird.
Eine Möglichkeit nur auf dem Frontbuffer zu zeichenen wäre in manchen Fällen gar nicht mal so schlecht. Zumal es im Screen-Modus auch nicht zu Überlappung mit einem Fenster kommen kann.
Als Beispiel fällt mir hier das langsame Zeichenen eines Graphen in einem Koordinatensystem ein.
Ökologisch ist das nicht, PC und Grafikkarte sind ständig am rödeln, auch wenn nur statische Grafik angezeigt wird.
Eine Möglichkeit nur auf dem Frontbuffer zu zeichenen wäre in manchen Fällen gar nicht mal so schlecht. Zumal es im Screen-Modus auch nicht zu Überlappung mit einem Fenster kommen kann.
Als Beispiel fällt mir hier das langsame Zeichenen eines Graphen in einem Koordinatensystem ein.
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.12 x64, OS: Win 11 24H2 x64, Desktopscaling: 150%, CPU: I7 12700 H, RAM: 32 GB, GPU: Intel(R) Iris(R) Xe Graphics | NVIDIA GeForce RTX 3070
Useralter in 2025: 57 Jahre.
PB 6.12 x64, OS: Win 11 24H2 x64, Desktopscaling: 150%, CPU: I7 12700 H, RAM: 32 GB, GPU: Intel(R) Iris(R) Xe Graphics | NVIDIA GeForce RTX 3070
Useralter in 2025: 57 Jahre.
- CptGreenwood
- Beiträge: 125
- Registriert: 12.07.2007 10:40
Ich habe die Hilfe mal durchforstet. Es scheint keine Möglichkeit in PB zu geben, direkt auf den Frontbuffer zu zeichnen. Schade eigentlich. Wie mein "Vorredner" schon sagt, alle Vorgänge die "langsam" ablaufen sollen, sind mit DoubleBuffering scheinbar ziemlich kompliziert.
@Rokur:
Dein Code würde sicherlich funktionieren, aber es wäre "flupp" alles auf einmal da. Es soll in der Spriteschleife ja der erste erscheinen, 2 Sek Pause, dann der zweite, 2 Sek Pause, dann der Dritte, u.s.w. Daran scheitere ich, das funktioniert nicht mit nem Delay, vielleicht wirklich nur über einen Timer.
@Rokur:
Dein Code würde sicherlich funktionieren, aber es wäre "flupp" alles auf einmal da. Es soll in der Spriteschleife ja der erste erscheinen, 2 Sek Pause, dann der zweite, 2 Sek Pause, dann der Dritte, u.s.w. Daran scheitere ich, das funktioniert nicht mit nem Delay, vielleicht wirklich nur über einen Timer.