SpriteEngine: Atlas,View,Layer,HotSpot,Flip,Animation,FX

Share your advanced PureBasic knowledge/code with the community.
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

SpriteEngine: Atlas,View,Layer,HotSpot,Flip,Animation,FX

Post by eddy »

  • screen layout : View -> Layers -> Sprite
  • view functions: Move, Rotate
  • layer functions: Hide, Move, Scale, Rotate
  • layer options: blend, filter, order, shadow
  • sprite functions: Hide, Move, Scale, Rotate, Deform, Skew, Flip
  • sprite options: HotSpot per frame, multi-frame animation, color gradient

Code: Select all

;:=============================================================================
;:- SpriteEngine.pbi
;:- Author          : Eddy
;:- Date            : September 25, 2013
;:- Compiler        : PureBasic 5.20 LTS
;:- Target OS       : Mac, Linux, Windows
;:- Source --------------------------------------------------------------------
;:- http://www.purebasic.fr/english/viewtopic.php?f=40&t=56507
;:=============================================================================
EnableExplicit
Structure SP_DEFORM
   x.f[4]
   y.f[4]
EndStructure
Structure SP_FRAME
   u.f[4]
   v.f[4]
   Width.f
   Height.f
   HotSpotX.f
   HotSpotY.f
EndStructure
Structure SP_ATLAS
   Atlas.i
   
   Texture.i
   Array Frames.SP_FRAME(0)
EndStructure
Structure SP_SPRITE
   Sprite.i
   
   *ParentLayer.SP_LAYER
   x.f
   y.f
   ScaleX.f
   ScaleY.f
   Angle.f
   State.i
   Frame.i
   Colors.i[4]
   *Deform.SP_DEFORM
EndStructure
Structure SP_LAYER
   Layer.i
   StructureUnion
      LayerPivot.i
      LayerRoll.i
      LayerScale.i
   EndStructureUnion
   LayerOffset.i
   LayerPosition.i
   LayerShadow.i
   
   Mesh.i
   MeshShadow.i
   Material.i
   MaterialShadow.i
   MaterialBlend.i
   MaterialFilter.i
   *Atlas.SP_ATLAS
   
   Map *AttachedSprites.SP_SPRITE()
   *ParentView.SP_VIEW
   x.f
   y.f
   ScaleX.f
   ScaleY.f
   State.i
   ShadowColor.i
   ShadowOffsetX.f
   ShadowOffsetY.f
EndStructure
Structure SP_VIEW
   View.i
   ViewPivot.i
   ViewOffset.i
   StructureUnion
      ViewPosition.i
      ViewRoll.i
   EndStructureUnion
   Camera.i
   
   Map *AttachedLayers.SP_LAYER()
   x.f
   y.f
   CameraX.i
   CameraY.i
   CameraWidth.i
   CameraHeight.i
   OffsetX.f
   OffsetY.f
   ScaleX.f
   ScaleY.f
EndStructure
Structure SP_ENGINE
   Map Atlases.SP_ATLAS()
   Map Views.SP_VIEW()
   Map Layers.SP_LAYER()
   Map Sprites.SP_SPRITE()
   *DefaultSprite.SP_SPRITE
   *DefaultLayer.SP_LAYER
   Array OrderUV.i(3, 3)
EndStructure
Global SpriteEngine.SP_ENGINE

Macro SP_Colon
   :
EndMacro
Macro SP_Override(Function)
   SP_Colon#Macro Function#SP_Colon#SP_#Function#SP_Colon#EndMacro
EndMacro
SP_Override(SpriteID)
SP_Override(RotateSprite)
SP_Override(FreeSprite)

Enumeration
   #Sprite_Hidden=%1
   #Sprite_FlipX=%10
   #Sprite_FlipY=%100
   #Sprite_FlipXY=#Sprite_FlipX|#Sprite_FlipY
   #Sprite_Disabled=%1000
   
   #Layer_Hidden=%1
   #Layer_Shadow=%10
EndEnumeration

Procedure.i ViewID(View)
   ProcedureReturn FindMapElement(SpriteEngine\Views(), ""+View)
EndProcedure
Procedure.i LayerID(Layer)
   ProcedureReturn FindMapElement(SpriteEngine\Layers(), ""+Layer)
EndProcedure
Procedure.i SpriteID(Sprite)
   ProcedureReturn FindMapElement(SpriteEngine\Sprites(), ""+Sprite)
EndProcedure
Procedure.i AtlasID(Atlas)
   ProcedureReturn FindMapElement(SpriteEngine\Atlases(), ""+Atlas)
EndProcedure

;---------- COLOR
Macro ColorRGB(ColorRGBA)
   RGB(Red(ColorRGBA), Green(ColorRGBA), Blue(ColorRGBA))
EndMacro
Macro ColorRGBA(ColorRGB, Alpha)
   RGBA(Red(ColorRGB), Green(ColorRGB), Blue(ColorRGB), Alpha)
EndMacro

;---------- ATLAS
Procedure FreeAtlas(Atlas)
   Protected *Atlas.SP_ATLAS=AtlasID(Atlas)
   ;free resources
   FreeTexture(*Atlas\Texture)
   DeleteMapElement(SpriteEngine\Atlases(), ""+Atlas)
EndProcedure
Procedure.i CreateAtlas(Atlas, Width, Height)
   Protected Result
   If Atlas=#PB_Any
      Static AtlasNumber=$FFFF : AtlasNumber+103 : Atlas=AtlasNumber
      AddMapElement(SpriteEngine\Atlases(), ""+Atlas)
      Result=Atlas
   Else
      If AtlasID(Atlas) : FreeAtlas(Atlas) : EndIf
      Result=AddMapElement(SpriteEngine\Atlases(), ""+Atlas)
   EndIf
   
   With SpriteEngine\Atlases()
      \Atlas=Atlas
      \Texture=CreateTexture(#PB_Any, Width, Height)
      \Frames(0)\u[0]=0 : \Frames(0)\v[0]=0
      \Frames(0)\u[1]=1 : \Frames(0)\v[1]=0
      \Frames(0)\u[2]=1 : \Frames(0)\v[2]=1
      \Frames(0)\u[3]=0 : \Frames(0)\v[3]=1
      \Frames(0)\Width=Width
      \Frames(0)\Height=Height
      ProcedureReturn Result
   EndWith
EndProcedure
Procedure.i LoadAtlas(Atlas, ImageFile.s, Quality=2)
   Protected TextureImage=LoadImage(#PB_Any, ImageFile)
   Protected TextureW=ImageWidth(TextureImage)
   Protected TextureH=ImageHeight(TextureImage)
   
   If Quality>0
      ;power of 2 texture size improves rendering quality
      TextureW=Pow(2, Round(Log(TextureW)/Log(2), #PB_Round_Up))
      TextureH=Pow(2, Round(Log(TextureH)/Log(2), #PB_Round_Up))
      
      ;texture square size improves compatibility with some GPU
      If Quality>1
         If TextureW<TextureH : TextureW=TextureH : Else : TextureH=TextureW : EndIf
      EndIf
   EndIf
   
   Protected Result=CreateAtlas(Atlas, TextureW, TextureH)
   With SpriteEngine\Atlases()
      StartDrawing(TextureOutput(\Texture))
      DrawingMode(#PB_2DDrawing_AlphaBlend)
      DrawImage(ImageID(TextureImage), 0, 0)
      StopDrawing()
   EndWith
   FreeImage(TextureImage)
   
   ProcedureReturn Result
EndProcedure
Procedure.i AtlasOutput(Atlas)
   Protected *Atlas.SP_ATLAS=AtlasID(Atlas)
   ProcedureReturn TextureOutput(*Atlas\Texture)
EndProcedure
Procedure.i SetAtlasFrame(Atlas, Frame, x, y, Width, Height, HotSpotX=0, HotSpotY=0, IsTurned=#False)
   Protected *Atlas.SP_ATLAS=AtlasID(Atlas)
   With *Atlas
      If Frame=#PB_Any
         Frame=ArraySize(\Frames())+1
      EndIf
      If Frame> ArraySize(\Frames())
         ReDim \Frames(Frame)
      EndIf
      
      If IsTurned : x-1 : EndIf
      Protected tw.f=TextureWidth(\Texture)
      Protected th.f=TextureHeight(\Texture)
      Protected u0.f=x/tw, v0.f=y/th
      Protected u1.f=(x+Width)/tw, v1.f=(y+Height)/th
   EndWith
   With *Atlas\Frames(Frame)
      If IsTurned
         \u[0]=u1 : \v[0]=v0
         \u[1]=u1 : \v[1]=v1
         \u[2]=u0 : \v[2]=v1
         \u[3]=u0 : \v[3]=v0
         \Width=Height
         \Height=Width
         \HotSpotX=HotSpotY
         \HotSpotY=\Height-HotSpotX
      Else
         \u[0]=u0 : \v[0]=v0
         \u[1]=u1 : \v[1]=v0
         \u[2]=u1 : \v[2]=v1
         \u[3]=u0 : \v[3]=v1
         \Width=Width
         \Height=Height
         \HotSpotX=HotSpotX
         \HotSpotY=HotSpotY
      EndIf
   EndWith
   ProcedureReturn Frame
EndProcedure
Procedure StartAtlas(Atlas, Margin=1)
EndProcedure
Procedure StopAtlas()
EndProcedure

;---------- SPRITE
Procedure FreeSprite(Sprite)
   Protected *Sprite.SP_Sprite=SpriteID(Sprite)
   ;detach parent
   FindMapElement(*Sprite\ParentLayer\AttachedSprites(), ""+Sprite)
   DeleteMapElement(*Sprite\ParentLayer\AttachedSprites())
   ;free resources
   If *Sprite\Deform : FreeMemory(*Sprite\Deform) : EndIf
   DeleteMapElement(SpriteEngine\Sprites(), ""+Sprite)
EndProcedure
Procedure.i CreateAnimatedSprite(Sprite, Layer, x.f, y.f, Frame=#PB_Default, Color=#PB_Default, Transparency=#PB_Default, Angle.f=#PB_Default, ScaleX.f=#PB_Default, ScaleY.f=#PB_Default)
   Protected Result
   If Sprite=#PB_Any
      Static SpriteNumber=$FFFF : SpriteNumber+103 : Sprite=SpriteNumber
      AddMapElement(SpriteEngine\Sprites(), ""+Sprite)
      Result=Sprite
   Else
      If SpriteID(Sprite) : FreeSprite(Sprite) : EndIf
      Result=AddMapElement(SpriteEngine\Sprites(), ""+Sprite)
   EndIf
   
   With SpriteEngine\Sprites()
      \Sprite=Sprite
      \ParentLayer=LayerID(Layer)
      \ParentLayer\AttachedSprites(""+Sprite)=SpriteEngine\Sprites()
      
      Protected cornerIndex, newColor=Color, newTransparency=Transparency, defaultColor
      For cornerIndex=0 To 3
         defaultColor=SpriteEngine\DefaultSprite\Colors[cornerIndex]
         If Color=#PB_Default : newColor=ColorRGB(defaultColor) : EndIf
         If Transparency=#PB_Default : newTransparency=Alpha(defaultColor) : EndIf
         \Colors[cornerIndex]=ColorRGBA(newColor, newTransparency)
      Next
      If Frame=#PB_Default : \Frame=SpriteEngine\DefaultSprite\Frame : Else : \Frame=Frame : EndIf
      If x=#PB_Default : \x=SpriteEngine\DefaultSprite\x : Else : \x=x : EndIf
      If y=#PB_Default : \y=SpriteEngine\DefaultSprite\y : Else : \y=y : EndIf
      If Angle=#PB_Default : \Angle=SpriteEngine\DefaultSprite\Angle : Else : \Angle=Angle : EndIf
      If ScaleX=#PB_Default : \ScaleX=SpriteEngine\DefaultSprite\ScaleX : Else : \ScaleX=ScaleX : EndIf
      If ScaleY=#PB_Default : \ScaleY=SpriteEngine\DefaultSprite\ScaleY : Else : \ScaleY=ScaleY : EndIf
      ProcedureReturn Result
   EndWith
EndProcedure
Procedure HideSprite(Sprite, IsHidden)
   Protected *Sprite.SP_SPRITE=SpriteID(Sprite)
   *Sprite\State & ~#Sprite_Hidden | Bool(IsHidden)*#Sprite_Hidden
EndProcedure
Procedure DisableSprite(Sprite, IsDisabled)
   Protected *Sprite.SP_SPRITE=SpriteID(Sprite)
   *Sprite\State & ~#Sprite_Disabled | Bool(IsDisabled)*#Sprite_Disabled
EndProcedure
Procedure MoveSprite(Sprite, x.f, y.f, Mode=#PB_Relative)
   Protected *Sprite.SP_SPRITE=SpriteID(Sprite)
   If Mode = #PB_Relative
      *Sprite\x+x
      *Sprite\y+y
   Else
      *Sprite\x=x
      *Sprite\y=y
   EndIf
EndProcedure
Procedure RotateSprite(Sprite, Angle.f, Mode=#PB_Relative)
   Protected *Sprite.SP_SPRITE=SpriteID(Sprite)
   If Mode=#PB_Relative
      *Sprite\Angle+Angle
   Else
      *Sprite\Angle=Angle
   EndIf
EndProcedure
Procedure ScaleSprite(Sprite, ScaleX.f, ScaleY.f, Mode=#PB_Absolute)
   Protected *Sprite.SP_SPRITE=SpriteID(Sprite)
   If Mode=#PB_Absolute
      *Sprite\ScaleX=ScaleX
      *Sprite\ScaleY=ScaleY
   Else
      *Sprite\ScaleX+ScaleX
      *Sprite\ScaleY+ScaleY
   EndIf
EndProcedure
Procedure FlipSprite(Sprite, FlipX=#False, FlipY=#False)
   Protected *Sprite.SP_SPRITE=SpriteID(Sprite)
   With *Sprite
      FlipX & ~(#Sprite_FlipX|#Sprite_FlipY)
      If FlipX : \State | #Sprite_FlipX : EndIf
      If FlipY : \State | #Sprite_FlipY : EndIf
   EndWith
EndProcedure
Procedure DeformSprite(Sprite, x0.f, y0.f, x1.f, y1.f, x2.f, y2.f, x3.f, y3.f)
   Protected *Sprite.SP_SPRITE=SpriteID(Sprite)
   With *Sprite\Deform
      *Sprite\Deform=AllocateMemory(SizeOf(SP_DEFORM))
      \x[0]=x0 : \y[0]=y0
      \x[1]=x1 : \y[1]=y1
      \x[2]=x2 : \y[2]=y2
      \x[3]=x3 : \y[3]=y3
   EndWith
EndProcedure
Procedure SkewSprite(Sprite, First.f, Second.f, Vertical=#False)
   If Vertical
      DeformSprite(Sprite, 0, First, 0, Second, 0, Second, 0, First)
   Else
      DeformSprite(Sprite, First, 0, First, 0, Second, 0, Second, 0)
   EndIf
EndProcedure
Procedure LayoutSprite(Sprite, Left.f=#PB_Ignore, Top.f=#PB_Ignore, Right.f=#PB_Ignore, Bottom.f=#PB_Ignore, InPixels=#True)
   Protected *Sprite.SP_SPRITE=SpriteID(Sprite)
   With *Sprite
      Protected w=\ParentLayer\ParentView\CameraWidth
      Protected h=\ParentLayer\ParentView\CameraHeight
      Protected LayoutX, LayoutY
      If Not InPixels
         If Top<>#PB_Ignore : Top*h : EndIf
         If Bottom<>#PB_Ignore : Bottom*h : EndIf
         If Right<>#PB_Ignore : Right*w : EndIf
         If Left<>#PB_Ignore : Left*w : EndIf
      EndIf
      LayoutX+1*Bool(Left<>#PB_Ignore)+2*Bool(Right<>#PB_Ignore)
      LayoutY+1*Bool(Top<>#PB_Ignore)+2*Bool(Bottom<>#PB_Ignore)
      Select LayoutX
         Case 0 :
         Case 1 :
         Case 2 :
         Case 3 :
      EndSelect
   EndWith
EndProcedure
Procedure SetSpriteTransparency(Sprite, Transparency, CornerIndex=#PB_Any)
   Protected *Sprite.SP_SPRITE=SpriteID(Sprite)
   If CornerIndex=#PB_Any
      For CornerIndex=0 To 3
         *Sprite\Colors[CornerIndex]=ColorRGBA(ColorRGB(*Sprite\Colors[CornerIndex]), Transparency)
      Next
   Else
      *Sprite\Colors[CornerIndex]=ColorRGBA(ColorRGB(*Sprite\Colors[CornerIndex]), Transparency)
   EndIf
EndProcedure
Procedure SetSpriteColor(Sprite, Color, CornerIndex=#PB_Any)
   Protected *Sprite.SP_SPRITE=SpriteID(Sprite)
   If CornerIndex=#PB_Any
      For CornerIndex=0 To 3
         *Sprite\Colors[CornerIndex]=ColorRGBA(Color, Alpha(*Sprite\Colors[CornerIndex]))
      Next
   Else
      *Sprite\Colors[CornerIndex]=ColorRGBA(Color, Alpha(*Sprite\Colors[CornerIndex]))
   EndIf
EndProcedure
Procedure SetSpriteFrame(Sprite, Frame)
   Protected *Sprite.SP_SPRITE=SpriteID(Sprite)
   *Sprite\Frame=Frame
EndProcedure
Procedure.f SpriteAngle(Sprite)
   Protected *Sprite.SP_SPRITE=SpriteID(Sprite)
   ProcedureReturn *Sprite\Angle
EndProcedure
Procedure.f SpriteX(Sprite)
   Protected *Sprite.SP_SPRITE=SpriteID(Sprite)
   ProcedureReturn *Sprite\x
EndProcedure
Procedure.f SpriteY(Sprite)
   Protected *Sprite.SP_SPRITE=SpriteID(Sprite)
   ProcedureReturn *Sprite\y
EndProcedure
Procedure.f SpriteScaleX(Sprite)
   Protected *Sprite.SP_SPRITE=SpriteID(Sprite)
   ProcedureReturn *Sprite\ScaleX
EndProcedure
Procedure.f SpriteScaleY(Sprite)
   Protected *Sprite.SP_SPRITE=SpriteID(Sprite)
   ProcedureReturn *Sprite\ScaleY
EndProcedure
Procedure.i SpriteColor(Sprite, CornerIndex=0)
   Protected *Sprite.SP_SPRITE=SpriteID(Sprite)
   ProcedureReturn ColorRGB(*Sprite\Colors[CornerIndex])
EndProcedure
Procedure.i SpriteTransparency(Sprite, CornerIndex=0)
   Protected *Sprite.SP_SPRITE=SpriteID(Sprite)
   ProcedureReturn Alpha(*Sprite\Colors[CornerIndex])
EndProcedure
Procedure.i SpriteFrame(Sprite)
   Protected *Sprite.SP_SPRITE=SpriteID(Sprite)
   ProcedureReturn *Sprite\Frame
EndProcedure
Procedure.i SpriteHidden(Sprite)
   Protected *Sprite.SP_SPRITE=SpriteID(Sprite)
   ProcedureReturn Bool(*Sprite\State & #Sprite_Hidden)
EndProcedure
Procedure.i SpriteState(Sprite)
   Protected *Sprite.SP_SPRITE=SpriteID(Sprite)
   ProcedureReturn *Sprite\State
EndProcedure

;---------- LAYER
Procedure FreeLayer(Layer)
   Protected *Layer.SP_LAYER=LayerID(Layer)
   ;delete dependencies
   ForEach *Layer\AttachedSprites()
      FreeSprite(*Layer\AttachedSprites()\Sprite)
   Next
   ;detach parent
   FindMapElement(*Layer\ParentView\AttachedLayers(), ""+Layer)
   DeleteMapElement(*Layer\ParentView\AttachedLayers())
   ;free resources
   FreeNode(*Layer\LayerPivot)
   FreeNode(*Layer\LayerOffset)
   FreeNode(*Layer\LayerPosition)
   FreeNode(*Layer\LayerShadow)
   FreeMesh(*Layer\Mesh)
   FreeMesh(*Layer\MeshShadow)
   FreeMaterial(*Layer\Material)
   FreeMaterial(*Layer\MaterialShadow)
   DeleteMapElement(SpriteEngine\Layers(), ""+Layer)
EndProcedure
Procedure.i CreateLayer(Layer, View, *AtlasID, MaterialBlend=#PB_Default, MaterialFilter=#PB_Default)
   Protected Result
   If Layer=#PB_Any
      Static LayerNumber=$FFFF : LayerNumber+103 : Layer=LayerNumber
      AddMapElement(SpriteEngine\Layers(), ""+Layer)
      Result=Layer
   Else
      If LayerID(Layer) : FreeLayer(Layer) : EndIf
      Result=AddMapElement(SpriteEngine\Layers(), ""+Layer)
   EndIf
   
   With SpriteEngine\Layers()
      \Layer=Layer
      \Atlas=*AtlasID
      \Material=CreateMaterial(#PB_Any, TextureID(\Atlas\Texture))
      MaterialCullingMode(\Material, #PB_Material_NoCulling)
      If MaterialBlend=#PB_Default : MaterialBlend=SpriteEngine\DefaultLayer\MaterialBlend : EndIf
      If MaterialFilter=#PB_Default : MaterialFilter=SpriteEngine\DefaultLayer\MaterialFilter : EndIf
      MaterialFilteringMode(\Material, MaterialFilter)
      MaterialBlendingMode(\Material, MaterialBlend)
      DisableMaterialLighting(\Material, #True)
      \MaterialShadow=CopyMaterial(\Material, #PB_Any)
      
      \Mesh=CreateMesh(#PB_Any, #PB_Mesh_TriangleList, #PB_Mesh_Dynamic)
      SetMeshMaterial(\Mesh, MaterialID(\Material))
      MeshVertexPosition(0, 0, 0)
      MeshVertexNormal(0, 0, 0)
      MeshVertexTangent(0, 0, 0)
      MeshVertexTextureCoordinate(0, 0)
      MeshVertexColor(RGBA(255, 255, 255, 255))
      MeshVertexPosition(1, 0, 0)
      MeshVertexPosition(1, 1, 0)
      MeshFace(0, 1, 2)
      FinishMesh(0)
      NormalizeMesh(\Mesh)
      
      \MeshShadow=CreateMesh(#PB_Any, #PB_Mesh_TriangleList, #PB_Mesh_Dynamic)
      SetMeshMaterial(\MeshShadow, MaterialID(\MaterialShadow))
      MeshVertexPosition(0, 0, 0)
      MeshVertexNormal(0, 0, 0)
      MeshVertexTangent(0, 0, 0)
      MeshVertexTextureCoordinate(0, 0)
      MeshVertexColor(RGBA(255, 255, 255, 255))
      MeshVertexPosition(1, 0, 0)
      MeshVertexPosition(1, 1, 0)
      MeshFace(0, 1, 2)
      FinishMesh(0)
      NormalizeMesh(\MeshShadow)
      
      \LayerShadow=CreateNode(#PB_Any)
      \LayerPosition=CreateNode(#PB_Any)
      \LayerOffset=CreateNode(#PB_Any)
      \LayerPivot=CreateNode(#PB_Any)
      SetRenderQueue(MeshID(\MeshShadow), 1, 10)
      SetRenderQueue(MeshID(\Mesh), 1, 100)
      AttachNodeObject(\LayerPosition, NodeID(\LayerShadow))
      AttachNodeObject(\LayerPosition, MeshID(\Mesh))
      AttachNodeObject(\LayerOffset, NodeID(\LayerPosition))
      AttachNodeObject(\LayerPivot, NodeID(\LayerOffset))
      \ParentView=ViewID(View)
      \ParentView\AttachedLayers(""+Layer)=SpriteEngine\Layers()
      AttachNodeObject(\ParentView\ViewPivot, NodeID(\LayerPivot))
      ScaleNode(\LayerOffset, \ParentView\ScaleX, \ParentView\ScaleY, 1)
      MoveNode(\LayerOffset, \ParentView\OffsetX, \ParentView\OffsetY, 500)
      ProcedureReturn Result
   EndWith
EndProcedure
Procedure HideLayer(Layer, IsHidden)
   Protected *Layer.SP_LAYER=LayerID(Layer)
   With *Layer
      If IsHidden
         If Not (\State & #Layer_Hidden)
            \State | #Layer_Hidden
            DetachNodeObject(\LayerPosition, MeshID(\Mesh))
            If (\State & #Layer_Shadow) : DetachNodeObject(\LayerShadow, MeshID(\MeshShadow)) : EndIf
         EndIf
      Else
         If \State & #Layer_Hidden
            \State & ~#Layer_Hidden
            AttachNodeObject(\LayerPosition, MeshID(\Mesh))
            If (\State & #Layer_Shadow) : AttachNodeObject(\LayerShadow, MeshID(\MeshShadow)) : EndIf
         EndIf
      EndIf
   EndWith
EndProcedure
Procedure MoveLayer(Layer, x.f, y.f, Mode=#PB_Relative)
   Protected *Layer.SP_LAYER=LayerID(Layer)
   If Mode = #PB_Relative
      *Layer\x+x
      *Layer\y+y
   Else
      *Layer\x=x
      *Layer\y=y
   EndIf
   MoveNode(*Layer\LayerPosition, x, y, 0, Mode)
EndProcedure
Procedure RotateLayer(Layer, Angle.f, Mode=#PB_Relative)
   Protected *Layer.SP_LAYER=LayerID(Layer)
   RotateNode(*Layer\LayerRoll, 0, 0, Angle, Mode)
EndProcedure
Procedure ScaleLayer(Layer, ScaleX.f, ScaleY.f, Mode=#PB_Absolute)
   Protected *Layer.SP_LAYER=LayerID(Layer)
   If Mode=#PB_Absolute
      *Layer\ScaleX=ScaleX
      *Layer\ScaleY=ScaleY
   Else
      *Layer\ScaleX+ScaleX
      *Layer\ScaleY+ScaleY
   EndIf
   ScaleNode(*Layer\LayerScale, ScaleX, ScaleY, 1, Mode)
EndProcedure
Procedure SetLayerShadow(Layer, CastShadow, Color.f=#PB_Ignore, Transparency.f=#PB_Ignore, OffsetX.f=#PB_Ignore, OffsetY.f=#PB_Ignore)
   Protected *Layer.SP_LAYER=LayerID(Layer)
   With *Layer
      If CastShadow
         If Not (\State & #Layer_Shadow)
            \State | #Layer_Shadow
            If Not (\State & #Layer_Hidden)
               AttachNodeObject(\LayerShadow, MeshID(\MeshShadow))
            EndIf
         EndIf
         If Color.f<>#PB_Ignore : \ShadowColor=ColorRGBA(Color, Alpha(\ShadowColor)) : EndIf
         If Transparency.f<>#PB_Ignore : \ShadowColor=ColorRGBA(ColorRGB(\ShadowColor), Transparency) : EndIf
         If OffsetX.f<>#PB_Ignore : \ShadowOffsetX=OffsetX : EndIf
         If OffsetY.f<>#PB_Ignore : \ShadowOffsetY=OffsetY : EndIf
         MoveNode(\LayerShadow, \ShadowOffsetX, \ShadowOffsetY, 0, #PB_Absolute)
         MaterialBlendingMode(\MaterialShadow, #PB_Material_AlphaBlend)
      Else
         If \State & #Layer_Shadow
            \State & ~#Layer_Shadow
            DetachNodeObject(\LayerShadow, MeshID(\MeshShadow))
         EndIf
      EndIf
   EndWith
EndProcedure
Procedure SetLayerOrder(Layer, Order, ShadowOrder=#PB_Ignore)
   Protected *Layer.SP_LAYER=LayerID(Layer)
   With *Layer
      If Order<>#PB_Ignore
         If Order<0 : Order=0 : EndIf
         If Order>10000 : Order=10000 : EndIf
         SetRenderQueue(MeshID(\Mesh), 1, Order)
      EndIf
      If ShadowOrder<>#PB_Ignore
         If ShadowOrder<0 : ShadowOrder=0 : EndIf
         If ShadowOrder>10000 : ShadowOrder=10000 : EndIf
         SetRenderQueue(MeshID(\MeshShadow), 1, ShadowOrder)
      EndIf
   EndWith
EndProcedure
Procedure.f LayerAngle(Layer)
   Protected *Layer.SP_LAYER=LayerID(Layer)
   ProcedureReturn NodeRoll(*Layer\LayerRoll)
EndProcedure
Procedure.f LayerX(Layer)
   Protected *Layer.SP_LAYER=LayerID(Layer)
   ProcedureReturn *Layer\x
EndProcedure
Procedure.f LayerY(Layer)
   Protected *Layer.SP_LAYER=LayerID(Layer)
   ProcedureReturn *Layer\y
EndProcedure
Procedure.f LayerScaleX(Layer)
   Protected *Layer.SP_LAYER=LayerID(Layer)
   ProcedureReturn *Layer\ScaleX
EndProcedure
Procedure.f LayerScaleY(Layer)
   Protected *Layer.SP_LAYER=LayerID(Layer)
   ProcedureReturn *Layer\ScaleY
EndProcedure
Procedure.i LayerHidden(Layer)
   Protected *Layer.SP_LAYER=LayerID(Layer)
   ProcedureReturn Bool(*Layer\State & #Layer_Hidden)
EndProcedure
Procedure.i LayerState(Layer)
   Protected *Layer.SP_LAYER=LayerID(Layer)
   ProcedureReturn *Layer\State
EndProcedure

;---------- VIEW
Procedure FreeView(View)
   Protected *View.SP_VIEW=ViewID(View)
   ;delete dependencies
   ForEach *View\AttachedLayers()
      FreeLayer(*View\AttachedLayers()\Layer)
   Next
   ;free resources
   FreeCamera(*View\Camera)
   FreeNode(*View\ViewPivot)
   DeleteMapElement(SpriteEngine\Views(), ""+View)
EndProcedure
Procedure.i CreateView(View, BackColor=0, IsStretched=#False, x.f=0, y.f=0, w.f=100, h.f=100)
   Protected Result
   If View=#PB_Any
      Static ViewNumber=$FFFF : ViewNumber+103 : View=ViewNumber
      AddMapElement(SpriteEngine\Views(), ""+View)
      Result=View
   Else
      If ViewID(View) : FreeView(View) : EndIf
      Result=AddMapElement(SpriteEngine\Views(), ""+View)
   EndIf
   
   With SpriteEngine\Views()
      \View=View
      \Camera=CreateCamera(#PB_Any, x, y, w, h)
      \CameraX=CameraViewX(\Camera)
      \CameraY=CameraViewY(\Camera)
      \CameraWidth=CameraViewWidth(\Camera)
      \CameraHeight=CameraViewHeight(\Camera)
      CameraBackColor(\Camera, BackColor)
      CameraRange(\Camera, 0.1, 1000)
      CameraProjectionMode(\Camera, #PB_Camera_Orthographic)
      SetOrientation(CameraID(\Camera), 1, 0, 0, 0)
      
      Protected hidden=CreateEntity(#PB_Any, MeshID(CreateCube(#PB_Any, 100)), #PB_Material_None)
      ScaleEntity(hidden, 100, 100, 0.01)
      HideEntity(hidden, 1)
      MoveEntity(hidden, 0, 0, 500)
      
      \ViewPivot=CreateNode(#PB_Any)
      \ViewOffset=CreateNode(#PB_Any)
      \ViewPosition=CreateNode(#PB_Any)
      AttachNodeObject(\ViewPosition, CameraID(\Camera))
      AttachNodeObject(\ViewOffset, NodeID(\ViewPosition))
      AttachNodeObject(\ViewPivot, NodeID(\ViewOffset))
      AttachNodeObject(\ViewPivot, EntityID(hidden))
      
      RenderWorld()
      If MousePick(\Camera, CameraViewX(\Camera), CameraViewY(\Camera))
         \OffsetX=PickX()
         \OffsetY=PickY()
         If IsStretched
            \ScaleX=Abs(PickX()/(ScreenWidth()/2))
            \ScaleY=Abs(PickY()/(ScreenHeight()/2))
         Else
            \ScaleX=Abs(PickX()/(CameraViewWidth(\Camera)/2))
            \ScaleY=Abs(PickY()/(CameraViewHeight(\Camera)/2))
         EndIf
         FreeEntity(hidden)
      EndIf
      
      ScaleNode(\ViewOffset, \ScaleX, \ScaleY, 1)
      
      Static newViewPos : newViewPos+$FFFF
      MoveNode(\ViewPivot, newViewPos, newViewPos, newViewPos)
      
      ProcedureReturn Result
   EndWith
EndProcedure
Procedure ViewCameraMode(View, RenderMode=#PB_Camera_Textured)
   Protected *View.SP_VIEW=ViewID(View)
   CameraRenderMode(*View\Camera, RenderMode)
EndProcedure
Procedure MoveView(View, x.f, y.f, Mode=#PB_Relative)
   Protected *View.SP_VIEW=ViewID(View)
   If Mode = #PB_Relative
      *View\x+x
      *View\y+y
   Else
      *View\x=x
      *View\y=y
   EndIf
   ProcedureReturn MoveNode(*View\ViewPosition, x, y, 0, Mode)
EndProcedure
Procedure RotateView(View, Angle.f, Mode=#PB_Relative)
   Protected *View.SP_VIEW=ViewID(View)
   RotateNode(*View\ViewRoll, 0, 0, Angle, Mode)
EndProcedure
Procedure.f ViewAngle(View)
   Protected *View.SP_VIEW=ViewID(View)
   ProcedureReturn NodeRoll(*View\ViewRoll)
EndProcedure
Procedure.f ViewX(View)
   Protected *View.SP_VIEW=ViewID(View)
   ProcedureReturn *View\x
EndProcedure
Procedure.f ViewY(View)
   Protected *View.SP_VIEW=ViewID(View)
   ProcedureReturn *View\y
EndProcedure
Procedure.i ViewCameraX(View)
   Protected *View.SP_VIEW=ViewID(View)
   ProcedureReturn *View\CameraX
EndProcedure
Procedure.i ViewCameraY(View)
   Protected *View.SP_VIEW=ViewID(View)
   ProcedureReturn *View\CameraY
EndProcedure
Procedure.i ViewCameraWidth(View)
   Protected *View.SP_VIEW=ViewID(View)
   ProcedureReturn *View\CameraWidth
EndProcedure
Procedure.i ViewCameraHeight(View)
   Protected *View.SP_VIEW=ViewID(View)
   ProcedureReturn *View\CameraHeight
EndProcedure

Procedure InitSpriteEngine()
   If InitSprite()
      With SpriteEngine
         \DefaultSprite=AddMapElement(\Sprites(), ""+#PB_Default)
         \DefaultLayer=AddMapElement(\Layers(), ""+#PB_Default)
         
         \OrderUV(0, 0)=0 : \OrderUV(0, 1)=1 : \OrderUV(0, 2)=2 : \OrderUV(0, 3)=3 ;Normal
         \OrderUV(1, 0)=1 : \OrderUV(1, 1)=0 : \OrderUV(1, 2)=3 : \OrderUV(1, 3)=2 ;Flip X
         \OrderUV(2, 0)=3 : \OrderUV(2, 1)=2 : \OrderUV(2, 2)=1 : \OrderUV(2, 3)=0 ;Flip Y
         \OrderUV(3, 0)=2 : \OrderUV(3, 1)=3 : \OrderUV(3, 2)=0 : \OrderUV(3, 3)=1 ;Flip X & Y
      EndWith
      Protected colorOpaque=RGBA(255, 255, 255, 255)
      Protected cornerIndex
      With SpriteEngine\DefaultSprite
         \ScaleX=1
         \ScaleY=1
         For cornerIndex=0 To 3 : \Colors[cornerIndex]=colorOpaque : Next
      EndWith
      With SpriteEngine\DefaultLayer
         \MaterialBlend=#PB_Material_AlphaBlend
         \MaterialFilter=#PB_Material_Bilinear
      EndWith
      
      ProcedureReturn #True
   EndIf
EndProcedure
Procedure RenderSprites()
   Protected *View.SP_VIEW, *Layer.SP_LAYER, *Sprite.SP_SPRITE
   Protected vertexIndex
   
   ForEach SpriteEngine\Views()
      ForEach SpriteEngine\Views()\AttachedLayers()
         *Layer=SpriteEngine\Views()\AttachedLayers()
         If *Layer\State & #Layer_Hidden : Continue : EndIf
         
         vertexIndex=0
         UpdateMesh(*Layer\Mesh, 0)
         ForEach *Layer\AttachedSprites()
            *Sprite=*Layer\AttachedSprites()
            If *Sprite\State & #Sprite_Hidden : Continue : EndIf
            
            With *Sprite
               Protected *Frame.SP_FRAME=\ParentLayer\Atlas\Frames(\Frame)
               Protected x0.f, y0.f, x1.f, y1.f, hx.f, hy.f, i, FlipMode=0
               Dim x.f(3) : Dim y.f(3)
               Dim u.f(3) : Dim v.f(3)
               
               hx=*Frame\HotSpotX
               hy=*Frame\HotSpotY
               If Not (\State & #Sprite_FlipXY)
                  CopyMemory(@*Frame\u[0], u(), 4*SizeOf(Float))
                  CopyMemory(@*Frame\v[0], v(), 4*SizeOf(Float))
               Else
                  FlipMode=1*Bool(\State & #Sprite_FlipX)+2*Bool(\State & #Sprite_FlipY)
                  If \State & #Sprite_FlipX : hx=*Frame\Width-hx : EndIf
                  If \State & #Sprite_FlipY : hy=*Frame\Height-hy : EndIf
                  For i=0 To 3
                     u(i)=*Frame\u[SpriteEngine\OrderUV(FlipMode, i)]
                     v(i)=*Frame\v[SpriteEngine\OrderUV(FlipMode, i)]
                  Next
               EndIf
               
               If \Angle=0 And \Deform=0
                  x0=\x-hx*\ScaleX : x1=x0+*Frame\Width*\ScaleX
                  y0=\y-hy*\ScaleY : y1=y0+*Frame\Height*\ScaleY
                  x(0)=x0 : y(0)=y0 : x(1)=x1 : y(1)=y0
                  x(2)=x1 : y(2)=y1 : x(3)=x0 : y(3)=y1
               Else
                  x0=-hx*\ScaleX : x1=x0+*Frame\Width*\ScaleX
                  y0=-hy*\ScaleY : y1=y0+*Frame\Height*\ScaleY
                  x(0)=x0 : y(0)=y0 : x(1)=x1 : y(1)=y0
                  x(2)=x1 : y(2)=y1 : x(3)=x0 : y(3)=y1
                  
                  If \Deform
                     For i=0 To 3
                        x(i)+\Deform\x[i]
                        y(i)+\Deform\y[i]
                     Next
                  EndIf
                  Protected radian.f=Radian(\Angle)
                  Protected cos.f=Cos(radian), sin.f=Sin(radian)
                  For i=0 To 3
                     Protected px.f=x(i), py.f=y(i)
                     x(i)=\x+cos*px-sin*py
                     y(i)=\y+sin*px+cos*py
                  Next
               EndIf
               
               For i=0 To 3
                  MeshVertexPosition(x(i), y(i), 0)
                  MeshVertexTextureCoordinate(u(i), v(i))
                  MeshVertexColor(\Colors[i])
               Next
               
               MeshFace(vertexIndex, vertexIndex+1, vertexIndex+2)
               MeshFace(vertexIndex+2, vertexIndex+3, vertexIndex)
               vertexIndex+4
            EndWith
         Next
         FinishMesh(0)
         
         With *Layer
            If \State & #Layer_Shadow
               Dim vertices.PB_MeshVertex(0)
               Dim faces.PB_MeshFace(0)
               GetMeshData(\Mesh, 0, vertices(), #PB_Mesh_Vertex|#PB_Mesh_Color|#PB_Mesh_UVCoordinate, 0, MeshVertexCount(\Mesh, 0)-1)
               GetMeshData(\Mesh, 0, faces(), #PB_Mesh_Face, 0, MeshIndexCount(\Mesh, 0)-1)
               
               UpdateMesh(\MeshShadow, 0)
               For i=0 To ArraySize(vertices())
                  MeshVertexPosition(vertices(i)\x, vertices(i)\y, 0)
                  MeshVertexTextureCoordinate(vertices(i)\u, vertices(i)\v)
                  MeshVertexColor(\ShadowColor)
               Next
               For i=0 To ArraySize(faces())
                  MeshIndex(faces(i)\Index)
               Next
               FinishMesh(0)
            EndIf
         EndWith
      Next
   Next
EndProcedure
Last edited by eddy on Sun Sep 29, 2013 2:22 pm, edited 21 times in total.
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Re: Sprite3D: Atlas,View,Layer,HotSpot

Post by eddy »

Image

Code: Select all

; ******************************************
; EXAMPLE1 - SPRITE ENGINE FEATURES
; ******************************************
CompilerIf #PB_Compiler_IsMainFile
   DisableExplicit
   If InitEngine3D()=0 Or InitSpriteEngine()=0
      MessageRequester("Init", "Failed!")
      End
   EndIf
   
   AntialiasingMode(#PB_AntialiasingMode_None)
   
   win=OpenWindow(#PB_Any, 0, 0, 800, 600, "Sprite Engine FX", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   OpenWindowedScreen(WindowID(win), 0, 0, WindowWidth(win), WindowHeight(win))
   
   ;draw atlas image
   fontID=LoadFont(0, "Arial", 22, #PB_Font_Bold|#PB_Font_HighQuality|#PB_Font_Italic)
   spriteAtlas=CreateAtlas(#PB_Any, 128, 128)
   If StartDrawing(AtlasOutput(spriteAtlas))
      
      DrawingMode(#PB_2DDrawing_Transparent|#PB_2DDrawing_AlphaBlend)
      DrawingFont(fontID)
      DrawText(25, 10, "ATLAS", RGBA(255, 255, 255, 255))
      txtW=TextWidth("ATLAS")
      txtH=TextHeight("ATLAS")
      
      DrawingMode(#PB_2DDrawing_Gradient|#PB_2DDrawing_AlphaBlend)
      BackColor(RGBA(255, 255, 0, 255))
      GradientColor(0.8, RGBA(255, 0, 0, 50))
      FrontColor(RGBA(200, 70, 10, 255))
      LinearGradient(0, 0, 0, 64)
      Box(5, 5, 16, 64)
      
      ResetGradientColors()
      BackColor(RGBA(0, 255, 0, 255))
      GradientColor(0.8, RGBA(0, 0, 255, 50))
      FrontColor(RGBA(60, 100, 255, 255))
      LinearGradient(0, 0, 64, 0)
      Box(21, 69, 64, 16)
      
      ResetGradientColors()
      BackColor(RGBA(255, 255, 255, 255))
      GradientColor(0.6, RGBA(150, 150, 150, 255))
      FrontColor(RGBA(255, 255, 255, 255))
      LinearGradient(25, 53, 30, 70)
      For i=0 To 4
         RoundBox(25+i*20, 45, 16, 16, 7, 4)
      Next
      
      DrawingMode(#PB_2DDrawing_Outlined|#PB_2DDrawing_AlphaBlend)
      FrontColor(RGBA(255, 255, 255, 255))
      Box(5, 5, 16, 64)
      Box(21, 69, 64, 16)
      Box(0, 0, 128, 128)
      StopDrawing()
   EndIf
   ;extract image frames
   redFrame=SetAtlasFrame(spriteAtlas, #PB_Any, 5, 5, 16, 64)
   blueFrame=SetAtlasFrame(spriteAtlas, #PB_Any, 21, 69, 64, 16, 32, 8, #True)
   textFrame=SetAtlasFrame(spriteAtlas, #PB_Any, 25, 10, txtW, txtH)
   
   ;create background view
   backView=CreateView(#PB_Any, RGB(10, 10, 10))
   If backView
      ;create FX layers
      addFxLayer=CreateLayer(#PB_Any, backView, AtlasID(spriteAtlas), #PB_Material_Add, #PB_Material_None)
      colorFxLayer=CreateLayer(#PB_Any, backView, AtlasID(spriteAtlas), #PB_Material_Color, #PB_Material_None)
      
      ;create FX sprites (changing default sprite color)
      SetSpriteColor(#PB_Default, RGB(93, 137, 175), 2)
      For i=1 To 10
         addFX=CreateAnimatedSprite(#PB_Any, addFxLayer, 650, 200, redFrame)
         ScaleSprite(addFX, 1, 1+i*0.1)
         RotateSprite(addFX, -90+i*20)
      Next
      SetSpriteColor(#PB_Default, RGB(93, 137, 175), 2)
      For i=1 To 10
         colorFX=CreateAnimatedSprite(#PB_Any, colorFxLayer, 650, 50, redFrame)
         ScaleSprite(colorFX, 1, 1+i*0.1)
         RotateSprite(colorFX, -90+i*20)
      Next
      SetSpriteColor(#PB_Default, RGB(255, 255, 255))
   EndIf
   
   ;create front view
   frontView=CreateView(#PB_Any, RGB(62, 62, 62), #False, 0, 0, 64.0, 85.34)
   Debug "View Camera="+ViewCameraY(frontView)+","+ViewCameraX(frontView)+","+ViewCameraWidth(frontView)+","+ViewCameraHeight(frontView)
   If frontView
      ;create smoothed and pixellated layers
      smoothLayer=CreateLayer(#PB_Any, frontView, AtlasID(spriteAtlas))
      pixelLayer=CreateLayer(#PB_Any, frontView, AtlasID(spriteAtlas), #PB_Material_AlphaBlend, #PB_Material_None)
      
      ;reorder layers and enable Shadow Casting
      SetLayerShadow(smoothLayer, #True, RGB(0, 0, 0), 100, 5, 5)
      SetLayerOrder(smoothLayer, 100, 90)
      SetLayerOrder(pixelLayer, 80)
      
      ;create sprites
      wholeImage=CreateAnimatedSprite(#PB_Any, pixelLayer, 5, 5, 0)
      barRed=CreateAnimatedSprite(#PB_Any, pixelLayer, 10, 150, redFrame)
      barBlue=CreateAnimatedSprite(#PB_Any, pixelLayer, 10+(16+8+1), 150+32, blueFrame)
      
      ;create rotated and scaled sprites
      smoothBar=CreateAnimatedSprite(#PB_Any, smoothLayer, 90, 190, blueFrame)
      RotateSprite(smoothBar, -10)
      pixelBar=CreateAnimatedSprite(#PB_Any, pixelLayer, 130, 190, blueFrame)
      RotateSprite(pixelBar, -10)
      ScaleSprite(pixelBar, 2, 1)
      Debug "Sprite Angle="+SpriteAngle(pixelBar)+" ScaleX="+SpriteScaleX(pixelBar)+" ScaleY="+SpriteScaleY(pixelBar)
      
      ;create deformed sprites
      smoothShape=CreateAnimatedSprite(#PB_Any, smoothLayer, 200, 150, redFrame)
      DeformSprite(smoothShape, -16, 0, 16, 0, 8, 0, -8, 0)
      pixelShape=CreateAnimatedSprite(#PB_Any, pixelLayer, 224, 153, redFrame)
      SkewSprite(pixelShape, 32, 0)
      
      ;create colorized and flipped sprites
      txt=CreateAnimatedSprite(#PB_Any, smoothLayer, 100, 300, textFrame)
      SetSpriteColor(txt, RGB(255, 214, 126))
      txtX=CreateAnimatedSprite(#PB_Any, smoothLayer, 100, 300, textFrame)
      FlipSprite(txtX, #True, #False)
      SetSpriteTransparency(txtX, 150)
      Debug "Sprite Transparency="+SpriteTransparency(txtX)
      txtY=CreateAnimatedSprite(#PB_Any, smoothLayer, 100, 300, textFrame)
      FlipSprite(txtY, #False, #True)
      SetSpriteColor(txtY, RGB(255, 14, 126), 0)
      SetSpriteColor(txtY, RGB(255, 14, 126), 2)
      Debug "Sprite Pos="+SpriteX(txtY)+","+SpriteX(txtY)+" Color="+Hex(SpriteColor(txtY, 2))
      txtBoth=CreateAnimatedSprite(#PB_Any, smoothLayer, 100, 300, textFrame)
      FlipSprite(txtBoth, #True, #True)
      SetSpriteTransparency(txtBoth, 50, 0)
      SetSpriteTransparency(txtBoth, 50, 2)
      Debug "Sprite FlipX="+Bool(SpriteState(txtBoth)& #Sprite_FlipX)+" FlipY="+Bool(SpriteState(txtBoth)& #Sprite_FlipY)
   EndIf
   
   
   Repeat
      RenderSprites()
      RenderWorld()
      FlipBuffers()
   Until WaitWindowEvent(1)=#PB_Event_CloseWindow
   End
CompilerEndIf
Last edited by eddy on Sun Sep 29, 2013 2:26 pm, edited 7 times in total.
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
SoS
User
User
Posts: 13
Joined: Sat Feb 18, 2006 4:46 am

Re: SpriteEngine: Atlas,View,Layer,HotSpot,Flip,Animation,FX

Post by SoS »

Hi Eddy
Your Procedure InitSpriteEngine() need a InitEngine3D() before InitSprite() (PB5.20b17)
Poshu
Enthusiast
Enthusiast
Posts: 459
Joined: Tue Jan 25, 2005 7:01 pm
Location: Canada

Re: SpriteEngine: Atlas,View,Layer,HotSpot,Flip,Animation,FX

Post by Poshu »

Seems interesting but we need a bit more information I guess.
Poshu
Enthusiast
Enthusiast
Posts: 459
Joined: Tue Jan 25, 2005 7:01 pm
Location: Canada

Re: SpriteEngine: Atlas,View,Layer,HotSpot,Flip,Animation,FX

Post by Poshu »

After toying with it: IT ROOOOOOOOCKS!

Just a question, I can't understand if we can create a transparent view, any help on this?
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Re: SpriteEngine: Atlas,View,Layer,HotSpot,Flip,Animation,FX

Post by eddy »

SoS wrote:Hi Eddy
Your Procedure InitSpriteEngine() need a InitEngine3D() before InitSprite() (PB5.20b17)
Fixed
Poshu wrote:After toying with it: IT ROOOOOOOOCKS!
Thanks
Just a question, I can't understand if we can create a transparent view, any help on this?
I don't know. I will check further to see if it's possible.

Todo:
- LoadAtlas(...)
- SkewSprite / DeformSprite
- Test: ZOrder
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
Poshu
Enthusiast
Enthusiast
Posts: 459
Joined: Tue Jan 25, 2005 7:01 pm
Location: Canada

Re: SpriteEngine: Atlas,View,Layer,HotSpot,Flip,Animation,FX

Post by Poshu »

I've got a problem. Take into account that: 1) I don't know anything to 3D in pure and 2) there is no documentation to work with SpriteEngine :p

so, here is code 1:

Code: Select all

UsePNGImageDecoder()

DisableExplicit
InitEngine3D(#Null,#Engine3DDLL)
InitSpriteEngine()

AntialiasingMode(#PB_AntialiasingMode_x6)

win=OpenWindow(0, 0, 0, 800, 600, "Animating Sprites", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
OpenWindowedScreen(win, 0, 0, 800, 600,0,0,0,#PB_Screen_WaitSynchronization)

spriteAtlas=CreateAtlas(#PB_Any, 800, 600)
sprite = LoadImage(#PB_Any,"Untitled.png")
If StartDrawing(AtlasOutput(spriteAtlas))
	DrawingMode(#PB_2DDrawing_Gradient |#PB_2DDrawing_AlphaBlend)
	DrawImage(ImageID(sprite),0,0)
	StopDrawing()
EndIf
SetAtlasFrame(spriteAtlas, 0, 0, 0, 1280, 800)
CreateView(view, RGB(163, 178, 195), 0, 0, 0, 100, 100)
CreateLayer(2, view, AtlasID(spriteAtlas))
s2=CreateAnimatedSprite(#PB_Any,2,0,0)
Repeat
	SetSpriteFrame(s2,0)
	RenderSprites()
	RenderWorld()
	FlipBuffers()
Until WaitWindowEvent(1)=#PB_Event_CloseWindow
End
Here is code 2:

Code: Select all

IncludeFile "Library/moteur.pb"
UsePNGImageDecoder()

DisableExplicit
InitEngine3D(#Null,#Engine3DDLL)
InitSpriteEngine()

AntialiasingMode(#PB_AntialiasingMode_x6)

win=OpenWindow(0, 0, 0, 800, 600, "Animating Sprites", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
OpenWindowedScreen(win, 0, 0, 800, 600,0,0,0,#PB_Screen_WaitSynchronization)

spriteAtlas=CreateAtlas(#PB_Any, 800, 600)
sprite = LoadImage(#PB_Any,"Untitled.png")
If StartDrawing(AtlasOutput(spriteAtlas))
	DrawingMode(#PB_2DDrawing_Gradient |#PB_2DDrawing_AlphaBlend)
	DrawImage(ImageID(sprite),0,0)
	StopDrawing()
EndIf
SetAtlasFrame(spriteAtlas, 0, 0, 0, 1280, 800)
CreateView(view, RGB(163, 178, 195), 0, 0, 0, 100, 100)
CreateLayer(2, view, AtlasID(spriteAtlas))
s2=CreateAnimatedSprite(#PB_Any,2,0,0)
ScaleSprite(s2, 0.999,0.999)
Repeat
	SetSpriteFrame(s2,0)
	RenderSprites()
	RenderWorld()
	FlipBuffers()
Until WaitWindowEvent(1)=#PB_Event_CloseWindow
End
And here is the much needed Untitled.png

The single difference is a ScaleSprite(), yet on the first example. the text is scrambled, while the second is fine. On some images it's scrambled beyond readability.
Am I doing something wrong?
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Re: SpriteEngine: Atlas,View,Layer,HotSpot,Flip,Animation,FX

Post by eddy »

Updated
- CreateAtlas function : fixed default frame initialization
Poshu wrote:Take into account that: 1) I don't know anything to 3D in pure and 2) there is no documentation to work with SpriteEngine :p
I'll post some code samples :wink:
Poshu wrote: The single difference is a ScaleSprite(), yet on the first example. the text is scrambled, while the second is fine. On some images it's scrambled beyond readability.
Am I doing something wrong?
- you found a bug in CreateAtlas function (I fixed it) :mrgreen:
- My SpriteEngine library is based on Engine3D : the powers of two texture size makes the texture optimized for GPU
Moreover, PB doc strongly recommends to make the texture dimension square and with power of 2

(Solution below)

Code: Select all

UsePNGImageDecoder()

DisableExplicit
InitEngine3D()
InitSpriteEngine()

AntialiasingMode(#PB_AntialiasingMode_x6)

win=OpenWindow(0, 0, 0, 800, 600, "Animating Sprites", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
OpenWindowedScreen(win, 0, 0, 800, 600, 0, 0, 0, #PB_Screen_WaitSynchronization)

spriteAtlas=CreateAtlas(#PB_Any, 1024, 1024) ; <----- power of 2 texture size
sprite = LoadImage(#PB_Any, "Untitled.png")
If StartDrawing(AtlasOutput(spriteAtlas))
   DrawingMode(#PB_2DDrawing_AlphaBlend)
   DrawImage(ImageID(sprite), 0, 0)
   StopDrawing()
EndIf
CreateView(view, RGB(163, 178, 195))
CreateLayer(2, view, AtlasID(spriteAtlas))
s2=CreateAnimatedSprite(#PB_Any, 2, 0, 0)
Repeat
   RenderSprites()
   RenderWorld()
   FlipBuffers()
Until WaitWindowEvent(1)=#PB_Event_CloseWindow
End
Last edited by eddy on Wed Sep 11, 2013 10:44 pm, edited 3 times in total.
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
Poshu
Enthusiast
Enthusiast
Posts: 459
Joined: Tue Jan 25, 2005 7:01 pm
Location: Canada

Re: SpriteEngine: Atlas,View,Layer,HotSpot,Flip,Animation,FX

Post by Poshu »

Ok. Somehow, I think I'm slowly getting the hang of it.
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Re: SpriteEngine: Atlas,View,Layer,HotSpot,Flip,Animation,FX

Post by eddy »

Updated
- RenderSprites function : fixed sprite position, render multi sprite
- new command: LoadAtlas
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Re: SpriteEngine: Atlas,View,Layer,HotSpot,Flip,Animation,FX

Post by eddy »

Updated
- fixed sprite rotation

Image
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Re: SpriteEngine: Atlas,View,Layer,HotSpot,Flip,Animation,FX

Post by eddy »

updated
- updated CreateLayer (MaterialFilter option)
- fixed RenderSprites

Code: Select all

CreateLayer(Layer, View, *AtlasID, MaterialBlend=#PB_Material_AlphaBlend, MaterialFilter=#PB_Material_Bilinear)
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
Mythros
Enthusiast
Enthusiast
Posts: 306
Joined: Mon Aug 19, 2013 3:28 pm

Re: SpriteEngine: Atlas,View,Layer,HotSpot,Flip,Animation,FX

Post by Mythros »

Can you PLEASE make this work with version 5.1?

I don't like to use beta versions of Purebasic.

I like my game to be stable as possible.

Thank You, kind sir! =)
Poshu
Enthusiast
Enthusiast
Posts: 459
Joined: Tue Jan 25, 2005 7:01 pm
Location: Canada

Re: SpriteEngine: Atlas,View,Layer,HotSpot,Flip,Animation,FX

Post by Poshu »

Well, 5.20 won't be beta for ever :p
Mythros
Enthusiast
Enthusiast
Posts: 306
Joined: Mon Aug 19, 2013 3:28 pm

Re: SpriteEngine: Atlas,View,Layer,HotSpot,Flip,Animation,FX

Post by Mythros »

Still, I want to stick with what I know. I don't like upgrading alot.
Post Reply