← Documentation Home

6) Files, Paths, and Save Data

Back to Tutorials

Goal: save and reload game state at a portable per-user path, then understand when to use text or typed binary values.


Step 1: Build a Platform-Correct Save Path

Dim savePath As String
savePath = PathCombine$(AppDataDir$(), "tutorial-save.txt")
DebugPrint("Save path: " + savePath)

AppDataDir$ chooses the user-local application data folder on macOS and Windows. PathCombine$ inserts the correct path separator, so avoid joining paths with a hard-coded slash.

Step 2: Write a Fresh Text Save

Dim fileRef As Integer
Dim score As Integer
Dim level As Integer

score = 1250
level = 4

If FileExists(savePath) Then
    DeleteFile(savePath)
End If
fileRef = OpenFile(savePath, True)

If fileRef <> 0 Then
    WriteLine(fileRef, Str(score))
    WriteLine(fileRef, Str(level))
    CloseFile(fileRef)
Else
    DebugPrint("Could not create the save file")
End If

A writeable OpenFile creates a missing file but does not promise to remove old trailing content. Deleting the old tutorial save first gives this simple format a clean start.

Step 3: Read and Convert the Values

If FileExists(savePath) Then
    fileRef = OpenFile(savePath)
    If fileRef <> 0 Then
        score = ToInt(ReadLine(fileRef))
        level = ToInt(ReadLine(fileRef))
        CloseFile(fileRef)
    End If
End If

DebugPrint("Loaded score: " + Str(score))
DebugPrint("Loaded level: " + Str(level))

Text files are easy to inspect during development. Keep a documented line order and convert each line into the expected type.

Step 4: Read Variable-Length Text Safely

fileRef = OpenFile("assets/dialogue.txt")
If fileRef <> 0 Then
    While Not EndOfFile(fileRef)
        DebugPrint(ReadLine(fileRef))
    Wend
    CloseFile(fileRef)
End If

EndOfFile prevents reading beyond the available lines. Close the file on every branch after a successful open.

Step 5: Use Typed Binary Values When Appropriate

Dim binaryPath As String
binaryPath = PathCombine$(AppDataDir$(), "tutorial-save.dat")

If FileExists(binaryPath) Then
    DeleteFile(binaryPath)
End If
fileRef = OpenFile(binaryPath, True)
If fileRef <> 0 Then
    WriteDword(fileRef, score)
    WriteDword(fileRef, level)
    DebugPrint("Bytes written: " + Str(FileTell(fileRef)))

    FileSeek(fileRef, 0)
    score = ReadDword(fileRef)
    level = ReadDword(fileRef)
    CloseFile(fileRef)
End If

Typed functions preserve numeric representation and avoid string conversion. Use FileTell, FileSeek, and FileSize when a format needs explicit byte positions.

Checkpoint: Save, Reset, and Load

Dim savePath As String
Dim fileRef As Integer
Dim playerName As String
Dim score As Integer
Dim level As Integer

savePath = PathCombine$(AppDataDir$(), "tutorial-save.txt")
playerName = "Luna"
score = 1250
level = 4

' Save a fresh three-line file.
If FileExists(savePath) Then
    DeleteFile(savePath)
End If
fileRef = OpenFile(savePath, True)
If fileRef <> 0 Then
    WriteLine(fileRef, playerName)
    WriteLine(fileRef, Str(score))
    WriteLine(fileRef, Str(level))
    CloseFile(fileRef)
End If

' Reset memory so the reload is visible.
playerName = ""
score = 0
level = 0

' Load the values in the same order.
If FileExists(savePath) Then
    fileRef = OpenFile(savePath)
    If fileRef <> 0 Then
        playerName = ReadLine(fileRef)
        score = ToInt(ReadLine(fileRef))
        level = ToInt(ReadLine(fileRef))
        CloseFile(fileRef)
    End If
End If

DebugPrint("Loaded " + playerName + _
    ", score " + Str(score) + _
    ", level " + Str(level))

The checkpoint should reload Luna, 1250, and 4. Open the text file shown by the earlier diagnostic to inspect the format.

Robust Save-Data Rules

  • Use a user data directory for saves and settings; use AppDir$ for read-only packaged assets.
  • Check every file handle before using it.
  • Close each successful open exactly once.
  • Write a format version first when save layouts may evolve.
  • Validate loaded ranges before applying them to the game.

Try It Yourself

Add a Boolean fullscreen setting with ToBoolean, write a version number on the first line, and refuse to load an unexpected version.

Functions Introduced

AppDataDir$, PathCombine$, OpenFile, ReadLine, WriteLine, EndOfFile, and FileSeek.


Navigation: Previous | Course outline | Next: Particle Effects