The IF...THEN...ELSE structure is used to control program flow based on conditions.
IF SCORE >= 50
PRINT "You passed!"
ENDIF
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
IF AGE >= 18
IF COUNTRY$ = "USA" THEN PRINT "You can vote."
ELSE
PRINT "You are too young to vote."
ENDIF
IF BALANCE < 0 THEN PRINT "Your account is overdrawn!" ELSE PRINT "Balance OK."
IF LOGIN$ = "admin"
PRINT "Access granted."
ENDIF
The IIF function evaluates a condition and returns one of two values.
STATUS$ = IIF(SCORE >= 60, "Pass", "Fail")
DISCOUNT = IIF(QUANTITY > 10, 1, 0)
COUNTRY$ = IIF(COUNTRY$ = "", "Unknown", COUNTRY$)
The SELECT...CASE structure simplifies multiple condition checks.
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 IS :
PRINT "Invalid day"
ENDSEL
SELECT CASE
CASE TEMP > 30 :
PRINT "Hot"
BREAK
CASE TEMP >= 20 AND TEMP <= 30 :
PRINT "Warm"
BREAK
CASE TEMP < 20 :
PRINT "Cold"
BREAK
ENDSEL
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
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
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
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)
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
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
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
This function prompts for numeric input and checks for valid range and characters.
sub getValidatedNumber()
while 1
! prompt for input
INPUT "Please enter a number (from 1 to 100):", num$
! remove whitespace
num$ = TRIM(0, num$)
! check if input is empty
if not LEN(num$)
pass
! check for invalid characters (only digits allowed)
elseif not INSET(num$, "0123456789")
PRINT "Invalid characters in string, please try again."
! convert to number and check range
else
num = VAL(num$)
if num < 1 or num > 100
PRINT "Invalid value, please try again."
else
rets num ! return valid number
endif
endif
endw
ends
! call the function and display the result
number = getValidatedNumber()
PRINT "You entered:", number
✍️ Note: The INPUT command needs an active screen buffer to work.
view 11
screen 80, 30, 3000
This function searches for a target value in an array and returns its index if found.
sub searchArray(arr[], target)
! search for the target value in the array
arr[].FIND target
rets V0 ! return the index (0 if not found)
ends
! create an array with 50 random numbers (1–50)
dim numbers[50].RND 50
searchValue = 10
! call the function and store the result
index = searchArray(numbers[], searchValue)
! check if the value was found
if index <> 0
PRINT "Value ", searchValue, " found at position ", index - 1
else
PRINT "Value ", searchValue, " not found in the array"
endif
This function loads lines of text from a file into an array.
sub loadFileIntoArray(filePath$, lines$[])
! check if file exists (SIZE returns -1 if not found)
if SIZE(filePath$) = -1 then rets -1
! load file contents into string array
lines$[].FILE filePath$
rets V0 ! return number of lines loaded
ends
! create a string array with 100 empty slots
dim fileBuffer$[100].ZERO
! load the file into the array and get the line count
lineCount = loadFileIntoArray("Licence.txt", byref fileBuffer$[])
! check for file not found error
if lineCount = -1
PRINT "Error: File not found"
end
endif
! print each line of the loaded file
for i = 0 to lineCount - 1
PRINT fileBuffer$[i]
next
This function swaps two values using a temporary variable.
sub swapValues(x, y)
! store the value of x in a temporary variable
local temp = x
! swap the values
x = y
y = temp
ends
firstValue = 5
secondValue = 10
! swap the two values using byref parameters
swapValues(byref firstValue, byref secondValue)
! print the swapped values
PRINT "After swapping: ", firstValue, " and ", secondValue
This function checks if a string is a palindrome (reads the same forwards and backwards).
sub checkPalindrome(inputString$)
! declare local variables
local reversedString$
local cleanedInput$
! remove spaces from the input
cleanedInput$ = REPLACE(inputString$, " ", "")
! reverse the cleaned string
reversedString$ = REVERSE(cleanedInput$)
! compare the reversed and original (case-insensitive)
if UCASE(reversedString$) = UCASE(cleanedInput$)
rets "The string is a palindrome!"
else
rets "The string is not a palindrome!"
endif
ends
! call the function and display the result
result$ = checkPalindrome("Rotator")
PRINT result$
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.
push 100
push 'A'
pop x
This sends 100 and the ASCII of 'A' to the stack, and retrieves 'A' into x
.
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
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)
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
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.
The Hobby BASIC stack is circular. When it becomes full, new values start replacing older ones from the beginning of the array.
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
for i = 1 to 5
idx = (top - i + arr_size) mod arr_size
print stack[idx]
next
Expected Output: 7 6 5 4 3
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.
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.
Ctrl + Z
to undo the last action.F11
to export the loader script.F12
to insert text at the cursor.Q
to quit the program.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.
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.
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.
For the program to function correctly, enable the Use Legacy Console option:
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.
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.
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
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
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).
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
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.
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)
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
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!"
You can also use the alternate format with separate RGB components:
rgb 1, 255, 165, 0 ! equivalent to rgb 1, 0x00A5FF (note: color is in 0xBBGGRR format)
This allows for personalized color schemes inside your apps or tools built with Hobby BASIC.
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")
Create a simple digital clock:
while 1
print at 0, 0, LEFT(PATH(10), 8) ! system time
wait 1000
endw
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
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
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
✍️ Note: Mouse input requires no screen buffer.
view 11
screen 80, 30, 0
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!
Hobby BASIC is fully Wide-native, supporting Greek identifiers and keywords. To use Greek keywords in your code,
first declare them with the fix command, linking the Greek word to the corresponding English command.
For example:
! After these mappings, you can write your program using Greek commands directly
ΠΡΟΒΟΛΗ fix VIEW
ΟΘΟΝΗ fix SCREEN
ΧΡΩΜΑ fix COLOR
ΣΒΗΣΙΜΟ fix CLS
ΤΥΠΩΣΕ fix PRINT
ΠΑΥΣΗ fix PAUSE
ΑΡΧΗ#
ΠΡΟΒΟΛΗ 11
ΟΘΟΝΗ 80, 30, 1000
ΣΒΗΣΙΜΟ
ΧΡΩΜΑ 0, 7
ΤΥΠΩΣΕ "Υποστηρίζω Ελληνικά"
ΠΑΥΣΗ
All source code, tokens, labels, and strings are handled as Wide, enabling case-sensitive Greek and Latin text everywhere.
✍️ Note: To display Greek characters correctly, Hobby BASIC requires a raster font that supports Wide glyphs.
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.
One of Hobby BASIC’s unique features is the ability to run remote .BAS
scripts
directly from the command line, without needing to download them manually. Try the following in the command line and see what it does.
HB.EXE https://files.catbox.moe/ia9qt7.BAS
Alternatively, you can run remote scripts dynamically from within another .BAS
program:
exec "run https://files.catbox.moe/ia9qt7.BAS"
This command fetches the .BAS
file from the specified URL, loads it into memory, and executes it in the console.
⚠️ Security Warning: Scripts from remote URLs run with full privileges. Only run code from trusted and verified sources.
A full Hobby BASIC demo running inside the Windows 10 console.
! 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.
! Windows 10 & 11 Compatibility:
! For the program to function correctly, enable the Use Legacy Console option.
! Right-click the app title bar and select Properties.
! Enable Use Legacy Console.
! Restart the console.
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
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.
👉 Watch a full video tour on YouTube to see Hobby BASIC in action.
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.