Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
For what it’s worth: Programming Clarity
#1
As someone close to the bottom of the “programming chain”, I just want to make a few comments on what makes programmes understandable, at least for me.  I know some members won’t agree with some of these things, and some seem pretty obvious, but I find they help me to understand someone else’s programming.
Comments: A few words at the end of, or before, a line that introduces new elements or features can be a great help, not only to other readers, but to the author when editing or reviewing later. They don’t greatly increase the programme  size, and are not included in the compiled programme, so why not use them?.
Variable Names: These should give an indication of what they represent. An abbreviated form, maybe with vowels removed, is often ok, but a full word is even better: “TopScore” is clearer than “TpScr”, and won’t be confused with say a “TopOfScreen”, but either one is better than “scmx%”. Some names will necessarily be a bit obscure, especially with advanced trig or system items, so may need a comment to give some indication of their purpose, when first introduced.
Labels: When a new section of a unit starts – whether in the Main or a Sub or Function – it helps if that section is spaced out, and given a meaningful label, telling the reader what the section does, e.g. “CheckBoundary:”. Although spaces are not allowed in labels, CapitalLetters or Under_Scores can be used instead.
Subs and Functions: should have a meaningful name that describes their purpose, and if necessary a comment explaining this.
Programme Names: These should give enough information to tell readers what they can expect to find in the programme. An Introductory page or paragraph that can be seen on opening can also be useful.
Many writers do these things as a matter of course, but occasionally they become so involved in making the programme smaller, or work or run faster, that these are overlooked, leaving readers like me mystified about the purpose of that section, or of the whole programme !
Of all the places on Earth, and all the planets in the Universe, I'd rather live here (Perth, W.A.) Big Grin
Please visit my Website at: http://oldendayskids.blogspot.com/
Reply
#2
You would have hated me back in the day...

Single letter variables.
Code in all caps.
No commenting anywhere.
No indentation.
No spacing between lines.

That's right:

Code: (Select All)
A$ = "HELLO WORLD!"
PRINT A$

Well, that and a few thousand more lines, usually.

Pete Big Grin
Reply
#3
I hear you loud and clear Phil. As someone who does all the things you like to see in code I also like to see code that has been constructed well.

It all boils down to habit and discipline. If you force yourself to write self documenting code (variable names that have meaning) and take the time to comment the code sections you'll get into the habit of doing so. Then it takes discipline to keep that habit constant.

It takes work and planning to do this but the payoff is huge in the end. As an example, here is a small section of code I am currently working on right now. I'm not saying others need to go to the extremes I do when commenting but some commenting and organization would be nice. Like you I've looked at code with non-descript variable names and zero comments and been mystified at the things I have seen. It's not just new programmers that get confused by spaghetti code.

Code: (Select All)

' Notes to remember:
'
' CREATE ACTIONS (animation, movement, and sound at same time)
' CREATE GUIDED MOTION (sort of like DRAW command)


OPTION _EXPLICIT

'$INCLUDE:'.\lib\common\lib_type_spoint.bi'
'$INCLUDE:'.\lib\common\lib_type_rect.bi'
'$INCLUDE:'.\lib\image\lib_img_flip.bi' '          IMG_Flip subroutine
'$INCLUDE:'.\lib\image\lib_img_introtate.bi'        IMG_INTRotate subroutine

'  ==============================================================================================================================================
'  //                                                                                                                                            \\
' //                                                        USER DATA TYPE DECLARATIONS                                                          \\
'//                                                                                                                                                \\
'====================================================================================================================================================
' --------------------------------------------------------------------------------------------------------------------------------------------------
'|        SPRITE SHEETS                                                                                                                            |
' --------------------------------------------------------------------------------------------------------------------------------------------------
TYPE TYPE_SHEETDB '                  SPRITE SHEET DATABSE PROPERTIES
    inUse AS INTEGER '                index in use (0 FALSE, -1 TRUE)
    Image AS LONG '                  image of sprite sheet
    Width AS INTEGER '                width of sprite sheet
    Height AS INTEGER '              height of sprite sheet
    GridWidth AS INTEGER '            width of each grid cell
    GridHeight AS INTEGER '          height of each grid cell
    Columns AS INTEGER '              number of colums on sprite sheet
    Rows AS INTEGER '                number of rows on sprite sheet
END TYPE
' --------------------------------------------------------------------------------------------------------------------------------------------------
'|        STILL IMAGES                                                                                                                              |
' --------------------------------------------------------------------------------------------------------------------------------------------------
TYPE TYPE_IMAGEDB '                  STILL IMAGE DATABASE PROPERTIES
    inUse AS INTEGER '                index in use (0 FALSE, -1 TRUE)
    Original AS LONG '                original still image (use to restore image)
    Image AS LONG '                  working still image
END TYPE
' --------------------------------------------------------------------------------------------------------------------------------------------------
'|        ANIMATIONS                                                                                                                                |
' --------------------------------------------------------------------------------------------------------------------------------------------------
TYPE TYPE_ANIMATIONCLIPDB '          ANIMATION CLIP PROPERTIES
    inUse AS INTEGER '                index in use (0 FALSE, -1 TRUE)
    Strip AS LONG '                  image of film strip cells
    Cells AS INTEGER '                numer of image cells
    Width AS INTEGER '                width of each image cell
    Height AS INTEGER '              height of image cells
    Direction AS INTEGER '            play direction of film strip
    Mode AS INTEGER '                play mode of film strip (0 play once, -1 loop) (use this to set SpriteDB().Mode after playback)
    FPS AS INTEGER '                  film strip frames per second
END TYPE
TYPE TYPE_ANIMATION '                ANIMATION PROPERIES
    hClp AS INTEGER '                animation clip database index pointer
    phClp AS INTEGER '                previous animation clip database index pointer
    Cell AS INTEGER '                current film strip cell displayed
    Frame AS INTEGER '                current frame number within FPS
    Auto AS INTEGER '                auto animation enabled (t/f)      (when off SPRITE_NextCell must be manually used)
    Clip AS TYPE_ANIMATIONCLIPDB '    animation clip properties
END TYPE
' --------------------------------------------------------------------------------------------------------------------------------------------------
'|        MOTION                                                                                                                                    |
' --------------------------------------------------------------------------------------------------------------------------------------------------
TYPE TYPE_MOTION '                    MOTION PROPERTIES
    xVec AS SINGLE '                  normalized x vector (0 to 1)
    yVec AS SINGLE '                  normalized y vector (0 to 1)
    xMag AS SINGLE '                  x vector multiplier (speed)
    yMag AS SINGLE '                  y vector multiplier (speed)
    xDir AS INTEGER '                x direction of travel (-1 or 1)
    yDir AS INTEGER '                y direction of travel (-1 or 1)
    Degree AS SINGLE '                degree direction of travel (0 to 360)
END TYPE
' --------------------------------------------------------------------------------------------------------------------------------------------------
'|        COLLISIONS                                                                                                                                |
' --------------------------------------------------------------------------------------------------------------------------------------------------
TYPE TYPE_COLLISION '                COLLISION PROPERTIES
    Method AS INTEGER '              Method of collision detection to use
    With AS INTEGER '                sprite that collision occurred with
    Point AS TYPE_SPOINT '            point of collision (circle, line, pixel)
    Rect AS TYPE_RECT '              area of collision (box)
    Radius AS SINGLE '                radius of circle collision
END TYPE
' --------------------------------------------------------------------------------------------------------------------------------------------------
'|        SPRITES                                                                                                                                  |
' --------------------------------------------------------------------------------------------------------------------------------------------------
TYPE TYPE_SPRITEDB
    inUse AS INTEGER '                index in use (0 FALSE, -1 TRUE)
    Animation AS TYPE_ANIMATION '    animation properties
    Still AS LONG '                  still image                    (points back to image database)
    Mode AS INTEGER '                Still image or animation (0 Still, -1 Animation)
    AutoMove AS INTEGER '            auto motion enabled (t/f)        (when off SPRITE_Move must manually be used)
    Image AS LONG '                  working sprite image (copied from animation cell or still image)
    Width AS INTEGER '                width of working sprite image  (always recalculate since still image can change)
    Height AS INTEGER '              height of working sprite image (always recalculate since still image can change)
    Rect AS TYPE_RECT '              working sprite image screen coordinates
    Collision AS TYPE_COLLISION '    collision properties
    Motion AS TYPE_MOTION '          motion properties
    Location AS TYPE_SPOINT '        x,y location of sprite
    Justify AS INTEGER '              working sprite image justification (0 to 9)
    Joffset AS TYPE_SPOINT '          custom justification x,y offsets
    Flip AS INTEGER '                working sprite image flip orientation (0 to 3)
    Rotate AS SINGLE '                working sprite image rotation (0 to 359.999)
    Zoom AS SINGLE '                  working sprite image zoom level (.1 or higher)
    Visible AS INTEGER '              working sprite image visible on screen (0 FALSE, -1 TRUE)
    Moved AS INTEGER '                sprite location or justification has changed (0 FALSE, -1 TRUE)
    Collided AS INTEGER '            sprite was involved in a collision (0 FALSE, -1 TRUE)
    Update AS INTEGER '              working sprite image needs updating (0 FALSE, -1 TRUE)
    Status AS INTEGER '              sprite status (0 IGNORE (dead), 1 NORMAL (alive), 2 PAUSE (no updates))

END TYPE

'  ==============================================================================================================================================
'  //                                                                                                                                            \\
' //                                                            VARIABLE DECLARATIONS                                                            \\
'//                                                                                                                                                \\
'====================================================================================================================================================

REDIM Sheetdb(0) AS TYPE_SHEETDB '        sprite sheet database
REDIM SpriteDB(0) AS TYPE_SPRITEDB '      sprite database
REDIM ImageDB(0) AS TYPE_IMAGEDB '        still image database
REDIM ClipDB(0) AS TYPE_ANIMATIONCLIPDB ' animation database



DIM Sheet AS INTEGER
DIM Standing AS INTEGER
DIM Background AS INTEGER

Sheet = SHEET_Load(".\lib\sprite\dkong.png", 64, 64)
Standing = IMAGE_Make(Sheet, 1, 1)
Background = IMAGE_Load(".\lib\sprite\backg.png")
SHEET_Delete Sheet
IMAGE_Rotate Standing, 60

SCREEN _NEWIMAGE(800, 600, 32)

IMAGE_Put Background, 0, 0
IMAGE_Put Standing, 100, 100
PRINT IMAGE_Width(Standing); IMAGE_Height(Standing)


'  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
'  V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V
'  ==============================================================================================================================================
'  //                                                                                                                                            \\
' //                                                      SPRITE SHEET SUBS AND FUNCTIONS                                                        \\
'//                                                                                                                                                \\
'====================================================================================================================================================
' ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
' | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |

'---------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION SHEET__NextIndex% () '                                                                                                  SHEET__NextIndex% |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| INTERNAL USE ONLY                                                                                                                            |
    '|                                                                                                                                              |
    '| Get the next available index in the sprite sheet database.                                                                                  |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    SHARED Sheetdb() AS TYPE_SHEETDB ' need access to sprite sheet database
    DIM Index AS INTEGER '            index counter

    Index = -1 '                                                    reset index counter
    DO '                                                            begin database search loop
        Index = Index + 1 '                                          increment index counter
    LOOP UNTIL Sheetdb(Index).inUse = 0 OR Index = UBOUND(Sheetdb) ' leave when free index found or end of database
    IF Sheetdb(Index).inUse <> 0 THEN '                              was a free index found?
        Index = Index + 1 '                                          no, increment the index counter
        REDIM _PRESERVE Sheetdb(Index) AS TYPE_SHEETDB '            increase the size of the database
    END IF
    Sheetdb(Index).inUse = -1 '                                      record index in use (TRUE)
    SHEET__NextIndex% = Index '                                      return index value

END FUNCTION
'---------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION SHEET_Exists% (hSht AS INTEGER) '                                                                                            SHEET_Exists% |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Returns the existence of a sprite sheet 0 (SPRITE_FALSE) or -1 (SPRITE_TRUE)                                                                |
    '|                                                                                                                                              |
    '| hSht - the sprite sheet handle                                                                                                              |
    '|                                                                                                                                              |
    '| Example: IsExisting% = SHEET_Exists%(MarioSheet%) ' test if the sprite sheet exists in the sprite sheet database                            |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    SHARED Sheetdb() AS TYPE_SHEETDB ' need access to sprite sheet database

    IF hSht < 0 OR hSht > UBOUND(Sheetdb) THEN ' handle out of array bounds?
        SHEET_Exists% = 0 '                      yes, sprite sheet does not exist (FALSE)
    ELSE '                                      no, within bounds
        SHEET_Exists% = Sheetdb(hSht).inUse '    return in use status (-1 TRUE or 0 FALSE)
    END IF

END FUNCTION
'---------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION SHEET_Load% (Filename AS STRING, GridWidth AS INTEGER, GridHeight AS INTEGER) '                                                SHEET_Load% |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Load a sprite sheet into the sprite sheet database.                                                                                          |
    '|                                                                                                                                              |
    '| Filename  - name of image file to load                                                                                                      |
    '| GridWidth  - width of each grid cell                                                                                                        |
    '| GridHeight - height of each grid cell                                                                                                        |
    '|                                                                                                                                              |
    '| Example: MarioSheet% = SHEET_Load%("MarioSheet.png", 64, 64) ' load sprite sheet with a 64 pixel by 64 pixel cell grid applied              |
    '|                                                                                                                                              |
    '| Note: The grid width and height can be modified later with the use of SHEET_GridSize. This will allow different sized sprites to be          |
    '|      contained within the same sprite sheet.                                                                                                |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST FUNCNAME = "SHEET_Load%" '  function name for error reporting
    SHARED Sheetdb() AS TYPE_SHEETDB ' need access to sprite sheet database
    DIM Index AS INTEGER '            index counter
    ' \\\\\
    IF GridWidth < 1 THEN SPRITE__Error FUNCNAME, "The grid width must be greater than zero"
    IF GridHeight < 1 THEN SPRITE__Error FUNCNAME, "The grid height must be greater than zero"
    IF _FILEEXISTS(Filename) = 0 THEN SPRITE__Error FUNCNAME, "The requested image file does not exist"
    ' /////
    Index = SHEET__NextIndex% '                                      get the next available index
    Sheetdb(Index).Image = _LOADIMAGE(Filename, 32) '                load the sprite sheet image
    ' \\\\\
    IF Sheetdb(Index).Image = -1 THEN SPRITE__Error FUNCNAME, "There was an error loading the sprite sheet image file"
    ' /////
    Sheetdb(Index).Width = _WIDTH(Sheetdb(Index).Image) '            record sprite sheet width
    Sheetdb(Index).Height = _HEIGHT(Sheetdb(Index).Image) '          record sprite sheet height
    ' \\\\\
    IF GridWidth > Sheetdb(Index).Width THEN SPRITE__Error FUNCNAME, "The grid width can't exceed the sprite sheet width"
    IF GridHeight > Sheetdb(Index).Height THEN SPRITE__Error FUNCNAME, "The grid height can't exceed the sprite sheet height"
    ' /////
    Sheetdb(Index).GridWidth = GridWidth '                          record grid cell width
    Sheetdb(Index).GridHeight = GridHeight '                        record grid cell height
    Sheetdb(Index).Columns = Sheetdb(Index).Width \ GridWidth '      record number of columns
    Sheetdb(Index).Rows = Sheetdb(Index).Height \ GridHeight '      record number of rows
    Sheetdb(Index).inUse = -1 '                                      record this index in use
    SHEET_Load% = Index '                                            return sheet handle

END FUNCTION
'---------------------------------------------------------------------------------------------------------------------------------------------------+
SUB SHEET_Delete (hSht AS INTEGER) '                                                                                                  SHEET_Delete |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Removes a sprite sheet from the sprite sheet database. The sprite sheet handle variable used to call this subroutine is set to -1.          |
    '|                                                                                                                                              |
    '| hSht - the sprite sheet handle                                                                                                              |
    '|                                                                                                                                              |
    '| Example: SHEET_Delete MarioSheet% ' delete the mario sprite sheet                                                                            |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST SUBNAME = "SHEET_Delete" '  subroutine name for error reporting
    SHARED Sheetdb() AS TYPE_SHEETDB ' need access to sprite sheet database
    ' \\\\\
    IF SHEET_Exists(hSht) = 0 THEN SPRITE__Error SUBNAME, "The requested sprite sheet does not exist"
    ' /////
    IF Sheetdb(hSht).Image < -1 THEN _FREEIMAGE Sheetdb(hSht).Image ' remove the sprite sheet image from RAM
    Sheetdb(hSht).inUse = 0 '                                        database index no longer in use (FALSE)
    hSht = -1 '                                                      set calling variable to -1

END SUB
'---------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION SHEET_ClearColor~& (hSht AS INTEGER) '                                                                                  SHEET_ClearColor~& |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Returns the transparent color of a sprite sheet.                                                                                            |
    '|                                                                                                                                              |
    '| hSht - sprite sheet handle                                                                                                                  |
    '|                                                                                                                                              |
    '| Example: TransparentColor~& = SHEET_ClearColor~&(MarioSheet%) ' get transparent color of sprite sheet                                        |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST FUNCNAME = "SHEET_ClearColor~&" ' function name for error reporting
    SHARED Sheetdb() AS TYPE_SHEETDB '      need access to sprite sheet database
    ' \\\\\
    IF SHEET_Exists(hSht) = 0 THEN SPRITE__Error FUNCNAME, "The requested sprite sheet does not exist"
    ' /////
    SHEET_ClearColor~& = _CLEARCOLOR(Sheetdb(hSht).Image) ' return sprite sheet transparent color

END FUNCTION
'---------------------------------------------------------------------------------------------------------------------------------------------------+
SUB SHEET_ClearColor (hSht AS INTEGER, cColor AS _UNSIGNED LONG) '                                                                SHEET_ClearColor |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Sets the transparent color of a sprite sheet'                                                                                                |
    '|                                                                                                                                              |
    '| hSht  - sprite sheet handle                                                                                                                |
    '| cColor - the color defined as transparent                                                                                                    |
    '|                                                                                                                                              |
    '| Example: SHEET_ClearColor MarioSheet%, _RGB32(255, 0, 255) ' set bright magenta as the transparent color                                    |
    '|                                                                                                                                              |
    '| Note: The sprite library will ultilize transparent colors contained within .PNG image files.                                                |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST SUBNAME = "SHEET_ClearColor" ' subroutine name for error reporting
    SHARED Sheetdb() AS TYPE_SHEETDB '  need access to sprite sheet database
    ' \\\\\
    IF SHEET_Exists(hSht) = 0 THEN SPRITE__Error SUBNAME, "The requested sprite sheet does not exist"
    ' /////
    _CLEARCOLOR cColor, Sheetdb(hSht).Image ' set sprite sheet transparent color

END SUB
'---------------------------------------------------------------------------------------------------------------------------------------------------+
SUB SHEET_GridSize (hSht AS INTEGER, GridWidth AS INTEGER, GridHeight AS INTEGER) '                                                  SHEET_GridSize |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Define the grid cell dimensions of a sprite sheet to allow for multiple sized images within a sprite sheet.                                  |
    '|                                                                                                                                              |
    '| hSht      - sprite sheet handle                                                                                                            |
    '| GridWidth  - width of each grid cell                                                                                                        |
    '| GridHeight - height of each grid cell                                                                                                        |
    '|                                                                                                                                              |
    '| Example: SHEET_GridSize MarioSheet%, 32, 32 ' define a 32x32 grid on the sprite sheet                                                        |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST SUBNAME = "SHEET_GridSize" ' subroutine name for error reporting
    SHARED Sheetdb() AS TYPE_SHEETDB ' need access to sprite sheet database
    ' \\\\\
    IF SHEET_Exists(hSht) = 0 THEN SPRITE__Error SUBNAME, "The requested sprite sheet does not exist"
    IF GridWidth < 1 THEN SPRITE__Error SUBNAME, "The grid width must be greater than zero"
    IF GridHeight < 1 THEN SPRITE__Error SUBNAME, "The grid height must be greater than zero"
    IF GridWidth > Sheetdb(hSht).GridWidth THEN SPRITE__Error SUBNAME, "The grid width can't exceed the sprite sheet width"
    IF GridHeight > Sheetdb(hSht).GridHeight THEN SPRITE__Error SUBNAME, "The grid height can't exceed the sprite sheet height"
    ' /////
    Sheetdb(hSht).GridWidth = GridWidth '  record grid cell width
    Sheetdb(hSht).GridHeight = GridHeight ' record grid cell height

END SUB
'---------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION SHEET_Width% (hSht AS INTEGER) '                                                                                              SHEET_Width% |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Returns the width of a sprite sheet.                                                                                                        |
    '|                                                                                                                                              |
    '| hSht - the sprite sheet handle                                                                                                              |
    '|                                                                                                                                              |
    '| Example: Swidth% = SHEET_Width%(MarioSheet%) ' get the width of the sprite sheet                                                            |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST FUNCNAME = "SHEET_Width%" '  function name for error reporting
    SHARED Sheetdb() AS TYPE_SHEETDB ' need access to sprite sheet database
    ' \\\\\
    IF SHEET_Exists(hSht) = 0 THEN SPRITE__Error FUNCNAME, "The requested sprite sheet does not exist"
    ' /////
    SHEET_Width% = Sheetdb(hSht).Width ' return width of sprite sheet

END FUNCTION
'---------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION SHEET_Height% (hSht AS INTEGER) '                                                                                            SHEET_Height% |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Returns the height of a sprite sheet.                                                                                                        |
    '|                                                                                                                                              |
    '| hSht - the sprite sheet handle                                                                                                              |
    '|                                                                                                                                              |
    '| Example: Sheight% = SHEET_Height%(MarioSheet%) ' get the height of the sprite sheet                                                          |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST FUNCNAME = "SHEET_Height%" ' function name for error reporting
    SHARED Sheetdb() AS TYPE_SHEETDB ' need access to sprite sheet database
    ' \\\\\
    IF SHEET_Exists(hSht) = 0 THEN SPRITE__Error FUNCNAME, "The requested sprite sheet does not exist"
    ' /////
    SHEET_Height% = Sheetdb(hSht).Height ' return height of sprite sheet

END FUNCTION
'+--------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION SHEET_GridWidth% (hSht AS INTEGER) '                                                                                      SHEET_GridWidth% |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Returns the width of the grid cells on a sprite sheet.                                                                                      |
    '|                                                                                                                                              |
    '| hSht - the sprite sheet handle                                                                                                              |
    '|                                                                                                                                              |
    '| Example: GridWidth% = SHEET_GridWidth%(MarioSheet%) ' get the width of the grid on sheet                                                    |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST FUNCNAME = "SHEET_GridWidth%" ' function name for error reporting
    SHARED Sheetdb() AS TYPE_SHEETDB '    need access to sprite sheet database
    ' \\\\\
    IF SHEET_Exists(hSht) = 0 THEN SPRITE__Error FUNCNAME, "The requested sprite sheet does not exist"
    ' /////
    SHEET_GridWidth% = Sheetdb(hSht).GridWidth ' return width of grid on sheet

END FUNCTION
'---------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION SHEET_GridHeight% (hSht AS INTEGER) '                                                                                    SHEET_GridHeight% |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Returns the height of the grid cells on a sprite sheet.                                                                                      |
    '|                                                                                                                                              |
    '| hSht - the sprite sheet handle                                                                                                              |
    '|                                                                                                                                              |
    '| Example: GridHeight% = SHEET_GridHeight%(MarioSheet%) ' get the height of the grid on the sheet                                              |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST FUNCNAME = "SHEET_GridHeight%" ' function name for error reporting
    SHARED Sheetdb() AS TYPE_SHEETDB '    need access to sprite sheet database
    ' \\\\\
    IF SHEET_Exists(hSht) = 0 THEN SPRITE__Error FUNCNAME, "The requested sprite sheet handle does not exist"
    ' /////
    SHEET_GridHeight% = Sheetdb(hSht).GridHeight ' return the height of grid on sheet

END FUNCTION

'  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
'  V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V
'  ==============================================================================================================================================
'  //                                                                                                                                            \\
' //                                                      STILL IMAGE SUBS AND FUNCTIONS                                                        \\
'//                                                                                                                                                \\
'====================================================================================================================================================
' ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
' | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |

'---------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION IMAGE__NextIndex% () '                                                                                                  IMAGE__NextIndex% |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| INTERNAL USE ONLY                                                                                                                            |
    '|                                                                                                                                              |
    '| Get the next available index in the still image database.                                                                                    |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    SHARED ImageDB() AS TYPE_IMAGEDB ' need access to still image database
    DIM Index AS INTEGER '            index counter

    Index = -1 '                                                    reset index counter
    DO '                                                            begin database search loop
        Index = Index + 1 '                                          increment index counter
    LOOP UNTIL ImageDB(Index).inUse = 0 OR Index = UBOUND(ImageDB) ' leave when free index found or end of database
    IF ImageDB(Index).inUse <> 0 THEN '                              was a free index found?
        Index = Index + 1 '                                          no, increment the index counter
        REDIM _PRESERVE ImageDB(Index) AS TYPE_IMAGEDB '            increase the size of the database
    END IF
    ImageDB(Index).inUse = -1 '                                      record index in use (TRUE)
    IMAGE__NextIndex% = Index '                                      return index value

END FUNCTION
'---------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION IMAGE_Exists% (hImg AS INTEGER) '                                                                                            IMAGE_Exists% |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Returns the existence of a still image 0 (SPRITE_FALSE) or -1 (SPRITE_TRUE)                                                                  |
    '|                                                                                                                                              |
    '| hImg - the still image handle                                                                                                                |
    '|                                                                                                                                              |
    '| Example: IsExisting% = IMAGE_Exists%(MarioStand%) ' test if the still image exists                                                          |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    SHARED ImageDB() AS TYPE_IMAGEDB ' need access to still image database

    IF hImg < 0 OR hImg > UBOUND(ImageDB) THEN ' handle out of array bounds?
        IMAGE_Exists% = 0 '                      yes, still image does not exist (FALSE)
    ELSE '                                      no, within bounds
        IMAGE_Exists% = ImageDB(hImg).inUse '    return in use status (-1 TRUE or 0 FALSE)
    END IF

END FUNCTION
'---------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION IMAGE_Make% (hSht AS INTEGER, Column AS INTEGER, Row AS INTEGER) '                                                            IMAGE_Make% |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Creates a still image from an individual sprite sheet image.                                                                                |
    '|                                                                                                                                              |
    '| hSht  - the sprite sheet handle                                                                                                            |
    '| Column - the sprite sheet column                                                                                                            |
    '| Row    - the sprite sheet row                                                                                                                |
    '|                                                                                                                                              |
    '| Example: MarioStanding% = IMAGE_Make%(MarioSheet%, 1, 1) ' get the mario standing still image                                                |
    '|                                                                                                                                              |
    '| Note: Column and Row are based on the current grid size setting of the sprite sheet.                                                        |
    '|      Use SHEET_GridSize to change the grid sizing to meet your needs.                                                                      |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST FUNCNAME = "IMAGE_Make%" '  function name for error reporting
    SHARED ImageDB() AS TYPE_IMAGEDB ' need access to still image database
    SHARED Sheetdb() AS TYPE_SHEETDB ' need access to sprite sheet database
    DIM Index AS INTEGER '            next available image database index
    DIM x1 AS INTEGER '                location of image on sprite sheet
    DIM y1 AS INTEGER '                (x1, y1) - (x2, y2)
    DIM x2 AS INTEGER
    DIM y2 AS INTEGER
    ' \\\\\
    IF SHEET_Exists(hSht) = 0 THEN SPRITE__Error FUNCNAME, "The requested sprite sheet does not exist"
    IF Column < 1 THEN SPRITE__Error FUNCNAME, "Column must be greater than 0"
    IF Row < 1 THEN SPRITE__Error FUNCNAME, "Row must be greater than 0"
    IF Column > Sheetdb(hSht).Columns THEN SPRITE__Error FUNCNAME, "Column exceeds the number of columns on the sprite sheet"
    IF Row > Sheetdb(hSht).Rows THEN SPRITE__Error FUNCNAME, "Row exceeds the number of rows on the sprite sheet"
    ' /////
    Index = IMAGE__NextIndex% '                                                                  get next available index
    ImageDB(Index).Original = _NEWIMAGE(Sheetdb(hSht).GridWidth, Sheetdb(hSht).GridHeight, 32) ' create image canvas
    x1 = Sheetdb(hSht).GridWidth * (Column - 1) '                                                calculate image location on sheet
    y1 = Sheetdb(hSht).GridHeight * (Row - 1)
    x2 = x1 + Sheetdb(hSht).GridWidth - 1
    y2 = y1 + Sheetdb(hSht).GridHeight - 1
    _PUTIMAGE , Sheetdb(hSht).Image, ImageDB(Index).Original, (x1, y1)-(x2, y2) '                clip image from sprite sheet
    ImageDB(Index).Image = _COPYIMAGE(ImageDB(Index).Original) '                                copy the working image
    IMAGE_Make% = Index '                                                                        return still image handle

END FUNCTION
'---------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION IMAGE_Load% (FileName AS STRING) '                                                                                            IMAGE_Load% |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Creates a still image from an image file.                                                                                                    |
    '|                                                                                                                                              |
    '| FileName - the image file name                                                                                                              |
    '|                                                                                                                                              |
    '| Example: MarioStanding% = IMAGE_Load%("MarioStanding.PNG") ' load the mario standing still image                                            |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST FUNCNAME = "IMAGE_Load%" '  function name for error reporting
    SHARED ImageDB() AS TYPE_IMAGEDB ' need access to still image database
    DIM Index AS INTEGER '            next available image database index
    ' \\\\\
    IF _FILEEXISTS(FileName) = 0 THEN SPRITE__Error FUNCNAME, "The requested image file does not exist"
    ' /////
    Index = IMAGE__NextIndex% '                                  get next available index
    ImageDB(Index).Original = _LOADIMAGE(FileName, 32) '        load the image file
    ' \\\\\
    IF ImageDB(Index).Original = -1 THEN SPRITE__Error FUNCNAME, "There was an error loading the image file"
    ' /////
    ImageDB(Index).Image = _COPYIMAGE(ImageDB(Index).Original) ' copy the working image
    IMAGE_Load% = Index '                                        return still image handle

END FUNCTION
'---------------------------------------------------------------------------------------------------------------------------------------------------+
SUB IMAGE_Delete (hImg AS INTEGER) '                                                                                                  IMAGE_Delete |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Removes a still image from the still image database and RAM.                                                                                |
    '|                                                                                                                                              |
    '| hImg - the still image handle                                                                                                                |
    '|                                                                                                                                              |
    '| Example: IMAGE_Delete MarioStanding% ' remove the mario standing still image                                                                |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+

    CONST SUBNAME = "IMAGE_Load%" '    subroutine name for error reporting
    SHARED ImageDB() AS TYPE_IMAGEDB ' need access to still image database
    ' \\\\\
    IF IMAGE_Exists(hImg) = 0 THEN SPRITE__Error SUBNAME, "The requested still image does not exist"
    ' /////
    IF ImageDB(hImg).Original < -1 THEN _FREEIMAGE ImageDB(hImg).Original ' remove the original still image from RAM
    IF ImageDB(hImg).Image < -1 THEN _FREEIMAGE ImageDB(hImg).Image '      remove the working still image from RAM
    ImageDB(hImg).inUse = 0 '                                              record database index not in use (FALSE)
    hImg = -1 '                                                            set calling handle to -1

END SUB




'---------------------------------------------------------------------------------------------------------------------------------------------------+
SUB IMAGE_Apply (hImg AS INTEGER, hSpr AS INTEGER) '                                                                                    IMAGE_Apply |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Applies a still image to a sprite.                                                                                                          |
    '|                                                                                                                                              |
    '| hImg - the still image handle                                                                                                                |
    '| hSpr - the sprite handle                                                                                                                    |
    '|                                                                                                                                              |
    '| Example: IMAGE_Apply MarioCrouching%, Mario% ' change mario still image to crouching                                                        |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST SUBNAME = "IMAGE_Apply" '      subroutine name for error reporting
    SHARED ImageDB() AS TYPE_IMAGEDB '  need access to still image database
    SHARED SpriteDB() AS TYPE_SPRITEDB ' need access to sprite database
    ' \\\\\
    IF IMAGE_Exists(hImg) = 0 THEN SPRITE__Error SUBNAME, "The requested still image does not exist"
    IF SPRITE_Exists(hSpr) = 0 THEN SPRITE__Error SUBNAME, "The requested sprite does not exist"
    ' /////
    SpriteDB(hSpr).Still = ImageDB(hImg).Image ' apply the working still image to the sprite

END SUB





'---------------------------------------------------------------------------------------------------------------------------------------------------+
SUB IMAGE_ClearColor (hImg AS INTEGER, cColor AS _UNSIGNED LONG) '                                                                IMAGE_ClearColor |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Sets the transparent color of a still image.                                                                                                |
    '|                                                                                                                                              |
    '| hImg  - the still image handle                                                                                                              |
    '| cColor - the color defined as transparent                                                                                                    |
    '|                                                                                                                                              |
    '| Example: IMAGE_ClearColor MarioStanding%, _RGB32(255, 0, 255) ' set bright magenta as the transparent color                                  |
    '|                                                                                                                                              |
    '| Note: The sprite library will ultilize transparent colors contained within .PNG image files.                                                |
    '|      The transparent color will get applied to both the original and working still images.                                                  |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST SUBNAME = "IMAGE_ClearColor" ' subroutine name for error reporting
    SHARED ImageDB() AS TYPE_IMAGEDB '  need access to still image database
    ' \\\\\
    IF IMAGE_Exists(hImg) = 0 THEN SPRITE__Error SUBNAME, "The requested still image does not exist"
    ' /////
    _CLEARCOLOR cColor, ImageDB(hImg).Original ' set original image transparent color
    _CLEARCOLOR cColor, ImageDB(hImg).Image '    set working still image transparent color

END SUB
'---------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION IMAGE_ClearColor~& (hImg AS INTEGER) '                                                                                  IMAGE_ClearColor~& |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Returns the transparent color of a still image.                                                                                              |
    '|                                                                                                                                              |
    '| hImg - the still image handle                                                                                                                |
    '|                                                                                                                                              |
    '| Example: TransparentColor~& = IMAGE_ClearColor~&(MarioStanding%) ' get transparent color of still image                                      |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST FUNCNAME = "IMAGE_ClearColor~&" ' function name for error reporting
    SHARED ImageDB() AS TYPE_IMAGEDB '      need access to still image database
    ' \\\\\
    IF IMAGE_Exists(hImg) = 0 THEN SPRITE__Error FUNCNAME, "The requested still image does not exist"
    ' /////
    IMAGE_ClearColor~& = _CLEARCOLOR(ImageDB(hImg).Original) ' return original still image transparent color

END FUNCTION
'---------------------------------------------------------------------------------------------------------------------------------------------------+
SUB IMAGE_Restore (hImg AS INTEGER) '                                                                                                IMAGE_Restore |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Restores the working still image to the original image.                                                                                      |
    '|                                                                                                                                              |
    '| hImg - the still image handle                                                                                                                |
    '|                                                                                                                                              |
    '| Example: IMAGE_Restore MarioStanding% ' restore the standing image                                                                          |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+

    CONST SUBNAME = "IMAGE_Restore" '  subroutine name for error reporting
    SHARED ImageDB() AS TYPE_IMAGEDB ' need access to still image database
    ' \\\\\
    IF IMAGE_Exists(hImg) = 0 THEN SPRITE__Error SUBNAME, "The requested still image does not exist"
    ' /////
    IF ImageDB(hImg).Image < -1 THEN _FREEIMAGE ImageDB(hImg).Image ' remove the working still image from RAM
    ImageDB(hImg).Image = _COPYIMAGE(ImageDB(hImg).Original) '        copy the original still image to the working still image

END SUB
'---------------------------------------------------------------------------------------------------------------------------------------------------+
SUB IMAGE_Flip (hImg AS INTEGER, Flip AS INTEGER) '                                                                                      IMAGE_Flip |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Flips the working still image.                                                                                                              |
    '|                                                                                                                                              |
    '| hImg - the still image handle                                                                                                                |
    '| Flip - the flip direction                                                                                                                    |
    '|                                                                                                                                              |
    '| Example: IMAGE_Flip MarioStanding%, 1 ' flip the standing image horizontally                                                                |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST SUBNAME = "IMAGE_Flip" '    subroutine name for error reporting
    SHARED ImageDB() AS TYPE_IMAGEDB ' need access to still image database
    ' \\\\\
    IF IMAGE_Exists(hImg) = 0 THEN SPRITE__Error SUBNAME, "The requested still image does not exist"
    IF Flip < 0 OR Flip > 3 THEN SPRITE__Error SUBNAME, "Flip must be 0 (FLIP_NONE), 1 (FLIP_HORIZONTAL), 2 (FLIP_VERTICAL), or 3 (FLIP_BOTH)"
    ' /////
    IMG_Flip ImageDB(hImg).Image, Flip ' flip the working still image

END SUB
'---------------------------------------------------------------------------------------------------------------------------------------------------+
SUB IMAGE_Zoom (hImg AS INTEGER, Zoom AS SINGLE) '                                                                                      IMAGE_Zoom |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Zooms the working still image.                                                                                                              |
    '|                                                                                                                                              |
    '| hImg - the still image handle                                                                                                                |
    '| Zoom - the zoom amount                                                                                                                      |
    '|                                                                                                                                              |
    '| Example: IMAGE_Zoom MarioStanding%, 1.5 ' zoom the standing image 150%                                                                      |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST SUBNAME = "IMAGE_Zoom" '    subroutine name for error reporting
    SHARED ImageDB() AS TYPE_IMAGEDB ' need access to still image database
    ' \\\\\
    IF IMAGE_Exists(hImg) = 0 THEN SPRITE__Error SUBNAME, "The requested still image does not exist"
    IF Zoom <= 0 THEN SPRITE__Error SUBNAME, "Zoom level must be greater than zero"
    ' /////
    IF Zoom <> 1 THEN IMG_Zoom ImageDB(hImg).Image, Zoom ' zoom the working still image if not 100%

END SUB
'---------------------------------------------------------------------------------------------------------------------------------------------------+
SUB IMAGE_Rotate (hImg AS INTEGER, Degree AS SINGLE) '                                                                                IMAGE_Rotate |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Rotates the working still image to the degree specified.                                                                                    |
    '|                                                                                                                                              |
    '| hImg  - the still image handle                                                                                                              |
    '| Degree - the degree of rotation                                                                                                              |
    '|                                                                                                                                              |
    '| Example: IMAGE_Rotate MarioStanding%, 45 ' rotate the standing image to 45 degrees                                                          |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST SUBNAME = "IMAGE_Rotate" '  subroutine name for error reporting
    SHARED ImageDB() AS TYPE_IMAGEDB ' need access to still image database
    ' \\\\\
    IF IMAGE_Exists(hImg) = 0 THEN SPRITE__Error SUBNAME, "The requested still image does not exist"
    ' /////
    IMG_INTRotate ImageDB(hImg).Image, Degree ' rotate the working still image

END SUB
'---------------------------------------------------------------------------------------------------------------------------------------------------+
SUB IMAGE_Put (hImg AS INTEGER, x AS INTEGER, y AS INTEGER) '                                                                            IMAGE_Put |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Draws the working still image to the screen at coordinates x,y.                                                                              |
    '|                                                                                                                                              |
    '| hImg - the still image handle                                                                                                                |
    '| x    - the screen x coordinate                                                                                                              |
    '| y    - the screen y coordinate                                                                                                              |
    '|                                                                                                                                              |
    '| Example: IMAGE_Put Statue%, 100, 150 ' draw an image of the statue to the screen                                                            |
    '|                                                                                                                                              |
    '| Note: The image is drawn to the current destination surface which may not be the screen.                                                    |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST SUBNAME = "IMAGE_Put" '      subroutine name for error reporting
    SHARED ImageDB() AS TYPE_IMAGEDB ' need access to still image database
    ' \\\\\
    IF IMAGE_Exists(hImg) = 0 THEN SPRITE__Error SUBNAME, "The requested still image does not exist"
    ' /////
    _PUTIMAGE (x, y), ImageDB(hImg).Image ' draw image onto current destination surface

END SUB
'---------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION IMAGE_Width% (hImg AS INTEGER) '                                                                                              IMAGE_Width% |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Return the width of the working still image.                                                                                                |
    '|                                                                                                                                              |
    '| hImg - the still image handle                                                                                                                |
    '|                                                                                                                                              |
    '| Example: iw% = IMAGE_Width%(MarioStanding%) ' return the still image width                                                                  |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST FUNCNAME = "IMAGE_Width%" '  function name for error reporting
    SHARED ImageDB() AS TYPE_IMAGEDB ' need access to still image database
    ' \\\\\
    IF IMAGE_Exists(hImg) = 0 THEN SPRITE__Error FUNCNAME, "The requested still image does not exist"
    ' /////
    IMAGE_Width% = _WIDTH(ImageDB(hImg).Image) ' return width of working still image

END FUNCTION
'---------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION IMAGE_Height% (hImg AS INTEGER) '                                                                                            IMAGE_Height% |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Return the height of the working still image.                                                                                                |
    '|                                                                                                                                              |
    '| hImg - the still image handle                                                                                                                |
    '|                                                                                                                                              |
    '| Example ih% = IMAGE_Height%(MarioStanding%) ' return the still image height                                                                  |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST FUNCNAME = "IMAGE_Height%" ' function name for error reporting
    SHARED ImageDB() AS TYPE_IMAGEDB ' need access to still image database
    ' \\\\\
    IF IMAGE_Exists(hImg) = 0 THEN SPRITE__Error FUNCNAME, "The requested still image does not exist"
    ' /////
    IMAGE_Height% = _HEIGHT(ImageDB(hImg).Image) ' return height of working still image

END FUNCTION

'  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
'  V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V
'  ==============================================================================================================================================
'  //                                                                                                                                            \\
' //                                                        ANIMATION SUBS AND FUNCTIONS                                                          \\
'//                                                                                                                                                \\
'====================================================================================================================================================
' ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
' | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |


'---------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION CLIP__NextIndex% () '                                                                                                    CLIP__NextIndex% |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| INTERNAL USE ONLY                                                                                                                            |
    '|                                                                                                                                              |
    '| Get the next available index in the animation clip database.                                                                                |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    SHARED ClipDB() AS TYPE_ANIMATIONCLIPDB ' need access to animation clip database
    DIM Index AS INTEGER '                    index counter

    Index = -1 '                                                  reset index counter
    DO '                                                          begin database search loop
        Index = Index + 1 '                                        increment index counter
    LOOP UNTIL ClipDB(Index).inUse = 0 OR Index = UBOUND(ClipDB) ' leave when free index found or end of database
    IF ClipDB(Index).inUse <> 0 THEN '                            was a free index found?
        Index = Index + 1 '                                        no, increment the index counter
        REDIM _PRESERVE ClipDB(Index) AS TYPE_ANIMATIONCLIPDB '    increase the size of the database
    END IF
    ClipDB(Index).inUse = -1 '                                    record index in use (TRUE)
    CLIP__NextIndex% = Index '                                    return index value

END FUNCTION
'---------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION CLIP_Exists% (hClp AS INTEGER) '                                                                                              CLIP_Exists% |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Returns the existence of an animation clip 0 (SPRITE_FALSE) or -1 (SPRITE_TRUE)                                                              |
    '|                                                                                                                                              |
    '| hClp - the animation clip handle                                                                                                            |
    '|                                                                                                                                              |
    '| Example: IsExisting% = CLIP_Exists%(MarioRunning%) ' test if the animation clip exists                                                      |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    SHARED ClipDB() AS TYPE_ANIMATIONCLIPDB ' need access to animation clip database

    IF hClp < 0 OR hClp > UBOUND(ClipDB) THEN ' handle out of array bounds?
        CLIP_Exists% = 0 '                      yes, animation clip does not exist (FALSE)
    ELSE '                                      no, within bounds
        CLIP_Exists% = ClipDB(hClp).inUse '    return in use status (-1 TRUE or 0 FALSE)
    END IF

END FUNCTION
'---------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION CLIP_Make% (hSht AS INTEGER, c AS INTEGER, r AS INTEGER, Cells AS INTEGER, Dir AS INTEGER, Mode AS INTEGER, FPS AS INTEGER) '  CLIP_Make% |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Creates an animation clip from image cells on a sprite sheet.                                                                                |
    '|                                                                                                                                              |
    '| hSht  - the sprite sheet handle                                                                                                              |
    '| c    - the sprite sheet column                                                                                                              |
    '| r    - the sprite sheet row                                                                                                                |
    '| Cells - the number of cells contained in the film strip                                                                                      |
    '| Dir  - the animation play direction 1 (CLIP_FORWARD) or -1 (CLIP_BACKWARD)                                                                  |
    '| Mode  - the animation play mode -1 (CLIP_LOOP) or 0 (CLIP_PLAYONCE)                                                                          |
    '| FPS  - the animation frames per second                                                                                                      |
    '|                                                                                                                                              |
    '| Example: MarioWalking% = CLIP_Make%(MarioSheet%, 2, 1, 2, 1, 0, 10) ' create the mario walking animaton sequence                            |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST FUNCNAME = "CLIP_Make%" '          function name for error reporting
    SHARED Sheetdb() AS TYPE_SHEETDB '        need access to sprite sheet database
    SHARED ClipDB() AS TYPE_ANIMATIONCLIPDB ' need access to animation clip database
    DIM Index AS INTEGER '                    next available animation clip database index
    DIM x1 AS INTEGER '                      location of animation clip on sprite sheet
    DIM y1 AS INTEGER '                      (x1, y1) - (x2, y2)
    DIM x2 AS INTEGER
    DIM y2 AS INTEGER
    ' \\\\\
    IF SHEET_Exists(hSht) = 0 THEN SPRITE__Error FUNCNAME, "The requested sprite sheet does not exist"
    IF c < 1 THEN SPRITE__Error FUNCNAME, "Column must be greater than 0"
    IF r < 1 THEN SPRITE__Error FUNCNAME, "Row must be greater than 0"
    IF c > Sheetdb(hSht).Columns THEN SPRITE__Error FUNCNAME, "Column exceeds the number of columns on the sprite sheet"
    IF r > Sheetdb(hSht).Rows THEN SPRITE__Error FUNCNAME, "Row exceeds the number of rows on the sprite sheet"
    IF Cells < 2 THEN SPRITE__Error FUNCNAME, "An animation clip must contain at least two cells"
    IF ABS(Dir) <> 1 THEN SPRITE__Error FUNCNAME, "The direction must be 1 (CLIP_FORWARD) or -1 (CLIP_BACKWARD)"
    IF Mode < 0 OR Mode > 1 THEN SPRITE__Error FUNCNAME, "Mode must either be -1 (CLIP_LOOP) or 0 (CLIP_PLAYONCE)"
    IF FPS < 1 THEN SPRITE__Error FUNCNAME, "FPS must be greater than zero"
    ' /////
    Index = CLIP__NextIndex% '                                                                      get next available index in database
    ClipDB(Index).Cells = Cells '                                                                    record number of film strip cells
    ClipDB(Index).Width = Sheetdb(hSht).GridWidth '                                                  record each cell width
    ClipDB(Index).Height = Sheetdb(hSht).GridHeight '                                                record each cell height
    ClipDB(Index).Direction = Dir '                                                                  record animation direction
    ClipDB(Index).Mode = Mode '                                                                      record animation play mode
    ClipDB(Index).FPS = FPS '                                                                        record animation frames per second
    x1 = Sheetdb(hSht).GridWidth * (c - 1) '                                                        calculate animation clip location on sheet
    y1 = Sheetdb(hSht).GridHeight * (r - 1)
    x2 = x1 + Sheetdb(hSht).GridWidth * Cells - 1
    y2 = y1 + Sheetdb(hSht).GridHeight - 1
    ClipDB(Index).Strip = _NEWIMAGE(Sheetdb(hSht).GridWidth * Cells, Sheetdb(hSht).GridHeight, 32) ' create film strip image
    _PUTIMAGE , Sheetdb(hSht).Image, ClipDB(Index).Strip, (x1, y1)-(x2, y2) '                        clip animation clip from sprite sheet
    CLIP_Make% = Index '                                                                            return animation clip handle

END FUNCTION
'---------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION CLIP_Load% (FileName AS STRING, cw AS INTEGER, Dir AS INTEGER, Mode AS INTEGER, FPS AS INTEGER) '                              CLIP_Load% |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Creates an animation clip from an image file.                                                                                                |
    '|                                                                                                                                              |
    '| FileName - the name of the image file                                                                                                        |
    '| cw      - the width of each animation strip cell                                                                                            |
    '| Dir      - the animation play direction 1 (CLIP_FORWARD) or -1 (CLIP_BACKWARD)                                                              |
    '| Mode    - the animation play mode -1 (CLIP_LOOP) or 0 (CLIP_PLAYONCE)                                                                      |
    '| FPS      - the animation frames per second                                                                                                  |
    '|                                                                                                                                              |
    '| Example: MarioWalking% = CLIP_Load%("MarioWalking.PNG", 64, 1, 0, 10) ' load the Mario walking animation sequence                            |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST FUNCNAME = "CLIP_Load%" '          function name for error reporting
    SHARED ClipDB() AS TYPE_ANIMATIONCLIPDB ' need access to animation clip database
    DIM Index AS INTEGER '                    next available animation clip database index
    ' \\\\\
    IF _FILEEXISTS(FileName) = 0 THEN SPRITE__Error FUNCNAME, "The requested animation clip image file does not exist"
    ' /////
    Index = CLIP__NextIndex% '                                get next available index in database
    ClipDB(Index).Strip = _LOADIMAGE(FileName, 32) '          load film strip image
    ' \\\\\
    IF ClipDB(Index).Strip = -1 THEN SPRITE__Error FUNCNAME, "There was an error loading the animation clip image file"
    IF _WIDTH(ClipDB(Index).Strip) / cw <> INT(_WIDTH(ClipDB(Index).Strip) / cw) THEN
        SPRITE__Error FUNCNAME, "The animation clip image is not evenly divisible by the cell width provided"
    END IF
    ' /////
    ClipDB(Index).Cells = _WIDTH(ClipDB(Index).Strip) \ cw '  calculate number of film strip cells
    ClipDB(Index).Width = cw '                                record each cell width
    ClipDB(Index).Height = _HEIGHT(ClipDB(Index).Strip) '    record each cell height
    ClipDB(Index).Direction = Dir '                          record animation direction
    ClipDB(Index).Mode = Mode '                              record animation play mode
    ClipDB(Index).FPS = FPS '                                record animation frames per second
    CLIP_Load% = Index '                                      return animation clip handle

END FUNCTION
'---------------------------------------------------------------------------------------------------------------------------------------------------+
SUB CLIP_Delete (hClp AS INTEGER) '                                                                                                    CLIP_Delete |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Deletes an animation clip.                                                                                                                  |
    '|                                                                                                                                              |
    '| hClp - the animation clip handle                                                                                                            |
    '|                                                                                                                                              |
    '| Example: CLIP_Delete SmallExplosion% ' remove the animation clip                                                                            |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST SUBNAME = "CLIP_Delete" '          subroutine name for error reporting
    SHARED ClipDB() AS TYPE_ANIMATIONCLIPDB ' need access to animation clip database
    ' \\\\\
    IF CLIP_Exists(hClp) = 0 THEN SPRITE__Error SUBNAME, "The requested animation clip does not exist"
    ' /////
    IF ClipDB(hClp).Strip < -1 THEN _FREEIMAGE ClipDB(hClp).Strip ' remove animation film strip from RAM
    ClipDB(hClp).inUse = 0 '                                        database index not used (FALSE)

END SUB
'---------------------------------------------------------------------------------------------------------------------------------------------------+
SUB CLIP_ClearColor (hClp AS INTEGER, cColor AS _UNSIGNED LONG) '                                                                  CLIP_ClearColor |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Sets the transparent color of an animation clip.                                                                                            |
    '|                                                                                                                                              |
    '| hClp  - the animation clip handle                                                                                                          |
    '| cColor - the color defined as transparent                                                                                                    |
    '|                                                                                                                                              |
    '| Example: CLIP_ClearColor MarioRunning%, _RGB32(255, 0, 255) ' set bright magenta as the transparent color                                    |
    '|                                                                                                                                              |
    '| Note: The sprite library will ultilize transparent colors contained within .PNG image files.                                                |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST SUBNAME = "CLIP_ClearColor" '      subroutine name for error reporting
    SHARED ClipDB() AS TYPE_ANIMATIONCLIPDB ' need access to animation clip database
    ' \\\\\
    IF CLIP_Exists(hClp) = 0 THEN SPRITE__Error SUBNAME, "The requested animation clip does not exist"
    ' /////
    _CLEARCOLOR cColor, ClipDB(hClp).Strip ' set film strip image transparent color

END SUB
'---------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION CLIP_ClearColor~& (hClp AS INTEGER) '                                                                                    CLIP_ClearColor~& |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Returns the transparent color of an animation clip.                                                                                          |
    '|                                                                                                                                              |
    '| hClp - the animation clip handle                                                                                                            |
    '|                                                                                                                                              |
    '| Example: TransparentColor~& = CLIP_ClearColor~&(MarioRunning%) ' get transparent color of animation clip                                    |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST FUNCNAME = "CLIP_ClearColor~&" '    function name for error reporting
    SHARED ClipDB() AS TYPE_ANIMATIONCLIPDB ' need access to animation clip database
    ' \\\\\
    IF CLIP_Exists(hClp) = 0 THEN SPRITE__Error FUNCNAME, "The requested animation clip does not exist"
    ' /////
    CLIP_ClearColor~& = _CLEARCOLOR(ClipDB(hClp).Strip) ' return film strip image transparent color

END FUNCTION
'---------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION CLIP_CellWidth% (hClp AS INTEGER) '                                                                                        CLIP_CellWidth% |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Return the width of each cell within an animation clip.                                                                                      |
    '|                                                                                                                                              |
    '| hClp - the animation clip handle                                                                                                            |
    '|                                                                                                                                              |
    '| Example: cw% = CLIP_CellWidth%(MarioRunning%) ' get the cell width of the animation clip                                                    |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST FUNCNAME = "CLIP_CellWidth%" '      function name for error reporting
    SHARED ClipDB() AS TYPE_ANIMATIONCLIPDB ' need access to animation clip database
    ' \\\\\
    IF CLIP_Exists(hClp) = 0 THEN SPRITE__Error FUNCNAME, "The requested animation clip does not exist"
    ' /////
    CLIP_CellWidth% = ClipDB(hClp).Width ' return cell width

END FUNCTION
'---------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION CLIP_CellHeight% (hClp AS INTEGER) '                                                                                      CLIP_CellHeight% |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Return the height of each cell within an animation clip.                                                                                    |
    '|                                                                                                                                              |
    '| hClp - the animation clip handle                                                                                                            |
    '|                                                                                                                                              |
    '| Example: ch% = CLIP_CellHeight%(MarioRunning%) ' get the cell height of the animation clip                                                  |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    CONST FUNCNAME = "CLIP_CellHeight%" '    function name for error reporting
    SHARED ClipDB() AS TYPE_ANIMATIONCLIPDB ' need access to animation clip database
    ' \\\\\
    IF CLIP_Exists(hClp) = 0 THEN SPRITE__Error FUNCNAME, "The requested animation clip does not exist"
    ' /////
    CLIP_CellHeight% = ClipDB(hClp).Height ' return cell height

END FUNCTION

























'---------------------------------------------------------------------------------------------------------------------------------------------------+
FUNCTION SPRITE_Exists% (hSpr AS INTEGER) '                                                                                          SPRITE_Exists% |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    '| Returns the existence of a sprite 0 (SPRITE_FALSE) or -1 (SPRITE_TRUE)                                                                      |
    '|                                                                                                                                              |
    '| hSpr - the sprite handle                                                                                                                    |
    '|                                                                                                                                              |
    '| Example: IsExisting% = SPRITE_Exists%(Mario%) ' test if the sprite exists in the sprite database                                            |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    SHARED SpriteDB() AS TYPE_SPRITEDB ' need access to sprite database

    IF hSpr < 0 OR hSpr > UBOUND(SpriteDB) THEN ' handle out of array bounds?
        SPRITE_Exists% = 0 '                      yes, still image does not exist (FALSE)
    ELSE '                                        no, within bounds
        SPRITE_Exists% = SpriteDB(hSpr).inUse '  return in use status (-1 TRUE or 0 FALSE)
    END IF

END FUNCTION




'-----------------------------------------------------------------------------------------------------------------------------------+---------------+
SUB SPRITE__Error (SubFunc AS STRING, Report AS STRING) '                                                                          | SPRITE__Error |
    '+------------------------------------------------------------------------------------------------------------------------------+---------------+
    '| INTERNAL USE ONLY                                                                                                                            |
    '|                                                                                                                                              |
    '| Reports errors found to programmer.                                                                                                          |
    '+----------------------------------------------------------------------------------------------------------------------------------------------+
    SCREEN 0, 0, 0, 0 '                                              pure text (Pete) screen
    SOUND 440, 1: SOUND 880, 1 '                                    play alert sound
    PRINT
    PRINT " ERROR reported by: "; SubFunc '                          report subroutine or function error occurred in
    PRINT
    PRINT " "; Report '                                              report the error that occurred
    PRINT
    PRINT " Press ESC to close this window and return to the IDE." ' display directions
    DO '                                                            begin wait loop
        _LIMIT 10 '                                                  10 FPS (don't hog CPU)
    LOOP UNTIL _KEYDOWN(27) '                                        leave when ESC key pressed
    SYSTEM '                                                        return to operating system (IDE)

END SUB





'$INCLUDE:'.\lib\image\lib_img_flip.bm'            IMG_Flip subroutine
'$INCLUDE:'.\lib\image\lib_img_zoom.bm'            IMG_Zoom subroutine
'$INCLUDE:'.\lib\image\lib_img_introtate.bm'        IMG_INTRotate subroutine
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Reply
#4
Good point IF:

you want make transparent programs that anyone can understand

BUT

I have my own coding style which is good for me
and i don't have time to "explain everything "


IN general there are no rules
Reply
#5
(07-26-2024, 09:11 AM)aurel Wrote: Good point IF:

you want make transparent programs that anyone can understand

BUT

I have my own coding style which is good for me
and i don't have time to "explain everything "


IN general there are no rules

And that is totally fine until you need help to troubleshoot some code that is not working.

It isn't about rules.  It is about describing a program just enough so that others can understand it in order to help troubleshoot problems, so hopefully it doesn't require explaining everything.

In a way, this reminds me of the saying "make time for health, or be prepared to make time for sickness."  A little bit of time up front in order to avoid a preventable larger amount of time later.
Reply
#6
Yeah self documenting code is really good but sometimes you just want to see something work and maybe not so helpful to self and others with comnments and descriptive names... one really has no idea how another or yourself will see the code now or in future.

But This Is a Forum! where you can ask anything publically or private PM.

Pretty sure most of us here would be happy to clear up some code for you. Who doesn't like talking about their code creations? Smile
b = b + ...
Reply
#7
About comments, a while back, someone, could have been on that other forum, gave the tip that, should you have multiple lines of code and you are heading out on vacation or even done for the night, a simple comment like "Here's Where I Left OFF" is easy to search for when you get back at it. I use this tip a lot but have it down to just "***..."
Reply
#8
(07-26-2024, 07:10 PM)Dimster Wrote: About comments, a while back, someone, could have been on that other forum, gave the tip that, should you have multiple lines of code and you are heading out on vacation or even done for the night, a simple comment like "Here's Where I Left OFF" is easy to search for when you get back at it. I use this tip a lot but have it down to just "***..."
Not me. My mind is like a steel trap. Once it slams shut, nothing gets in!

Pete Big Grin
Reply
#9
@ diimster Yes, I do a similar thing while developing a programme. I get it "sort of" working, then go through it from the top, stopping it after each section and ensuring that the section works, and insert a line ' ***** ok to here *** and move to the next section. Works for me.
Of all the places on Earth, and all the planets in the Universe, I'd rather live here (Perth, W.A.) Big Grin
Please visit my Website at: http://oldendayskids.blogspot.com/
Reply
#10
Funny, since a long time I include '@@someRemark everywhere in my code that still needs attention.
It's finished when Alt-S-F @@ doesn't find anything anymore
45y and 2M lines of MBASIC>BASICA>QBASIC>QBX>QB64 experience
Reply




Users browsing this thread: 1 Guest(s)