Keyboard & Mouse Input

INKEY$ returns the next key in the keyboard buffer or "" if none, without waiting.

25.1 INKEY$ — non-blocking key reads

INKEY$ returns the next key in the keyboard buffer or "" if none, without waiting.

Useful codes: Enter CHR$(13), Esc CHR$(27), Backspace CHR$(8), Tab CHR$(9); extended: Up 72 ("H"), Down 80 ("P"), Left 75 ("K"), Right 77 ("M"), Home 71, End 79, PgUp 73, PgDn 81, Insert 82, Delete 83, F1–F10 59–68.

INKEY$ delivers key repeats at the keyboard repeat rate and cannot detect several keys held at once — fine for menus and text, poor for action games.

PRINT "Press keys (Esc to quit)"
DO
    k$ = INKEY$
    IF k$ <> "" THEN
        IF LEN(k$) = 1 THEN
            PRINT "Key: "; k$; "  code"; ASC(k$)
        ELSE                                   ' extended key: CHR$(0) + scan code
            SELECT CASE RIGHT$(k$, 1)
                CASE "H": PRINT "Up arrow"
                CASE "P": PRINT "Down arrow"
                CASE "K": PRINT "Left arrow"
                CASE "M": PRINT "Right arrow"
                CASE ";": PRINT "F1"
                CASE ELSE: PRINT "Extended code"; ASC(k$, 2)
            END SELECT
        END IF
    END IF
    _LIMIT 60
LOOP UNTIL k$ = CHR$(27)

25.2 _KEYHIT and _KEYDOWN — game-quality input

_KEYHIT returns the next key event: a positive code when a key is pressed, negative when released, 0 if none.

_KEYDOWN(code) returns true while the key is held — check as many keys as you like each frame.

ASCII (65–90 / 97–122) Note: letter codes differ for lowercase/uppercase when Shift or Caps Lock is active — check both if needed. _KEYCLEAR empties the keyboard buffers.

SCREEN _NEWIMAGE(640, 480, 32)
DIM px AS SINGLE, py AS SINGLE
px = 320: py = 240
CONST SPEED = 4
DO
    IF _KEYDOWN(18432) OR _KEYDOWN(119) THEN py = py - SPEED   ' Up or w
    IF _KEYDOWN(20480) OR _KEYDOWN(115) THEN py = py + SPEED   ' Down or s
    IF _KEYDOWN(19200) OR _KEYDOWN(97) THEN px = px - SPEED    ' Left or a
    IF _KEYDOWN(19712) OR _KEYDOWN(100) THEN px = px + SPEED   ' Right or d
    IF px < 10 THEN px = 10
    IF px > 630 THEN px = 630
    IF py < 10 THEN py = 10
    IF py > 470 THEN py = 470
    CLS
    LINE (px - 10, py - 10)-(px + 10, py + 10), _RGB32(0, 255, 128), BF
    _PRINTSTRING (10, 10), "Arrows/WASD to move, diagonals work too. Esc quits."
    _DISPLAY
    _LIMIT 60
LOOP UNTIL _KEYDOWN(27)

25.3 Mouse input

true if a new mouse event was read (call in a loop until false) _MOUSEX, _MOUSEY button state (1 left, 2 right, 3 middle) wheel movement for the current event _MOUSEHIDE / _MOUSESHOW _MOUSEMOVE x, y move the pointer

SCREEN _NEWIMAGE(800, 600, 32)
_TITLE "Mini Paint — left: draw, right: clear, wheel: brush size"
DIM mx AS INTEGER, my AS INTEGER, lastX AS INTEGER, lastY AS INTEGER
DIM brush AS INTEGER, wasDown AS INTEGER
brush = 3
DO
    DO WHILE _MOUSEINPUT                       ' read ALL pending mouse events
        brush = brush - _MOUSEWHEEL            ' wheel: -1 up, +1 down
    LOOP
    IF brush < 1 THEN brush = 1
    IF brush > 30 THEN brush = 30
    mx = _MOUSEX: my = _MOUSEY
    IF _MOUSEBUTTON(1) THEN
        IF wasDown THEN
            FOR t = 0 TO 1 STEP 0.1            ' interpolate between frames for smooth strokes
                CIRCLE (lastX + (mx - lastX) * t, lastY + (my - lastY) * t), brush, _RGB32(255, 255, 0)
            NEXT
        END IF
        wasDown = -1
    ELSE
        wasDown = 0
    END IF
    IF _MOUSEBUTTON(2) THEN CLS
    lastX = mx: lastY = my
    _DISPLAY
    _LIMIT 120
LOOP UNTIL _KEYDOWN(27)

25.4 Detecting clicks (press, not hold)

The same edge-detection technique works for keys: compare the current _KEYDOWN state with the previous frame's.

' inside the frame loop:
down = _MOUSEBUTTON(1)
IF down AND NOT wasDown THEN PRINT "Clicked at"; _MOUSEX; _MOUSEY
wasDown = down

25.5 Game controllers and legacy input

QB64: _DEVICES (count of input devices), _DEVICE$(n) (name), _DEVICEINPUT, _BUTTON(n), _AXIS(n) read gamepads and joysticks.

Legacy: STICK(n) and STRIG(n) read the old PC game port.

Event trapping: ON KEY(n) GOSUB label with KEY(n) ON traps function keys in QBasic style.

Classic BASIC: INKEY$ (Microsoft BASICs, Spectrum), GET A$ (Commodore/Applesoft), PEEK(197) for the C64's current key, PEEK(-16384) on the Apple II. BBC BASIC: INKEY(-n) checks if a specific key is held. FreeBASIC: Inkey, MultiKey(SC_UP) (scan codes from fbgfx.bi), GetMouse x, y, wheel, buttons, GetJoystick. VB.NET: Windows Forms events KeyDown, KeyUp, KeyPress, MouseDown, MouseMove, MouseWheel; console: Console.KeyAvailable, Console.ReadKey(True).