Little 2D Old School Library

Applications, Games, Tools, User libs and useful stuff coded in PureBasic
User avatar
flaith
Enthusiast
Enthusiast
Posts: 704
Joined: Mon Apr 25, 2005 9:28 pm
Location: $300:20 58 FC 60 - Rennes
Contact:

Little 2D Old School Library

Post by flaith »

Hi guys,

I started this little library last year and want to share it with you, not really exceptional compared to some great library in the forum.

You can create animated sprite, layers, animated sprite inside the layers, FPS Manager included.
Sources code commented.

FPS Manager: FPS_Manager.pbi

Code: Select all

; From SDL_gfx by ferzkopp
; SDL_framerate.c
; http://www.ferzkopp.net/Software/SDL_gfx-2.0/
; http://sourceforge.net/p/sdl2gfx/code/5/tree/trunk/SDL2_framerate.c
;// Nicolas "flaith" Djurovic
;// 2012-2013

;-CONSTANTS
; Highest possible rate supported by framerate controller in Hz (1/s).
#FPS_UPPER_LIMIT    = 200
; Lowest possible rate supported by framerate controller in Hz (1/s).
#FPS_LOWER_LIMIT    = 1
; Default rate of framerate controller in Hz (1/s).
#FPS_DEFAULT        = 30

;-METHOD
Interface FPSObject
  FPS_setFramerate.i(__rate)
  FPS_getFramerate.i()
  FPS_getFramecount.i()
  FPS_framerateDelay.i()
EndInterface

;-TEMPLATE
; Structure holding the state and timing information of the framerate controller. 
Structure FPSmanager
  *vTable
  obj.FPSObject                      ; To be able to call class inside class
  ; Private
  framecount.i
  rateticks.f
  baseticks.i
  lastticks.i
  rate.i
EndStructure

;-DECLARE
Declare.i FPS_initFramerate()
Declare.i CLASS_setFramerate(*manager.FPSmanager, __rate.i)
Declare.i CLASS_getFramerate(*manager.FPSmanager)
Declare.i CLASS_getFramecount(*manager.FPSmanager)
Declare.i CLASS_framerateDelay(*manager.FPSmanager)

;-VIRTUAL TABLES
DataSection 
  VTable_FPSClass: 
    Data.i @CLASS_setFramerate()
    Data.i @CLASS_getFramerate()
    Data.i @CLASS_getFramecount()
    Data.i @CLASS_framerateDelay()
EndDataSection

;-INTERNAL PROCEDURE
Procedure.i getTicks()
  Protected.i _ticks = ElapsedMilliseconds()

  If _ticks = 0
    ProcedureReturn 1
  Else
    ProcedureReturn _ticks
  EndIf
EndProcedure

;-*************************************************************
;-Initialize framerate manager
; set Default framerate of 30Hz and reset delay interpolation.
; \param manager : Pointer to the framerate manager.
; \return        : Pointer for sucess and 0 for error.
Procedure.i FPS_initFramerate()
  Protected *manager.FPSManager

  *manager = AllocateMemory(SizeOf(FPSmanager))
  If *manager
    ;Need to initialize structure for the call of class inside another class
    InitializeStructure(*manager, FPSmanager)
    ;Make sure the *vTable field points to our virtual table.
    *manager\vTable     = ?VTable_FPSClass
    ;now the call of class inside class can be done
    *manager\obj        = *manager
    ;Initialise the variables if any
    *manager\framecount = 0
    *manager\rate       = #FPS_DEFAULT
    *manager\rateticks  = 1000.0 / #FPS_DEFAULT
    *manager\baseticks  = getTicks()
    *manager\lastticks  = *manager\baseticks
    ;Return a pointer to our new object.
    ProcedureReturn *manager
  Else
    ProcedureReturn 0
  EndIf
EndProcedure

;-Set the framerate in Hz 
; Sets a new framerate For the manager And reset delay interpolation.
; Rate values must be between FPS_LOWER_LIMIT And FPS_UPPER_LIMIT inclusive To be accepted.
; \param manager : Pointer to the framerate manager.
; \param rate    : The new framerate in Hz (frames per second).
; \return        : 0 For sucess and -1 for error.
Procedure.i CLASS_setFramerate(*manager.FPSmanager, __rate.i)
  If (__rate >= #FPS_LOWER_LIMIT) And (__rate <= #FPS_UPPER_LIMIT)
    *manager\framecount = 0
    *manager\rate       = __rate
    *manager\rateticks  = 1000.0 / __rate
    ProcedureReturn 0
  Else
    ProcedureReturn -1
  EndIf
EndProcedure

;-Return current target framerate 
; Get the currently set framerate of the manager in Hz.
; \param manager : Pointer To the framerate manager.
; \return        : Current framerate in Hz or -1 for error.
Procedure.i CLASS_getFramerate(*manager.FPSmanager)
  If *manager = #Null
    ProcedureReturn -1
  Else
    ProcedureReturn *manager\rate
  EndIf
EndProcedure

;-Return current framecount
; Get the current framecount from the framerate manager. 
; A frame is counted each time SDL_framerateDelay is called.
; \param manager : Pointer To the framerate manager.
; \return        : Current frame count or -1 for error.
Procedure.i CLASS_getFramecount(*manager.FPSmanager)
  If *manager = #Null
    ProcedureReturn -1
  Else
    ProcedureReturn *manager\framecount
  EndIf
EndProcedure

;-Delay execution
; Maintain a constant framerate and calculate fps.
; Generate a delay to accomodate currently set framerate. Call once in the
; graphics/rendering loop. If the computer cannot keep up with the rate (i.e.
; drawing too slow), the delay is zero And the delay interpolation is reset.
; \param manager : Pointer To the framerate manager.
; \return        : The time that passed since the last call to the function in ms. May return 0.
Procedure.i CLASS_framerateDelay(*manager.FPSmanager)
  Protected.i _current_ticks
  Protected.i _target_ticks
  Protected.i _the_delay
  Protected.i _time_passed = 0

  ; No manager, no delay
  If *manager = #Null : ProcedureReturn 0 : EndIf
 
  ; Initialize uninitialized manager 
  If *manager\baseticks = 0 : *manager = FPS_initFramerate() : EndIf

  ; Next frame
  *manager\framecount + 1

  ; Get/calc ticks 
  _current_ticks      = getTicks()
  _time_passed        = _current_ticks - *manager\lastticks
  *manager\lastticks  = _current_ticks
  _target_ticks       = *manager\baseticks + (*manager\framecount * *manager\rateticks)

  If _current_ticks <= _target_ticks
    _the_delay = _target_ticks - _current_ticks
    Delay(_the_delay)
  Else
    *manager\framecount = 0
    *manager\baseticks  = getTicks()
  EndIf

  ProcedureReturn _time_passed
EndProcedure
“Fear is a reaction. Courage is a decision.” - WC
User avatar
flaith
Enthusiast
Enthusiast
Posts: 704
Joined: Mon Apr 25, 2005 9:28 pm
Location: $300:20 58 FC 60 - Rennes
Contact:

Re: Little 2D Old School Library

Post by flaith »

The library: GLMFS2D.pbi

Code: Select all

;// GLMFS2D Library
;// Nicolas "flaith" Djurovic
;// 2012-2013
;// No licence

EnableExplicit

;-Constants
#DEBUG_NAME             = "GLMFS2D.LOG"
#DEBUG_FILENUM          = 999

#GLMFS_VERSION          = "0.22"                           ;Library Version
#GLMFS_FREQ_MIN         = $E000                            ;Animated sequences starting value
#GLMFS_MAX_SPR_MAP      = 255                              ;Max NB sprites by Map

Enumeration 
  #GS2D_FORWARD
  #GS2D_BACKWARD
  #GS2D_RETURNBACK                                         ;Future use
EndEnumeration

; ****************
;-** Structures **
; ****************
;Game
Structure CS_GAME
  ScreenHeight.i
  ScreenWidth.i
EndStructure

;Font
Structure CS_FontSprite
  NumFontSprite.i                                          ;Sprite Font num
  CharWidth.i                                              ;Keep size of chars in case we resize them
  CharHeight.i
  Color.i
EndStructure

Structure CS_Font
  FontName.s
  CharByLine.i
  ImageWidth.i
  ImageHeight.i
  CharWidth.i
  CharHeight.i
  TransparentColor.i
  SpaceForDisable.i                                        ;Future use
  LastNumFontUsed.i                                        ;Last font number used
  Map FontColor.CS_FontSprite()                            ;Font List
EndStructure

;Sprite
Structure CS_MeeSprite
  Spr.i[#GLMFS_MAX_SPR_MAP]                                ;#GLMFS_MAX_SPR_MAP sprite by map
EndStructure

;Sheet sprites structure
Structure CS_MeeAllSprite
  Num.i                                                    ;Image num loaded
  Width.i
  Height.i
  MaxSprite.i
  MaskSprite.i
  Sprite.CS_MeeSprite                                      ;Sprites' list
EndStructure

;Animations Structure
Structure CS_MeeAnimSprite
  MapNameSprite.s                                          ;Which Sprite sheet to use?
  X.i
  Y.i
  FrameStart.i                                             ;Sprite Frame start (sprite number)
  FrameEnd.i                                               ;and end sprite number
  CurrentFrame.i                                           ;Start by which sprite number
  StartDelay.i                                             ;Animation starts now
  DelayBetweenFrame.i                                      ;Delay between two frame
  LoopTimes.i                                              ;Loop times, if -1 : only one time
  Display.i                                                ;Sprite is display or not
EndStructure

Structure CS_MeeLayer
  MapSpriteName.s                                          ;Which shhet sprite to use for the layer?
  MapWidth.i
  MapHeight.i
  MapSpriteWidth.i
  MapSpriteHeight.i
  Array TBL_Tile.i(1)                                      ;Array tiles: n values max (from 0 to n-1) : MapHeight x MapWidth
EndStructure

; ************
;-** Global **
; ************
;Game
Global GAME.CS_GAME
;Fonts
Global NewMap GSFont.CS_Font()
Global.i ActualSizeH = 0, ActualSizeW = 0, SpaceForDisable = 1, ResizeMode = #PB_Image_Raw
Global.i TransparentColor
;Sprites
Global NewMap GSprite.CS_MeeAllSprite()
Global NewMap GSpriteAnim.CS_MeeAnimSprite()
Global NewMap GSLayer.CS_MeeLayer()
Global NewMap GSequence.i()
Global.i IDSprite = 2222                                  ;Sprite ID starts at ...
Global.i DebugSprite, NextSprite = #False

; *************************
;-** Internal Procedures **
; *************************
;-DEBUGLOG
Procedure GS2D_DEBUGLOG(__value.s)
  CompilerIf Defined(__DEBUG__, #PB_Constant)
    OpenFile(#DEBUG_FILENUM,#DEBUG_NAME)
      FileSeek(#DEBUG_FILENUM, Lof(#DEBUG_FILENUM))
      WriteStringN(#DEBUG_FILENUM,__value)
    CloseFile(#DEBUG_FILENUM)
  CompilerEndIf
EndProcedure

;-Fonts
Procedure GS2D_SetResizeMode(__Flag.i = #PB_Image_Raw)
  ResizeMode = __Flag
EndProcedure

Procedure GS2D_ResizeFont(__FontID.i, __FontSpriteID.i, __Width.i = -1, __Height.i = -1)
  Protected.f _RatioH, _RatioW
  Protected.i _SpriteTMP, _ColorTMP
  Protected.i _ImgTMP
  Protected.i _CharW, _CharH

  If FindMapElement(GSFont(), Str(__FontID))
    If FindMapElement(GSFont()\FontColor(), Str(__FontSpriteID))
      If __Width <> -1
        _RatioW   = __Width / GSFont()\FontColor()\CharWidth
      Else
        _RatioW   = 1                                          ;cf below, multiplication with HEIGHT
      EndIf
    
      If __Height <> -1
        _RatioH   = __Height / GSFont()\FontColor()\CharHeight
      Else
        _RatioH   = _RatioW
      EndIf
      
      SpaceForDisable = _RatioW
      _CharH = GSFont()\FontColor()\CharHeight * _RatioH
      _CharW = GSFont()\FontColor()\CharWidth  * _RatioW

      ;Create a temp image to keep the original one
      CopyImage(__FontID, _ImgTMP)
      ResizeImage(_ImgTMP, GSFont()\ImageWidth * _RatioW, GSFont()\ImageHeight * _RatioH, ResizeMode)

      ;No more need of this sprite font
      FreeSprite(__FontSpriteID)

      ;and now we can create the new sprite font
      _SpriteTMP = CreateSprite(#PB_Any,GSFont()\ImageWidth * _RatioW, GSFont()\ImageHeight * _RatioH)
      StartDrawing(SpriteOutput(_SpriteTMP))
        ;Using box for the font color
        Box(0,0,GSFont()\ImageWidth * _RatioW, GSFont()\ImageHeight * _RatioH, GSFont()\FontColor()\Color)
        ;Display on the box with alpha
        DrawAlphaImage(ImageID(_ImgTMP), 0, 0)
      StopDrawing()
      TransparentSpriteColor(_SpriteTMP, GSFont()\TransparentColor)
      ;Free memory
      FreeImage(_ImgTMP)

      ;Important !!!!
      ;Now we give the same ID of our sprite previously created
      PokeI(@__FontSpriteID, _SpriteTMP)

      ;Nez information about the font
      _ColorTMP = GSFont()\FontColor()\Color
      GSFont()\LastNumFontUsed = -1
      AddMapElement(GSFont()\FontColor(), Str(__FontSpriteID), #PB_Map_ElementCheck)    ;update
        GSFont()\FontColor()\NumFontSprite    = __FontSpriteID
        GSFont()\FontColor()\CharHeight       = _CharH
        GSFont()\FontColor()\CharWidth        = _CharW
        GSFont()\FontColor()\Color            = _ColorTMP
    Else
      ;Error
      GS2D_DEBUGLOG("Error resizing font for "+GSFont()\FontName)
      GS2D_DEBUGLOG("MAP Num Font Sprite ID = "+Str(GSFont()\FontColor()\NumFontSprite))
      GS2D_DEBUGLOG("FontSpriteID           = "+Str(__FontSpriteID))
    EndIf
  EndIf
EndProcedure

Procedure.i GS2D_CreateFontColor(__FontID.i, __Color.i)
  Protected.i _Sprite
  
  If FindMapElement(GSFont(), Str(__FontID))
    _Sprite = CreateSprite(#PB_Any, GSFont()\ImageWidth, GSFont()\ImageHeight)
    If _Sprite
      StartDrawing(SpriteOutput(_Sprite))
        ;Using box for the font color
        Box(0,0,GSFont()\ImageWidth,GSFont()\ImageHeight, __Color)
        ;Display on the box with alpha
        DrawAlphaImage(ImageID(__FontID), 0, 0)
      StopDrawing()
      TransparentSpriteColor(_Sprite, GSFont()\TransparentColor)

      AddMapElement(GSFont()\FontColor(), Str(_Sprite))
        GSFont()\FontColor()\NumFontSprite    = _Sprite
        GSFont()\FontColor()\CharHeight       = GSFont()\CharHeight
        GSFont()\FontColor()\CharWidth        = GSFont()\CharWidth
        GSFont()\FontColor()\Color            = __Color
        GSFont()\LastNumFontUsed  = -1
      ProcedureReturn _Sprite
    Else
      ProcedureReturn #False
    EndIf
  Else
    ProcedureReturn #False
  EndIf
EndProcedure

Procedure GS2D_DrawText(__FontID.i, __X.i,__Y.i,__Text.s, __FontSpriteID.i = -1)
  Protected.i _Len = Len(__Text)
  Protected.s _Char
  Protected.i _Ascii, _FontLine, _ClipX, _ClipY
  Protected.i _Index
  
  If FindMapElement(GSFont(), Str(__FontID))
    If __FontSpriteID = -1
      If GSFont()\LastNumFontUsed <> -1
        __FontSpriteID = GSFont()\LastNumFontUsed
      Else
        If FindMapElement(GSFont()\FontColor(), Str(__FontSpriteID))
          __FontSpriteID = GSFont()\FontColor()\NumFontSprite
          If Not __FontSpriteID
            ;Error
            GS2D_DEBUGLOG("Error GS2D_DrawText #1")
            End
          EndIf
        Else
          ;if equal -1 and LastNumFontUsed = -1 too, we take the first
          ResetMap(GSFont()\FontColor())
          NextMapElement(GSFont()\FontColor())
          __FontSpriteID = GSFont()\FontColor()\NumFontSprite
        EndIf
      EndIf
    Else
      If FindMapElement(GSFont()\FontColor(), Str(__FontSpriteID))
        __FontSpriteID = GSFont()\FontColor()\NumFontSprite
        If Not __FontSpriteID
          ;Error
          GS2D_DEBUGLOG("Error GS2D_DrawText #2")
          End
        EndIf
      EndIf
    EndIf

    For _Index = 1 To _Len
      _Char     = Mid(__Text,_Index,1)
      _Ascii    = Asc(_Char) - 32
      _ClipX    = (_Ascii % GSFont()\CharByLine) * GSFont()\FontColor()\CharWidth
      _ClipY    = (_Ascii / GSFont()\CharByLine) * GSFont()\FontColor()\CharHeight
      ClipSprite(__FontSpriteID, _ClipX, _ClipY, GSFont()\FontColor()\CharWidth, GSFont()\FontColor()\CharHeight)
      DisplayTransparentSprite(__FontSpriteID, __X, __Y)
      __X + GSFont()\FontColor()\CharWidth
    Next
    GSFont()\LastNumFontUsed = __FontSpriteID
  Else
    ;Error
    GS2D_DEBUGLOG("No Font map found !")
    End
  EndIf
EndProcedure

Procedure GS2D_GetCharHeight(__FontID.i, __FontSpriteID.i = -1)
  Protected.i _CharHeight = 0

  If FindMapElement(GSFont(), Str(__FontID))
    If __FontSpriteID = -1
      _CharHeight = GSFont()\CharHeight
    ElseIf FindMapElement(GSFont()\FontColor(), Str(__FontSpriteID))
      _CharHeight = GSFont()\FontColor()\CharHeight
    EndIf
  EndIf
  ProcedureReturn _CharHeight
EndProcedure

Procedure GS2D_GetCharWidth(__FontID.i, __FontSpriteID.i = -1)
  Protected.i _CharWidth = 0

  If FindMapElement(GSFont(), Str(__FontID))
    If __FontSpriteID = -1
      _CharWidth = GSFont()\CharWidth
    ElseIf FindMapElement(GSFont()\FontColor(), Str(__FontSpriteID))
      _CharWidth = GSFont()\FontColor()\CharWidth
    EndIf
  EndIf
  ProcedureReturn _CharWidth
EndProcedure

Procedure.i GS2D_CatchFont(*FontPTR, __FontName.s, __FontWidth.i, __FontHeight.i, __CharByLine.i, __TransparentColor.i = $FF00FF)
  Protected.i _ImgFont

  _ImgFont = CatchImage(#PB_Any, *FontPTR)
  If _ImgFont
    TransparentColor = __TransparentColor
    AddMapElement(GSFont(), Str(_ImgFont))
    GSFont()\FontName           = __FontName
    GSFont()\CharByLine         = __CharByLine
      GSFont()\ImageWidth       = ImageWidth(_ImgFont)
      GSFont()\ImageHeight      = ImageHeight(_ImgFont)
      GSFont()\CharWidth        = __FontWidth
      GSFont()\CharHeight       = __FontHeight
      GSFont()\TransparentColor = __TransparentColor
    ProcedureReturn _ImgFont
  Else
    ProcedureReturn #False
  EndIf
EndProcedure

;-Sprites
;Generate an unique ID
Procedure.i GS2D_GetSpriteAnimID()
  Protected.i _ID = IDSprite
  IDSprite + 1
  ProcedureReturn _ID
EndProcedure

;Generate and cut sprites from sheet though each sprite will have an unique ID
;and will be add in the map GSprite
Procedure GS2D_GrabImage(__ImageNum.i, __NameOfSprite.s, __SpriteWidth.i, __SpriteHeight.i, __SpriteTotal.i, __MaskColor.i)
  Protected.i _SprWidth, _MaxSprWidth, _SprColor, _NewImage

  _SprWidth      = ImageWidth(__ImageNum)
  _MaxSprWidth   = _SprWidth / __SpriteWidth               ;nb Images max for the width

  AddMapElement(GSprite(), __NameOfSprite)
    GSprite()\Num         = __ImageNum
    GSprite()\Width       = __SpriteWidth
    GSprite()\Height      = __SpriteHeight
    GSprite()\MaskSprite  = __MaskColor
    GSprite()\MaxSprite   = __SpriteTotal

  ;How to get each sprite from a sheet
  ;example :
  ;
  ;The image sheet includes 5 Images (NB_Frame) 
  ;Width max = 3 because Image_width / Img_width = 3 (nb_Image_width)
  ;
  ; <----------- Image_width ----------->
  ;
  ;   column=1
  ; +-----------+-----------+-----------+
  ; !<--------->! ^         !           !
  ; ! Img_width ! |         !           !
  ; !           ! Img_height!           !
  ; !           ! |         !           !
  ; !           ! |         !           !
  ; !          1! v        2!          3!
  ; +-----------+-----------+-----------+
  ; !           !           !
  ; !           !           !
  ; !           !           !
  ; !           !           !
  ; !           !           !
  ; !          4!          5!
  ; +-----------+-----------+
  Protected.i _Colonne, _X, _Y, _NewSprite, _Index

  _Colonne = 1                                             ;Start at the 1st column
  _X = 0 : _Y = 0                                          ;and position 0,0
  For _Index = 1 To __SpriteTotal
    ;Select a part to create the new sprite
    _NewImage = GrabImage(__ImageNum, #PB_Any, _X, _Y, __SpriteWidth, __SpriteHeight)
    If _NewImage
      _NewSprite = CreateSprite(#PB_Any, __SpriteWidth, __SpriteHeight)
      If IsSprite(_NewSprite)
        TransparentSpriteColor(_NewSprite, __MaskColor)    ;Define his maskcolor (for transparency)
        StartDrawing(SpriteOutput(_NewSprite))
          DrawImage(ImageID(_NewImage), 0, 0)
        StopDrawing()
        
        GSprite()\Sprite\Spr[_Index] = _NewSprite          ;Add it in the list
        
        If _Colonne % _MaxSprWidth = 0                     ;Go to the next line if result = 0
          _Colonne = 1 : _X = 0 : _Y + __SpriteHeight
        Else
          _Colonne + 1 : _X + __SpriteWidth                ;else we continue with the same line
        EndIf
      Else
        GS2D_DEBUGLOG("Error creating new sprite !!!")
        End
      EndIf
    Else
      GS2D_DEBUGLOG("Error creating new image !!!")
      End
    EndIf
  Next _Index
EndProcedure

;We can load a file
Procedure.i GS2D_LoadAnimSprite(__FileName.s, __NameOfSprite.s, __SpriteWidth.i, __SpriteHeight.i, __SpriteTotal.i = 1, __MaskColor.i = -1)
  Protected.i _ImgNum

  If ReadFile(0,__FileName)
    _ImgNum = LoadImage(#PB_Any, __FileName)
    If _ImgNum
      GS2D_GrabImage(_ImgNum, __NameOfSprite, __SpriteWidth, __SpriteHeight, __SpriteTotal, __MaskColor)
      ProcedureReturn _ImgNum
    Else
      ;Error:
      GS2D_DEBUGLOG("Cannot load sprites filename "+__FileName+"!!!")
      ProcedureReturn #False
      End
    EndIf
  Else
    ProcedureReturn #False
  EndIf
EndProcedure

;or we can catch it from memory
Procedure.i GS2D_CatchAnimSprite(*SpritePTR, __NameOfSprite.s, __SpriteWidth.i, __SpriteHeight.i, __SpriteTotal.i = 1, __MaskColor.i = -1)
  Protected.i _ImgNum

  _ImgNum = CatchImage(#PB_Any, *SpritePTR)
  If _ImgNum
    GS2D_GrabImage(_ImgNum, __NameOfSprite, __SpriteWidth, __SpriteHeight, __SpriteTotal, __MaskColor)
    ProcedureReturn _ImgNum
  Else
    ;Error:
    GS2D_DEBUGLOG("Cannot catch sprites "+__NameOfSprite+"!!!")
    ProcedureReturn #False
  EndIf
EndProcedure

Procedure GS2D_DrawSprite(__Name.s, __NumFrame.i, __PosX, __PosY)
  ;If the sprites map exist
  If FindMapElement(GSprite(),__Name)
    ;We can display it
    DisplayTransparentSprite(GSprite()\Sprite\Spr[__NumFrame], __PosX, __PosY)
  EndIf
EndProcedure

;Creation of the animations in the GSpriteAnim map
;The GSpriteAnim map don't have any image, only the name of the sprite sheet map
;the start and end number of the sprite, the delay, only datas
Procedure.i GS2D_CreateAnimSprite(__NumSpriteImage.i, __Name.s, __FirstFrame.i, __LastFrame.i, __DelayBetweenFrame.i = 200, __NbTimes = 0)
  Protected.i _SpriteImageNum = __NumSpriteImage

  ;Check if the map exist
  If FindMapElement(GSprite(),__Name)
    If __NumSpriteImage = #PB_Any
      _SpriteImageNum = GS2D_GetSpriteAnimID()                  ; Generate a nuw number
    EndIf
    AddMapElement(GSpriteAnim(),Str(_SpriteImageNum))           ; Add an animation
      GSpriteAnim()\MapNameSprite     = __Name                  ; Insert Sprite sheet name
      GSpriteAnim()\X                 = -1                      ; X and Y not use for now
      GSpriteAnim()\Y                 = -1
      GSpriteAnim()\FrameStart        = __FirstFrame            ; Animation starts with the sprite number
      GSpriteAnim()\FrameEnd          = __LastFrame             ; and end with
      GSpriteAnim()\CurrentFrame      = 1                       ; We start with the first frame
      GSpriteAnim()\StartDelay        = ElapsedMilliseconds()   ; Animation starts now
      GSpriteAnim()\DelayBetweenFrame = __DelayBetweenFrame     ; What is the delay between each frame?
      GSpriteAnim()\LoopTimes         = __NbTimes               ; Do we have a loop?
      GSpriteAnim()\Display           = #True                   ; Do we display it?
  Else
    _SpriteImageNum = -1
  EndIf

  ProcedureReturn _SpriteImageNum
EndProcedure

;We enable/disable display of animation
;if param __Type = #true, we put Display to #false and reverse
Procedure.i GS2D_RemoveAnimSprite(__NumSpriteImage.i, __Type.i)
  If FindMapElement(GSpriteAnim(), Str(__NumSpriteImage))
    GSpriteAnim()\Display           = 1 - __Type                ; Inverted because if #true we display, but if it's #true while remove : no more display
    GSpriteAnim()\CurrentFrame      = 1
  EndIf
EndProcedure

;We display the animation
Procedure.i GS2D_DrawAnimSprite(__NumSpriteImage.i, __X.i, __Y.i, __Direction = #GS2D_FORWARD)
  ;Do the map exist?
  If FindMapElement(GSpriteAnim(), Str(__NumSpriteImage))
    ;and sprites map too?
    If FindMapElement(GSprite(), GSpriteAnim()\MapNameSprite)
      ;Which direction
      Select __Direction
        ;Forward
        Case #GS2D_FORWARD
          ;If actual time - defined time when we created the sprite >= delay
          If ElapsedMilliseconds() - GSpriteAnim()\StartDelay >= GSpriteAnim()\DelayBetweenFrame
            ;New start delay
            GSpriteAnim()\StartDelay = ElapsedMilliseconds()
            ;Go to next frame
            GSpriteAnim()\CurrentFrame + 1
            ;IF actual frame + frame start > end frame + 1 and no loop activated
            If GSpriteAnim()\CurrentFrame + GSpriteAnim()\FrameStart > GSpriteAnim()\FrameEnd + 1 And GSpriteAnim()\LoopTimes = -1
              ;The current frame is the last frame
              GSpriteAnim()\CurrentFrame = GSpriteAnim()\FrameEnd - GSpriteAnim()\FrameStart + 1
            EndIf
            ;Else we start from the beginning
            If GSpriteAnim()\CurrentFrame + GSpriteAnim()\FrameStart > GSpriteAnim()\FrameEnd + 1 And GSpriteAnim()\LoopTimes <> -1
              GSpriteAnim()\CurrentFrame = 1
            EndIf
          EndIf
          ;Can we display it?
          If GSpriteAnim()\Display = #True
            DisplayTransparentSprite(GSprite()\Sprite\Spr[GSpriteAnim()\FrameStart + GSpriteAnim()\CurrentFrame - 1], __X, __Y)
          EndIf
        ;And backward
        Case #GS2D_BACKWARD
          ;Check time between frame
          If ElapsedMilliseconds() - GSpriteAnim()\StartDelay >= GSpriteAnim()\DelayBetweenFrame
            GSpriteAnim()\StartDelay = ElapsedMilliseconds()
            GSpriteAnim()\CurrentFrame + 1
            ;if the last defined frame - current frame + 1 < defined frame at the beginning and no loop
            If GSpriteAnim()\FrameEnd - GSpriteAnim()\CurrentFrame + 1 < GSpriteAnim()\FrameStart And GSpriteAnim()\LoopTimes = -1
              ;Frame to display = 1st defined frame
              GSpriteAnim()\CurrentFrame = GSpriteAnim()\FrameStart
            EndIf
            ;else used the 1st frame
            If GSpriteAnim()\FrameEnd - GSpriteAnim()\CurrentFrame + 1 < GSpriteAnim()\FrameStart And GSpriteAnim()\LoopTimes <> -1
              GSpriteAnim()\CurrentFrame = 1
            EndIf
          EndIf
          ;Display the frame?
          If GSpriteAnim()\Display = #True
            DisplayTransparentSprite(GSprite()\Sprite\Spr[GSpriteAnim()\FrameEnd - GSpriteAnim()\CurrentFrame + 1], __X, __Y)
          EndIf
      EndSelect
      ProcedureReturn GSpriteAnim()\CurrentFrame
    Else
      ; Error: MapSprite non trouvé
    EndIf
  Else
    ; Error: SpriteNum pas trouvé
  EndIf
EndProcedure

;-Sequences
; We create an animation sequence with an ID sprite starting by #GLMFS_FREQ_MIN
Procedure.i GS2D_CreateSequence(__ValueSequence.i, __NumSpriteAnim.i)
  If __ValueSequence < #GLMFS_FREQ_MIN
    ;Error:
    GS2D_DEBUGLOG("Error: Sequence value must be greater or equal to $"+Hex(#GLMFS_FREQ_MIN)+" !!!")
    ProcedureReturn #False
  Else
    AddMapElement(GSequence(),Str(__ValueSequence))
      GSequence() = __NumSpriteAnim
    ProcedureReturn #True
  EndIf
EndProcedure

;-Layers
; Create layers
; Dynamic restore
Procedure GS2D_Restore(__address)
  !MOV eax, [p.v___address]
  !MOV [PB_DataPointer],eax
EndProcedure

Procedure.i GS2D_CreateLayers(__MapSpriteName.s, __AdrData.i)
  Protected.i _LayerTotal, _index, _LineColumn
  Protected.s _LayerName
  Protected.i _LayerMapHeight, _LayerMapWidth
  Protected.i _LayerSpriteHeight, _LayerSpriteWidth
  Protected.i _TileNum
  
  ;Map already created?
  If MapSize(GSLayer()) > 0
    ClearMap(GSLayer())
  EndIf

  GS2D_Restore(__AdrData)
  Read.i _LayerTotal
  Read.i _LayerMapWidth
  Read.i _LayerMapHeight
  Read.i _LayerSpriteWidth
  Read.i _LayerSpriteHeight
  For _index = 1 To _LayerTotal
    Read.s _LayerName
    AddMapElement(GSLayer(), _LayerName)
    ReDim GSLayer()\TBL_Tile(_LayerMapWidth*_LayerMapHeight)
    GSLayer()\MapSpriteName   = __MapSpriteName
    GSLayer()\MapHeight       = _LayerMapHeight
    GSLayer()\MapWidth        = _LayerMapWidth
    GSLayer()\MapSpriteHeight = _LayerSpriteHeight
    GSLayer()\MapSpriteWidth  = _LayerSpriteWidth
    For _LineColumn = 0 To (_LayerMapWidth*_LayerMapHeight)-1
      Read.i _TileNum
      GSLayer()\TBL_Tile(_LineColumn) = _TileNum
    Next _LineColumn
  Next _index

  ProcedureReturn #True
EndProcedure

;Display our layer
Procedure.i GS2D_DrawLayer(__NameOfLayer.s, __PosX.i, __PosY.i)
  Protected.i _PositionTile, _TileFrame
  Protected.i _TileY, _TileX
  Protected.i _AbsoluteX, _AbsoluteY
  Protected.i _MapWidth, _MapHeight
  Protected.i _MapSpriteWidth, _MapSpriteHeight

  ;Find our map
  If FindMapElement(GSLayer(), __NameOfLayer)
    ;Sprite map found?
    If FindMapElement(GSprite(), GSLayer()\MapSpriteName)
      _MapHeight        = GSLayer()\MapHeight
      _MapWidth         = GSLayer()\MapWidth
      _MapSpriteHeight  = GSLayer()\MapSpriteHeight
      _MapSpriteWidth   = GSLayer()\MapSpriteWidth
      ; ok, now we will read each tile of the map
      ; We start by the tile number in the position Y
      ; Calculate from current position with the height of a sprite
      ; of the map, with map level1 (32)
      ; --- Ex: if __PosY = 60 ==> _TileY = 1
      _TileY     = __PosY / _MapSpriteHeight
      ; and the Y value to display the tile
      ; --- Ex: with _TileY = 1, we have (60 % 32), le remaining is 28
      ;         here _AbsoluteY = -28 in Y
      _AbsoluteY = -(__PosY % _MapSpriteHeight)
      ; While we stay inside the height of the screen
      While _AbsoluteY < GAME\ScreenHeight
        ; _TileY = modulo of last TileY division by the total of map sprite height
        ; --- Ex: _TileY = 1 % 15 => 1
        _TileY     = _TileY % _MapHeight
        ; _TileX = absolute value of current X position / size of the sprite
        ; --- Ex: if __PosX = 300
        ;         _TileX = 300 / 32 => 9
        _TileX     = __PosX / _MapSpriteWidth
        ; Calculate X position (using minus because Purebasic handle clipping)
        ; --- Ex: _AbsoluteX = -(300 % 32) = -12 in X
        _AbsoluteX = -(__PosX % _MapSpriteWidth)
        ; While X < max width of the screen
        While _AbsoluteX < GAME\ScreenWidth
          ; Search tile number in the one dimension array
          ; (line * map width) + column
          ; --- Ex: _PositionTile = (1 * 20) + 9
          ;         so 29th Tile in the array GSLayer()\TBL_Tile
          ;         Etc...
          _PositionTile = (_TileY * _MapWidth) + _TileX
          ; What is the tile number => _TileFrame
          _TileFrame    = GSLayer()\TBL_Tile(_PositionTile)
          ; Frame created in the Frequences Map?
          If _TileFrame >= #GLMFS_FREQ_MIN
            ; Yes, so search it
            If FindMapElement(GSequence(), Str(_TileFrame))
              ; and we display the animation
              GS2D_DrawAnimSprite(GSequence(), _AbsoluteX, _AbsoluteY)
            Else
              ; Error: Frequence not created
            EndIf
          ; else if frame <> 0, we display it
          ElseIf _TileFrame <> 0
            DisplayTransparentSprite(GSprite()\Sprite\Spr[_TileFrame], _AbsoluteX, _AbsoluteY)
          EndIf
          ; Next TileX
          _TileX + 1
          ; Position X + sprite width of the curent map (ex: level1 = 32)
          _AbsoluteX + _MapSpriteWidth
        ; End of the bloc lines display
        Wend
        ; Next line
        _TileY + 1
        _AbsoluteY + _MapSpriteHeight
      ; End of the bloc colums display
      Wend
    Else
      ProcedureReturn #False
    EndIf
  Else
    ProcedureReturn #False
  EndIf

  ProcedureReturn #True
EndProcedure

;-Get the FPS
Procedure.i GS2D_GetFPS()
Static.i _InitTime, _FPSTime, _FPSCount, _FPSReturnValue

  _InitTime = ElapsedMilliseconds()
  If _InitTime - _FPSTime <= 1000
    _FPSCount + 1
  Else 
    _FPSReturnValue = _FPSCount
    _FPSCount       = 0
    _FPSTime        = _InitTime
  EndIf
  
  ProcedureReturn _FPSReturnValue
EndProcedure

;-*** Init
Procedure GS2D_Init(__ScrWidth.i = 800, __ScrHeight.i = 600)
  UsePNGImageDecoder():InitSprite():InitKeyboard()
  GAME\ScreenWidth  = __ScrWidth
  GAME\ScreenHeight = __ScrHeight

  CompilerIf Defined(__DEBUG__, #PB_Constant)
    CreateFile(#DEBUG_FILENUM,#DEBUG_NAME)
      WriteStringN(#DEBUG_FILENUM,"DEBUG LOG--DATE:"+FormatDate(" %dd/%mm/%yyyy at %hh:%ii:%ss", Date()))
      CloseFile(#DEBUG_FILENUM)
  CompilerEndIf
EndProcedure
“Fear is a reaction. Courage is a decision.” - WC
User avatar
flaith
Enthusiast
Enthusiast
Posts: 704
Joined: Mon Apr 25, 2005 9:28 pm
Location: $300:20 58 FC 60 - Rennes
Contact:

Re: Little 2D Old School Library

Post by flaith »

Test code: GLMFS2D_test.pb

Code: Select all

; To create a debug log (file: GS2D_DEBUG.LOG)
; remove the rem of the following constant
;#__DEBUG__              = 0

#SCREEN_Width         = 320
#SCREEN_Height        = 240
#SPR_MAP_LVL1_HEIGHT  = 32                                 ;Sprites Heigh for MAP Level1
#SPR_MAP_LVL1_WIDTH   = 32                                 ;Heigh Width fo MAP Level1
#NB_CHAR_BY_LINE      = 28                                 ;28 Char by Line inside Font Image

;*** 31/07/2013
;FPS Manager
XIncludeFile "FPS_Manager.pbi"
;**************
;Lib Sprites and Layers
XIncludeFile "GLMFS2D.pbi"

; Next MUST be after the include because the constant #GLMFS_FREQ_MIN
; is declared in GLMFS2D.pbi
Enumeration #GLMFS_FREQ_MIN
  #SEQWATER
  #SEQFIRE
EndEnumeration

; XIncludeFile 
; ***********
;-** Datas **
; ***********
DataSection
  ;Fonts
  DS_IMG_Font_GOBLINS: : IncludeBinary "IMG_FONT_G&G.png"
  DS_IMG_Font_APPLE:   : IncludeBinary "IMG_FONT_APPLE.png"
  ;Some sprites
  DS_SpriteZombies:    : IncludeBinary "GNG_Zombies.png"
  DS_SpriteLvl1:       : IncludeBinary "GNG_MAP_Sprite_Lvl01.png"
  ;Define the layers
  DS_Layers_Lvl1:
    Data.i  5                                             ;LayerTotal
    Data.i  20,15                                         ;MapWidth x MapHeight
    Data.i  #SPR_MAP_LVL1_HEIGHT,#SPR_MAP_LVL1_WIDTH      ;Sprite Width x Sprite Height
    Data.s  "BACKGROUND_MOUNTAIN"                         ;Layer's name
    Data.i  00,00,00,00,00,72,73,00,72,74 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,75,76,00,75,77 , 78,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,79,80,81,83,84,81 , 85,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.s  "BACKGROUND_YARD"
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  63,63,10,63,20,11,63,64,00,00 , 00,00,00,00,65,63,63,63,63,63
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.s  "PLAYER_LAYER"
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  24,24,24,24,24,24,66,67,00,68 , 69,00,00,00,70,66,24,24,24,24
    Data.i  71,71,71,71,71,71,71,00,00,00 , 00,00,00,00,00,71,71,71,71,71
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.s  "FORGROUND_LAYER"
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  102,101,102,101,102,101,102,00,00,00 , 00,00,00,00,00,102,101,102,101,102
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.s  "SEQUENCE"
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    ;Add the #SEQWATER for the animated sprites in the layer
    Data.i  00,00,00,00,00,00,00,#SEQWATER,#SEQWATER,#SEQWATER , #SEQWATER,#SEQWATER,#SEQWATER,#SEQWATER,#SEQWATER,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
    Data.i  00,00,00,00,00,00,00,00,00,00 , 00,00,00,00,00,00,00,00,00,00
EndDataSection

#SPR_ZOMBIE_HEIGHT    = 66                                 ;Height zombie sprite
#SPR_ZOMBIE_WIDTH     = 46                                 ;Width zombie sprite
#SPEED_ZOMBIE         = 1                                  ;Speed of the walking zombie

; ********************
;-** FONT Constants **
; ********************
; GOBLINS : 16x16
#FONT_GNG_WIDTH       = 16
#FONT_GNG_HEIGHT      = 16
; APPLE : 6x8
#FONT_APPLE_WIDTH     = 6
#FONT_APPLE_HEIGHT    = 8
; ----------------------------

;- *** Main ******************************
GS2D_Init(#SCREEN_Width, #SCREEN_Height)

Global.i ImgFontGNG, ImgFontAPPLE
Global.i FontGNG_White, FontGNG_Black, FontGNG_Grey, FontGNG_Red, FontGNG_Green, FontGNG_Blue, FontGNG_Red, FontGNG_Yellow
Global.i FontAPPLE_White, FontAPPLE_Black, FontAPPLE_Grey, FontAPPLE_Red, FontAPPLE_Green, FontAPPLE_Blue, FontAPPLE_Red, FontAPPLE_Yellow

Global.i ImGSpriteZombies, SprAnimZombie1, SprAnimZombie2, SprAnimZombie3
Global.i ImgMapLvl1, Water
Global.i PosX_Zombie1, CurFrameZombie3

Global.i refreshrate
Global.i POSX = 0, POSY = 0

;*** 31/07/2013
; FPS
Global fps.FPSObject
Global rate.i, time_passed.i
;**************
Global.i Event, Quit = 0

If OpenWindow(0, 0, 0, #SCREEN_Width, #SCREEN_Height, "Test Anim Sprite lib GS2D V"+#GLMFS_VERSION, #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget)
  If OpenWindowedScreen(WindowID(0), 0, 0, WindowWidth(0), WindowHeight(0), 1, 0, 0);, #PB_Screen_NoSynchronization)
    ExamineDesktops()

    ;Loading fonts
    ImgFontGNG        = GS2D_CatchFont(?DS_IMG_Font_GOBLINS, "GOBLINS", #FONT_GNG_WIDTH, #FONT_GNG_HEIGHT, #NB_CHAR_BY_LINE, $FF00FF)
    ImgFontAPPLE      = GS2D_CatchFont(?DS_IMG_Font_APPLE, "APPLE", #FONT_APPLE_WIDTH, #FONT_APPLE_HEIGHT, #NB_CHAR_BY_LINE)

    ; Create sprite sheets
    ImGSpriteZombies  = GS2D_CatchAnimSprite(?DS_SpriteZombies, "ZOMBIE", #SPR_ZOMBIE_WIDTH, #SPR_ZOMBIE_HEIGHT, 18, $FF00FF)
    ImgMapLvl1        = GS2D_CatchAnimSprite(?DS_SpriteLvl1, "MAP01", #SPR_MAP_LVL1_WIDTH, #SPR_MAP_LVL1_HEIGHT, 104, $FF00FF)
    ;or
    ;ImgMapLvl1        = GS2D_LoadAnimSprite("GNG_MAP_Sprite_Lvl01.png","MAP01", #SPR_MAP_LVL1_WIDTH, #SPR_MAP_LVL1_HEIGHT, 104, $FF00FF)
    
    ;Create the layer after the sprite
    If ImgFontGNG And ImGSpriteZombies And ImgMapLvl1 And GS2D_CreateLayers("MAP01", ?DS_Layers_Lvl1)
      ;Create font yellow and red
      FontGNG_Yellow   = GS2D_CreateFontColor(ImgFontGNG, $00CCEE)
      FontGNG_Red      = GS2D_CreateFontColor(ImgFontGNG, $0000FF)
      ;And change the size of the red font
      GS2D_ResizeFont(ImgFontGNG, FontGNG_Red, 8)

      FontAPPLE_Green  = GS2D_CreateFontColor(ImgFontAPPLE, $00FF00)
      FontAPPLE_Grey   = GS2D_CreateFontColor(ImgFontAPPLE, $808080)

      ;Change the size of the green font
      GS2D_ResizeFont(ImgFontAPPLE, FontAPPLE_Green, 12)

      ;Create our animation from our sprite sheet
      SprAnimZombie1  = GS2D_CreateAnimSprite(#PB_Any, "ZOMBIE", 7, 9, 400)
      SprAnimZombie2  = GS2D_CreateAnimSprite(#PB_Any, "ZOMBIE", 16, 18, 400)
      SprAnimZombie3  = GS2D_CreateAnimSprite(#PB_Any, "ZOMBIE", 1, 7, 1000, -1)
      Water           = GS2D_CreateAnimSprite(#PB_Any, "MAP01", 86, 88)
      ;Create an animation sequence for the sprite 'water"
      GS2D_CreateSequence(#SEQWATER, water)

      PosX_Zombie1    = Random(#SCREEN_Width-#SPR_ZOMBIE_WIDTH-3*32)
      
      ;*** 31/07/2013
      ; Manage FPS
      time_passed = 0
      fps = FPS_initFramerate()
      rate = fps\FPS_getFramerate()
      fps\FPS_setFramerate(60)
      ;**************

      Repeat
        Repeat
          Event = WaitWindowEvent(5)

          Select Event 
            Case #PB_Event_Gadget
              If EventGadget() = 0
                quit = 1
              EndIf
            
            Case #PB_Event_CloseWindow
              quit = 1 
          EndSelect
        Until Event = 0

        ExamineKeyboard()
        If KeyboardPushed(#PB_Key_Escape) : quit = 1 : EndIf

        If KeyboardPushed(#PB_Key_Left)  : If POSX > 0 : POSX - 5 : EndIf : EndIf
        If KeyboardPushed(#PB_Key_Right) : If POSX < (GSLayer()\MapWidth * #SPR_MAP_LVL1_WIDTH) - #SCREEN_Width : POSX + 5 : EndIf : EndIf

        If KeyboardPushed(#PB_Key_Up)    : If POSY > 0 : POSY - 5 : EndIf : EndIf
        If KeyboardPushed(#PB_Key_Down)  : If POSY < (GSLayer()\MapHeight * #SPR_MAP_LVL1_HEIGHT) - #SCREEN_Height : POSY + 5 : EndIf : EndIf

        FlipBuffers()
        ClearScreen(0)
  
        ; ---------------
        ;Display the layers in the correct order
        GS2D_DrawLayer("BACKGROUND_MOUNTAIN",POSX/3,POSY/3)
        GS2D_DrawLayer("BACKGROUND_YARD",POSX,POSY)
        GS2D_DrawLayer("PLAYER_LAYER",POSX,POSY)
        ; ---------------            
        ;Zombies
        GS2D_DrawAnimSprite(SprAnimZombie2,  10, 5*32-#SPR_ZOMBIE_HEIGHT)
        CurFrameZombie3 = GS2D_DrawAnimSprite(SprAnimZombie3, PosX_Zombie1, 5*32-#SPR_ZOMBIE_HEIGHT)
        If CurFrameZombie3 = 7 And NextSprite = #False
          GS2D_RemoveAnimSprite(SprAnimZombie3, #True)
          NextSprite = #True
        ElseIf NextSprite = #True
          GS2D_DrawAnimSprite(SprAnimZombie1, PosX_Zombie1, 5*32-#SPR_ZOMBIE_HEIGHT)
          PosX_Zombie1 + #SPEED_ZOMBIE
          If PosX_Zombie1 > #SCREEN_Width And CurFrameZombie3 = 7 : PosX_Zombie1 = Random(#SCREEN_Width-#SPR_ZOMBIE_WIDTH-3*32) : NextSprite = #False : GS2D_RemoveAnimSprite(SprAnimZombie3, #False) : EndIf
        EndIf
        GS2D_DrawLayer("FORGROUND_LAYER",POSX,POSY)
        GS2D_DrawLayer("SEQUENCE",POSX,POSY)
        GS2D_DrawText(ImgFontGNG,0,224,"Hz:", FontGNG_Yellow)
        GS2D_DrawText(ImgFontGNG,80,224,"FPS:", FontGNG_Yellow)
        GS2D_DrawText(ImgFontGNG,145,228,Str(GS2D_GetFPS()), FontGNG_Red)
        ;*** 31/07/2013
        If time_passed > 0
          GS2D_DrawText(ImgFontGNG,50,228,Str(1000/time_passed), FontGNG_Red)
        EndIf          
        GS2D_DrawText(ImgFontAPPLE,#SCREEN_Width-(GS2D_GetCharWidth(ImgFontAPPLE, FontAPPLE_Grey)*Len("Framerate: "+Str(fps\FPS_getFramerate()))),232, "Framerate: "+Str(fps\FPS_getFramerate()), FontAPPLE_Grey)
        ;**************
        ;A little advertisement for me :)
        GS2D_DrawText(ImgFontAPPLE, Random(#SCREEN_Width-(GS2D_GetCharWidth(ImgFontAPPLE, FontAPPLE_Green)*Len("(c)Flaith 2012-2013"))), Random(#SCREEN_Height-(GS2D_GetCharHeight(ImgFontAPPLE, FontAPPLE_Green))), "(c)Flaith 2012-2013", FontAPPLE_Green)
        ; ---------------
        ;*** 31/07/2013
        time_passed = fps\FPS_framerateDelay()
        ;**************
      Until Quit = 1
      GS2D_DEBUGLOG("END LOG---")
    Else
      ;Error: Sprites not created
      GS2D_DEBUGLOG("Cannot create sprites !!!")
      End
    EndIf
  Else
    ;Error: Cannot create screen
    GS2D_DEBUGLOG("Cannot open the screen !!!")
    End
  EndIf
EndIf
“Fear is a reaction. Courage is a decision.” - WC
User avatar
flaith
Enthusiast
Enthusiast
Posts: 704
Joined: Mon Apr 25, 2005 9:28 pm
Location: $300:20 58 FC 60 - Rennes
Contact:

Re: Little 2D Old School Library

Post by flaith »

The images :
Sprite Map level
Sprite Zombie
Font Apple
Font G&G

or all (src + img) in this Zip file : GLMFS2D.zip
“Fear is a reaction. Courage is a decision.” - WC
Jan2004
Enthusiast
Enthusiast
Posts: 163
Joined: Fri Jan 07, 2005 7:17 pm

Re: Little 2D Old School Library

Post by Jan2004 »

A very nice example. Varied code, interesting for educational purposes. Thank you. I had a lot of fun watching the animation, now I am a little scared.
User avatar
flaith
Enthusiast
Enthusiast
Posts: 704
Joined: Mon Apr 25, 2005 9:28 pm
Location: $300:20 58 FC 60 - Rennes
Contact:

Re: Little 2D Old School Library

Post by flaith »

Jan2004 wrote:A very nice example. Varied code, interesting for educational purposes. Thank you. I had a lot of fun watching the animation, now I am a little scared.
Thanks for your feedback :D
“Fear is a reaction. Courage is a decision.” - WC
Post Reply