@Icke
schon mal guter Ansatz
> Um den Screen zu füllen sollte man größere Flächen nehmen, z.B. Box.
siehe B)
> ...dann widerum die bereits gesetzten Boxes nicht noch einmal setzen lassen.
siehe C)
ausserdem hast du durch das zeichnen aufs Fenster das Problem A) umgangen
Two-Picture-Fade
A) das erste Problem:
Die Screen-Buffer
durch das Double-Buffering ist es nicht möglich, auf bereits vorhandenes zu zeichnen,
da
zwei Buffer existieren.
wenn wir jetzt in jedem frame ein neues Pixel setzen,
wird in jedem der zwei Screenbuffer nur die Hälfte der Informationen stehen.
also brauchen wir einen extra-Buffer (ein Sprite) in den wir zeichnen,
und der in jedem Frame angezeigt wird.
B) das zweite Problem:
Die Framerate
wenn wir in jedem Frame ein Pixel verändern, brauchen wir für einen 800x600 Screen
480000 Frames, bei 60FPS sind das 8000 Sekunden oder 2:13:20
auf einem TFT oder LCD können wir (bei manchen) die Framerate extrem pushen,
und ohne V-Sync Flippen, aber bei vielen Monitoren geht das nicht,
ich habe das in meinem Beispiel mal gemacht,
aber ich bräuchte Hilfe (hallo Danilo

oder wer immer sich damit auskennt),
um das Buffer-Drawing und das Screen-Drawing zeitlich zu trennen, z.b. durch Threads
mir ging es hauptsächlich um den Algorythmus, und damit zu
C) das dritte Problem:
Der Algorythmus
wenn wir die Pixel per Zufall auswählen,
dann werden bereits gesetzte Pixel erneut gezeichnet,
je weiter der Prozess fortgeschritten ist, umso mehr.
also brauchen wir einen algorythmus,
mit dem jedes pixel genau einmal gezeichnet wird.
Die Lösung hier stammt aus den 80er Jahren und wurde für den C64 veröffentlicht.
allerdings wurde das damals auf dem Textbildschirm mit 40*25 Zeichen gemacht,
also ging es um 1000 Punkte, nicht um 480000, aber das Prinzip ist das gleiche.
normalerweise überträgt man Daten,
indem man einen Zähler immer um 1 hochsetzt.
man kann auch um andere werte hochsetzen,
und am Ende des Buffers um die Bufferlänge runtersetzen,
dann wird "streifenweise" übertragen.
um wirklich jede Speicherstelle zu erreichen,
muss man
ungerade Schrittweiten nehmen.
(mit geraden würde es zu überschneidungen kommen)
das löse ich dadurch, daß ich aus einem angegebenen
Mode
eine ungerade Zahl für die Schrittweite erzeuge,
aus 0 wird 1, aus 1 wird 3, aus 2 wird 5, usw.
für die meisten Schrittweiten sieht die Übertragung sehr regelmäßig aus,
aber ein paar werte erzeugen scheinbar zufällige Muster.
leider weiss ich nicht mehr, in welchem Verhältnis diese Schrittweiten
zur Buffergröße standen, also müssen wir rumprobieren,
im vorliegenden Beispiel hab ich einfach mal eine willkürliche Zahl genommen,
leider ist das Ergebnis immer noch ziemlich regelmäßig.
aber es gibt Werte, mit denen es 'gut' aussieht, glaubt mir
ausserdem arbeite ich mit der überblendung von einem sprite zu einem anderen,
eine überblendung von einem rein schwarzen zu einem rein roten Screen
erscheint mir etwas 'anwendungsarm'
so, hier nun der
Code: Alles auswählen
#ScrW = 800
#ScrH = 600
InitSprite()
InitKeyboard()
OpenScreen( #ScrW, #ScrH,32,"Test")
; ich Create mal alle 3 verwendeten Sprites vorab,
; damit man sieht, welche nummern ich verwende...
CreateSprite(8000, #ScrW, #ScrH) ; Ursprung
CreateSprite(8001, #ScrW, #ScrH) ; Ziel
CreateSprite(8002, #ScrW, #ScrH) ; Angezeigter Blendzustand
; ***************** Anfang Demo-Sprites Erzeugung
; ich grabbe hier mal irgendwas,
; man kann auch beliebige Grafix laden,
; (bitte auf exaktes format achten...)
; oder den vorher dargestellten Screen
; in Sprite 8000 grabben....
; einfach ein buntiges Bildchen für Sprite 8000
ClearScreen(0,0,0)
StartDrawing(ScreenOutput())
For n=0 To 999
Circle(Random(#ScrW),Random(#ScrH),4+Random(28),RGB(130+Random(120),130+Random(120),130+Random(120)))
Next
StopDrawing()
FlipBuffers()
Repeat:ExamineKeyboard():Until KeyboardPushed(#PB_Key_All) ; einfach mal schauen, wie's aussieht
FlipBuffers()
GrabSprite(8000, 0, 0, #ScrW, #ScrH)
; und nen rein roten Screen für 8001
ClearScreen(255,0,0)
GrabSprite(8001, 0, 0, #ScrW, #ScrH)
ClearScreen(0,0,0)
; ***************** Ende Demo-Sprites Erzeugung
; *** die Argumente für die Routine
; der Blendmode bestimmt das relative Pixel-Offset (Schrittweite der Überblendung)
; erlaubt sind alle Werte von 0 bis zur Hälfte der Pixel-Anzahl
BlendMode = 126845
; Die Festlegung der Blendtime ist notwendig, um die adäquate Framerate zu berechnen
; Angabe in Sekunden
BlendTime = 10
; ****
; **** Die Eigentliche Routine
; ****
AnzPix.l = #ScrW * #ScrH ; Gesamtanzahl der vorhandenen Pixel
Nxt.l = BlendMode*2+1
; aus dem Mode wird eine ungerade Zahl gemacht
; für die Schrittweite der Überblendung
If Nxt > AnzPix Or Nxt < 0 : End : EndIf ; Abbruch, wenn die Schrittweite größer als der Screen ist.
ActPix.l = 0 ; aktuelles Pixel, das übertragen wird.
FrmRt = AnzPix / BlendTime ; VORSICHT: dreckige Lösung
SetFrameRate(FrmRt) ; die Framerate wird hochgepusht
CopySprite(8000,8002)
DisplaySprite(8002,0,0)
FlipBuffers(0)
count = 1
Repeat
PixY = ActPix/#ScrW
PixX = ActPix-PixY*#ScrW
UseBuffer(8002) ; in Sprite 8002 ausgeben
ClipSprite(8001, PixX, PixY, 1, 1) ; nur das aktuelle Pixel
DisplaySprite(8001, PixX, PixY) ; in den Blend-Buffer übertragen
UseBuffer(-1) ; wieder auf Screen ausgeben
ActPix + Nxt ; Pixel-Offset dazuaddieren
If ActPix >= AnzPix ; innerhalb des Bereichs halten
ActPix - AnzPix
EndIf
DisplaySprite(8002,0,0) ; aktuellen Blend-Buffer anzeigen
FlipBuffers(0) ; OHNE V-SYNC flippen !
count+1
ExamineKeyboard()
Until count >= AnzPix Or KeyboardPushed(1)
Repeat:ExamineKeyboard():Until KeyboardPushed(#PB_Key_All) ; und nochmal auf taste warten
Taste drücken zum Starten,
am Ende nochmal Taste drücken.
der Vorgang kann mit ESC abgebrochen werden.