Isn't it better to create an array of sprites instead of redrawing the sprite each time ?
Just an idea with DisplayGif(*Object, ...) or DisplayTransparentGif(*Object, ...)
AnimatedGIFSprite
Re: AnimatedGIFSprite
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Re: AnimatedGIFSprite
Hi, thanks for your idea, but I think this should be moved to viewtopic.php?t=80564 because this is more like a sequence of post on my original Topic about Help with Animated Gifs.
Yes and No! In fact, I'm not sure if I understood what you're talking about. If I'm right you're saying what I said I was doing, decomposing the Animated Gifs into JPEGs and displaying them one by one, from a stack of images.
This is probably what I'll have to do, because it saves time and memory on a big game like mine. I can use lower resolutions, highly compressed JPGs and reduce the number of frames. The use of Animated GIFs is really looking too heavy for what I need!
It's this that you're proposing? I'd like to use the ClipSprite too, but I didn't try it yet, and I'm not sure if it works fine with Animated Gifs, as well as it works with static images. Probably I'll usee it for this as I used it for my maps...
Yes and No! In fact, I'm not sure if I understood what you're talking about. If I'm right you're saying what I said I was doing, decomposing the Animated Gifs into JPEGs and displaying them one by one, from a stack of images.
This is probably what I'll have to do, because it saves time and memory on a big game like mine. I can use lower resolutions, highly compressed JPGs and reduce the number of frames. The use of Animated GIFs is really looking too heavy for what I need!
It's this that you're proposing? I'd like to use the ClipSprite too, but I didn't try it yet, and I'm not sure if it works fine with Animated Gifs, as well as it works with static images. Probably I'll usee it for this as I used it for my maps...
Last edited by Kamarro on Sun Jan 22, 2023 4:32 pm, edited 1 time in total.
Re: AnimatedGIFSprite
Sometimes we lose time with things without any purpose, but I decided to try this little change on the main program and got a surprise: This animation of the dog running is really well done. Try this changes to see it really running. It's very good, and with only 7 frames! Nice!
Code: Select all
;
; https://www.purebasic.fr/english/viewtopic.php?p=594218
;
CompilerIf #PB_Compiler_IsMainFile
EnableExplicit
CompilerEndIf
Structure AnimatedGIFInfo_Structure
Frames.i
ActualFrame.i
OrgImage.i
Sprite.i
EndStructure
Structure AnimatedGIFSprite_Structure
Window.i
Map GIFInfoMap.AnimatedGIFInfo_Structure()
EndStructure
Global AnimatedGIFSprite.AnimatedGIFSprite_Structure
Define X
Procedure AnimateGIFSprites(*GIF.AnimatedGIFInfo_Structure)
SetImageFrame(*GIF\OrgImage, *GIF\ActualFrame)
;Debug "AddWindowTimer: " + Str(AnimatedGIFSprite\Window) + " " + Str(Sprite) + " " + Str(*AnimatedGIFSprite\FrameDelay)
AddWindowTimer(AnimatedGIFSprite\Window, *GIF\Sprite, GetImageFrameDelay(*GIF\OrgImage))
If StartDrawing(SpriteOutput(*GIF\Sprite))
DrawImage(ImageID(*GIF\OrgImage), 0, 0)
StopDrawing()
EndIf
*GIF\ActualFrame + 1
If *GIF\ActualFrame = *GIF\Frames
*GIF\ActualFrame = 0
EndIf
EndProcedure
Procedure AnimateGIFSpritesTimerEvent()
Protected *GIF.AnimatedGIFInfo_Structure
*GIF = FindMapElement(AnimatedGIFSprite\GIFInfoMap(), Str(EventTimer()))
If *GIF
RemoveWindowTimer(AnimatedGIFSprite\Window, *GIF\Sprite)
AnimateGIFSprites(*GIF)
EndIf
EndProcedure
Procedure AnimateGIFSpritesUpdate(EventLoop=#False)
If Not EventLoop
While WindowEvent() : Wend
EndIf
EndProcedure
Procedure.i LoadAnimatedGIFSprite(Sprite.i, Filename$, Mode.i=0, StartAnimationPosition.i=0)
Protected Image.i, Result.i, *AnimatedGIFSprite.AnimatedGIFInfo_Structure
If AnimatedGIFSprite\Window = 0
AnimatedGIFSprite\Window = OpenWindow(#PB_Any, 0, 0, 0, 0, "", #PB_Window_Invisible)
BindEvent(#PB_Event_Timer, @AnimateGIFSpritesTimerEvent(), AnimatedGIFSprite\Window)
EndIf
Image = LoadImage(#PB_Any, Filename$)
If Image
If Sprite = #PB_Any
Sprite = CreateSprite(#PB_Any, ImageWidth(Image), ImageHeight(Image), Mode)
Result = Sprite
Else
Result = CreateSprite(Sprite, ImageWidth(Image), ImageHeight(Image), Mode)
EndIf
If Result
*AnimatedGIFSprite = AddMapElement(AnimatedGIFSprite\GIFInfoMap(), Str(Sprite))
*AnimatedGIFSprite\OrgImage = Image
*AnimatedGIFSprite\Sprite = Sprite
*AnimatedGIFSprite\Frames = ImageFrameCount(Image)
If StartAnimationPosition > 0 And StartAnimationPosition <= 100
*AnimatedGIFSprite\ActualFrame = *AnimatedGIFSprite\Frames / (100 / StartAnimationPosition) - 1
EndIf
AnimateGIFSprites(*AnimatedGIFSprite)
EndIf
EndIf
ProcedureReturn Result
EndProcedure
;-Demo
CompilerIf #PB_Compiler_IsMainFile
Define.i Width, Height, Depth, ScreenReady, AnySprite
Define GIFFilename$
UseGIFImageDecoder()
If InitSprite() = 0 Or InitKeyboard() = 0
MessageRequester("Error", "Sprite system can't be initialized")
End
EndIf
If ExamineScreenModes()
While NextScreenMode()
Width = ScreenModeWidth()
If Width >= 800
Height = ScreenModeHeight()
Depth = ScreenModeDepth()
;Debug Str(Width) + "x" + Str(Height) + "," + Str(Depth)
Break
EndIf
Wend
Else
MessageRequester("Error", "Screen modes can't be detected")
End
EndIf
If MessageRequester("Choose screen mode", "Use OpenScreen()?", #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
If OpenScreen(Width, Height, Depth, "")
ScreenReady = #True
EndIf
Else
If OpenWindow(0, 0, 0, Width, Height, "Press ESC for exit", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
If OpenWindowedScreen(WindowID(0), 0, 0, Width, Height)
ScreenReady = #True
EndIf
EndIf
EndIf
If ScreenReady
GIFFilename$ = GetUserDirectory(#PB_Directory_Downloads) + "animated-dog-image-0175.gif"
ReceiveHTTPFile("https://www.animatedimages.org/data/media/202/animated-dog-image-0175.gif", GIFFilename$)
If FileSize(GIFFilename$) > 0
LoadAnimatedGIFSprite(1, GIFFilename$)
AnySprite = LoadAnimatedGIFSprite(#PB_Any, GIFFilename$, 0, 50)
Else
LoadAnimatedGIFSprite(1, #PB_Compiler_Home + "Examples/Sources/Data/PureBasicLogo.gif")
AnySprite = LoadAnimatedGIFSprite(#PB_Any, #PB_Compiler_Home + "Examples/Sources/Data/PureBasicLogo.gif", 0, 50)
EndIf
Repeat
FlipBuffers()
AnimateGIFSpritesUpdate() ; !!! only needed if no windows event loop is available !!!
ClearScreen(RGB(0, 128, 0))
;DisplaySprite(1, 100, 100)
DisplayTransparentSprite(AnySprite, X, 100)
Delay(150)
If X<1500 : X+30 : Else : X=100 : EndIf
ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape)
If FileSize(GIFFilename$) > 0
DeleteFile(GIFFilename$)
EndIf
EndIf
CompilerEndIf
Re: AnimatedGIFSprite
mk-soft variant:
Code: Select all
;
; https://www.purebasic.fr/english/viewtopic.php?p=594218
;
CompilerIf #PB_Compiler_IsMainFile
EnableExplicit
CompilerEndIf
Structure SpriteList_Structure
Sprite.i
Delay.i
EndStructure
Structure AnimatedGIFInfo_Structure
List SpriteList.SpriteList_Structure()
EndStructure
Structure AnimatedGIFSprite_Structure
Window.i
Map GIFInfoMap.AnimatedGIFInfo_Structure()
EndStructure
Global AnimatedGIFSprite.AnimatedGIFSprite_Structure
Procedure AnimateGIFSpritesTimerEvent()
Protected *AnimatedGIFSprite.AnimatedGIFInfo_Structure, Sprite.i
Sprite = EventTimer()
*AnimatedGIFSprite = FindMapElement(AnimatedGIFSprite\GIFInfoMap(), Str(Sprite))
If *AnimatedGIFSprite
RemoveWindowTimer(AnimatedGIFSprite\Window, Sprite)
If Not NextElement(*AnimatedGIFSprite\SpriteList())
FirstElement(*AnimatedGIFSprite\SpriteList())
EndIf
;Debug "AddWindowTimer: " + Str(Sprite) + " " + Str(*AnimatedGIFSprite\SpriteList()\Delay) + " " + Str(ListIndex(*AnimatedGIFSprite\SpriteList()))
AddWindowTimer(AnimatedGIFSprite\Window, Sprite, *AnimatedGIFSprite\SpriteList()\Delay)
EndIf
EndProcedure
Procedure AnimateGIFSpritesUpdate(EventLoop=#False)
If Not EventLoop
While WindowEvent() : Wend
EndIf
EndProcedure
Procedure.i LoadAnimatedGIFSprite(Sprite.i, Filename$, Mode.i=0, StartAnimationPosition.i=0)
Protected Image.i, Result.i, *AnimatedGIFSprite.AnimatedGIFInfo_Structure, Frame.i, ActualFrame
If AnimatedGIFSprite\Window = 0
AnimatedGIFSprite\Window = OpenWindow(#PB_Any, 0, 0, 0, 0, "", #PB_Window_Invisible)
BindEvent(#PB_Event_Timer, @AnimateGIFSpritesTimerEvent(), AnimatedGIFSprite\Window)
EndIf
Image = LoadImage(#PB_Any, Filename$)
If Image
If Sprite = #PB_Any
Sprite = CreateSprite(#PB_Any, ImageWidth(Image), ImageHeight(Image), Mode)
Result = Sprite
Else
Result = CreateSprite(Sprite, ImageWidth(Image), ImageHeight(Image), Mode)
EndIf
If Result
*AnimatedGIFSprite = AddMapElement(AnimatedGIFSprite\GIFInfoMap(), Str(Sprite))
AddElement(*AnimatedGIFSprite\SpriteList())
SetImageFrame(Image, 0)
*AnimatedGIFSprite\SpriteList()\Delay = GetImageFrameDelay(Image)
*AnimatedGIFSprite\SpriteList()\Sprite = Sprite
If StartDrawing(SpriteOutput(*AnimatedGIFSprite\SpriteList()\Sprite))
DrawImage(ImageID(Image), 0, 0)
StopDrawing()
EndIf
For Frame = 1 To ImageFrameCount(Image) - 1
AddElement(*AnimatedGIFSprite\SpriteList())
SetImageFrame(Image, Frame)
*AnimatedGIFSprite\SpriteList()\Delay = GetImageFrameDelay(Image)
*AnimatedGIFSprite\SpriteList()\Sprite = CreateSprite(#PB_Any, ImageWidth(Image), ImageHeight(Image), Mode)
If StartDrawing(SpriteOutput(*AnimatedGIFSprite\SpriteList()\Sprite))
DrawImage(ImageID(Image), 0, 0)
StopDrawing()
EndIf
Next Frame
If StartAnimationPosition > 0 And StartAnimationPosition <= 100
ActualFrame = Frame / (100 / StartAnimationPosition) - 1
If ActualFrame < 0
ActualFrame = 0
EndIf
EndIf
SelectElement(*AnimatedGIFSprite\SpriteList(), ActualFrame)
AddWindowTimer(AnimatedGIFSprite\Window, Sprite, *AnimatedGIFSprite\SpriteList()\Delay)
EndIf
EndIf
ProcedureReturn Result
EndProcedure
Procedure DisplayAnimatedSprite(Sprite.i, x.i, y.i)
Protected *AnimatedGIFSprite.AnimatedGIFInfo_Structure
*AnimatedGIFSprite = FindMapElement(AnimatedGIFSprite\GIFInfoMap(), Str(Sprite))
If *AnimatedGIFSprite
DisplaySprite(*AnimatedGIFSprite\SpriteList()\Sprite, x, y)
EndIf
EndProcedure
Procedure DisplayAnimatedTransparentSprite(Sprite.i, x.i, y.i, Intensity.i=255, Color.i=#PB_Ignore)
Protected *AnimatedGIFSprite.AnimatedGIFInfo_Structure
*AnimatedGIFSprite = FindMapElement(AnimatedGIFSprite\GIFInfoMap(), Str(Sprite))
If *AnimatedGIFSprite
If Color.i = #PB_Ignore
DisplayTransparentSprite(*AnimatedGIFSprite\SpriteList()\Sprite, x, y, Intensity)
Else
DisplayTransparentSprite(*AnimatedGIFSprite\SpriteList()\Sprite, x, y, Intensity, Color)
EndIf
EndIf
EndProcedure
;-Demo
CompilerIf #PB_Compiler_IsMainFile
Define.i Width, Height, Depth, ScreenReady, AnySprite
Define GIFFilename$
UseGIFImageDecoder()
If InitSprite() = 0 Or InitKeyboard() = 0
MessageRequester("Error", "Sprite system can't be initialized")
End
EndIf
If ExamineScreenModes()
While NextScreenMode()
Width = ScreenModeWidth()
If Width >= 800
Height = ScreenModeHeight()
Depth = ScreenModeDepth()
;Debug Str(Width) + "x" + Str(Height) + "," + Str(Depth)
Break
EndIf
Wend
Else
MessageRequester("Error", "Screen modes can't be detected")
End
EndIf
If MessageRequester("Choose screen mode", "Use OpenScreen()?", #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
If OpenScreen(Width, Height, Depth, "")
ScreenReady = #True
EndIf
Else
If OpenWindow(0, 0, 0, Width, Height, "Press ESC for exit", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
If OpenWindowedScreen(WindowID(0), 0, 0, Width, Height)
ScreenReady = #True
EndIf
EndIf
EndIf
If ScreenReady
GIFFilename$ = GetUserDirectory(#PB_Directory_Downloads) + "animated-dog-image-0175.gif"
ReceiveHTTPFile("https://www.animatedimages.org/data/media/202/animated-dog-image-0175.gif", GIFFilename$)
If FileSize(GIFFilename$) > 0
LoadAnimatedGIFSprite(1, GIFFilename$)
AnySprite = LoadAnimatedGIFSprite(#PB_Any, GIFFilename$, 0, 50)
Else
LoadAnimatedGIFSprite(1, #PB_Compiler_Home + "Examples/Sources/Data/PureBasicLogo.gif")
AnySprite = LoadAnimatedGIFSprite(#PB_Any, #PB_Compiler_Home + "Examples/Sources/Data/PureBasicLogo.gif", 0, 50)
EndIf
Repeat
FlipBuffers()
AnimateGIFSpritesUpdate() ; !!! only needed if no windows event loop is available !!!
ClearScreen(RGB(0, 128, 0))
DisplayAnimatedSprite(1, 100, 100)
DisplayAnimatedTransparentSprite(AnySprite, 300, 300)
ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape)
If FileSize(GIFFilename$) > 0
DeleteFile(GIFFilename$)
EndIf
EndIf
CompilerEndIf
Re: AnimatedGIFSprite
My God, I'm getting really older, distracted, or very tired. I didn't realise that you were talking about infratec's source and not my other question.mk-soft wrote: Sun Jan 22, 2023 3:50 pm Isn't it better to create an array of sprites instead of redrawing the sprite each time ?
Just an idea with DisplayGif(*Object, ...) or DisplayTransparentGif(*Object, ...)
Sorry for my misunderstanding. Now I can see why I didn't understood your suggestion.
And yes, of course you're right. An array is a better option and probably a bit faster and portable if we intend to export the results.
Sorry again for my mistake.
Cheers!
Re: AnimatedGIFSprite
Changed the code in first post:
added a FinishAnimatedGIFSprites() procedure.
Also added a version from mk-soft which don't use a hidden window and events.
added a FinishAnimatedGIFSprites() procedure.
Also added a version from mk-soft which don't use a hidden window and events.