Effekte bei 2D Spielen basieren auf dem selben Prinzip wie auch Animationen. Man erzeugt ein großes Bild mit allen Teilen der Animation. Das große Bild besteht dann also aus jede Menge kleinen Bildern, ähnlich wie bei alten Filmen. Um den Effekt anzuzeigen, wird immer nur einen Ausschnitt von dem Bild dargestellt, nämlich dem aktuellen Teil der Animation (das selbe was auch ein Projektor mit dem altem Film machen würde). Um nun einen Effekt endlos zu wiederholen, z.B. ein blinkendes Bild, klebt man einfach die beiden Endes des Films aneinander, fängt also von vorne an, sobald die Animation zu ende ist.
Der Grund für dieses Vorgehen ist, das die Übertragung von Bildern in die Grafikkarte sehr langsam ist und es daher zu lange dauern würde den Effekt dann zu berechnen, wenn er benötigt würde. Es ist daher effizienter, am Anfang ein großes Bild zu Übertragen und der Grafikkarte mitzuteilen, das sie immer nur einen Teil des Bildes anzeigen soll. Bei 3D sieht das ganze wieder etwas anders aus, weil man dort Code an die Grafikkarte übertragen kann (Shader Scripte) und die Grafikkarte den Effekt dann selbst berechnen kann (es entfällt also die Übertragung CPU -> GPU).
Deine gewünschten Effekte (z.B. Aufblinken) sind nicht ganz einfach zu realisieren, weil Bilder normalerweise im RGB Format gespeichert werden und dabei nur Informationen über den Rot/Grün/Blau Anteil vorhanden sind. Es ist nicht direkt möglich die Helligkeit einer Farbe zu ändern. Um dies gut machen zu können, muss man die Farben in einen anderen Farbraum konvertieren, z.B. HSV. Bei HSV wird eine Farbe durch einen Wert (H), ihre Sättigung (S) und ihre Helligkeit (V) angegeben. Dies erlaubt es die Helligkeit einfach zu verändern. Danach muss das ganze dann wieder in RGB konvertiert werden, da die 2D Lib von PureBasic auch nur RGB versteht.
Ich habe dir mal ein Beispiel für das Aufblinken geschrieben, da ich noch eine Prozedur zum Konvertieren zwischen RGB und HSV hatte:
Code: Alles auswählen
EnableExplicit
Structure HSV
H.i
S.d
V.d
EndStructure
#IMAGE_PATH = "test.jpg" ;Anpassen!
#EFFECT_STEPS = 10 ;[3, inf)
#EFFECT_TIME = 50 ;ms
Procedure HSVtoRGB(H.i, S.d, V.d)
Protected hi.i = H / 60
Protected f.d = H / 60 - hi
Protected p.i = V * (1 - S) * 255
Protected q.i = V * (1 - S * f) * 255
Protected t.i = V * (1 - S * (1- f)) * 255
Select hi
Case 0, 6
ProcedureReturn RGB(V * 255, t, p)
Case 1
ProcedureReturn RGB(q, V * 255, p)
Case 2
ProcedureReturn RGB(p, V * 255, t)
Case 3
ProcedureReturn RGB(p, q, V * 255)
Case 4
ProcedureReturn RGB(t, p, V * 255)
Case 5
ProcedureReturn RGB(V * 255, p, q)
EndSelect
EndProcedure
Procedure RGBtoHSV(RGB.i, *H.INTEGER, *S.DOUBLE, *V.DOUBLE)
Protected R.d = Red(RGB) / 255
Protected G.d = Green(RGB) / 255
Protected B.d = Blue(RGB) / 255
Protected MAX.d = R
If B > MAX : MAX = B : EndIf
If G > MAX : MAX = G : EndIf
Protected MIN.d = R
If B < MIN : MIN = B : EndIf
If G < MIN : MIN = G : EndIf
If MAX = MIN ; R = G = B
*H\i = 0
ElseIf R = MAX
*H\i = Round((60 * (G-B))/(MAX-MIN), #PB_Round_Nearest)
ElseIf G = MAX
*H\i = Round(120 + (60*(B-R))/(MAX-MIN), #PB_Round_Nearest)
Else ; B = MAX
*H\i = Round(240 + (60*(R-G))/(MAX-MIN), #PB_Round_Nearest)
EndIf
If *H\i < 0 : *H\i + 360 : EndIf
If MAX = 0
*S\d = 0
Else
*S\d = (MAX-MIN)/MAX
EndIf
*V\d = MAX
EndProcedure
Procedure CreateEffect(Filename.s, *Width.INTEGER, *Height.INTEGER)
If LoadImage(0, Filename)
Protected Width = ImageWidth(0)
Protected Height = ImageHeight(0)
*Width\i = Width
*Height\i = Height
Protected NewImage = CreateImage(#PB_Any, Width * (2*#EFFECT_STEPS-2), Height)
If NewImage
Dim InputImage.HSV (Width, Height)
Protected x.i, y.i, i.i
StartDrawing(ImageOutput(0))
For x = 0 To Width - 1
For y = 0 To Height - 1
RGBtoHSV(Point(x,y), @InputImage(x,y)\H, @InputImage(x,y)\S, @InputImage(x,y)\V)
Next
Next
StopDrawing()
StartDrawing(ImageOutput(NewImage))
For i = 0 To #EFFECT_STEPS - 1
For x = 0 To Width - 1
For y = 0 To Height - 1
Protected V.d = InputImage(x,y)\V + (i * (0.3 / #EFFECT_STEPS))
If V > 1 : V = 1 : EndIf
Plot(x+i*Width, y, HSVtoRGB(InputImage(x,y)\H, InputImage(x,y)\S, V))
If i > 0 And i < #EFFECT_STEPS - 1
Plot(x + ((2*#EFFECT_STEPS-3)-(i-1))*Width, y, HSVtoRGB(InputImage(x,y)\H, InputImage(x,y)\S, V))
EndIf
Next
Next
Next
StopDrawing()
FreeImage(0)
ProcedureReturn NewImage
EndIf
FreeImage(0)
EndIf
ProcedureReturn #False
EndProcedure
UsePNGImageDecoder()
UseJPEGImageDecoder()
Define Width.i
Define Height.i
Define Image = CreateEffect(#IMAGE_PATH, @Width, @Height)
If Image
If OpenWindow(0, 0, 0, Width, Height, "Effect", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_ScreenCentered)
If InitSprite()
If OpenWindowedScreen(WindowID(0), 0, 0, Width, Height, 0, 0, 0)
If CreateSprite(0, ImageWidth(Image), ImageHeight(Image))
StartDrawing(SpriteOutput(0))
DrawImage(ImageID(Image), 0, 0)
StopDrawing()
EndIf
Define.i StartTime = ElapsedMilliseconds()
Repeat
ClearScreen(RGB(0, 0, 0))
Define.i Time = ElapsedMilliseconds() - StartTime
Define Anim = (Time / #EFFECT_TIME) % (2*#EFFECT_STEPS-2)
ClipSprite(0, Anim * Width, 0, Width, Height)
DisplaySprite(0, 0, 0)
FlipBuffers()
Delay(10)
Until WindowEvent() = #PB_Event_CloseWindow
EndIf
EndIf
CloseWindow(0)
EndIf
EndIf
Der Code erzeugt eine Animation, bei dem das Inputbild erstmal heller und dann wieder dunkler wird, es blinkt also auf. Das ganze ist nicht optimiert und soll auch nur mal die generelle Vorgehensweise zeigen.
Dark