Advanced SmallBASIC Techniques: Graphics, Sound, and File I/OSmallBASIC is a compact, easy-to-learn BASIC interpreter that’s surprisingly powerful for hobby projects, education, and quick prototypes. Once you’ve mastered the basics — variables, control structures, simple I/O — you can start using SmallBASIC’s more advanced features: graphics, sound, and file input/output. This article covers techniques, examples, and best practices for each area so you can build richer, more interactive programs.
Table of Contents
- Graphics: drawing, animation, sprites, and double buffering
- Sound: beeps, tones, music playback, and timing
- File I/O: reading, writing, structured data, and binary files
- Putting it together: a sample project (simple game)
- Tips, performance considerations, and debugging strategies
Graphics: drawing, animation, sprites, and double buffering
SmallBASIC includes a straightforward graphics API that supports drawing primitives, images, colors, and basic transformations. Key commands include SCREEN, LINE, PSET, CIRCLE, PAINT, DRAW, and LOAD/PUT for bitmaps.
Modes and setting up the screen
Use SCREEN to initialize graphics mode. Many SmallBASIC builds support multiple screen modes (e.g., SCREEN 0 for text, SCREEN 1–n for graphics). Consult your SmallBASIC version for exact mode numbers, but a common pattern:
SCREEN 0 ' text mode SCREEN 1 ' simple graphics mode
You can set the window size using WINDOW or related functions in some builds, or rely on defaults.
Drawing primitives
- PSET x,y — set pixel at (x,y)
- LINE x1,y1,x2,y2 — draw a line
- CIRCLE x,y,r — draw a circle outline
- CIRCLE x,y,r,1 — draw a filled circle (fill flag depends on implementation)
- RECT and BOX — draw rectangles (if available)
Example: drawing a simple scene
SCREEN 1 COLOR 12,1 ' foreground, background LINE 10,10,200,10 CIRCLE 100,100,50 PSET 150,150
Colors
Use COLOR to set foreground (and sometimes background) colors. Some versions support named colors or RGB functions. Example:
COLOR 14,0 ' yellow on black
Sprites and images
SmallBASIC supports loading bitmap images with LOAD and displaying with PUT, or capturing regions with GET. Typical workflow:
- LOAD “sprite.bmp”, id
- PUT id, x, y
- GET x,y,x2,y2, id
Example:
LOAD "player.bmp", 1 PUT 1, playerX, playerY
If your build supports image memory, use SAVEIMAGE / LOADIMAGE equivalents to manage multiple sprites without reloading from disk.
Animation and double buffering
Flicker-free animation requires either manual clearing/redrawing with careful timing or double buffering if supported. A basic manual approach:
- Erase previous sprite by redrawing background region
- Update positions
- Draw sprites in new positions
- WAIT or use TIMER to control frame rate
Example loop:
SCREEN 1 playerX = 50 playerY = 50 DO ' erase (redraw background) COLOR 0 BOX 0,0,320,240 ' update playerX = playerX + 2 ' draw COLOR 14 CIRCLE playerX, playerY, 10,1 SLEEP 30 LOOP UNTIL playerX > 320
If your SmallBASIC supports double buffering or an off-screen buffer, render to the off-screen canvas then BLIT/PUT it to the screen each frame.
Transformations and simple physics
Implement simple motion and collision using vector math (dx, dy) and boundary checks. For rotation or scaling, you can precompute rotated frames for sprites or use any built-in affine transforms if available.
Sound: beeps, tones, music playback, and timing
SmallBASIC provides basic sound functions — PLAY, BEEP, TONE, or SOUND depending on the build — that let you produce tones, play short melodies, or control frequencies and durations.
Generating tones
Common commands:
- BEEP frequency, duration
- TONE frequency, duration
- SOUND channel, frequency, duration
Example:
BEEP 440, 500 ' 440 Hz for 500 ms (A4)
Using PLAY for melodies
Some SmallBASIC versions implement a PLAY string similar to QBASIC’s PLAY, letting you write notes in a compact form:
PLAY "T120 O4 C D E F G A B"
Where T is tempo, O is octave, and notes are letters with optional durations.
Timing and synchronization
Use SLEEP or TIMER functions to pace music and animations. For precise timing, run sound in a separate thread if the interpreter supports it, or interleave short sound commands while tracking elapsed time.
Example: simple melody with tempo control
notes = "C D E F G A B C" FOR i = 1 TO 8 note = VAL(STRMID(notes, i*2-1, 1)) BEEP 440 + (i-1)*20, 200 SLEEP 200 NEXT
File I/O: reading, writing, structured data, and binary files
SmallBASIC supports file operations such as OPEN, INPUT#, PRINT#, LINE INPUT, WRITE, GET, PUT, and CLOSE. Use these to save settings, high scores, or larger data.
Text files
Open a file for output (writing) or input (reading):
OPEN "scores.txt" FOR OUTPUT AS #1 PRINT #1, "Alice", 1200 CLOSE #1 OPEN "scores.txt" FOR INPUT AS #1 WHILE NOT EOF(#1) LINE INPUT #1, line$ PRINT line$ WEND CLOSE #1
Use PRINT# to write lines or WRITE# for quoted, comma-separated values. LINE INPUT reads a full line including commas.
CSV and structured text
For simple structured data, store CSV lines and parse with SPLIT or by using INSTR/LEFT/MID functions. Example writing CSV:
OPEN "players.csv" FOR OUTPUT AS #1 PRINT #1, "name,score" PRINT #1, "Alice,1200" CLOSE #1
Reading and parsing:
OPEN "players.csv" FOR INPUT AS #1 LINE INPUT #1, header$ WHILE NOT EOF(#1) LINE INPUT #1, row$ parts = SPLIT(row$, ",") name$ = parts(0) score = VAL(parts(1)) WEND CLOSE #1
If your SmallBASIC lacks SPLIT, use INSTR and string functions to parse.
Binary files
For compact storage or speed, use BINARY access (GET/PUT or OPEN … FOR BINARY). This is useful for storing raw sprite data or game state.
Example:
OPEN "data.bin" FOR BINARY AS #1 WRITE #1, value ' or PUT/GET depending on dialect CLOSE #1
Check your build’s manual for exact binary read/write syntax.
Error handling and file safety
- Always CLOSE files after use.
- Check for file existence before reading (DIR or FILEEXISTS functions).
- Use temporary files and then RENAME to avoid data loss on crashes.
- Handle EOF and I/O errors gracefully with ON ERROR or conditional checks if supported.
Putting it together: a sample project (simple game)
Below is a condensed outline for a small game combining graphics, sound, and file I/O: a one-player avoider game that saves high scores.
Core components:
- Graphics: draw player (circle) and enemies (rectangles), animate movement
- Sound: play a tone on collision and a short victory jingle on beat score
- File I/O: read/write “highscore.txt”
Skeleton code (conceptual — adapt to your SmallBASIC version):
SCREEN 1 ' load high score IF FILEEXISTS("highscore.txt") THEN OPEN "highscore.txt" FOR INPUT AS #1 LINE INPUT #1, hs$ highScore = VAL(hs$) CLOSE #1 ELSE highScore = 0 END IF playerX = 160: playerY = 200 score = 0 DO ' input IF INKEY$ = "a" THEN playerX = playerX - 5 IF INKEY$ = "d" THEN playerX = playerX + 5 ' update enemies... ' collision detection IF collided THEN BEEP 200, 300 IF score > highScore THEN highScore = score ' save high score OPEN "highscore.txt" FOR OUTPUT AS #1 PRINT #1, STR$(highScore) CLOSE #1 EXIT DO END IF ' draw BOX 0,0,320,240 CIRCLE playerX, playerY, 8,1 ' draw enemies... ' play sound for scoring IF score MOD 10 = 0 THEN BEEP 880, 100 SLEEP 30 LOOP
Adjust for your interpreter’s exact commands and available features.
Tips, performance considerations, and debugging strategies
- Minimize disk I/O during gameplay; preload assets into memory.
- Reduce per-frame drawing: redraw only changed regions when possible.
- Use integer math where possible for speed.
- Comment and modularize code with SUB/FUNCTION if supported.
- Use PRINT and logging to a debug file for non-graphical debugging.
- Test on target hardware; older machines may have limited colors/resolution.
Advanced SmallBASIC programming is about combining simple, well-understood parts — drawing, timing, sound, and persistent storage — to make interactive experiences. As you experiment, keep a small library of utilities (sprite loaders, collision helpers, file wrappers) so future projects start from a stronger base.