๐Ÿ“˜ Hobby BASIC - Get Started

โœ… Conditionals in Hobby BASIC

1. IF...THEN...ELSE Statement

The IF...THEN...ELSE structure is used to control program flow based on conditions.

Example 1: Simple IF Statement

IF SCORE >= 50
    PRINT "You passed!"
ENDIF

Example 2: IF...ELSEIF...ELSE

IF (GRADE$ = "A" AND ATTENDANCE >= 90) OR AGE > 18
    PRINT "Great job!"
ELSEIF (GRADE$ = "B" OR AGE <= 18) AND ATTENDANCE >= 50
    PRINT "Good effort!"
ELSE
    PRINT "Keep improving!"
ENDIF

Example 3: Nested IF Statements

IF AGE >= 18
    IF COUNTRY$ = "USA" THEN PRINT "You can vote."
ELSE
    PRINT "You are too young to vote."
ENDIF

Example 4: Single-line IF with THEN

IF BALANCE < 0 THEN PRINT "Your account is overdrawn!" ELSE PRINT "Balance OK."

Example 5: IF without ELSE

IF LOGIN$ = "admin"
    PRINT "Access granted."
ENDIF

2. IIF Function

The IIF function evaluates a condition and returns one of two values.

Example 6: Basic IIF Usage

STATUS$ = IIF(SCORE >= 60, "Pass", "Fail")

Example 7: Numeric IIF Example

DISCOUNT = IIF(QUANTITY > 10, 1, 0)

Example 8: String Assignment with IIF

COUNTRY$ = IIF(COUNTRY$ = "", "Unknown", COUNTRY$)

3. SELECT...CASE...ENDSEL Statement

The SELECT...CASE structure simplifies multiple condition checks.

Example 9: Simple SELECT...CASE

INPUT "Enter day of week (1-7): ", DAY

SELECT CASE DAY
CASE IS 1 :
    PRINT "Monday"
    BREAK
CASE IS 2 :
    PRINT "Tuesday"
    BREAK
CASE IS 3 :
    PRINT "Wednesday"
    BREAK
CASE IS 4 :
    PRINT "Thursday"
    BREAK
CASE IS 5 :
    PRINT "Friday"
    BREAK
CASE IS 6,7 :
    PRINT "Weekend"
    BREAK
CASE :
    PRINT "Invalid day"
ENDSEL

Example 10: SELECT...CASE without parameter

SELECT CASE
CASE TEMP > 30 :
    PRINT "Hot"
    BREAK
CASE TEMP >= 20 AND TEMP <= 30 :
    PRINT "Warm"
    BREAK
CASE TEMP < 20 :
    PRINT "Cold"
    BREAK
ENDSEL

โœ… Loops and Control Statements

1. FOR...NEXT Loop

The FOR...NEXT loop in Hobby BASIC is used to repeat a block of code for a specific number of times.

Example 1: Basic FOR Loop with PASS

FOR I = 1 TO 5
    IF I = 3 THEN PASS
    PRINT I
NEXT I

Expected Output: 1 2 4 5

2. DO...UNTIL Loop

The DO...UNTIL loop executes a block of code repeatedly until a condition is met.

Example 2: DO Loop with PASS

I = 0
DO
    I = I + 1
    IF I = 2 THEN PASS
    PRINT I
UNTIL I = 4

Expected Output: 1 3 4

3. WHILE...ENDW Loop

The WHILE...ENDW loop repeats a block of code as long as the condition is true.

โœ๏ธ Note: Hobby BASIC uses ENDW instead of WEND.

Example 3: WHILE Loop

I = 1
WHILE I <= 5
    PRINT I
    I = I + 1
ENDW

Expected Output: 1 2 3 4 5

4. PASS Statement

The PASS statement is used to skip the current iteration of a loop. It is similar to the continue statement in C.

Example 4: Simple PASS Usage

FOR I = 1 TO 3
    PASS
    PRINT I
NEXT I

Expected Output: (Nothing printed)

5. BREAK Statement

The BREAK statement is used to exit a loop prematurely when a certain condition is met.

Example 5: Simple BREAK Usage

FOR I = 1 TO 9
    IF I = 5 THEN BREAK
    PRINT I
NEXT

Expected Output: 1 2 3 4

6. Nested Loops with BREAK and PASS

You can also use BREAK and PASS inside nested loops to control the flow.

Example 6: Nested Loops with PASS

FOR I = 1 TO 3
    FOR J = 1 TO 3
        IF J = 2 THEN PASS
        PRINT "I=", I, " J=", J
    NEXT J
NEXT I

Expected Output:

I=1 J=1
I=1 J=3
I=2 J=1
I=2 J=3
I=3 J=1
I=3 J=3

7. Complex Example: Search for Prime Numbers

In this example, we will search for prime numbers up to a limit using BREAK and PASS.

Example 7: Search for Prime Numbers

LIMIT = 20
PRINT "Prime numbers up to ", LIMIT
PRINT 2, " ";

FOR NUM = 3 TO LIMIT STEP 2
    ISPRIME = 1
    I = 3
    WHILE I * I <= NUM
        IF NUM % I = 0
            ISPRIME = 0
            BREAK
        ENDIF
        I = I + 2
    ENDW
    IF ISPRIME THEN PRINT NUM;
NEXT

Expected Output: 2 3 5 7 11 13 17 19

โœ… Functions in Hobby BASIC

1. Searching for a Value in an Array

This function searches for a target value in an array and returns its index if found.

Example: searchArray Function

sub searchArray(arr[], target)
    arr[].FIND target
    rets V0
ends

dim numbers[50].RND 50
searchValue = 10

index = searchArray(numbers[], searchValue)

if index <> 0
    PRINT "Value ", searchValue, " found at position ", index - 1
else
    PRINT "Value ", searchValue, " not found in the array"
endif

2. Loading File Content into an Array

This function loads lines of text from a file into an array.

Example: loadFileIntoArray Function

sub loadFileIntoArray(filePath$, lines$[])
    if SIZE(filePath$) = -1 then rets -1
    lines$[].FILE filePath$
    rets V0
ends

dim fileBuffer$[100].ZERO

lineCount = loadFileIntoArray("Licence.txt", byref fileBuffer$[])

if lineCount = -1
    PRINT "Error: File not found"
    end
endif

for i = 0 to lineCount - 1
    PRINT fileBuffer$[i]
next

3. Swapping Two Values

This function swaps two values using a temporary variable.

Example: swapValues Function

sub swapValues(x, y)
    local temp = x
    x = y
    y = temp
ends

firstValue = 5
secondValue = 10

swapValues(byref firstValue, byref secondValue)

PRINT "After swapping: ", firstValue, " and ", secondValue

4. Checking if a String is a Palindrome

This function checks if a string is a palindrome (reads the same forwards and backwards).

Example: checkPalindrome Function

sub checkPalindrome(inputString$)

    local reversedString$
    local cleanedInput$

    cleanedInput$ = REPLACE(inputString$, " ", "")

    reversedString$ = REVERSE(cleanedInput$)

    if UCASE(reversedString$) = UCASE(cleanedInput$)
        rets "The string is a palindrome!"
    else
        rets "The string is not a palindrome!"
    endif
ends

result$ = checkPalindrome("Rotator")
PRINT result$

โœ… The Stack in Hobby BASIC

In Hobby BASIC, the stack operates in a LIFO (Last In, First Out) manner and consists of 262,140 double words. You can manipulate it using the basic PUSH and POP commands or directly through the stack[] array.

โœ๏ธ Note: The stack[] array and the internal stack are the same. Any operation on stack[] directly affects the stack. However, commands like FILL, SHUFFLE, SORT, etc., do not update the internal stack pointer, so use them with care.

Example: Basic PUSH and POP

push 100
push 'A'
pop x

This sends 100 and the ASCII of 'A' to the stack, and retrieves 'A' into x.

Example: Multiple PUSH and Top Check

push 1, 2, 3, 'A'
top = PEEK(10)              ! Get top of the stack
print CHR(stack[top - 1])   ! Prints 'A'
pop 4                       ! pop 4 times

Sorting the Stack

x = 0
dim stack[10]               ! reinitialize stack with 10 elements
times 10 push x++           ! pushes 0..9 onto the stack
stack[].SORTD               ! now stack[] = [9, 8, โ€ฆ, 0]

for i = 0 to 9
    print stack[i]
next

Expected Output: 9 8 7 6 5 4 3 2 1 0 (Descending order)

Value Replacement

dim stack[5]
push 10, 20, 30, 20, 40
stack[].REPLACE 20, 99
times 5 pop x : print x

Expected Output: 40 99 30 99 10

Extra: Stack SHUFFLE

dim stack[5]
push 1, 2, 3, 4, 5
stack[].SHUFFLE
times 5 pop x : print x

โœ๏ธ Note: SHUFFLE randomly shuffles stack values. The result will vary.

Handling the Circular Stack

The Hobby BASIC stack is circular. When it becomes full, new values start replacing older ones from the beginning of the array.

Example: Circular Stack Behavior

dim stack[5]
push 1, 2, 3, 4, 5
push 6, 7
top = PEEK(10)
arr_size = 5
for i = 0 to arr_size - 1
    print stack[i]
next

Expected Output: 6 7 3 4 5

Reading Top to Bottom with Wrap-around

๐Ÿ”„ Always use mod to handle circular wrapโ€‘around when reading from top to bottom.
for i = 1 to 5
    idx = (top - i + arr_size) mod arr_size
    print stack[idx]
next

Expected Output: 7 6 5 4 3

Alternative: Simple POP

times 5 pop x : print x

Expected Output: 7 6 5 4 3

The stack in Hobby BASIC is a powerful tool. Its circular nature makes it highly efficient not only for simple PUSH and POP operations but also for advanced manipulations like sorting, shuffling, and value replacements using the stack[] array.

โœ… Drawing Tool Guide

Introduction

This drawing tool is developed in Hobby BASIC and designed specifically for use within the Hobby BASIC environment. DRAW can load, create, edit, and save ANSI images.

Image

Basic Controls

The Attributes Picker

Click on the BG or FG labels to select background or foreground color.

Then choose one of the 16 available colors from the color picker.

๐Ÿ’ก Right-click on the labels to swap the foreground and background colors.

If an area is selected, the color swap will apply to that area automatically.

โœ๏ธ Note: This method overrides color number 8 (GRAY) as it is used for temporary storage.

The Color Dialog Box

Right-click on the color picker to open the color dialog box.

Any change you make to one of the 16 basic colors in the console will affect the entire DRAW window.

Remember, DRAW itself is a console window made with Hobby BASIC.

๐ŸŽจ About Color Schemes

When you save an image in DRAW, the program automatically stores the associated color scheme in the DATA\TEMP folder. The scheme is saved as a plain text file (.TXT) with the same name as your image. To load this scheme, use Option 3 from the main menu.

Function Keys

๐Ÿ“Œ Windows 10 & 11 Compatibility

For the program to function correctly, enable the Use Legacy Console option:

  1. Right-click the app title bar and select Properties.
  2. Enable Use Legacy Console.
  3. Restart the console.

โœ… Creating Snapshots

Introduction

The DRAW program, Hobby BASIC's drawing tool, offers three options when starting:

โš ๏ธ Note: Options 1 and 2 define the font and canvas size used during your drawing session. Make sure to choose the correct mode when loading an image you previously created, to match its original dimensions.

Loading an ANSI Image

For example, if we save an image named TEST.ANS in the DATA\MEDIA\ANSI\ folder, we can load it as follows:

! ROWS = 80
! COLS = 25

screen 80, 50, 0
cls
ansi PATH("DATA\MEDIA\ANSI\TEST.ANS")
inkey

The critical setting here is ROWS, which must be 80.

Saving a Portion of an Image

The following code creates a new ANSI image, TEST1.ANS, with a size of 40x25 from the original TEST.ANS file.

screen 80, 50, 0
cls
ansi PATH("DATA\MEDIA\ANSI\TEST.ANS")
ansi 0, 0, 40, 25, PATH("DATA\MEDIA\ANSI\TEST1.ANS")
inkey

Loading the Cropped Image

To load TEST1.ANS, the console window must match the image size:

screen 40, 25, 0
cls
ansi PATH("DATA\MEDIA\ANSI\TEST1.ANS")
inkey

โ„น๏ธ Using SNAP for More Flexibility

SNAP loads a snapshot file at position x, y, or saves a rectangular area of the screen to a file. Snapshot files require the .HB extension. SNAP allows us to load an image of any size into a console window of any dimensions (as long as it fits within the window).

Creating and Loading a Snapshot

To load TEST.ANS and create a snapshot named TEST.HB with a size of 40x25, use the following code:

screen 80, 50, 0
cls
ansi PATH("DATA\MEDIA\ANSI\TEST.ANS")
snap 0, 0, 40, 25, PATH("DATA\SNAP\TEST.HB")
inkey

Now, we can load this snapshot at any position within the console window:

screen 80, 50, 0
cls
snap 10, 10, PATH("DATA\SNAP\TEST.HB")
inkey

๐Ÿ“˜ Hobby BASIC - Try These

๐Ÿ“Œ Built-in Functions Overview

Useful one-liners and built-in functions:

print ABS(-10)                ! 10
print RND()%100               ! random number 0-99
print STR(25) + " years"      ! "25 years"
print FORMAT(1, 23456)        ! "22,9 KB"
print PAD("42", '0', 5)       ! "00042"
print EXTRACT("abc123!@#", 0) ! "123"

๐Ÿ‘‰ Use PAUSE or INKEY to prevent the window from closing.

๐Ÿงต Strings in Hobby BASIC

String manipulation with built-ins:

a$ = "Hello World"
print LEFT(a$, 5)         ! "Hello"
print RIGHT(a$, 5)        ! "World"
print REVERSE(a$)         ! "dlroW olleH"
a$(0) = 'h'               ! Change first char (0-based)

๐Ÿงฎ Arrays (1D & 2D)

Working with arrays and array functions:

dim nums[5] = 5, 3, 1, 4, 2
nums[].SORTA
nums[].OUT 3

nums[].REPLACE 3, 99
nums[].OUT 3

! 2D example:
dim matrix[2, 2] = 1, 2, 3, 4
print matrix[0, 0], matrix[1, 1]  ! prints 1 4

๐ŸŽจ Console Drawing & Screen Tools

Manipulate screen output using built-in commands:

cls
color 1, 14
print "Yellow on Blue!"

paint 0, 0, 80, 25, 'ฮ‘', 1
invert 10, 10, 15, 5
redraw 10, 10, 15, 5, 'ฮ‘', '-'

You can redefine any of the 16 default console colors using the RGB command:

rgb 1, 0x00A5FF   ! Set color #1 to orange
color 0, 1
print "Now using custom orange text!"

This allows for personalized color schemes inside your apps or tools built with Hobby BASIC.

๐Ÿ“‚ File & Snapshot Utilities

Working with files and snapshots:

! Load text from file into array
dim lines$[]
lines$[].FILE "LICENCE.TXT"
for i = 0 to SIZE(lines$[]) - 1
  print lines$[i]
next

! Save a portion of screen
snap 0, 0, 40, 15, PATH("DATA\SNAP\TEST.HB")

! Load the snapshot
snap 10, 10, PATH("DATA\SNAP\TEST.HB")

๐Ÿ” Mini Lab: Digital Clock

Create a simple digital clock:

while 1
  print at 0, 0, LEFT(PATH(10), 8)    ! system time
  wait 1000
endw

๐Ÿ—บ๏ธ Mini Mini Lab: Three Points

TYPE is a user-defined structure that can hold variables or strings.

! Define a Coord structure for 3 points
type Coord (x, y) 3

! Assign coordinates to each point
Coord:[0].x = 10 : Coord:[0].y = 5    ! Point 0 at (10,5)
Coord:[1].x = 20 : Coord:[1].y = 15   ! Point 1 at (20,15)
Coord:[2].x = 30 : Coord:[2].y = 25   ! Point 2 at (30,25)

! Loop through and print each point
for i = 0 to 2
    print "Point ", i, ": (", Coord:[i].x, ", ", Coord:[i].y, ")"
next

โŒจ๏ธ Keyboard Input

Wait for a key press and display the key code:


LOOP#
    inkey

    ! V0 = Keycode
    ! V1 = SHIFT,  ALT,  CTRL, etc.
    ! V2 = F1..F12,  INS,  DEL,  HOME,  Arrows Keys

    print "Key:", V0, " Mod:", V1, " Extra:", V2

    if V0 = 13 then print "Enter was pressed"
    if V0 = 27 then end     ! Exit with Esc

    goto LOOP

๐Ÿ–ฑ๏ธ Mouse Tracking

Track mouse position and button state:


while 1
    mouse

    ! V0 = mouse x
    ! V1 = mouse y
    ! V2 = button: 1 left,  2 right,  4 double-click

    print "X:", V0, " Y:", V1, " Btn:", V2

    if V2 = 2 then print "Right click!"
    if V2 = 1 then break    ! Left click to exit

    wait 1
endw

โš™๏ธ FIX and TIMES

FIX replaces code before execution, letting you use alternative keywords or rename commands.

TIMES is like a compact loop. It runs a single-line command multiple times using V3 as the counter.

wait1Sec fix wait 10
display fix print

times 100 display V3 : wait1Sec

With the above fix, you can write display instead of print, or even use your native language!

๐Ÿ› ๏ธ DEBUG() Window Examples

Use the DEBUG window to visualize variable contents in real time:

dim values[5] = 10, 20, 30, 40, 50

for i = 0 to 4
  DEBUG(i, values[i])  ! show key-value pairs in debugger
next

Viewing output of an external command.

exec "tasklist", list$
debug(list$)

This will show the list of running processes from the Windows tasklist command directly inside the DEBUG window.

๐ŸŽฎ Demo Game

A full Hobby BASIC demo running inside the Windows 10 console.

A full Hobby BASIC demo running inside the Windows 10 console
โ–ถ View source code


    !  DEMO.BAS
    !  Hobby BASIC Interpreter

    !  2D Platformer Demo in Hobby BASIC.

    !  This is a simple 2D platformer demo designed for the Windows console.
    !  It showcases basic platformer mechanics, including movement and jumping, using keyboard input.

    !  Use the arrow keys to play.
    !  Press Spacebar to jump.

    FILE_OR_FOLDER_EXISTS = 3
    MB_ICONERROR = 0x10

    ! Check if system is compatible (Windows 7 or later)
    if VAL(PATH(6)) < 6
        alert MB_ICONERROR, PATH(3), "2D Platformer Demo requires Windows 7 or later" : end
    endif

    ! Check the path to the tileset graphics
    path_gfx$ = PATH("DATA\SNAP\TILESET.HB")
    if FILE(path_gfx$, FILE_OR_FOLDER_EXISTS) = 0 then alert MB_ICONERROR, "Not found", path_gfx$ : end

    SND1=700
    sound PATH("DATA\MEDIA\SFX\WAV\SFX1.WAV"), SND1

    ! Define key constants for arrow keys and other controls
    enum VK_LEFT=37, VK_UP, VK_RIGHT, VK_DOWN

    FRAME1 = 7   ! Hero facing right
    FRAME2 = 17  ! Hero facing left
    FRAME3 = 8   ! Climbing frame

    VK_ESC = 27
    VK_SPACE = 32

    ! Set fixed tile size and initial level
    TILE_SIZE = 8
    level = 1

    ! Define an array of RGB color codes
    dim rgb_color[] = \
        0x000000, 0x584751, 0x49AB52, 0x3A4994, 0x3E628E, 0x43266B, 0x3381C1, 0xB8A7B0, \
        0xA48E9A, 0xDE8833, 0x52B55A, 0x33A8F3, 0x304C6E, 0xACA2FF, 0x4892CE, 0xC9BBC2

    ! Map definitions for different levels (using arrays)
    dim map1[11, 7] = \
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
    1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 9, \
    0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, \
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

    dim map2[11, 7] = \
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, \
    2, 2, 2, 2, 2, 2, 2, 5, 1, 1, 1, \
    2, 2, 2, 2, 2, 2, 2, 4, 0, 0, 0, \
    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, \
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

    dim map3[11, 7] = \
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
    1, 1, 1, 1, 5, 2, 2, 2, 2, 2, 2, \
    0, 0, 0, 0, 4, 2, 2, 6, 2, 2, 9, \
    0, 0, 0, 0, 4, 2, 1, 1, 1, 1, 1, \
    0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0

    dim map4[11, 7] = \
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, \
    1, 1, 1, 1, 5, 2, 2, 3, 2, 2, 1, \
    0, 0, 0, 0, 4, 2, 2, 2, 2, 2, 0, \
    0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0

    ! Hero's initial position for each level
    dim hero_pos$[] = "00", "03", "04", "02", "03"

    ! Set window title
    title "๐ŸŽฎ 2D Platformer Demo (Hobby BASIC)  |  Use โ† โ†‘ โ†’ to move, Space to jump"

    ! Initial setup for the screen and graphics
    view 0, 7   ! hide window, font size 8x8
    screen 80, 75, 0
    cursor 0
    color 0, 0
    cls

    ! Load the graphics for tiles
    snap 0, 0, path_gfx$

    ! Create the tileset (different tiles for ground, walls, hero, etc.)
    bsave 00, 0, TILE_SIZE , TILE_SIZE , 0  ! ground
    bsave 08, 0, TILE_SIZE , TILE_SIZE , 1  ! floor
    bsave 16, 0, TILE_SIZE , TILE_SIZE , 2  ! sky
    bsave 24, 0, TILE_SIZE , TILE_SIZE , 3  ! wall
    bsave 32, 0, TILE_SIZE , TILE_SIZE , 4  ! ladder
    bsave 40, 0, TILE_SIZE , TILE_SIZE , 5  ! ladder and floor
    bsave 48, 0, TILE_SIZE , TILE_SIZE , 6  ! stone
    bsave 56, 0, TILE_SIZE , TILE_SIZE , 7  ! hero right
    flip 56, 0, TILE_SIZE , TILE_SIZE , 0
    bsave 56, 0, TILE_SIZE , TILE_SIZE , 17 ! hero left
    bsave 64, 0, TILE_SIZE , TILE_SIZE , 8  ! hero climb
    bsave 72, 0, TILE_SIZE , TILE_SIZE , 9  ! sign

    ! Set the color scheme for the game
    for index = 0 to 15
        rgb index, rgb_color[index]
    next


start#

    view 0   ! hide window
    if level = 5 then level = 1  ! Loop back to level 1
    map//level[].SIZE
    map_width = V1
    map_height = V2
    dim map[map_width, map_height]
    map[].COPY map//level[]
    ROWS = map_width * TILE_SIZE
    COLS = map_height * TILE_SIZE
    dim stage[ROWS, COLS]
    screen ROWS, COLS, 0
    color 9, 9
    paint TILE_SIZE, TILE_SIZE, ROWS, COLS, -1, -1
    draw_map()  ! Draw the current map
    grab 0, 0, ROWS, COLS, stage[], 0
    x = VAL(LEFT(hero_pos$[level], 1)) * TILE_SIZE
    y = VAL(RIGHT(hero_pos$[level], 1)) * TILE_SIZE
    bloads x, y, FRAME1
    view 1  ! show window


! Main game loop
main#

    ! Handle jump logic
    if jump = 1
        if y = JUMP_HEIGHT
            jump = -1
            vy = 1
        endif
    else
        if falling()  ! Check if the player is falling
            vy = 1
        else
            vy = 0
        endif
    endif

    ! Handle spacebar press for jumping
    if KEY(VK_SPACE) and jump = 0
        sound SND1
        jump = 1
        JUMP_HEIGHT = y - 12  ! Set jump height
        vy = -1
    endif

    ! Handle ladder climbing
    if KEY(VK_UP)
        if ladder(x, y)
            do: if KEY(VK_UP)
                    grab x, y, TILE_SIZE, TILE_SIZE, stage[], x, y
                    y--
                    bloads x, y, FRAME3  ! Climbing frame
                    wait 20
                elseif KEY(VK_DOWN)
                    break
                endif
            until not ladder(x, y + TILE_SIZE - 1)
        endif
    endif

    ! Handle left/right movement
    if KEY(VK_LEFT) and can_move(-1) and x > 0
        dir = 1
        vx = -1
    elseif KEY(VK_RIGHT) and can_move(TILE_SIZE)
        if x > ROWS - 10
            level++
            goto start
        endif
        dir = 0
        vx = 1
    else
        vx = 0
    endif

    ! Update position and redraw the hero
    if vx or vy or jump > 0
        grab x, y, TILE_SIZE, TILE_SIZE, stage[], x, y
        x += vx
        y += vy
        if dir
            bloads x, y, FRAME2  ! Hero facing left
        else
            bloads x, y, FRAME1  ! Hero facing right
        endif
    endif

    wait 20

    ! Exit if ESC key is pressed
    if not KEY(27) then goto main

    color 0, 7 : cls
    view 11, 1  ! Default mode
    end


! Check if the player is on a ladder
sub ladder(x, y)
    local i
    for i = 1 to TILE_SIZE -1
        cinfo x + i, y - 1
        if V1 = 4 then rets 1
    next
    rets 0
ends


! Check if the player is falling
sub falling()
    local i
    for i = 1 to TILE_SIZE -1
        cinfo x + i, y + TILE_SIZE
        if MATCH(V1, 1, 7, 8, 10, 12, 15) then jump = 0 : rets 0
    next
    rets 1
ends


! Check if the player can move left or right
sub can_move(dx)
    local i
    for i = 0 to TILE_SIZE -1
        cinfo x + dx, y + i
        if MATCH(V1, 1, 7, 8, 10, 12, 15) then rets 0
    next
    rets 1
ends


! Draw the current level map using tiles
sub draw_map()
    local x, y

    for y = 0 to map_height - 1
        for x = 0 to map_width - 1
            bloads x * TILE_SIZE, y * TILE_SIZE, map[x, y]
        next
    next
ends
    

๐Ÿ“˜ About Hobby BASIC

Hobby BASIC is a lightweight yet surprisingly powerful BASIC interpreter for the Windows console, written entirely in x86 assembly.
It enables the creation of games with ANSI graphics in the console, which is quite unusual.
What began in 2015 as a personal fun project continues to evolve to this day.

This quick guide offers just a small glimpse of what Hobby BASIC can do.
๐Ÿ‘‰ To download it and learn more, visit the Hobby BASIC topic on the Flat Assembler forum.

๐Ÿ”š Conclusion

This guide covers the fundamental concepts of Hobby BASIC, from conditions and loops to functions and drawing tools. With this knowledge, you can start creating your own programs.