Request: Frames for Images and Sprites
Request: Frames for Images and Sprites
I wonder why PureBasic doesn't have a frames parameter for images and sprites. How are you supposed to handle animations? Do you have to code your own frames system for animations? Why can't we just have this:
Syntax:
DrawImage(ImageID, x, y [, frame, Width, Height])
DisplaySprite(#Sprite, x, y [, frame])
Result = CreateImage(#Image, Width, Height [, frames, Depth])
Result = CreateSprite(#Sprite, Width, Height [, frames, Mode])
etc...
And then new functions where you can load multiple images/sprites in a left-to-right, top-to-bottom order.
Syntax:
LoadAnimImage(#Image,FileName$,width,height,firstframe,frames [, Flags])
LoadAnimSprite(#Sprite,FileName$,width,height,firstframe,frames [, Mode])
Syntax:
DrawImage(ImageID, x, y [, frame, Width, Height])
DisplaySprite(#Sprite, x, y [, frame])
Result = CreateImage(#Image, Width, Height [, frames, Depth])
Result = CreateSprite(#Sprite, Width, Height [, frames, Mode])
etc...
And then new functions where you can load multiple images/sprites in a left-to-right, top-to-bottom order.
Syntax:
LoadAnimImage(#Image,FileName$,width,height,firstframe,frames [, Flags])
LoadAnimSprite(#Sprite,FileName$,width,height,firstframe,frames [, Mode])
- Hroudtwolf
- Addict
- Posts: 803
- Joined: Sat Feb 12, 2005 3:35 am
- Location: Germany(Hessen)
- Contact:
- Fluid Byte
- Addict
- Posts: 2336
- Joined: Fri Jul 21, 2006 4:41 am
- Location: Berlin, Germany
I must admit these BlitzBasic functions wouldn't be bad but you can live witout it. Here's a brief example:
Code: Select all
InitSprite() : InitKeyboard()
OpenWindow(0,0,0,640,480,"void",#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0),0,0,640,480,0,0,0)
CreateSprite(0,512,64)
StartDrawing(SpriteOutput(0))
For i=0 To 7
Box(64*i,0,64,64,50 + i*28)
Next
StopDrawing()
Repeat
EventID = WindowEvent()
ClearScreen($804020)
ExamineKeyboard()
AnimDelay + 1
If AnimDelay = 8
AnimDelay = 0
If AnimMode : AnimFrame - 1 : Else : AnimFrame + 1 : EndIf
If AnimFrame = 7 Or AnimFrame = 0 : AnimMode = 1-AnimMode : EndIf
EndIf
ClipSprite(0,AnimFrame * 64,0,64,64)
For x=0 To 3
For y=0 To 3
DisplaySprite(0,130 + x * 100,50 + y * 100)
Next
Next
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape) Or EventID = #PB_Event_CloseWindow
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
Thanks, and extra thanks for the code example.
I didn't know about ClipSprite. I suppose it's enough but I would still prefer built in frame support, I think there is a limit to the size of an image, 8192x8192, it doesn't say if there is a limit for sprites but it's probably the same. This means there is a limit to how many frames you have eg. a 256x256 image has a max of 32 frames. So the only way around that if you need it is to code your own frame system I guess.
I didn't know about ClipSprite. I suppose it's enough but I would still prefer built in frame support, I think there is a limit to the size of an image, 8192x8192, it doesn't say if there is a limit for sprites but it's probably the same. This means there is a limit to how many frames you have eg. a 256x256 image has a max of 32 frames. So the only way around that if you need it is to code your own frame system I guess.
- Kaeru Gaman
- Addict
- Posts: 4826
- Joined: Sun Mar 19, 2006 1:57 pm
- Location: Germany
for sprites there is a limit in the screensize.
it's not that good idea to try to clip sprites bigger than the screen.
but you can also load the frames into single sprites following each other by number.
I wrote an Include some time ago that uses a matrix of frames to clip from, think it is for 3.94
perhaps you can use it, sorry for the german comments
it's not that good idea to try to clip sprites bigger than the screen.
but you can also load the frames into single sprites following each other by number.
I wrote an Include some time ago that uses a matrix of frames to clip from, think it is for 3.94
perhaps you can use it, sorry for the german comments
Code: Select all
; *******************************************************************
Declare FreeAnim() ; muss vordeklariert werden,
; weil auch von InitAnim benutzt
; *******************************************************************
Procedure InitAnim(No_of_Anims.l)
;*************************** Beginn Fehler-Pufferung
Static AnimReInit
If AnimReInit = 1 ; erneuter Aufruf?
FreeAnim() ; Speicherplatz freigeben.
Else ; erster Aufruf?
;*************************** Ende Fehler-Pufferung
Structure Animat ; Struktur definieren
PosX.l ; X-Position im Screen
Posy.l ; Y-Position im Screen
FraW.l ; Breite eines Einzelframes
FraH.l ; Höhe eines Einzelframes.
SetW.l ; Anzahl Frames in einer Reihe des Sets
SetH.l ; Anzahl Reihen im Set
Fram.l ; Aktueller Frame
NoFr.l ; Anzahl Frames gesamt
Mode.l ; Verzögerungs-Modus
Dely.l ; Aktuelle Verzögerung
msBf.l ; Millisekunden-Buffer
cont.l ; counter für frame-verzögerung
EndStructure
Global AnimErrorTxt.s ; FehlerNummer
Global AnimErrorNr.l ; FehlerText
Global AnimCount.l ; Anzahl Anims
Global SetOffset.l ; Erste Sprite-Nr.
;*************************** Beginn Fehler-Pufferung
EndIf
AnimReInit = 1
;*************************** Ende Fehler-Pufferung
AnimCount = No_of_Anims
SetOffset = 7000 ; hier verändern, wenn gewünscht
Dim Anim.Animat(No_of_Anims)
EndProcedure
; *******************************************************************
Procedure.l FreeAnim()
;*************************** Beginn Fehler-Pufferung
If AnimCount > 0 ; sind Anims vorhanden?
;*************************** Ende Fehler-Pufferung
For n=1 To AnimCount
If IsSprite(SetOffset+n) ; alle benutzten sprites
FreeSprite(SetOffset+n) ; werden freigegeben
EndIf
Next
Dim Anim.Animat(0) ; Array-Speicher freigeben
AnimCount = 0
;*************************** Beginn Fehler-Pufferung
ProcedureReturn 1 ; FreeAnim erfolgreich
Else
ProcedureReturn 0 ; FreeAnim fehlgeschlagen
EndIf
;*************************** Ende Fehler-Pufferung
EndProcedure
; *******************************************************************
Procedure.l CreateAnim(Nr.l, File.s, Mode.l, Width.l, Height.l, TRed.l, TGrn.l, TBlu.l)
SetNr = SetOffset+Nr
;*************************** Beginn Fehler-Pufferung
AnimErrorNr = 0 : AnimErrorTxt = ""
If AnimCount = 0
AnimErrorNr = 1 : AnimErrorTxt = "Nicht initialsiert"
EndIf
If LoadSprite(SetNr, File, 0) = 0
AnimErrorNr = 2 : AnimErrorTxt = "Ladefehler"
EndIf
If Height = 0 Or Width = 0
AnimErrorNr = 3 : AnimErrorTxt = "Null-Größe"
EndIf
If Nr > AnimCount Or Nr < 1
AnimErrorNr = 4 : AnimErrorTxt = "Ungültige Anim"
EndIf
If TRed<0 Or TRed>255 Or TGrn<0 Or TGrn>255 Or TBlu<0 Or TBlu>255
AnimErrorNr = 6 : AnimErrorTxt = "Ungültiger Farbwert"
EndIf
If AnimErrorNr = 0 ; nur ausführen, wenn kein Fehler aufgetreten ist
;*************************** Ende Fehler-Pufferung
SetWi = SpriteWidth(SetNr)
SetHe = SpriteHeight(SetNr)
If Mode = 0
Anim(Nr)\FraW = Width ; Sprite-Größe ist angegeben
Anim(Nr)\FraH = Height
Anim(Nr)\SetW = SetWi/Width ; Set-Größe wird ermittelt
Anim(Nr)\SetH = SetHe/Height
Else
Anim(Nr)\FraW = SetWi/Width ; Sprite-Größe wird ermittelt
Anim(Nr)\FraH = SetHe/Height
Anim(Nr)\SetW = Width ; Set-Größe ist angegeben
Anim(Nr)\SetH = Height
EndIf
Anim(Nr)\NoFr = Anim(Nr)\SetW * Anim(Nr)\SetH
TransparentSpriteColor(SetNr, TRed, TGrn, TBlu)
;*************************** Beginn Fehler-Pufferung
ProcedureReturn 1 ; fehlerfrei
Else
ProcedureReturn 0 ; fehlgeschlagen
EndIf
;*************************** Ende Fehler-Pufferung
EndProcedure
; *******************************************************************
Procedure SetAnimTransparence(Nr.l, TRed.l, TGrn.l, TBlu.l)
SetNr = SetOffset+Nr
;*************************** Beginn Fehler-Pufferung
AnimErrorNr = 0 : AnimErrorTxt = ""
If AnimCount = 0
AnimErrorNr = 1 : AnimErrorTxt = "Nicht initialsiert"
EndIf
If Nr > AnimCount Or Nr < 1 Or IsSprite(SetNr)=0
AnimErrorNr = 4 : AnimErrorTxt = "Ungültige Anim"
EndIf
If TRed<0 Or TRed>255 Or TGrn<0 Or TGrn>255 Or TBlu<0 Or TBlu>255
AnimErrorNr = 6 : AnimErrorTxt = "Ungültiger Farbwert"
EndIf
If AnimErrorNr = 0 ; nur ausführen, wenn kein Fehler aufgetreten ist
;*************************** Ende Fehler-Pufferung
TransparentSpriteColor(SetNr, TRed, TGrn, TBlu)
;*************************** Beginn Fehler-Pufferung
ProcedureReturn 1 ; fehlerfrei
Else
ProcedureReturn 0 ; fehlgeschlagen
EndIf
;*************************** Ende Fehler-Pufferung
EndProcedure
; *******************************************************************
Procedure.l SetAnimDelay(Nr.l, Mode.l, Value.l)
SetNr = SetOffset+Nr
;*************************** Beginn Fehler-Pufferung
AnimErrorNr = 0 : AnimErrorTxt = ""
If AnimCount = 0
AnimErrorNr = 1 : AnimErrorTxt = "Nicht initialsiert"
EndIf
If Nr > AnimCount Or Nr < 1 Or IsSprite(SetNr)=0
AnimErrorNr = 4 : AnimErrorTxt = "Ungültige Anim"
EndIf
If Value < 0
AnimErrorNr = 5 : AnimErrorTxt = "Ungültiges Delay"
EndIf
If AnimErrorNr = 0 ; nur ausführen, wenn kein Fehler aufgetreten ist
;*************************** Ende Fehler-Pufferung
Anim(Nr)\Mode = Mode
Anim(Nr)\Dely = Value
;*************************** Beginn Fehler-Pufferung
ProcedureReturn 1 ; fehlerfrei
Else
ProcedureReturn 0 ; fehlgeschlagen
EndIf
;*************************** Ende Fehler-Pufferung
EndProcedure
; *******************************************************************
Procedure.l ShowAnim(Nr.l, AX.l, AY.l)
SetNr = SetOffset+Nr
;*************************** Beginn Fehler-Pufferung
AnimErrorNr = 0 : AnimErrorTxt = ""
If AnimCount = 0
AnimErrorNr = 1 : AnimErrorTxt = "Nicht initialsiert"
EndIf
If Nr > AnimCount Or Nr < 1 Or IsSprite(SetNr)=0
AnimErrorNr = 4 : AnimErrorTxt = "Ungültige Anim"
EndIf
If AnimErrorNr = 0 ; nur ausführen, wenn kein Fehler aufgetreten ist
;*************************** Ende Fehler-Pufferung
If Anim(Nr)\Mode = 1 ; nach Millisekunden
ActTim = ElapsedMilliseconds()
If ActTim<0 And Anim(Nr)\msBf > 0 ; dies dient zum vermeiden
Anim(Nr)\msBf = ActTim+Anim(Nr)\Dely ; eines Hängenbleibens, falls
EndIf ; der Rechner 14 Tage läuft
If ActTim >= Anim(Nr)\msBf ; wenn die zeit verstrichen,
Anim(Nr)\msBf = ActTim+Anim(Nr)\Dely ; timer aktualisieren
Animate = 1 ; animieren erlauben
EndIf
Else ; nach Frames
Anim(Nr)\cont +1
If Anim(Nr)\cont > Anim(Nr)\Dely ; wenn anzahl frames vorbei,
Anim(Nr)\cont = 0 ; counter auf null
Animate = 1 ; animieren erlauben
EndIf
EndIf
If Animate = 1 ; wenn animieren
Anim(Nr)\Fram +1 ; nächstes Bild
If Anim(Nr)\Fram >= Anim(Nr)\NoFr ; nach letztem?
Anim(Nr)\Fram = 0 ; also erstes
EndIf
EndIf
FrOfY = Anim(Nr)\Fram/Anim(Nr)\SetW
FrOfX = Anim(Nr)\Fram-Anim(Nr)\SetW*FrOfY
ClipSprite(SetNr,FrOfX*Anim(Nr)\FraW,FrOfY*Anim(Nr)\FraH,Anim(Nr)\FraW,Anim(Nr)\FraH)
Anim(Nr)\PosX = AX
Anim(Nr)\PosY = AY
DisplayTransparentSprite(SetNr, AX, AY)
;*************************** Beginn Fehler-Pufferung
ProcedureReturn 1 ; fehlerfrei
Else
ProcedureReturn 0 ; fehlgeschlagen
EndIf
;*************************** Ende Fehler-Pufferung
EndProcedure
; *******************************************************************
Procedure.l MoveAnim(Nr.l, XM.l, YM.l)
SetNr = SetOffset+Nr
;*************************** Beginn Fehler-Pufferung
AnimErrorNr = 0 : AnimErrorTxt = ""
If AnimCount = 0
AnimErrorNr = 1 : AnimErrorTxt = "Nicht initialsiert"
EndIf
If Nr > AnimCount Or Nr < 1 Or IsSprite(SetNr)=0
AnimErrorNr = 4 : AnimErrorTxt = "Ungültige Anim"
EndIf
If AnimErrorNr = 0 ; nur ausführen, wenn kein Fehler aufgetreten ist
;*************************** Ende Fehler-Pufferung
If Anim(Nr)\Mode = 1 ; nach Millisekunden
ActTim = ElapsedMilliseconds()
If ActTim<0 And Anim(Nr)\msBf > 0 ; dies dient zum vermeiden
Anim(Nr)\msBf = ActTim+Anim(Nr)\Dely ; eines Hängenbleibens, falls
EndIf ; der Rechner 14 Tage läuft
If ActTim >= Anim(Nr)\msBf ; wenn die zeit verstrichen,
Anim(Nr)\msBf = ActTim+Anim(Nr)\Dely ; timer aktualisieren
Animate = 1 ; animieren erlauben
EndIf
Else ; nach Frames
Anim(Nr)\cont +1
If Anim(Nr)\cont > Anim(Nr)\Dely ; wenn anzahl frames vorbei,
Anim(Nr)\cont = 0 ; counter auf null
Animate = 1 ; animieren erlauben
EndIf
EndIf
If Animate = 1 ; wenn animieren
Anim(Nr)\Fram +1 ; nächstes Bild
If Anim(Nr)\Fram >= Anim(Nr)\NoFr ; nach letztem?
Anim(Nr)\Fram = 0 ; also erstes
EndIf
EndIf
FrOfY = Anim(Nr)\Fram/Anim(Nr)\SetW
FrOfX = Anim(Nr)\Fram-Anim(Nr)\SetW*FrOfY
ClipSprite(SetNr,FrOfX*Anim(Nr)\FraW,FrOfY*Anim(Nr)\FraH,Anim(Nr)\FraW,Anim(Nr)\FraH)
AX = Anim(Nr)\PosX + XM
AY = Anim(Nr)\PosY + YM
DisplayTransparentSprite(SetNr, AX, AY)
;*************************** Beginn Fehler-Pufferung
ProcedureReturn 1 ; fehlerfrei
Else
ProcedureReturn 0 ; fehlgeschlagen
EndIf
;*************************** Ende Fehler-Pufferung
EndProcedure
; *******************************************************************
oh... and have a nice day.
Thanks Kaeru, but I have decided to go with this sort of thing. I like it's simplicity.
1. store the separate image IDs in a memory block and return that.
2. pass the memory block to functions like this:
DrawImageFrame(ImageIDList, x, y [, frame, Width, Height])
and ImageFrame(ImageIDList,frame) so you can use it like this
DrawImage(ImageFrame(ImageIDList,frame), x, y [, Width, Height])
1. store the separate image IDs in a memory block and return that.
2. pass the memory block to functions like this:
DrawImageFrame(ImageIDList, x, y [, frame, Width, Height])
and ImageFrame(ImageIDList,frame) so you can use it like this
DrawImage(ImageFrame(ImageIDList,frame), x, y [, Width, Height])
- Kaeru Gaman
- Addict
- Posts: 4826
- Joined: Sun Mar 19, 2006 1:57 pm
- Location: Germany
- Hroudtwolf
- Addict
- Posts: 803
- Joined: Sat Feb 12, 2005 3:35 am
- Location: Germany(Hessen)
- Contact:
- Kaeru Gaman
- Addict
- Posts: 4826
- Joined: Sun Mar 19, 2006 1:57 pm
- Location: Germany
@hagibaba
oh yes.. I've seen your other topic.. ok
@Wolf
maybe that is a quite old information, aslike that you could only use (2^n)² images for textures...
newer grafix cards are possibly able to deal with clipping from larger sprites,
but I would not count on it, especially when writing games with low system requirements.
perhaps you WANT to write a game for older computers, that really everyone could play it.
then you have to take care of such issues like (2^n)² textures and small enough clippings....
oh yes.. I've seen your other topic.. ok
@Wolf
maybe that is a quite old information, aslike that you could only use (2^n)² images for textures...
newer grafix cards are possibly able to deal with clipping from larger sprites,
but I would not count on it, especially when writing games with low system requirements.
perhaps you WANT to write a game for older computers, that really everyone could play it.
then you have to take care of such issues like (2^n)² textures and small enough clippings....
oh... and have a nice day.