← Documentation Home

5) Input, Assets, and Audio

Back to Tutorials

Goal: load visual and audio assets, animate a sprite, and support keyboard, mouse, controller, and typed-text input.

Prepare: create an assets folder beside your source file. Add player.png, a four-frame horizontal player-sheet.png with 32 × 32 frames, and click.wav.


Step 1: Load Once and Check Every Handle

Dim playerImage As Integer
Dim playerSprite As Integer
Dim clickSfx As Integer

playerImage = LoadImage("assets/player.png")
playerSprite = LoadSprite("assets/player-sheet.png", 32, 32)
clickSfx = LoadSfx("assets/click.wav")

If playerImage = 0 Then
    DebugPrint("Could not load player.png")
End If
If playerSprite = 0 Then
    DebugPrint("Could not load player-sheet.png")
End If
If clickSfx = 0 Then
    DebugPrint("Could not load click.wav")
End If

Runtime resources use Integer handles. A zero handle means loading failed; verify the relative path and file format before drawing or playing it.

Step 2: Put Hotspots at the Visual Center

If playerImage <> 0 Then
    SetImageHotspot( _
        playerImage, _
        ImageWidth(playerImage) / 2, _
        ImageHeight(playerImage) / 2 _
    )
End If

If playerSprite <> 0 Then
    SetSpriteHotspot(playerSprite, 16, 16)
End If

Drawing positions refer to the hotspot. Centered hotspots make rotation, scaling, pointer-following, and physics alignment much easier.

Step 3: Animate a Sprite Sheet

Dim frame As Integer
Dim lastFrameTime As Integer

If MilliSecs() - lastFrameTime >= 120 Then
    frame = (frame + 1) Mod 4
    lastFrameTime = MilliSecs()
End If

If playerSprite <> 0 Then
    DrawSprite(playerSprite, frame, playerX, playerY)
End If

Sprite frame indexes are zero-based. The timer changes frames about eight times per second instead of advancing once per rendered frame.

Step 4: Add Mouse Interaction and Sound

playerX = MouseX()
playerY = MouseY()

If MouseHit(0) And clickSfx <> 0 Then
    SetSfxVolume(clickSfx, 0.75)
    SetSfxPan(clickSfx, 0.0)
    PlaySfx(clickSfx)
End If

Mouse button 0 is the primary button. Use MouseHit for a single click and MouseButton for continuous dragging.

Step 5: Support a Controller Without Requiring One

Dim axisX As Double
Dim axisY As Double

If JoyCount() > 0 And JoyConnected(0) Then
    axisX = JoyAxis#(0, JOY_AXIS_LEFT_X)
    axisY = JoyAxis#(0, JOY_AXIS_LEFT_Y)

    If axisX > 0.15 Or axisX < -0.15 Then
        playerX = playerX + Round(axisX * 5.0)
    End If
    If axisY > 0.15 Or axisY < -0.15 Then
        playerY = playerY + Round(axisY * 5.0)
    End If

    If JoyButtonHit(0, JOY_BUTTON_A) And clickSfx <> 0 Then
        PlaySfx(clickSfx)
    End If
End If

The 0.15 dead zone ignores small stick noise. Always check availability before reading a controller.

Step 6: Collect Player Names Correctly

SetTextInput("Player 1")
StartTextInput()

Do
    Cls()
    DrawText(fontRef, 40, 40, "Name: " + GetTextInput$())
    DrawText(fontRef, 40, 70, "Press Enter to accept")
    Flip()
Loop Until KeyHit(KEY_ENTER)

Dim playerName As String
playerName = GetTextInput$()
StopTextInput()

Text entry is separate from key polling so keyboard layouts, composed characters, and platform input behavior are handled by the runtime.

Checkpoint: Asset and Input Viewer

Graphics(800, 600, False)
SetClsColor(14, 18, 30)

Dim fontRef As Integer
Dim spriteRef As Integer
Dim clickSfx As Integer
Dim playerX As Integer
Dim playerY As Integer
Dim frame As Integer
Dim lastFrameTime As Integer
Dim running As Boolean

fontRef = LoadFont("", 18)
spriteRef = LoadSprite("assets/player-sheet.png", 32, 32)
clickSfx = LoadSfx("assets/click.wav")
playerX = 400
playerY = 300
running = True

If spriteRef <> 0 Then
    SetSpriteHotspot(spriteRef, 16, 16)
End If
If clickSfx <> 0 Then
    SetSfxVolume(clickSfx, 0.75)
End If

Do
    If KeyDown(KEY_LEFT) Then
        playerX = playerX - 4
    End If
    If KeyDown(KEY_RIGHT) Then
        playerX = playerX + 4
    End If
    If KeyDown(KEY_UP) Then
        playerY = playerY - 4
    End If
    If KeyDown(KEY_DOWN) Then
        playerY = playerY + 4
    End If

    If MouseHit(0) Then
        playerX = MouseX()
        playerY = MouseY()
        If clickSfx <> 0 Then
            PlaySfx(clickSfx)
        End If
    End If

    If JoyCount() > 0 And JoyConnected(0) Then
        playerX = playerX + Round(JoyAxis#(0, JOY_AXIS_LEFT_X) * 5.0)
        playerY = playerY + Round(JoyAxis#(0, JOY_AXIS_LEFT_Y) * 5.0)
    End If

    If MilliSecs() - lastFrameTime >= 120 Then
        frame = (frame + 1) Mod 4
        lastFrameTime = MilliSecs()
    End If

    Cls()
    If spriteRef <> 0 Then
        DrawSprite(spriteRef, frame, playerX, playerY)
    Else
        SetDrawColor(80, 210, 255)
        DrawFilledRect(playerX - 16, playerY - 16, 32, 32)
    End If
    DrawText(fontRef, 20, 20, _
        "Arrows/controller move. Click teleports. ESC exits.")
    Flip()

    If KeyHit(KEY_ESC) Then
        running = False
    End If
Loop Until Not running

FreeSfx(clickSfx)
FreeSprite(spriteRef)
FreeFont(fontRef)

The fallback rectangle keeps the tutorial usable even when the sprite is missing. This is a useful development pattern for optional content.

Resource Lifecycle

  1. Load before the loop.
  2. Check the returned handle.
  3. Reuse the handle while the resource is needed.
  4. Free it once, after its final use.

Try It Yourself

Add background music with PlayBGM, change the sprite tint with SetSpriteColorMod, and use DrawSpriteEx to rotate or scale the current frame.

Functions Introduced

LoadImage, LoadSprite, DrawSprite, MouseHit, JoyAxis#, StartTextInput, LoadSfx, and PlaySfx.


Navigation: Previous | Course outline | Next: Files, Paths, and Save Data