Controller Library
#7
I created a small simulated game that allows the player to reconfigure buttons as a demo to show others how this can be done. The program source code below along with the assets (sounds, graphics, and library files) are now included with the library. I updated the first post with a new ZIP file that you can download.

Also, the library is now at version 1.01. I found some bone head logic mistakes I made and corrected them.

Code: (Select All)
'------------------------------
' Controller Library Demo
' "Reconfiguring Buttons"
'
' Terry Ritchie
' April 26th, 2023
'------------------------------
' Default Keys:
'
'   W      - UP    (Mario JUMP)
'   S      - DOWN  (Mario CROUCH)
'   A      - Mario LEFT
'   D      - Mario RIGHT
'   C      - Mario CROUCH
'   SPACE  - Mario JUMP
'   RCTRL  - Mario FIRE
'   RSHIFT - Mario RUN
'
' Hitting mystery box on bottom
' releases coins.
'
'------------------------------

'$INCLUDE:'CONTROLLER.BI'

OPTION _EXPLICIT '                all variables must be explicitly defined

CONST STAND = 1 '                 action sprites - Standing
CONST CROUCH = 2 '                crouching
CONST RUNSTART = 3 '              get ready to run
CONST WALK = 4 '                  walking/running (6 animation images)
CONST JUMP = 5 '                  jumping
CONST FIRE = 6 '                  bullet sprites (4 animation images)
CONST COIN = 7 '                  coin sprite

TYPE TYPE_RECTANGLE '             RECTANGLE PROPERTIES
    x1 AS INTEGER '               upper left x
    y1 AS INTEGER '               upper left y
    x2 AS INTEGER '               lower right x
    y2 AS INTEGER '               lower right y
END TYPE

TYPE TYPE_BUTTON '                DEFINED BUTTON PROPERTIES
    UP AS INTEGER '               UP button(s)
    DOWN AS INTEGER '             DOWN button(s)
    RIGHT AS INTEGER '            RIGHT button(s)
    LEFT AS INTEGER '             LEFT buttons(s)
    FIRE AS INTEGER '             FIRE button(s)
    RUN AS INTEGER '              RUN button(s)
    JUMP AS INTEGER '             JUMP button(s)
    CROUCH AS INTEGER '           CROUCH button(s)
    F1 AS INTEGER '               F1 button (key - enter config mode)
    F2 AS INTEGER '               F2 button (key - reset button defaults)
    F3 AS INTEGER '               F3 button (key - leave config mode)
END TYPE

TYPE TYPE_MARIO '                 MARIO PROPERTIES
    x AS SINGLE '                 x location (center bottom)
    y AS SINGLE '                 y location (center bottom)
    Frame AS INTEGER '            animation frame
    Action AS INTEGER '           STAND, CROUCH, RUNSTART, WALK, JUMP
    Rect AS TYPE_RECTANGLE '      sprite image location
    FPS AS INTEGER '              mario animation update speed
    Direction AS INTEGER '        direction mario is traveling
    Speed AS INTEGER '            speed of mario (walking or running)
    Facing AS INTEGER '           direction mario is facing
    Jumping AS INTEGER '          mario currently jumping (t/f)
    Running AS INTEGER '          mario currently running (t/f)
    Walking AS INTEGER '          mario currently walking (t/f)
    RunTimer AS INTEGER '         period to show ready to run image
    Yvel AS SINGLE '              y velocity of mario jump
    Vector AS SINGLE '            y vector of mario jump
    Floor AS INTEGER '            lowest point on screen mario can go
END TYPE

TYPE TYPE_BULLET '                BULLET PROPERTIES
    InUse AS INTEGER '            this bullet currently active (t/f)
    x AS SINGLE '                 x coordinate of bullet
    y AS SINGLE '                 y coordinate of bullet
    Direction AS INTEGER '        direction bullet is traveling
    Cell AS INTEGER '             current bullet animation cell
END TYPE

TYPE TYPE_COIN '                  COIN PROPERTIES
    InUse AS INTEGER '            this coin currently active (t/f)
    y AS SINGLE '                 y coordinate of coin
    vector AS SINGLE '            y vector of coin
END TYPE

'+------------------------------+
'| Program variable definitions |
'+------------------------------+

REDIM Bullets(1) AS TYPE_BULLET ' bullet array
REDIM Coins(1) AS TYPE_COIN '     coin array
DIM Button AS TYPE_BUTTON '       player buttons
DIM WorkScreen AS LONG '          graphics drawn here
DIM BackGround AS LONG '          static background image
DIM Sprite(7, 6) AS LONG '        mario sprite image pool
DIM Mario AS TYPE_MARIO '         mario properties
DIM Box AS TYPE_RECTANGLE '       mystery box coordinates
DIM MysteryBox AS LONG '          mystery box image
DIM FPSFrame AS INTEGER '         current frame (1 to 30)
DIM BulletTimer AS INTEGER '      time to wait between bullets
DIM SNDBump AS LONG '             bump sound
DIM SNDCoin AS LONG '             coin sound
DIM SNDConf AS LONG '             configuration screen sound
DIM SNDFire AS LONG '             bullet firing sound
DIM SNDJump AS LONG '             jump sound
DIM SNDSong AS LONG '             theme song

'______________________________________________________________________________________________________________________

'+---------------+
'| Program setup |
'+---------------+

__INITIALIZE_CONTROLLERS '             controller library initialize
SET_DEFAULT_BUTTONS '                  set default input buttons
LOAD_ASSETS '                          load demo graphics and sounds
INITIALIZE_VARIABLES '                 initialize demo variables
SCREEN _NEWIMAGE(640, 480, 32) '       create view screen
_SNDLOOP SNDSong '                     play theme song

'+--------------------------+
'| Main program loop begins |
'+--------------------------+

DO '                                   begin demo loop
    _LIMIT 30 '                        30 frames per second
    IF __BUTTON_DOWN(Button.F1) THEN ' player press F1 key?
        CONFIGURE_BUTTONS '            yes, configure buttons
    END IF
    UPDATE_MARIO '                     update mario position
    DRAW_SCREEN '                      draw demo screen
    MOVE_MARIO '                       check for player inputs
LOOP UNTIL _KEYDOWN(27) '              leave demo when ESC pressed

'+-------------------------------+
'| Free assets from RAM and exit |
'+-------------------------------+

CLEANUP '                              remove all assets from memory
SYSTEM '                               return to OS

'______________________________________________________________________________________________________________________


' _____________________________________________________________________________________________________________________________________________
'/                                                                                                                                             \
SUB CONFIGURE_BUTTONS () '                                                                                                   CONFIGURE_BUTTONS |
    ' _________________________________________________________________________________________________________________________________________|____
    '/                                                                                                                                              \
    '| Allows player to reconfigure keyboard keys, joystick/game pad buttons, and joystick/game pad axes as buttons.                                |
    '\______________________________________________________________________________________________________________________________________________/

    SHARED Button AS TYPE_BUTTON ' need access to buttons
    SHARED SNDSong AS LONG '       need access to theme song
    SHARED SNDConf AS LONG '       need access to configure sound

    DIM Menu(8) AS STRING '        horizontal line of menu text
    DIM MenuLine AS INTEGER '      current highlighted menu line
    DIM CreateMenu AS INTEGER '    -1 when menu needs recreating
    DIM m AS INTEGER '             menu counter
    DIM s AS INTEGER '             slot counter
    DIM KeyHit AS INTEGER '        player keyboard input using _KEYHIT
    DIM Hit AS INTEGER '           player keyboard input using INKEY$

    __SET_AXIS_THRESHOLD .9 '                                                       set axis threshold to register as a button press
    __BUTTON_REASSIGN_ALLOWED '                                                     allow reassigning of buttons
    _SNDSTOP SNDSong '                                                              stop theme song
    _SNDPLAY SNDConf '                                                              play configure sound
    MenuLine = 1 '                                                                  highlight starts on line 1
    CreateMenu = -1 '                                                               menu needs creating
    DO '                                                                            begin main loop
        _LIMIT 30 '                                                                 don't hog the CPU
        CLS , _RGB32(92, 148, 252) '                                                clear screen with light blue
        IF __BUTTON_DOWN(Button.F2) THEN '                                          was F2 key pressed?
            SET_DEFAULT_BUTTONS '                                                   yes, set all buttons to default values
            CreateMenu = -1 '                                                       menu needs recreated
            _SNDPLAY SNDConf '                                                      play configure sound
        END IF
        IF CreateMenu THEN '                                                        does menu need (re)created?
            CreateMenu = 0 '                                                        yes, reset creation flag
            Menu(1) = "  UP      " '                                                create beginning of each menu item
            Menu(2) = "  DOWN    "
            Menu(3) = "  LEFT    "
            Menu(4) = "  RIGHT   "
            Menu(5) = "  JUMP    "
            Menu(6) = "  FIRE    "
            Menu(7) = "  RUN     "
            Menu(8) = "  CROUCH  "
            FOR s = 1 TO 4 '                                                        cycle through 4 slots
                Menu(1) = Menu(1) + " " + __BUTTON_NAME$(Button.UP, s) + " " '      add assigned button names to each menu line
                Menu(2) = Menu(2) + " " + __BUTTON_NAME$(Button.DOWN, s) + " "
                Menu(3) = Menu(3) + " " + __BUTTON_NAME$(Button.LEFT, s) + " "
                Menu(4) = Menu(4) + " " + __BUTTON_NAME$(Button.RIGHT, s) + " "
                Menu(5) = Menu(5) + " " + __BUTTON_NAME$(Button.JUMP, s) + " "
                Menu(6) = Menu(6) + " " + __BUTTON_NAME$(Button.FIRE, s) + " "
                Menu(7) = Menu(7) + " " + __BUTTON_NAME$(Button.RUN, s) + " "
                Menu(8) = Menu(8) + " " + __BUTTON_NAME$(Button.CROUCH, s) + " "
            NEXT s
        END IF
        COLOR _RGB32(255, 255, 0), _RGB32(0, 0, 255) '                              yellow text on blue background
        _PRINTMODE _FILLBACKGROUND '                                                show the background color
        LOCATE 2, 25 '                                                              position cursor
        PRINT "                             " '                                     print header
        LOCATE 3, 25
        PRINT " CONFIGURE CONTROLLER INPUTS "
        LOCATE 4, 25
        PRINT "                             "
        LINE (192, 16)-(423, 63), _RGB32(255, 255, 0), B '                          draw a box around header
        COLOR _RGB32(0, 0, 0) '                                                     black text
        _PRINTMODE _KEEPBACKGROUND '                                                transparent text background
        LOCATE 6, 6 '                                                               draw input instructions
        PRINT "UP/DOWN: Select Action      DEL: Remove Button    F2: Reset Defaults"
        LOCATE 7, 6
        PRINT "ENTER  : Configure Button                         F3: Return to Game"
        LOCATE 9, 1
        PRINT
        PRINT "   ACTION      METHOD 1         METHOD 2         METHOD 3         METHOD 4     "
        PRINT
        FOR m = 1 TO 8 '                                                            cycle through 8 menu lines
            PRINT " ";
            IF m = MenuLine THEN '                                                  is this menu line highlighted?
                COLOR _RGB32(255, 255, 0), _RGB32(0, 0, 255) '                      yes, yellow text on blue background
                _PRINTMODE _FILLBACKGROUND '                                        show the background color
            END IF
            PRINT Menu(m) '                                                         print the menu line
            COLOR _RGB32(0, 0, 0) '                                                 black text
            _PRINTMODE _KEEPBACKGROUND '                                            transparent text background
            PRINT
        NEXT m
        FOR m = 135 TO 391 STEP 32 '                                                draw grid lines around menu items
            LINE (8, m)-(632, m + 32), _RGB32(0, 0, 0), B
        NEXT m
        LINE (83, 135)-(83, 423), _RGB32(0, 0, 0)
        LINE (219, 135)-(219, 423), _RGB32(0, 0, 0)
        LINE (355, 135)-(355, 423), _RGB32(0, 0, 0)
        LINE (491, 135)-(491, 423), _RGB32(0, 0, 0)
        KeyHit = _KEYHIT '                                                          get any key pressed by player
        IF KeyHit = 18432 THEN '                                                    was the UP ARROW key pressed?
            MenuLine = MenuLine - 1 '                                               yes, move highlight up one line
            IF MenuLine = 0 THEN MenuLine = 1 '                                     keep highlight at top if necessary
        ELSEIF KeyHit = 20480 THEN '                                                no, was the DOWN ARROW key pressed?
            MenuLine = MenuLine + 1 '                                               yes, move highlight down one line
            IF MenuLine = 9 THEN MenuLine = 8 '                                     keep highlight at bottom if necessary
        ELSEIF KeyHit = 21248 THEN '                                                no, was the DELETE key pressed?
            COLOR _RGB32(255, 255, 0), _RGB32(255, 0, 0) '                          yes, yellow text on red background
            _PRINTMODE _FILLBACKGROUND '                                            show the background color
            LOCATE 29, 15 '                                                         position cursor
            PRINT " PRESS 1, 2, 3, or 4 TO REMOVE METHOD FROM ACTION "; '           display instructions
            _DISPLAY '                                                              update screen to show instructions
            DO '                                                                    begin key press loop
                _LIMIT 30 '                                                         don't hog the CPU
                Hit = VAL(INKEY$) '                                                 get value of any key pressed
            LOOP UNTIL Hit '                                                        leave when value not equal to zero
            IF Hit >= 1 AND Hit <= 4 THEN '                                         is value between 1 and 4?
                CreateMenu = -1 '                                                   yes, the menu will need recreated
                SELECT CASE MenuLine '                                              which menu line is highlighted?
                    CASE 1 '                                                        line 1
                        __REMOVE_BUTTON Button.UP, Hit '                            remove button from chosen slot
                    CASE 2 '                                                        line 2
                        __REMOVE_BUTTON Button.DOWN, Hit '                          remove button from chosen slot
                    CASE 3 '                                                        line 3
                        __REMOVE_BUTTON Button.LEFT, Hit '                          etc..
                    CASE 4
                        __REMOVE_BUTTON Button.RIGHT, Hit
                    CASE 5
                        __REMOVE_BUTTON Button.JUMP, Hit
                    CASE 6
                        __REMOVE_BUTTON Button.FIRE, Hit
                    CASE 7
                        __REMOVE_BUTTON Button.RUN, Hit
                    CASE 8
                        __REMOVE_BUTTON Button.CROUCH, Hit
                END SELECT
                _SNDPLAY SNDConf '                                                  play configure sound
            END IF
            _KEYCLEAR '                                                             clear all keyboard buffers
        ELSEIF KeyHit = 13 THEN '                                                   no, was the ENTER key pressed?
            COLOR _RGB32(255, 255, 0), _RGB32(255, 0, 0) '                          yes, yellow text on red background
            _PRINTMODE _FILLBACKGROUND '                                            show background color
            LOCATE 29, 12 '                                                         position cursor
            PRINT " SELECT KEYBOARD KEY, JOYSTICK AXIS, OR JOYSTICK BUTTON "; '     display instructions
            _DISPLAY '                                                              update display to show instructions
            CreateMenu = -1 '                                                       the menu will need recreated
            SELECT CASE MenuLine '                                                  which menu line is highlighted?
                CASE 1 '                                                            line 1
                    __AUTOASSIGN_BUTTON Button.UP '                                 assign button/axis to UP button
                CASE 2 '                                                            line 2
                    __AUTOASSIGN_BUTTON Button.DOWN '                               assign button/axis to DOWN button
                CASE 3 '                                                            line 3
                    __AUTOASSIGN_BUTTON Button.LEFT '                               etc..
                CASE 4
                    __AUTOASSIGN_BUTTON Button.RIGHT
                CASE 5
                    __AUTOASSIGN_BUTTON Button.JUMP
                CASE 6
                    __AUTOASSIGN_BUTTON Button.FIRE
                CASE 7
                    __AUTOASSIGN_BUTTON Button.RUN
                CASE 8
                    __AUTOASSIGN_BUTTON Button.CROUCH
            END SELECT
            _SNDPLAY SNDConf '                                                      play configure sound
        END IF
        _DISPLAY '                                                                  update screen with changes
    LOOP UNTIL __BUTTON_DOWN(Button.F3) '                                           leave when F3 key pressed
    _SNDLOOP SNDSong '                                                              start theme song again

END SUB
' _____________________________________________________________________________________________________________________________________________
'/                                                                                                                                             \
SUB CLEANUP () '                                                                                                                       CLEANUP |
    ' _________________________________________________________________________________________________________________________________________|____
    '/                                                                                                                                              \
    '| Removes all sounds and graphics from RAM. (Always clean up after yourself before exiting program)                                            |
    '\______________________________________________________________________________________________________________________________________________/

    SHARED Sprite() AS LONG '   need access to sprite images
    SHARED WorkScreen AS LONG ' need access to work screen
    SHARED BackGround AS LONG ' need access to background image
    SHARED MysteryBox AS LONG ' need access to mystery box image
    SHARED SNDBump AS LONG '    need access to all sounds
    SHARED SNDCoin AS LONG
    SHARED SNDConf AS LONG
    SHARED SNDFire AS LONG
    SHARED SNDJump AS LONG
    SHARED SNDSong AS LONG
    DIM i AS INTEGER '          generic counter
    DIM j AS INTEGER '          generic counter

    SCREEN 0, 0, 0, 0 '                                    go to pure text screen
    CLS '                                                  clear screen
    _SNDCLOSE SNDBump '                                    remove sounds from RAM
    _SNDCLOSE SNDCoin
    _SNDCLOSE SNDFire
    _SNDCLOSE SNDJump
    _SNDCLOSE SNDSong
    _SNDCLOSE SNDConf
    _FREEIMAGE WorkScreen '                                remove images from RAM
    _FREEIMAGE BackGround
    _FREEIMAGE MysteryBox
    FOR i = 1 TO 7
        FOR j = 1 TO 6
            IF Sprite(i, j) THEN _FREEIMAGE Sprite(i, j) ' remove sprite images from RAM
        NEXT j
    NEXT i

END SUB
' _____________________________________________________________________________________________________________________________________________
'/                                                                                                                                             \
SUB SPAWN_COIN () '                                                                                                                 SPAWN_COIN |
    ' _________________________________________________________________________________________________________________________________________|____
    '/                                                                                                                                              \
    '| Spawns a coin.                                                                                                                               |
    '\______________________________________________________________________________________________________________________________________________/

    SHARED Coins() AS TYPE_COIN '  need access to coin array
    SHARED Box AS TYPE_RECTANGLE ' need access to mystery box coordinates
    SHARED SNDCoin AS LONG '       need access to coin sound
    DIM c AS INTEGER '             coin counter

    c = 0 '                                              reset coin counter
    DO '                                                 loop through coin array
        c = c + 1 '                                      increment coin counter
    LOOP UNTIL Coins(c).InUse = 0 OR c = UBOUND(Coins) ' leave when array scannded
    IF Coins(c).InUse THEN '                             if index in use then all indexes used
        c = c + 1 '                                      increment coin counter
        REDIM _PRESERVE Coins(c) AS TYPE_COIN '          increase size of coin array
    END IF
    _SNDPLAY SNDCoin '                                   play coin sound
    Coins(c).InUse = -1 '                                mark this index in use
    Coins(c).y = Box.y1 + 7 '                            calculate y coordinate of coin
    Coins(c).vector = -5 '                               set initial vertical vector

END SUB
' _____________________________________________________________________________________________________________________________________________
'/                                                                                                                                             \
SUB UPDATE_COINS () '                                                                                                             UPDATE_COINS |
    ' _________________________________________________________________________________________________________________________________________|____
    '/                                                                                                                                              \
    '| Updates the position of active coins and draws them to the screen.                                                                           |
    '\______________________________________________________________________________________________________________________________________________/

    SHARED Sprite() AS LONG '      need access to sprite images
    SHARED Coins() AS TYPE_COIN '  need access to coin array
    SHARED Box AS TYPE_RECTANGLE ' need access to mystery box coordinates
    DIM c AS INTEGER '             coin counter

    c = 0 '                                                    reset coin counter
    DO '                                                       loop through coin array
        c = c + 1 '                                            increment coin counter
        IF Coins(c).InUse THEN '                               is this coin in use?
            Coins(c).y = Coins(c).y + Coins(c).vector '        yes, update coin y coordinate
            Coins(c).vector = Coins(c).vector * .91 '          decrease vertical vector amount slightly
            _PUTIMAGE (Box.x1, Coins(c).y), Sprite(COIN, 1) '  draw coin to screen
            IF Coins(c).y < 1 THEN Coins(c).InUse = 0 '        deactivate coin when it reaches top of screen
        END IF
    LOOP UNTIL c = UBOUND(Coins) '                             leave when array scanned

END SUB
' _____________________________________________________________________________________________________________________________________________
'/                                                                                                                                             \
SUB DRAW_SCREEN () '                                                                                                               DRAW_SCREEN |
    ' _________________________________________________________________________________________________________________________________________|____
    '/                                                                                                                                              \
    '| Brings all the components together to create one frame of the demo.                                                                          |
    '\______________________________________________________________________________________________________________________________________________/

    SHARED Sprite() AS LONG '    need access to sprite images
    SHARED Mario AS TYPE_MARIO ' need access to mario properties
    SHARED WorkScreen AS LONG '  need access to the work screen
    SHARED BackGround AS LONG '  need access to the background image
    SHARED MysteryBox AS LONG '  need access to the mystery box image

    '+--------------------+
    '| Update view screen |
    '+--------------------+

    _DEST WorkScreen '                                                                                               draw on work screen
    _PUTIMAGE , BackGround, WorkScreen '                                                                             erase work screen with background
    _PRINTMODE _KEEPBACKGROUND '                                                                                     transparent text background
    LOCATE 1, 6 '                                                                                                    position cursor
    COLOR _RGB32(0, 0, 0) '                                                                                          black text
    PRINT "PRESS F1 TO CONFIGURE BUTTONS" '                                                                          print instructions
    IF Mario.Facing = -1 THEN '                                                                                      is mario facing left?
        _PUTIMAGE (Mario.Rect.x2, Mario.Rect.y1)-(Mario.Rect.x1, Mario.Rect.y2), Sprite(Mario.Action, Mario.Frame) ' yes, flip sprite horizontally
    ELSE '                                                                                                           no, mario is facing right
        _PUTIMAGE (Mario.Rect.x1, Mario.Rect.y1), Sprite(Mario.Action, Mario.Frame) '                                draw sprite as drawn
    END IF
    UPDATE_BULLETS '                                                                                                 draw active bullets
    UPDATE_COINS '                                                                                                   draw active coins
    _PUTIMAGE (144, 48), MysteryBox '                                                                                draw mystery box
    _DEST 0 '                                                                                                        draw on view screen
    _PUTIMAGE , WorkScreen '                                                                                         stretch work screen (zoom 2X)
    _DISPLAY '                                                                                                       update view screen with changes

END SUB
' _____________________________________________________________________________________________________________________________________________
'/                                                                                                                                             \
SUB UPDATE_MARIO () '                                                                                                             UPDATE_MARIO |
    ' _________________________________________________________________________________________________________________________________________|____
    '/                                                                                                                                              \
    '| Updates mario's position on screen and checks for collision between mario and mystery box.                                                   |
    '\______________________________________________________________________________________________________________________________________________/

    SHARED Mario AS TYPE_MARIO '   need access to mario properties
    SHARED Box AS TYPE_RECTANGLE ' need access to mystery box coordinates
    SHARED FPSFrame AS INTEGER '   need access to master frame counter
    SHARED SNDBump AS LONG '       need access to bump sound

    FPSFrame = FPSFrame + 1 '                                                  increment master frame counter
    IF FPSFrame = 31 THEN FPSFrame = 1 '                                       reset master frame counter when needed
    Mario.x = Mario.x + Mario.Direction * Mario.Speed '                        update mario x position
    IF Mario.x >= 336 THEN Mario.x = Mario.x - 336 '                           move mario to left side of screen
    IF Mario.x <= -16 THEN Mario.x = Mario.x + 336 '                           move mario to right side of screen

    '+---------------------------------+
    '| Calculate mario sprite location |
    '+---------------------------------+

    Mario.Rect.x1 = Mario.x - 15 '                                             calculate mario rectangular coordinates
    Mario.Rect.y1 = Mario.y - 63
    Mario.Rect.x2 = Mario.Rect.x1 + 31
    Mario.Rect.y2 = Mario.Rect.y1 + 63
    IF COLLISION(Mario.Rect, Box) THEN '                                       has mario collided with mystery box?
        _SNDPLAY SNDBump '                                                     play bump sound

        '+-------------------------------------+
        '| Mario has collided with mystery box |
        '+-------------------------------------+

        IF Mario.x < Box.x1 - 8 THEN '                                         yes, is mario at left side of box?

            '+----------------------------+
            '| Mario hit left side of box |
            '+----------------------------+

            Mario.Direction = 0 '                                              yes, stop mario movement
            Mario.x = Box.x1 - 17 '                                            position mario at left side of box
        ELSEIF Mario.x > Box.x2 + 8 THEN '                                     no, is mario at right side of box?

            '+-----------------------------+
            '| Mario hit right side of box |
            '+-----------------------------+

            Mario.Direction = 0 '                                              yes, stop mario movement
            Mario.x = Box.x2 + 16 '                                            position mario at right side of box
        ELSE '                                                                 no, must have hit box from underneath

            '+-------------------------------+
            '| Mario hit box from underneath |
            '+-------------------------------+

            SPAWN_COIN '                                                       create a coin
            Mario.y = Box.y2 + 64 '                                            position mario just underneath box
            Mario.Yvel = 0 '                                                   stop upward movement

        END IF

        '+-----------------------------------+
        '| Recalculate mario sprite location |
        '+-----------------------------------+

        Mario.Rect.x1 = Mario.x - 15 '                                         recalculate mario rectangular coordinates
        Mario.Rect.y1 = Mario.y - 63
        Mario.Rect.x2 = Mario.Rect.x1 + 31
        Mario.Rect.y2 = Mario.Rect.y1 + 63
    END IF

END SUB
' _____________________________________________________________________________________________________________________________________________
'/                                                                                                                                             \
SUB MOVE_MARIO () '                                                                                                                 MOVE_MARIO |
    ' _________________________________________________________________________________________________________________________________________|____
    '/                                                                                                                                              \
    '| Moves mario according to player input.                                                                                                       |
    '\______________________________________________________________________________________________________________________________________________/

    SHARED Mario AS TYPE_MARIO '   need access to mario properties
    SHARED Button AS TYPE_BUTTON ' need access to buttons
    SHARED FPSFrame AS INTEGER '   need access to master frame counter
    SHARED SNDJump AS LONG '       need access to jump sound

    '+-------------------------------+
    '| Check for button/axis presses |
    '+-------------------------------+

    IF __BUTTON_DOWN(Button.FIRE) THEN FIRE_BULLET '                           fire a bullet
    IF NOT Mario.Jumping THEN '                                                is mario currently jumping?

        '+---------------------------------------------------+
        '| Must not be jumping to walk, run, jump, or crouch |
        '+---------------------------------------------------+

        IF __BUTTON_DOWN(Button.LEFT) THEN '                                   no, is player pressing a left button?

            '+--------------------+
            '| Walk and face left |
            '+--------------------+

            Mario.Walking = -1 '                                               yes, remember that mario is walking
            Mario.Direction = -1 '                                             mario is walking to the left
            Mario.Facing = -1 '                                                mario is facing left
            Mario.Action = WALK '                                              use walking sprites
            IF FPSFrame MOD Mario.FPS = 0 THEN Mario.Frame = Mario.Frame + 1 ' increment to next walking animation frame
            IF Mario.Frame = 7 THEN Mario.Frame = 1 '                          reset animation frame counter when necessary
        ELSEIF __BUTTON_DOWN(Button.RIGHT) THEN '                              no, is player pressing a right button?

            '+---------------------+
            '| Walk and face right |
            '+---------------------+

            Mario.Walking = -1 '                                               yes, remember that mario is walking
            Mario.Direction = 1 '                                              mario is walking to the right
            Mario.Facing = 1 '                                                 mario is facing right
            Mario.Action = WALK '                                              use walking sprites
            IF FPSFrame MOD Mario.FPS = 0 THEN Mario.Frame = Mario.Frame + 1 ' increment to next walking animation frame
            IF Mario.Frame = 7 THEN Mario.Frame = 1 '                          reset animation frame counter when necessary
        ELSE '                                                                 no, mario is standing still

            '+--------------+
            '| Stop walking |
            '+--------------+

            Mario.Action = STAND '                                             use standing sprite
            Mario.Frame = 1 '                                                  reset animation frame counter (sprite only has 1 frame)
            Mario.Direction = 0 '                                              mario is standing still
            Mario.Walking = 0 '                                                remember that mario is not walking
        END IF
        IF Mario.Walking THEN '                                                is mario currently walking?

            '+--------------------------------+
            '| Must be walking before running |
            '+--------------------------------+

            IF __BUTTON_DOWN(Button.RUN) THEN '                                yes, is player pressing a run button?

                '+---------------+
                '| Start running |
                '+---------------+

                IF NOT Mario.Running THEN '                                    yes, is mario already running?
                    Mario.Action = RUNSTART '                                  no, use getting ready to run sprite
                    Mario.Frame = 1 '                                          reset animation frame counter (sprite only has 1 frame)
                    Mario.RunTimer = Mario.RunTimer + 1 '                      increment getting ready to run timer
                    IF Mario.RunTimer = 5 THEN Mario.Running = -1 '            start mario running after 5 frames have passed
                    Mario.Direction = 0 '                                      mario stands still during these 5 frames
                ELSE '                                                         yes, mario is already running
                    Mario.Speed = 4 '                                          set mario speed
                    Mario.FPS = 2 '                                            set animation frames per second (15 FPS)
                END IF
            ELSE '                                                             no, a run button is not being pressed

                '+--------------+
                '| Stop running |
                '+--------------+

                Mario.Speed = 2 '                                              set mario speed
                Mario.FPS = 5 '                                                set animation frames per second (6 FPS)
                Mario.Running = 0 '                                            mario is no longer running
                Mario.RunTimer = 0 '                                           reset getting ready to run timer
            END IF
        END IF
        IF __BUTTON_DOWN(Button.CROUCH) OR __BUTTON_DOWN(Button.DOWN) THEN '   is player pressing a button to crouch?
            Mario.Action = CROUCH '                                            yes, use crouching sprite
            Mario.Frame = 1 '                                                  reset animation frame counter (sprite only has 1 frame)
            Mario.Direction = 0 '                                              mario is standing still
        ELSEIF __BUTTON_DOWN(Button.JUMP) OR __BUTTON_DOWN(Button.UP) THEN '   no, is player pressing a button to jump?
            _SNDPLAY SNDJump '                                                 play jump sound
            Mario.Jumping = -1 '                                               yes, mario is now jumping
            Mario.Yvel = -5 '                                                  set vertical velocity
            Mario.Vector = -1 '                                                set vertical vector direction
            Mario.Action = JUMP '                                              use jumping sprite
            Mario.Frame = 1 '                                                  reset animation frame counter (sprite only has 1 frame)
        END IF
    ELSE '                                                                     yes, mario is currently jumping

        '+---------------------------+
        '| Perform jump arc sequence |
        '+---------------------------+

        Mario.Vector = Mario.Vector + .2 '                                     increment vertical vector direction (will change direction at 0)
        Mario.Yvel = Mario.Yvel + Mario.Vector '                               add vector quantity to vertical velocity
        Mario.y = Mario.y + Mario.Yvel '                                       add vertical velocity to mario y coordinate
        IF Mario.y >= Mario.Floor THEN '                                       has mario hit floor on way down?

            '+--------------+
            '| Stop jumping |
            '+--------------+

            Mario.Jumping = 0 '                                                yes, mario is no longer jumping
            Mario.y = Mario.Floor '                                            place mario onto floor
        END IF
    END IF

END SUB
' _____________________________________________________________________________________________________________________________________________
'/                                                                                                                                             \
SUB UPDATE_BULLETS () '                                                                                                         UPDATE_BULLETS |
    ' _________________________________________________________________________________________________________________________________________|____
    '/                                                                                                                                              \
    '| Updates location of active bullets and draws them to the screen.                                                                             |
    '\______________________________________________________________________________________________________________________________________________/

    SHARED Mario AS TYPE_MARIO '       need access to mario properties
    SHARED Sprite() AS LONG '          need access to sprite images
    SHARED Bullets() AS TYPE_BULLET '  need access to bullet array
    SHARED BulletTimer AS INTEGER '    need access to bullet timer
    DIM b AS INTEGER '                 bullet counter

    IF BulletTimer THEN BulletTimer = BulletTimer - 1 '                                           decrement bullet timer if needed
    b = 0 '                                                                                       reset bullet counter
    DO '                                                                                          loop through bullet array
        b = b + 1 '                                                                               increment bullet counter
        IF Bullets(b).InUse THEN '                                                                is this bullet active?
            Bullets(b).x = Bullets(b).x + Bullets(b).Direction * 6 '                              yes, update bullet x coordinate
            IF Bullets(b).y < Mario.Floor - 9 THEN '                                              has bullet reached the floor?
                Bullets(b).y = Bullets(b).y + 3 '                                                 no, add to the bullet's y coordinate
            ELSE '                                                                                yes, bullet at floor
                Bullets(b).y = Bullets(b).y - 4 '                                                 bounce bullet back up
            END IF
            IF Bullets(b).x > 336 OR Bullets(b).x < -16 THEN '                                    has bullet left screen?
                Bullets(b).InUse = 0 '                                                            yes, this bullet no longer active
            ELSE '                                                                                no, bullet still on screen
                _PUTIMAGE (Bullets(b).x - 16, Bullets(b).y - 16), Sprite(FIRE, Bullets(b).Cell) ' draw bullet
                Bullets(b).Cell = Bullets(b).Cell + 1 '                                           increment animation cell
                IF Bullets(b).Cell = 5 THEN Bullets(b).Cell = 1 '                                 reset animation cell when needed
            END IF
        END IF
    LOOP UNTIL b = UBOUND(Bullets) '                                                              leave when array scanned

END SUB
' _____________________________________________________________________________________________________________________________________________
'/                                                                                                                                             \
SUB FIRE_BULLET () '                                                                                                               FIRE_BULLET |
    ' _________________________________________________________________________________________________________________________________________|____
    '/                                                                                                                                              \
    '| Fires a bullet.                                                                                                                              |
    '\______________________________________________________________________________________________________________________________________________/

    SHARED Mario AS TYPE_MARIO '      need access to mario properties
    SHARED Bullets() AS TYPE_BULLET ' need access to bullet array
    SHARED BulletTimer AS INTEGER '   need access to bullet timer
    SHARED SNDFire AS LONG '          need access to bullet sound
    DIM b AS INTEGER '                bullet counter

    IF BulletTimer THEN EXIT SUB '                           leave if not time to fire bullet
    BulletTimer = 10 '                                       must wait 10 frames between bullets (3 rounds per second)
    b = 0 '                                                  reset bullet counter
    DO '                                                     loop through bullet array
        b = b + 1 '                                          increment bullet counter
    LOOP UNTIL Bullets(b).InUse = 0 OR b = UBOUND(Bullets) ' leave when array scanned
    IF Bullets(b).InUse THEN '                               if this index in use then all indexes used
        b = b + 1 '                                          increment bullet counter
        REDIM _PRESERVE Bullets(b) AS TYPE_BULLET '          increase size of array
    END IF
    Bullets(b).InUse = -1 '                                  mark this index in use
    _SNDPLAY SNDFire '                                       play bullet sound
    IF Mario.Facing = 1 THEN '                               mario facing right?
        Bullets(b).x = Mario.Rect.x2 '                       yes, bullet comes from right side of mario
    ELSE '                                                   no, mario facing left
        Bullets(b).x = Mario.Rect.x1 '                       bullet comes from left side of mario
    END IF
    Bullets(b).y = Mario.Rect.y1 + 31 '                      bullet comes from vertical center of mario
    Bullets(b).Direction = Mario.Facing '                    remember bullet direction
    Bullets(b).Cell = 1 '                                    animation frame 1

END SUB
' _____________________________________________________________________________________________________________________________________________
'/                                                                                                                                             \
FUNCTION COLLISION (R1 AS TYPE_RECTANGLE, R2 AS TYPE_RECTANGLE) '                                                                    COLLISION |
    ' _________________________________________________________________________________________________________________________________________|____
    '/                                                                                                                                              \
    '| Detects and reports a collision between two rectangular areas provided, -1 (TRUE) if in collision, 0 (FALSE) otherwise.                      |
    '|                                                                                                                                              |
    '| R1 - rectangle 1                                                                                                                             |
    '| R2 - rectangle 2                                                                                                                             |
    '\______________________________________________________________________________________________________________________________________________/

    COLLISION = 0 '                      assume no collision
    IF R1.x2 >= R2.x1 THEN '             does R1 overlap R2?
        IF R1.x1 <= R2.x2 THEN
            IF R1.y2 >= R2.y1 THEN
                IF R1.y1 <= R2.y2 THEN
                    COLLISION = -1 '     yes, report rectangles in state of collision
                END IF
            END IF
        END IF
    END IF

END FUNCTION
' _____________________________________________________________________________________________________________________________________________
'/                                                                                                                                             \
SUB SET_DEFAULT_BUTTONS () '                                                                                               SET_DEFAULT_BUTTONS |
    ' _________________________________________________________________________________________________________________________________________|____
    '/                                                                                                                                              \
    '| Sets the default buttons. Will use keyboard and/or joystick 1 if they are detected.                                                          |
    '\______________________________________________________________________________________________________________________________________________/

    SHARED Button AS TYPE_BUTTON ' need access to button array
    STATIC Configured AS INTEGER ' -1 when buttons previously created and configured

    '+-----------------------------------+
    '| Clear previous button assignments |
    '+-----------------------------------+

    IF Configured THEN '                                             have buttons been created and configured
        __REMOVE_BUTTON Button.UP, 0 '                               yes, clear all previous button assignments
        __REMOVE_BUTTON Button.DOWN, 0
        __REMOVE_BUTTON Button.LEFT, 0
        __REMOVE_BUTTON Button.RIGHT, 0
        __REMOVE_BUTTON Button.FIRE, 0
        __REMOVE_BUTTON Button.RUN, 0
        __REMOVE_BUTTON Button.JUMP, 0
        __REMOVE_BUTTON Button.CROUCH, 0
    END IF

    '+-------------------------------------------------------+
    '| Configure keyboard keys as buttons if keyboard exists |
    '+-------------------------------------------------------+

    IF __KEYBOARD_EXISTS THEN '                                      does keyboard exist?
        __ASSIGN_BUTTON Button.UP, __KEYBOARDCID, CLKEY_W '          UP       = W KEY               [SLOT1]
        __ASSIGN_BUTTON Button.DOWN, __KEYBOARDCID, CLKEY_S '        DOWN     = S KEY               [SLOT1]
        __ASSIGN_BUTTON Button.LEFT, __KEYBOARDCID, CLKEY_A '        LEFT     = A KEY               [SLOT1]
        __ASSIGN_BUTTON Button.RIGHT, __KEYBOARDCID, CLKEY_D '       RIGHT    = D KEY               [SLOT1]
        __ASSIGN_BUTTON Button.FIRE, __KEYBOARDCID, CLKEY_RCTRL '    FIRE     = RIGHT CONTROL KEY   [SLOT1]
        __ASSIGN_BUTTON Button.RUN, __KEYBOARDCID, CLKEY_RSHIFT '    RUN      = RIGHT SHIFT KEY     [SLOT1]
        __ASSIGN_BUTTON Button.JUMP, __KEYBOARDCID, CLKEY_SPACEBAR ' JUMP     = SPACE BAR KEY       [SLOT1]
        __ASSIGN_BUTTON Button.CROUCH, __KEYBOARDCID, CLKEY_C '      CROUCH   = C KEY               [SLOT1]

        '+----------------------+
        '| Optional assignments |
        '+----------------------+

        '__ASSIGN_BUTTON Button.UP, __KEYBOARDCID, CLKEY_UP '         UP       = UP ARROW KEY        [SLOT2]
        '__ASSIGN_BUTTON Button.DOWN, __KEYBOARDCID, CLKEY_DOWN '     DOWN     = DOWN ARROW KEY      [SLOT2]
        '__ASSIGN_BUTTON Button.LEFT, __KEYBOARDCID, CLKEY_LEFT '     LEFT     = LEFT ARROW KEY      [SLOT2]
        '__ASSIGN_BUTTON Button.RIGHT, __KEYBOARDCID, CLKEY_RIGHT '   RIGHT    = RIGHT ARROW KEY     [SLOT2]
        '__ASSIGN_BUTTON Button.FIRE, __KEYBOARDCID, CLKEY_LCTRL '    FIRE     = LEFT CONTROL KEY    [SLOT2]


    END IF

    '+---------------------------------------------------------------+
    '| Configure joystick 1 axes and buttons if it exists (optional) |
    '+---------------------------------------------------------------+

    'IF __JOYPAD_EXISTS(1) THEN '                                                                   does joystick 1 exist?
    '    __ASSIGN_AXIS Button.UP, __JOYPAD1CID, -2 '                                                UP       = JOYSTICK 1 AXIS 2   [SLOT3 or 1]
    '    __ASSIGN_AXIS Button.DOWN, __JOYPAD1CID, 2 '                                               DOWN     = JOYSTICK 1 AXIS 2   [SLOT3 or 1]
    '    __ASSIGN_AXIS Button.LEFT, __JOYPAD1CID, -1 '                                              LEFT     = JOYSTICK 1 AXIS 1   [SLOT3 or 1]
    '    __ASSIGN_AXIS Button.RIGHT, __JOYPAD1CID, 1 '                                              RIGHT    = JOYSTICK 1 AXIS 1   [SLOT3 or 1]
    '    __ASSIGN_BUTTON Button.FIRE, __JOYPAD1CID, 1 '                                             FIRE     = JOYSTICK 1 BUTTON 1 [SLOT3 or 1]
    '    IF __BUTTON_TOTAL(__JOYPAD1CID) > 1 THEN __ASSIGN_BUTTON Button.JUMP, __JOYPAD1CID, 2 '    JUMP     = JOYSTICK 1 BUTTON 2 [SLOT2 or 1]
    '    IF __BUTTON_TOTAL(__JOYPAD1CID) > 2 THEN __ASSIGN_BUTTON Button.RUN, __JOYPAD1CID, 3 '     RUN      = JOYSTICK 1 BUTTON 4 [SLOT2 or 1]
    '    IF __BUTTON_TOTAL(__JOYPAD1CID) >= 3 THEN __ASSIGN_BUTTON Button.CROUCH, __JOYPAD1CID, 4 ' CROUCH   = JOYSTICK 1 BUTTON 5 [SLOT2 or 1]
    'END IF
    Configured = -1 '                                                buttons have been created and configured

END SUB
' _____________________________________________________________________________________________________________________________________________
'/                                                                                                                                             \
SUB LOAD_ASSETS () '                                                                                                               LOAD_ASSETS |
    ' _________________________________________________________________________________________________________________________________________|____
    '/                                                                                                                                              \
    '| Load the demo's graphics and sounds                                                                                                          |
    '\______________________________________________________________________________________________________________________________________________/

    SHARED Sprite() AS LONG '   need access to sprite images
    SHARED WorkScreen AS LONG ' need access to work screen
    SHARED BackGround AS LONG ' need access to background image
    SHARED MysteryBox AS LONG ' need access to mystery box image
    SHARED SNDBump AS LONG '    need access to sounds
    SHARED SNDCoin AS LONG
    SHARED SNDConf AS LONG
    SHARED SNDFire AS LONG
    SHARED SNDJump AS LONG
    SHARED SNDSong AS LONG
    DIM Sheet AS LONG '         demo sprite sheet
    DIM Ground AS LONG '        ground square image
    DIM i AS INTEGER '          generic counter

    SNDBump = _SNDOPEN("CB_Bump.ogg") '                                                      load sounds
    SNDCoin = _SNDOPEN("CB_Coin.ogg")
    SNDFire = _SNDOPEN("CB_Fire.ogg")
    SNDJump = _SNDOPEN("CB_Jump.ogg")
    SNDSong = _SNDOPEN("CB_Song.ogg")
    SNDConf = _SNDOPEN("CB_Conf.ogg")
    Sheet = _LOADIMAGE("CBDemo.PNG", 32) '                                                   sprite sheet image
    WorkScreen = _NEWIMAGE(320, 240, 32) '                                                   work screen image
    BackGround = _NEWIMAGE(320, 240, 32) '                                                   background image
    Sprite(STAND, 1) = _NEWIMAGE(32, 64, 32) '                                               standing image
    Sprite(CROUCH, 1) = _NEWIMAGE(32, 64, 32) '                                              crouching image
    Sprite(RUNSTART, 1) = _NEWIMAGE(32, 64, 32) '                                            ready to run image
    Sprite(JUMP, 1) = _NEWIMAGE(32, 64, 32) '                                                jumping image
    MysteryBox = _NEWIMAGE(32, 32, 32) '                                                     mystery box image
    Sprite(COIN, 1) = _NEWIMAGE(32, 32, 32) '                                                coin image
    Ground = _NEWIMAGE(32, 32, 32) '                                                         ground image
    _PUTIMAGE , Sheet, MysteryBox, (128, 64)-(159, 95) '                                     get mystery box image from sprite sheet
    _PUTIMAGE , Sheet, Sprite(COIN, 1), (160, 64)-(191, 95) '                                get coin image from sprite sheet
    _PUTIMAGE , Sheet, Ground, (192, 64)-(223, 95) '                                         get ground image from sprite sheet
    _PUTIMAGE , Sheet, Sprite(STAND, 1), (0, 0)-(31, 64) '                                   get standing image from sprite sheet
    _PUTIMAGE , Sheet, Sprite(CROUCH, 1), (32, 0)-(63, 63) '                                 get crouching image from sprite sheet
    _PUTIMAGE , Sheet, Sprite(RUNSTART, 1), (64, 0)-(95, 63) '                               get ready to run image from sprite sheet
    _PUTIMAGE , Sheet, Sprite(JUMP, 1), (288, 0)-(319, 63) '                                 get jumping image from sprite sheet
    FOR i = 1 TO 6 '                                                                         cycle through 6 animation cells
        Sprite(WALK, i) = _NEWIMAGE(32, 64, 32) '                                            walking animation image cell
        _PUTIMAGE , Sheet, Sprite(WALK, i), (64 + i * 32, 0)-(95 + i * 32, 63) '             get walking animation cell from sprite sheet
        IF i < 5 THEN '                                                                      cycle through 4 animation cells
            Sprite(FIRE, i) = _NEWIMAGE(32, 32, 32) '                                        bullet animation image cell
            _PUTIMAGE , Sheet, Sprite(FIRE, i), ((i - 1) * 32, 64)-((i - 1) * 32 + 31, 95) ' get bullet animation cell from sprite sheet
        END IF
    NEXT i
    _DEST BackGround '                                                                       draw on background image
    CLS , _RGB32(0, 255, 0) '                                                                clear background image in green
    FOR i = 0 TO 288 STEP 32 '                                                               cycle through the floor area
        _PUTIMAGE (i, 176), Ground '                                                         draw the floor ground blocks
        _PUTIMAGE (i, 208), Ground
    NEXT i
    _FREEIMAGE Ground '                                                                      ground image no longer needed
    _FREEIMAGE Sheet '                                                                       sprite sheet no longer needed
    _DEST 0 '                                                                                return to main screen

END SUB
' _____________________________________________________________________________________________________________________________________________
'/                                                                                                                                             \
SUB INITIALIZE_VARIABLES () '                                                                                             INITIALIZE_VARIABLES |
    ' _________________________________________________________________________________________________________________________________________|____
    '/                                                                                                                                              \
    '| Initialize all demo variables                                                                                                                |
    '\______________________________________________________________________________________________________________________________________________/

    SHARED Button AS TYPE_BUTTON ' need access to buttons
    SHARED Mario AS TYPE_MARIO '   need access to mario properties
    SHARED Box AS TYPE_RECTANGLE ' need access to box coordinates

    Mario.FPS = 5 '                                      mario animation speed
    Mario.Direction = 1 '                                mario travel direction (right)
    Mario.Facing = 1 '                                   mario facing direction (right)
    Mario.Floor = 176 '                                  floor that mario can't go beyond
    Mario.x = 159 '                                      x coordinate of mario (bottom center of sprite)
    Mario.y = Mario.Floor '                              y coordinate of mario (bottom center of sprite)
    Mario.Action = STAND '                               mario is currently standing
    Mario.Frame = 1 '                                    first animation frame
    Mario.Rect.x1 = Mario.x - 15 '                       calculate mario sprite rectangular coordinates
    Mario.Rect.y1 = Mario.y - 63
    Mario.Rect.x2 = Mario.Rect.x1 + 31
    Mario.Rect.y2 = Mario.Rect.y1 + 63
    Box.x1 = 144 '                                       mystery box rectangular coordinates
    Box.y1 = 48
    Box.x2 = Box.x1 + 31
    Box.y2 = Box.y1 + 31
    __ASSIGN_BUTTON Button.F1, __KEYBOARDCID, CLKEY_F1 ' F1 key
    __ASSIGN_BUTTON Button.F2, __KEYBOARDCID, CLKEY_F2 ' F2 key
    __ASSIGN_BUTTON Button.F3, __KEYBOARDCID, CLKEY_F3 ' F3 key
END SUB

'$INCLUDE:'CONTROLLER.BM'


Attached Files Image(s)
       
Software and cathedrals are much the same — first we build them, then we pray.
QB64 Tutorial
Reply


Messages In This Thread
Controller Library - by TerryRitchie - 04-12-2023, 03:29 PM
RE: Controller Library - by TempodiBasic - 04-13-2023, 09:38 PM
RE: Controller Library - by TerryRitchie - 04-13-2023, 10:28 PM
RE: Controller Library - by OldMoses - 04-16-2023, 04:35 PM
RE: Controller Library - by TerryRitchie - 04-17-2023, 02:07 AM
RE: Controller Library - by OldMoses - 04-17-2023, 11:48 AM
RE: Controller Library - by TerryRitchie - 04-26-2023, 06:23 PM
RE: Controller Library - by TempodiBasic - 05-02-2023, 09:51 AM
RE: Controller Library - by TempodiBasic - 05-13-2023, 11:26 AM
RE: Controller Library - by TerryRitchie - 05-13-2023, 01:35 PM
RE: Controller Library - by TerryRitchie - 05-18-2023, 03:12 AM



Users browsing this thread: 5 Guest(s)