5) Input, Assets, and Audio
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
- Load before the loop.
- Check the returned handle.
- Reuse the handle while the resource is needed.
- 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