Chapter 7: Talking to Players

A game isn't much of a game if the player can't DO anything, right? We've been using INKEY$ in our examples, but there's SO much more to input in Crash BASIC!

Whether your players are mashing keys on a keyboard, clicking with a mouse, or tapping on their phone screen, Crash BASIC has you covered. Let's learn how to listen to your players!


Two Kinds of Input

Before we dive in, let's understand that there are two fundamentally different ways to get input:

1. Blocking Input — The program STOPS and waits for the player to type something. Great for menus, name entry, answering questions.

2. Real-time Input — The program keeps running and checks what keys/buttons are pressed RIGHT NOW. Essential for action games where you need smooth, responsive controls.

We'll cover both!


INPUT: Stop and Ask

When you need the player to type something—a name, a number, an answer—use INPUT:

INPUT "What is your name"; name$
PRINT "Hello, "; name$; "!"

PAUSE

The program stops at INPUT and waits. The player types their answer, presses Enter, and the value goes into the variable.

You can ask for numbers too:

INPUT "How many enemies"; enemyCount
INPUT "Difficulty (1-10)"; difficulty

PRINT "Creating "; enemyCount; " enemies at difficulty "; difficulty

PAUSE

Fancy Input with a Cursor

Want a more game-like input field with a blinking cursor? Use WITH CURSOR:

COLOR 14
INPUT WITH CURSOR("_") "Enter your name: "; name$
PRINT "Welcome, "; name$

PAUSE

The cursor character can be whatever you want:

  • "_" — Classic underscore cursor
  • CHR$(219) — Solid block cursor

The input field uses your current COLOR for the text and border, so it matches your game's style!

Multiple Values

You can even ask for multiple values at once:

INPUT "Enter X, Y coordinates"; x, y
PRINT "You entered: "; x; ", "; y

PAUSE

The player types values separated by commas.


INKEY$: Quick Check, No Waiting

INKEY$ is the opposite of INPUT—it checks for a keypress WITHOUT stopping the program. If a key was pressed, it returns that key. If not, it returns an empty string.

SCREEN 13
PRINT "Press any key..."

DO
    k$ = INKEY$
LOOP WHILE k$ = ""

PRINT "You pressed: "; k$

PAUSE

This is what we've been using in our game loops:

SCREEN 13
x = 160

DO
    k$ = INKEY$

    IF k$ = "a" THEN x = x - 5
    IF k$ = "d" THEN x = x + 5

    BEGIN FRAME
    CLS
    CIRCLE (x, 100), 10, 14
    END FRAME
    DELAY 16
LOOP

The Problem with INKEY$

INKEY$ works, but it has a limitation: it only catches ONE key at a time from a buffer. If you're holding down a key, you get repeated characters with a delay (like when you hold a key in a text editor).

This feels sluggish for games. Try holding "a" in that example above—see how it stutters?

For smooth, responsive controls, we need something better...


KEYDOWN: The Secret to Smooth Controls

KEYDOWN is a game-changer. Instead of checking what key WAS pressed, it checks what key IS pressed RIGHT NOW. Hold a key down? KEYDOWN returns 1 the entire time. Release it? Instantly returns 0.

SCREEN 13
x = 160
y = 100

DO
    ' Check keys in real-time
    IF KEYDOWN("LEFT") THEN x = x - 3
    IF KEYDOWN("RIGHT") THEN x = x + 3
    IF KEYDOWN("UP") THEN y = y - 3
    IF KEYDOWN("DOWN") THEN y = y + 3

    BEGIN FRAME
    CLS
    CIRCLE (x, y), 10, 14
    END FRAME
    DELAY 16
LOOP

Try THIS version! Hold down an arrow key—smooth as butter! The character moves continuously without any stutter.

Key Names for KEYDOWN

KEYDOWN uses string names for keys:

Key Name
Arrow keys "LEFT", "RIGHT", "UP", "DOWN"
Space bar "SPACE"
Escape "ESC"
Enter "ENTER"
Letters "A", "B", "C", etc. (uppercase)
Numbers "0", "1", "2", etc.

Multiple Keys at Once!

Here's the REAL magic of KEYDOWN—you can check multiple keys simultaneously:

SCREEN 13
x = 160
y = 100

DO
    ' Diagonal movement works!
    IF KEYDOWN("LEFT") THEN x = x - 3
    IF KEYDOWN("RIGHT") THEN x = x + 3
    IF KEYDOWN("UP") THEN y = y - 3
    IF KEYDOWN("DOWN") THEN y = y + 3

    ' Fire while moving!
    IF KEYDOWN("SPACE") THEN
        CIRCLE (x, y - 20), 3, 12    ' Bullet!
    END IF

    BEGIN FRAME
    CLS
    CIRCLE (x, y), 10, 14
    LOCATE 1, 1
    PRINT "Arrows to move, SPACE to fire"
    END FRAME
    DELAY 16
LOOP

With INKEY$, you can only detect one key. With KEYDOWN, you can move diagonally AND fire at the same time! This is how real games feel responsive.


Mouse Input: Point and Click

For menu-driven games, strategy games, or any game where clicking matters, you need mouse input.

Where Is the Mouse?

SCREEN 13

DO
    mx = MOUSEX()
    my = MOUSEY()

    BEGIN FRAME
    CLS
    CIRCLE (mx, my), 5, 15
    LOCATE 1, 1
    PRINT "Mouse: "; mx; ", "; my
    END FRAME

    DELAY 16
LOOP

MOUSEX() and MOUSEY() return the current mouse position on your game canvas.

Is the Mouse Button Pressed?

SCREEN 13

DO
    mx = MOUSEX()
    my = MOUSEY()

    BEGIN FRAME
    CLS

    IF MOUSEDOWN() THEN
        CIRCLE (mx, my), 10, 14, 14    ' Filled yellow when clicking
    ELSE
        CIRCLE (mx, my), 10, 7         ' Gray outline otherwise
    END IF
    END FRAME

    DELAY 16
LOOP

MOUSEDOWN() returns 1 while the left mouse button is held down, 0 when released.

You can also check specific buttons:

  • MOUSEDOWN(0) — Left button (same as no parameter)
  • MOUSEDOWN(1) — Middle button
  • MOUSEDOWN(2) — Right button

Clicking on Things: COLLISION

To detect if the player clicked on a button or object, combine MOUSEDOWN with COLLISION:

SCREEN 13

buttonX = 110
buttonY = 80
buttonW = 100
buttonH = 40

DO
    BEGIN FRAME
    CLS

    ' Draw the button
    LINE (buttonX, buttonY)-(buttonX + buttonW, buttonY + buttonH), 14, BF
    LOCATE 12, 15
    PRINT "CLICK ME"

    ' Check for click
    IF MOUSEDOWN() THEN
        IF COLLISION("POINT", MOUSEX(), MOUSEY(), buttonX, buttonY, buttonW, buttonH) THEN
            LINE (buttonX, buttonY)-(buttonX + buttonW, buttonY + buttonH), 10, BF
            LOCATE 12, 15
            PRINT "CLICKED!"
        END IF
    END IF
    END FRAME

    DELAY 16
LOOP

COLLISION("POINT", ...) checks if a point (the mouse) is inside a rectangle (the button). The parameters are:

  • Point X, Point Y (the mouse position)
  • Rectangle X, Y, Width, Height (the button)

Mobile-Friendly Input: TAP and DRAG

Here's something cool: Crash BASIC runs in a web browser, which means your games can work on phones and tablets! But touchscreens don't have keyboards or mice. That's where TAP and DRAG come in.

TAP: Touch and Hold

TAP() returns 1 while the player is touching/clicking the screen (without dragging), 0 otherwise. It works on BOTH mobile (finger) and desktop (mouse)!

SCREEN 13

DO
    BEGIN FRAME
    CLS

    IF TAP() THEN
        ' Player is tapping!
        CIRCLE (MOUSEX(), MOUSEY()), 20, 14, 14
        LOCATE 1, 1
        PRINT "TAPPING!"
    ELSE
        LOCATE 1, 1
        PRINT "Tap anywhere!"
    END IF
    END FRAME

    DELAY 16
LOOP

TAP is perfect for:

  • Firing weapons (tap to shoot)
  • Selecting things (tap on items)
  • Charge-up mechanics (hold to charge, release to fire)

DRAG: Swipe and Slide

DRAGX() and DRAGY() return how far the player is dragging:

  • Values range from -1 to 1
  • -1 = dragging full left (or up for DRAGY)
  • 0 = not dragging
  • 1 = dragging full right (or down for DRAGY)
SCREEN 13

cameraX = 0
cameraY = 0

DO
    ' Drag to pan the camera
    dx = DRAGX()
    dy = DRAGY()

    IF dx <> 0 OR dy <> 0 THEN
        cameraX = cameraX - dx * 5
        cameraY = cameraY - dy * 5
    END IF

    BEGIN FRAME
    CLS
    CIRCLE (160 + cameraX, 100 + cameraY), 30, 14
    LOCATE 1, 1
    PRINT "Drag to pan!"
    LOCATE 2, 1
    PRINT "Camera: "; INT(cameraX); ", "; INT(cameraY)
    END FRAME

    DELAY 16
LOOP

DRAG is perfect for:

  • Scrolling/panning the view
  • Aiming (drag to set angle and power)
  • Swipe gestures (swipe left/right to change pages)
  • Virtual joysticks

Why TAP and DRAG Are Awesome

The best part about TAP and DRAG? They work on both mobile AND desktop!

  • On mobile: TAP detects finger touches, DRAG detects swipes
  • On desktop: TAP detects mouse clicks, DRAG detects click-and-drag

Write your game once, and it works everywhere. No separate code for touch vs. mouse!


Virtual Gamepad: Classic Controls on Mobile

What if you've already built a game using KEYDOWN() for arrow keys and buttons? Do you have to rewrite everything for touch screens? NOPE! Crash BASIC has a secret weapon: the Virtual Gamepad.

The virtual gamepad displays on-screen buttons—a D-pad for directions, A/B/X/Y action buttons, and a START button—that inject virtual key presses. Your existing KEYDOWN code works without changes!

Detecting Mobile Devices

First, use ISMOBILE() to check if the player is on a touch device:

SCREEN 13

IF ISMOBILE() THEN
    PRINT "You're on a mobile device!"
ELSE
    PRINT "You're on a desktop/laptop"
END IF

PAUSE

ISMOBILE() returns 1 on phones, tablets, and touchscreens, 0 on traditional desktops.

Setting Up the Gamepad

Map each gamepad button to a keyboard key, then turn it on:

IF ISMOBILE() THEN
    ' Map D-pad to WASD
    GAMEPAD MAP "UP", "W"
    GAMEPAD MAP "DOWN", "S"
    GAMEPAD MAP "LEFT", "A"
    GAMEPAD MAP "RIGHT", "D"

    ' Map action buttons
    GAMEPAD MAP "A", "SPACE"
    GAMEPAD MAP "B", "ENTER"
    GAMEPAD MAP "X", "Q"
    GAMEPAD MAP "Y", "E"
    GAMEPAD MAP "START", "ESCAPE"

    ' Show the gamepad
    GAMEPAD ON
END IF

Now when a player presses the UP button on the virtual D-pad, KEYDOWN("W") returns 1! Your existing game code just works.

A Complete Mobile-Ready Game

SCREEN 13

' Enable virtual gamepad on mobile
IF ISMOBILE() THEN
    GAMEPAD MAP "UP", "UP"
    GAMEPAD MAP "DOWN", "DOWN"
    GAMEPAD MAP "LEFT", "LEFT"
    GAMEPAD MAP "RIGHT", "RIGHT"
    GAMEPAD MAP "A", "SPACE"
    GAMEPAD ON
END IF

playerX = 160
playerY = 100

DO
    ' These checks work with BOTH keyboard AND virtual gamepad!
    IF KEYDOWN("LEFT") THEN playerX = playerX - 3
    IF KEYDOWN("RIGHT") THEN playerX = playerX + 3
    IF KEYDOWN("UP") THEN playerY = playerY - 3
    IF KEYDOWN("DOWN") THEN playerY = playerY + 3

    ' Fire with A button or spacebar
    IF KEYDOWN("SPACE") THEN
        CIRCLE (playerX, playerY - 20), 3, 12
    END IF

    BEGIN FRAME
    CLS
    CIRCLE (playerX, playerY), 10, 14
    LOCATE 1, 1
    IF ISMOBILE() THEN
        PRINT "Use the virtual gamepad!"
    ELSE
        PRINT "Arrows to move, SPACE to fire"
    END IF
    END FRAME

    DELAY 16
LOOP

Gamepad Controls

Command What It Does
GAMEPAD MAP "button", "key" Map a button to simulate a keyboard key
GAMEPAD ON Show the virtual gamepad overlay
GAMEPAD OFF Hide the virtual gamepad overlay
GAMEPAD RESET Clear all button mappings
GAMEPAD DPAD JOYSTICK Display D-pad as analog joystick (supports diagonals)
GAMEPAD DPAD BUTTONS Display D-pad as 4 separate buttons (default)
Button Names
D-pad "UP", "DOWN", "LEFT", "RIGHT"
Action buttons "A", "B", "X", "Y"
Center button "START"

Joystick Mode for Diagonal Movement

By default, the D-pad shows four separate directional buttons. But some games need diagonal movement! Use GAMEPAD DPAD JOYSTICK to switch to a draggable joystick that can press multiple directions at once:

' Set up a game with diagonal movement
GAMEPAD MAP "UP", "W"
GAMEPAD MAP "DOWN", "S"
GAMEPAD MAP "LEFT", "A"
GAMEPAD MAP "RIGHT", "D"
GAMEPAD MAP "A", "SPACE"

GAMEPAD ON
GAMEPAD DPAD JOYSTICK  ' Now the D-pad is a joystick!

' Game loop - diagonal movement works automatically
DO
    dx = 0
    dy = 0
    IF KEYDOWN("W") THEN dy = dy - 2
    IF KEYDOWN("S") THEN dy = dy + 2
    IF KEYDOWN("A") THEN dx = dx - 2
    IF KEYDOWN("D") THEN dx = dx + 2

    playerX = playerX + dx
    playerY = playerY + dy
    DELAY 16
LOOP

When the player drags the joystick diagonally (like up-right), both "W" and "D" keys are pressed simultaneously. Switch back anytime with GAMEPAD DPAD BUTTONS.


Raw Touch Coordinates: TOUCHX and TOUCHY

Sometimes you want to know the exact position of a finger touch, separate from mouse input. TOUCHX() and TOUCHY() give you that:

SCREEN 13

DO
    tx = TOUCHX()
    ty = TOUCHY()

    BEGIN FRAME
    CLS

    IF tx >= 0 AND ty >= 0 THEN
        ' Active touch - draw at touch position
        CIRCLE (tx, ty), 15, 14, 14
        LOCATE 1, 1
        PRINT "Touch: "; tx; ", "; ty
    ELSE
        LOCATE 1, 1
        PRINT "Touch the screen!"
    END IF
    END FRAME

    DELAY 16
LOOP

TOUCHX() and TOUCHY() return -1 when there's no active touch—unlike MOUSEX()/MOUSEY() which always return a position. This lets you distinguish between:

  • No touch at all (-1)
  • Touch at coordinate 0 (0)

Choosing the Right Input Method

Here's a quick guide:

Situation Use This
Player types text/numbers INPUT
Menu selection (one key) INKEY$
Action game movement KEYDOWN
Point-and-click game MOUSEX, MOUSEY, MOUSEDOWN
Mobile-friendly game TAP, DRAGX, DRAGY
Universal (works everywhere) TAP + DRAG + KEYDOWN combo

For the most compatible games, combine multiple input methods:

SCREEN 13

playerX = 160
playerY = 100

DO
    ' Keyboard controls
    IF KEYDOWN("LEFT") THEN playerX = playerX - 3
    IF KEYDOWN("RIGHT") THEN playerX = playerX + 3
    IF KEYDOWN("UP") THEN playerY = playerY - 3
    IF KEYDOWN("DOWN") THEN playerY = playerY + 3

    ' Touch/drag controls (mobile-friendly!)
    dx = DRAGX()
    dy = DRAGY()
    IF dx <> 0 OR dy <> 0 THEN
        playerX = playerX + dx * 5
        playerY = playerY + dy * 5
    END IF

    ' Keep player on screen
    IF playerX < 10 THEN playerX = 10
    IF playerX > 310 THEN playerX = 310
    IF playerY < 10 THEN playerY = 10
    IF playerY > 190 THEN playerY = 190

    BEGIN FRAME
    CLS
    CIRCLE (playerX, playerY), 10, 14
    LOCATE 1, 1
    PRINT "Arrows or drag to move!"
    END FRAME

    DELAY 16
LOOP

Now your game works with keyboard OR touch!


Putting It All Together: A Menu System

Let's build a complete menu with multiple input options:

SCREEN 13

' Menu state
selected = 1
menuItems = 3

DO
    BEGIN FRAME
    CLS

    LOCATE 3, 12
    PRINT "=== MAIN MENU ==="

    ' Draw menu items
    FOR i = 1 TO menuItems
        LOCATE 5 + i * 2, 10

        IF i = selected THEN
            PRINT "> ";
        ELSE
            PRINT "  ";
        END IF

        IF i = 1 THEN PRINT "Start Game"
        IF i = 2 THEN PRINT "Options"
        IF i = 3 THEN PRINT "Quit"
    NEXT i

    LOCATE 15, 5
    PRINT "UP/DOWN to select, ENTER to confirm"
    LOCATE 16, 8
    PRINT "Or tap/click an option!"
    END FRAME

    ' Keyboard navigation
    IF KEYDOWN("UP") THEN
        selected = selected - 1
        IF selected < 1 THEN selected = menuItems
        DELAY 150    ' Debounce
    END IF

    IF KEYDOWN("DOWN") THEN
        selected = selected + 1
        IF selected > menuItems THEN selected = 1
        DELAY 150
    END IF

    ' Mouse/touch selection
    IF TAP() THEN
        my = MOUSEY()
        FOR i = 1 TO menuItems
            itemY = (5 + i * 2) * 8    ' Convert text row to pixel Y
            IF my >= itemY AND my < itemY + 16 THEN
                selected = i
            END IF
        NEXT i
    END IF

    ' Confirm selection
    IF KEYDOWN("ENTER") OR (TAP() AND MOUSEY() >= 56 AND MOUSEY() < 120) THEN
        IF selected = 1 THEN
            CLS
            PRINT "Starting game..."
            DELAY 1000
        ELSEIF selected = 2 THEN
            CLS
            PRINT "Options screen..."
            DELAY 1000
        ELSEIF selected = 3 THEN
            END
        END IF
    END IF

    DELAY 16
LOOP

This menu:

  • Works with UP/DOWN arrows
  • Works with ENTER to confirm
  • Works with mouse clicks
  • Works with touch on mobile
  • Highlights the current selection

Quick Reference

Function Returns Use For
INPUT "prompt"; var Typed value Text entry, questions
INKEY$ Key character or "" Single key checks
KEYDOWN("KEY") 1 or 0 Smooth real-time controls
MOUSEX() X position Mouse/touch location
MOUSEY() Y position Mouse/touch location
MOUSEDOWN([btn]) 1 or 0 Click detection
TAP() 1 or 0 Touch-friendly clicks
DRAGX() -1 to 1 Horizontal swipes
DRAGY() -1 to 1 Vertical swipes
TOUCHX() X or -1 Raw touch X coordinate
TOUCHY() Y or -1 Raw touch Y coordinate
ISMOBILE() 1 or 0 Detect touch devices
GAMEPAD ON/OFF — Show/hide virtual gamepad
GAMEPAD MAP "btn", "key" — Map button to key
GAMEPAD DPAD JOYSTICK — D-pad as analog joystick
GAMEPAD DPAD BUTTONS — D-pad as separate buttons
COLLISION("POINT",...) 1 or 0 Click on object detection

Try It Yourself!

  1. Make a drawing program where you draw with the mouse (hint: PSET at MOUSEX(), MOUSEY() when MOUSEDOWN)
  2. Create a "Simon Says" game that shows a sequence of colors and the player must tap them in order
  3. Build a virtual joystick using DRAGX and DRAGY to control a character
  4. Make a typing game where random letters appear and the player must type them (use INKEY$)

Your players are ready to interact—give them something fun to do!

See you in Chapter 8!


Next Chapter: We'll organize our code with subroutines and functions—because good code is reusable code!