Page 1 of 1

PB5.2 : Prefab, Layer, Sprite, Anim, FX

Posted: Sat Jul 06, 2013 2:45 pm
by eddy
- added: prefab & instance tools
- added: sprite & layer drawing methods
- added: sprite & layer customizable life-cycle methods (init,start,method,destroy,draw)
- added: sprite animation & frameset
- added: sprite offset (hotspot)
- added: delayed actions

Code: Select all

;-TOP
; Comment : Prefab functions, Layer & Sprite system, Sprite FX
; Author  : eddy
; Web     : http://www.purebasic.fr/english/viewtopic.php?f=12&t=417196
; File:   : PrefabSpriteFX.pbi
; Version : v0.9

EnableExplicit

CompilerIf #PB_Compiler_Debugger
   Import ""
      PB_DEBUGGER_SendError(Message.p-ascii)
      PB_DEBUGGER_SendWarning(Message.p-ascii)
   EndImport
CompilerElse
   Macro PB_DEBUGGER_SendError(Message) : EndMacro
   Macro PB_DEBUGGER_SendWarning(Message) : EndMacro
CompilerEndIf

Prototype InstanceMethod(*Instance)
Prototype InstanceDataMethod(*Instance, *CustomData)
Enumeration
   #Instance_Empty=0
   #Instance_Sprite
   #Instance_Layer
   #Instance_Particles
   
   #Blending_Normal=0
   #Blending_Add
   #Blending_Mult
   #Blending_2XMult
   #Blending_Invert
   
   #State_Prefab=%1
   #State_Alive=%10
   #State_Visible=%100
   #State_Enabled=%1000
   #State_Starting=%10000
   #State_AliveEnabledStarting=#State_Alive | #State_Enabled | #State_Starting
   #State_AliveEnabled=#State_Alive | #State_Enabled
   #State_AliveVisible=#State_Alive | #State_Visible
EndEnumeration
Structure VECTOR
   x.f
   y.f
EndStructure
Structure FRAME
   x.f
   y.f
   w.f
   h.f
EndStructure
Structure ANIMATION
   Array Frames.FRAME(0)
   Array FrameIds.i(0)
   *CurrentFrame.FRAME
   CurrentIndex.i   
EndStructure
Structure INSTANCE
   *PrefabSource.PREFAB
   *InitInstance.InstanceMethod
   *DestroyInstance.InstanceMethod
   State.i
   *CustomData
EndStructure
Structure POINT_INSTANCE Extends INSTANCE
   Pos.VECTOR
   Offset.VECTOR
   Angle.f
EndStructure
Structure SIZE_INSTANCE Extends POINT_INSTANCE
   Scale.VECTOR
   Width.i
   Height.i
EndStructure
Structure VISIBLE_INSTANCE Extends SIZE_INSTANCE
   Opacity.f
   Color.i
EndStructure
Structure SPRITE Extends VISIBLE_INSTANCE
   Sprite.i
   *Anim.ANIMATION
   
   *StartInstance.InstanceDataMethod
   *UpdateInstance.InstanceDataMethod
   *DrawInstance.InstanceMethod
EndStructure
Structure LAYER Extends VISIBLE_INSTANCE
   Blending.i
   List Sprites.SPRITE()
   
   *StartInstance.InstanceMethod
   *UpdateInstance.InstanceMethod
   *DrawInstance.InstanceMethod
EndStructure
Structure DISPLAY_SCREEN
   List Layers.LAYER()
EndStructure
Structure PREFAB
   Prefab.i
   InstanceType.i
   CreatePrefabResult.i
   StructureUnion
      *InstanceTemplate.INSTANCE
      *SpriteTemplate.SPRITE
      *LayerTemplate.LAYER
   EndStructureUnion
   StructureUnion
      *Parent
      *ParentLayer.LAYER
      *ParentScreen.DISPLAY_SCREEN
   EndStructureUnion
EndStructure
Structure DELAYED_ACTION
   StartTime.i
   EndTime.i
   Interval.i
   StructureUnion
      *Action
   EndStructureUnion
   StructureUnion
      *a
   EndStructureUnion
   StructureUnion
      *b
   EndStructureUnion
   StructureUnion
      *c
   EndStructureUnion
   StructureUnion
      *d
   EndStructureUnion
EndStructure
Global NewList Prefabs.PREFAB()
Global NewList Layers.LAYER()
Global NewList DelayedActions.DELAYED_ACTION()
Global DisplayScreen.DISPLAY_SCREEN

; ********************
; DELAYED ACTIONS
; ********************

Procedure DelayActionLoop(Delay, Duration, LoopInterval, *Action, *a=#Null, *b=#Null, *c=#Null, *d=#Null)
   Protected *newAction.DELAYED_ACTION=AddElement(DelayedActions())
   With *newAction
      \StartTime=ElapsedMilliseconds()+Delay
      \EndTime=\StartTime+Duration
      \Interval=LoopInterval
      \Action=*Action
      \a=*a
      \b=*b
      \c=*c
      \d=*d
   EndWith
EndProcedure

Procedure DelayAction(Delay, *Action, *a=#Null, *b=#Null, *c=#Null, *d=#Null)
   DelayActionLoop(Delay, 0, 0, *Action, *a, *b, *c, *d)
EndProcedure

; ********************
; DRAW FUNCTIONS
; ********************

Procedure RotateVector(*vector.VECTOR, Angle.f)
   Protected px.f=*vector\x
   Protected py.f=*vector\y
   Protected radian.f=Radian(Angle)
   Protected ca.f=Cos(radian)
   Protected sa.f=Sin(radian)
   *vector\x=ca*px-sa*py
   *vector\y=sa*px+ca*py
EndProcedure

Procedure ScaleVector(*vector.VECTOR, *Scale.VECTOR)
   *vector\x**Scale\x
   *vector\y**Scale\y
EndProcedure

Procedure ComputeVisibleInstances(*Source.VISIBLE_INSTANCE, *Target.VISIBLE_INSTANCE, *Result.VISIBLE_INSTANCE)
   With *Result
      \Scale=*Target\Scale
      \Angle=*Target\Angle
      \Pos\x=*Source\Pos\x+*Target\Pos\x
      \Pos\y=*Source\Pos\y+*Target\Pos\y
      RotateVector(\Pos, *Target\Angle)
      \Pos\x+*Target\Offset\x
      \Pos\y+*Target\Offset\y
      
      \Opacity=*Source\Opacity*(*Target\Opacity)
      \Color=*Source\Color
      If *Target\Color<>#PB_Default
         If *Source\Color=#PB_Default
            \Color=*Target\Color
         Else
            \Color=AlphaBlend(*Source\Color, *Target\Color)
         EndIf
      EndIf
   EndWith
EndProcedure

Procedure DefaultDrawSprite(*Sprite.SPRITE)
   With *Sprite
      If \Anim
         Protected *frm.FRAME=\Anim\CurrentFrame
         ClipSprite(\Sprite, *frm\x, *frm\y, *frm\w, *frm\h)
      EndIf
      
      Protected final.VISIBLE_INSTANCE
      ComputeVisibleInstances(*Sprite, \PrefabSource\ParentLayer, final)
      
      Protected x1.f=-\Offset\x*\Scale\x, x2.f=(\Width-\Offset\x)*\Scale\x
      Protected y1.f=-\Offset\y*\Scale\y, y2.f=(\Height-\Offset\y)*\Scale\y
      Protected Dim p.VECTOR(3), i
      p(0)\x=x1 : p(0)\y=y1
      p(1)\x=x2 : p(1)\y=y1
      p(2)\x=x2 : p(2)\y=y2
      p(3)\x=x1 : p(3)\y=y2
      For i=0 To 3
         RotateVector(p(i), \Angle)
      Next
      If final\Scale\x<>1 Or final\Scale\y<>1 
         For i=0 To 3
            ScaleVector(p(i), final\Scale)
         Next
      EndIf 
      If final\Angle
         For i=0 To 3
            RotateVector(p(i), final\Angle)
         Next
      EndIf 
      TransformSprite(\Sprite, p(0)\x, p(0)\y, p(1)\x, p(1)\y, p(2)\x, p(2)\y, p(3)\x, p(3)\y)
      DisplayTransparentSprite(\Sprite, final\Pos\x, final\Pos\y, 255*final\Opacity, final\Color)
   EndWith
EndProcedure

Procedure DefaultDrawLayer(*Layer.LAYER)
   ForEach *Layer\Sprites()
      Protected *sprite.SPRITE=*Layer\Sprites()
      With *sprite
         If (\State & #State_AliveEnabledStarting)=#State_AliveEnabledStarting And \StartInstance
            \State & ~#State_Starting
            \StartInstance(*sprite, *sprite\CustomData)
         EndIf
         If (\State & #State_AliveEnabled)=#State_AliveEnabled And \UpdateInstance
            \UpdateInstance(*sprite, *sprite\CustomData)
         EndIf
         If (\State & #State_AliveVisible)=#State_AliveVisible And \DrawInstance
            ;             Select *Layer\Blending
            ;                Case #Blending_Normal
            ;                   SpriteBlendingMode(#PB_Sprite_BlendSourceAlpha, #PB_Sprite_BlendInvertSourceAlpha)
            ;                Case #Blending_Add
            ;                   SpriteBlendingMode(#PB_Sprite_BlendOne, #PB_Sprite_BlendOne)
            ;                Case #Blending_Mult
            ;                   SpriteBlendingMode(#PB_Sprite_BlendZero, #PB_Sprite_BlendSourceColor)
            ;                Case #Blending_2XMult
            ;                   SpriteBlendingMode(#PB_Sprite_BlendDestinationColor, #PB_Sprite_BlendSourceColor)
            ;                Case #Blending_Invert
            ;                   SpriteBlendingMode(#PB_Sprite_BlendInvertDestinationColor, #PB_Sprite_BlendOne)
            ;             EndSelect
            
            \DrawInstance(*sprite)
         EndIf
      EndWith
   Next
EndProcedure

Procedure DisplayScreen()
   ForEach DelayedActions()
      With DelayedActions()
         If \StartTime<ElapsedMilliseconds()
            CallFunctionFast(\Action, \a, \b, \c, \d)
            If \Interval
               \StartTime=ElapsedMilliseconds()+\Interval
            EndIf 
            If \EndTime<ElapsedMilliseconds()
               DeleteElement(DelayedActions())
            EndIf 
         EndIf 
      EndWith
   Next 
   
   ForEach DisplayScreen\Layers()
      Protected *layer.LAYER=DisplayScreen\Layers()
      
      With *layer
         If (\State & #State_AliveEnabledStarting)=#State_AliveEnabledStarting And \StartInstance
            \State & ~#State_Starting
            \StartInstance(*layer)
         EndIf
         If (\State & #State_AliveEnabled)=#State_AliveEnabled And \UpdateInstance
            \UpdateInstance(*layer)
         EndIf
         If (\State & #State_AliveVisible)=#State_AliveVisible And \DrawInstance
            \DrawInstance(*layer)
         EndIf
      EndWith
   Next
EndProcedure

; ********************
; PREFAB
; ********************

Procedure.b IsPrefab(Prefab)
   ForEach Prefabs()
      If Prefabs()\Prefab=Prefab : ProcedureReturn #True : EndIf
   Next
EndProcedure

Procedure.i PrefabID(Prefab)
   If IsPrefab(Prefab)
      ProcedureReturn Prefabs()
   EndIf
EndProcedure

Procedure FreePrefab(Prefab)
   Protected *prefabID.PREFAB=PrefabID(Prefab)
   With *prefabID
      FreeMemory(\InstanceTemplate)
      DeleteElement(Prefabs())
   EndWith
EndProcedure

Procedure.i CreatePrefab(Prefab, InstanceType, *Parent, TemplateSize)
   Static PrefabCounter.i=1000000
   If Prefab>1000000 : PB_DEBUGGER_SendError("#Prefab object number is very high (over 1000000)!") : EndIf
   
   If Prefab<>#PB_Any And IsPrefab(Prefab)
      FreePrefab(Prefab)
   EndIf
   
   Protected *prefabID.PREFAB=AddElement(Prefabs())
   With *prefabID
      \InstanceType=InstanceType
      \Parent=*Parent
      \InstanceTemplate=AllocateMemory(TemplateSize)
      \InstanceTemplate\PrefabSource=*prefabID
      \InstanceTemplate\State | #State_Prefab | #State_Enabled | #State_Visible | #State_Starting
      If Prefab=#PB_Any
         PrefabCounter+17
         \Prefab=PrefabCounter
         \CreatePrefabResult=\Prefab
      Else
         \Prefab=Prefab
         \CreatePrefabResult=*prefabID
      EndIf
      ProcedureReturn *prefabID
   EndWith
EndProcedure

Procedure.i CreateSpritePrefab(Prefab, Image, Layer, *Init=#Null, *Start=#Null, *Update=#Null, *Destroy=#Null)
   Protected *prefabID.PREFAB=CreatePrefab(Prefab, #Instance_Sprite, Layer, SizeOf(SPRITE))
   With *prefabID\SpriteTemplate
      InitializeStructure(*prefabID\SpriteTemplate, SPRITE)
      \Scale\x=1
      \Scale\y=1
      \Width=ImageWidth(Image)
      \Height=ImageHeight(Image)
      \Offset\x=\Width/2
      \Offset\y=\Width/2
      \Opacity=1
      \Color=#PB_Default
      \InitInstance=*Init
      \StartInstance=*Start
      \UpdateInstance=*Update
      \DestroyInstance=*Destroy
      \DrawInstance=@DefaultDrawSprite()
      Protected *ImageMemory=EncodeImage(Image, #PB_ImagePlugin_PNG, 10, 32)
      \Sprite=CatchSprite(#PB_Any, *ImageMemory, #PB_Sprite_BilinearFiltering | #PB_Sprite_AlphaBlending)
      FreeMemory(*ImageMemory)
   EndWith
   ProcedureReturn *prefabID\CreatePrefabResult
EndProcedure

Procedure.i CreateLayerPrefab(Prefab, BlendingMode=#Blending_Normal, *Init=#Null, *Start=#Null, *Update=#Null, *Destroy=#Null)
   Protected *prefabID.PREFAB=CreatePrefab(Prefab, #Instance_Layer, @DisplayScreen, SizeOf(LAYER))
   With *prefabID\LayerTemplate
      InitializeStructure(*prefabID\LayerTemplate, LAYER)
      \Scale\x=1
      \Scale\y=1
      \Width=0
      \Height=0
      \Offset\x=0
      \Offset\y=0
      \Opacity=1
      \Color=#PB_Default
      \InitInstance=*Init
      \StartInstance=*Start
      \UpdateInstance=*Update
      \DestroyInstance=*Destroy
      \DrawInstance=@DefaultDrawLayer()
      \Blending=BlendingMode
   EndWith
   ProcedureReturn *prefabID\CreatePrefabResult
EndProcedure

; ********************
; INSTANCE
; ********************

Procedure.i CreateThis(Prefab, Count=1, Delay=0)
   If Delay=0
      If Count=1
         Protected *prefabID.PREFAB=PrefabID(Prefab)
         With *prefabID
            Protected *instance.INSTANCE
            Select \InstanceType
               Case #Instance_Sprite
                  *instance=AddElement(\ParentLayer\Sprites())
                  CopyStructure(\InstanceTemplate, *instance, SPRITE)
               Case #Instance_Layer
                  *instance=AddElement(\ParentScreen\Layers())
                  CopyStructure(\InstanceTemplate, *instance, LAYER)
            EndSelect
            
            *instance\State | #State_Alive & ~#State_Prefab
            
            If *instance\InitInstance
               *instance\InitInstance(*instance)
            EndIf
            ProcedureReturn *instance
         EndWith
      Else
         Protected creationLoop
         For creationLoop=1 To Count
            CreateThis(Prefab)
         Next
      EndIf
   Else
      DelayAction(Delay, @CreateThis(), Prefab, Count)      
   EndIf 
EndProcedure

Procedure FreeThis(*This.INSTANCE)
   With *This
      If \DestroyInstance
         \DestroyInstance(*This)
      EndIf
      If \CustomData
         FreeMemory(\CustomData)
      EndIf
      
      *This\State & ~#State_Alive
      
      Select \PrefabSource\InstanceType
         Case #Instance_Sprite
            ChangeCurrentElement(\PrefabSource\ParentLayer\Sprites(), *This)
            DeleteElement(\PrefabSource\ParentLayer\Sprites())
         Case #Instance_Layer
            ChangeCurrentElement(\PrefabSource\ParentScreen\Layers(), *This)
            DeleteElement(\PrefabSource\ParentScreen\Layers())
      EndSelect
   EndWith
EndProcedure

Procedure OffsetThis(*This.POINT_INSTANCE, x.f, y.f)
   *This\Offset\x=x
   *This\Offset\y=y
EndProcedure

Procedure RotateThis(*This.POINT_INSTANCE, Angle.f, Mode=#PB_Absolute)
   If Mode=#PB_Absolute
      *This\Angle=Angle
   Else
      *This\Angle+Angle
   EndIf
EndProcedure

Procedure MoveThis(*This.POINT_INSTANCE, x.f, y.f, Mode=#PB_Absolute)
   If Mode=#PB_Absolute
      *This\Pos\x=x
      *This\Pos\y=y
   Else
      *This\Pos\x+x
      *This\Pos\y+y
   EndIf
EndProcedure

Procedure ScaleThis(*This.SIZE_INSTANCE, x.f, y.f)
   *This\Scale\x=x
   *This\Scale\y=y
EndProcedure

Procedure OpacifyThis(*This.VISIBLE_INSTANCE, Opacity.f=1.0)
   *This\Opacity=Opacity
EndProcedure

Procedure ColorizeThis(*This.VISIBLE_INSTANCE, Color=#PB_Default)
   *This\Color=Color
EndProcedure

Procedure HideThis(*This.POINT_INSTANCE, hide.b)
   If hide
      *This\State & ~#State_Visible
   Else
      *This\State | #State_Visible
   EndIf   
EndProcedure 

Procedure AnimateThis(*This.SPRITE, FrameIndex, FrameLoop.s="", FrameSet.s="")
   With *This\Anim
      If FrameSet<>""
         FrameSet=LCase(FrameSet)
         Protected rowLength=Val(StringField(FrameSet, 1, "x"))
         Protected colLength=Val(StringField(FrameSet, 2, "x"))
         If colLength<1 : PB_DEBUGGER_SendError("FrameSet is invalid: column length must be greater than 1!") : EndIf
         If rowLength<1 : PB_DEBUGGER_SendError("FrameSet is invalid: row length must be greater than 1!") : EndIf
         
         *This\Anim=AllocateMemory(SizeOf(ANIMATION))
         InitializeStructure(*This\Anim, ANIMATION)
         
         ReDim \Frames(colLength*rowLength-1)
         Protected i, j, frameId, frmW.f, frmH.f
         frmW=SpriteWidth(*This\Sprite)/colLength
         frmH=SpriteHeight(*This\Sprite)/rowLength
         For j=0 To rowLength-1
            For i=0 To colLength-1
               frameId=i+j*colLength
               \Frames(frameId)\x=i* frmW
               \Frames(frameId)\y=j* frmH
               \Frames(frameId)\w=frmW
               \Frames(frameId)\h=frmH
            Next
         Next
      EndIf
      If FrameLoop<>""
         Protected loopIndex, loopLength=CountString(FrameLoop, ",")+1
         
         ReDim \FrameIds(loopLength-1)
         For loopIndex=0 To loopLength-1
            frameId=Val(StringField(FrameLoop, loopIndex+1, ","))
            If frameId<0 : PB_DEBUGGER_SendError("FrameLoop is invalid: frame ID must be greater than 1!") : EndIf
            \FrameIds(loopIndex)=frameId
         Next
      EndIf
      
      
      If *This\Anim
         \CurrentIndex=FrameIndex
         \CurrentFrame=\Frames(\FrameIds(\CurrentIndex))
         *This\Width=\CurrentFrame\w
         *This\Height=\CurrentFrame\h
      EndIf
   EndWith
EndProcedure

Procedure.b ThisIsAnimated(*This.SPRITE)
   ProcedureReturn Bool(*This\Anim)
EndProcedure

Procedure.b ThisIsHidden(*This.POINT_INSTANCE)
   ProcedureReturn Bool(*This\State & #State_Visible)
EndProcedure

Procedure.b ThisIsAlive(*This.POINT_INSTANCE)
   ProcedureReturn Bool(*This\State & #State_Alive)
EndProcedure

Procedure.b ThisIsEnabled(*This.POINT_INSTANCE)
   ProcedureReturn Bool(*This\State & #State_Enabled)
EndProcedure 

Procedure.f ThisPositionX(*This.POINT_INSTANCE)
   ProcedureReturn *This\Pos\x
EndProcedure

Procedure.f ThisPositionY(*This.POINT_INSTANCE)
   ProcedureReturn *This\Pos\y
EndProcedure

Procedure.f ThisOffsetX(*This.POINT_INSTANCE)
   ProcedureReturn *This\Offset\x
EndProcedure

Procedure.f ThisOffsetY(*This.POINT_INSTANCE)
   ProcedureReturn *This\Offset\y
EndProcedure

Procedure.f ThisAngle(*This.POINT_INSTANCE)
   ProcedureReturn *This\Angle
EndProcedure

Procedure.f ThisWidth(*This.SIZE_INSTANCE)
   ProcedureReturn *This\Width
EndProcedure

Procedure.f ThisHeight(*This.SIZE_INSTANCE)
   ProcedureReturn *This\Height
EndProcedure

Procedure.f ThisScaleX(*This.SIZE_INSTANCE)
   ProcedureReturn *This\Scale\x
EndProcedure

Procedure.f ThisScaleY(*This.SIZE_INSTANCE)
   ProcedureReturn *This\Scale\y
EndProcedure

Procedure.f ThisOpacity(*This.VISIBLE_INSTANCE)
   ProcedureReturn *This\Opacity
EndProcedure

Procedure.i ThisColor(*This.VISIBLE_INSTANCE)
   ProcedureReturn *This\Color
EndProcedure

Procedure.i ThisFrameIndex(*This.SPRITE)
   If *This\Anim
      ProcedureReturn *This\Anim\CurrentIndex
   Else
      ProcedureReturn 0
   EndIf
EndProcedure

Procedure.i ThisFrameCount(*This.SPRITE)
   If *This\Anim
      ProcedureReturn ArraySize(*This\Anim\FrameIds())
   Else
      ProcedureReturn 1
   EndIf
EndProcedure

Re: Sprite, Layer, Prefab

Posted: Sat Jul 06, 2013 2:48 pm
by eddy
Here is the first sample :

Code: Select all

DisableExplicit
UsePNGImageEncoder()
UsePNGImageDecoder()
InitSprite()

win=OpenWindow(#PB_Any, 0, 0, 610, 410, "PB 5.20b - Sprite alphablending", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(win), 5, 5, 600, 400, 0, 0, 0, #PB_Screen_NoSynchronization)

FlareImage=CreateImage(#PB_Any, 200, 200, 32, #PB_Image_Transparent)
If StartDrawing(ImageOutput(FlareImage))
   DrawingMode(#PB_2DDrawing_Gradient| #PB_2DDrawing_AlphaBlend| #PB_2DDrawing_Transparent)
   BackColor(RGBA(255, 255, 255, 255))
   GradientColor(0.2, RGBA(255, 230, 100, 70))
   GradientColor(0.6, RGBA(255, 60, 0, 30))
   FrontColor(RGBA(100, 0, 0, 0))
   CircularGradient(105, 100, 100)
   Circle(100, 100, 100)
   StopDrawing()
EndIf

Procedure UpdateLayer(Layer)
   MoveThis(Layer, Random(5), Random(5))
   RotateThis(Layer, 0.01, #PB_Relative)
EndProcedure

DefaultLayer=CreateThis(CreateLayerPrefab(#PB_Any, #Blending_Normal, #Null, #Null, @UpdateLayer()))
OffsetThis(DefaultLayer, ScreenWidth()/2, ScreenHeight()/2)

Global sx, sy, op.f, zx.f, zy.f
Procedure InitFlare(This)   
   MoveThis(This, sx+Random(20), sy+Random(20))
   ScaleThis(This, zx, zy)
   RotateThis(This, Random(360), #PB_Absolute)
   OffsetThis(This, ThisWidth(This)/2, ThisHeight(This)/2)
   OpacifyThis(This, op)   
EndProcedure
Procedure StartFlare(This, *CustomData)
   
EndProcedure
Procedure UpdateFlare(This, *CustomData)
   Global a.f
   RotateThis(This, 0.05, #PB_Relative)   
   ScaleThis(This, 0.4+0.1*Cos(a), 0.4+0.1*Sin(a))
EndProcedure
Define FlarePrefab=CreateSpritePrefab(#PB_Any, FlareImage, DefaultLayer, @InitFlare(), @StartFlare(), @UpdateFlare())
sx=30 : sy=30 : op=1 : zx=2 : zy=2
For i=0 To 3 : CreateThis(FlarePrefab) : Next
sx=-170 : sy=-70 : op=1 : zx=2 : zy=2
For i=0 To 3 : CreateThis(FlarePrefab) : Next



Repeat
   a+0.003   
   ClearScreen(RGB(0,0,0))
   DisplayScreen()
   FlipBuffers()
Until WindowEvent()=#PB_Event_CloseWindow

Re: Prefab, Layer, Sprite, FX

Posted: Sat Jul 06, 2013 2:57 pm
by ts-soft
:D

Run fine here on linux, only the #black is not defined.

Greetings - Thomas

Re: Prefab, Layer, Sprite, FX

Posted: Sat Jul 06, 2013 5:42 pm
by eddy
[Updated]
- Sprite frameset
- Sprite animation loop
- changed: CreateThis(...) with count parameter
- Fixed:Start method is executed only once before the first Update method call.
- Fixed:Layer scale & rotation effect on sprites
- Added: ThisIsAlive, ThisIsVisible, ThisIsAnimated, ThisIsEnabled

Here is a test of animated sprites

Code: Select all

DisableExplicit
UsePNGImageEncoder()
UsePNGImageDecoder()
InitSprite()

win=OpenWindow(#PB_Any, 0, 0, 610, 410, "PB 5.20b - Animated Sprite", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(win), 5, 5, 600, 400, 0, 0, 0, #PB_Screen_NoSynchronization)

FlareImage=CreateImage(#PB_Any, 200, 200, 32, #PB_Image_Transparent)
If StartDrawing(ImageOutput(FlareImage))
   DrawingMode(#PB_2DDrawing_Gradient| #PB_2DDrawing_AlphaBlend| #PB_2DDrawing_Transparent)
   BackColor(RGBA(255, 255, 255, 255))
   GradientColor(0.2, RGBA(255, 230, 100, 70))
   GradientColor(0.8, RGBA(255, 60, 0, 30))
   FrontColor(RGBA(100, 0, 0, 0))
   
   CircularGradient(50, 50, 50)
   Circle(50, 50, 50)
   
   CircularGradient(50+100, 50, 40)
   Circle(50+100, 50, 50)
   
   CircularGradient(50, 50+100, 30)
   Circle(50, 50+100, 50)
   
   CircularGradient(50+100, 50+100, 20)
   Circle(50+100, 50+100, 50)
   
   StopDrawing()
EndIf

DefaultLayer=CreateThis(CreateLayerPrefab(#PB_Any, #Blending_Normal))
OffsetThis(DefaultLayer, ScreenWidth()/2, ScreenHeight()/2)

Procedure InitFlare(This)
   AnimateThis(This, 1, "0,1,2,3,2,1", "2x2")
EndProcedure
Procedure StartFlare(This, *CustomData)
   AnimateThis(This, Random(ThisFrameCount(This)-1))
   MoveThis(This, -100+Random(200), -100+Random(200))
EndProcedure
Procedure UpdateFlare(This, *CustomData)
   frameIndex=(ThisFrameIndex(This)+1)  % ThisFrameCount(This) 
   AnimateThis(This, frameIndex)
EndProcedure
Define FlarePrefab=CreateSpritePrefab(#PB_Any, FlareImage, DefaultLayer, @InitFlare(), @StartFlare(), @UpdateFlare())
CreateThis(FlarePrefab, 4)

Repeat
   ClearScreen(RGB(0, 0, 0))
   DisplayScreen()
   FlipBuffers()
Until WindowEvent()=#PB_Event_CloseWindow

Re: Prefab, Layer, Sprite, Anim, FX

Posted: Sat Jul 06, 2013 10:20 pm
by Andre
I tried the includefile and the two examples on my MacBook with MacOS 10.5.8 and the new PB5.20 beta5 - unfortunately I get an IMA every time at the following line in the procedure CreateThis() (in the includefile):

Code: Select all

               CopyStructure(\InstanceTemplate, *instance, LAYER)
Every element of the structured variable *instance is shown with a value of '0.

Don't know what happens here, which is different than Windows?

Re: Prefab, Layer, Sprite, Anim, FX

Posted: Sat Jul 06, 2013 10:30 pm
by eddy
Andre wrote: Every element of the structured variable *instance is shown with a value of '0.
Don't know what happens here, which is different than Windows?
LAYER structure contains a "List" property.
In this case, the structured variable *instance need to be initiliazed.
Tell me if it works with the following lines.

Code: Select all

InitializeStructure(*instance, LAYER)
CopyStructure(\InstanceTemplate, *instance, LAYER)
This inconsistency is probably a bug. :?

Re: Prefab, Layer, Sprite, Anim, FX

Posted: Sat Jul 06, 2013 10:40 pm
by Andre
@eddy: sorry, didn't help, I'm still getting the IMA. I've inserted the additional line of code, so it looks like this now:

Code: Select all

            Case #Instance_Layer
               *instance=AddElement(\ParentScreen\Layers())
               InitializeStructure(*instance, LAYER)
               CopyStructure(\InstanceTemplate, *instance, LAYER)

Re: Prefab, Layer, Sprite, Anim, FX

Posted: Sat Jul 06, 2013 11:01 pm
by eddy
@Andre
I sent you a private message about this issue.

Re: Prefab, Layer, Sprite, Anim, FX

Posted: Sat Jul 06, 2013 11:14 pm
by rsts
Another nice one (or two) :)

Thanks for posting

Re: Prefab, Layer, Sprite, Anim, FX

Posted: Sun Jul 07, 2013 12:06 am
by eddy
[Updated]
- added: methods to delay actions
- changed: CreateThis(...) with Delay parameter

Code: Select all

DelayActionLoop(1000, 5000, 2000, @CreateThis(), BoxPrefab, 1) // after a delay 1s, create a new box every 2s during 5s
DelayAction(8000, @HideThis(), Layer, 1) // after a delay 8s, hide layer

Re: PB5.2 : Prefab, Layer, Sprite, Anim, FX

Posted: Sun Aug 18, 2013 8:46 pm
by True29
Purebasic 5.20 beta 11 didnt work :(