Skip to content

Game Loop

As every game functions generally in a loop, the game loop is the core of your Scorbit integration. This is where you'll update game state and send data to the Scorbit cloud service. The game loop should run continuously updating scores, modes, and player states, and committing changes at the end of each frame.

Basic Structure

// Initial setup before entering to game loop
sb_device_info_t device_info = {
    .provider = "your_provider",      // Required: your provider name
    .machine_id = 1234,              // Required: your machine ID
    .game_code_version = "1.0.0",    // Required: version tracking
    .hostname = "staging",           // Optional: staging, production, or custom URL
    .uuid = NULL,                    // Optional: will be auto-generated if NULL
    .serial_number = 0               // Optional: device serial number
};

// Use encrypt_tool to generate your encrypted key from your private key
const char* encrypted_key = "your_encrypted_key_here";

// Create game state object with encrypted key
sb_game_handle_t state = sb_create_game_state2(encrypted_key, &device_info);

// Main game loop
while (1) {
    if (game_finished()) {
        sb_set_game_finished(state);
    }

    if (game_started()) {
        sb_set_game_started(state);
    }

    if ()
    // Update scores, modes, and player states
    update_game_state(state);

    // IMPORTANT: call commit unconditionally at the end of each cycle
    sb_commit(state);
}

// Cleanup when done
sb_destroy_game_state(state);
void game_loop() {
    // Initialize game state with your device info
    scorbit::DeviceInfo info;
    info.provider = "your_provider";      // Required: your provider name
    info.machineId = 1234;               // Required: your machine ID
    info.gameCodeVersion = "1.0.0";      // Required: version tracking
    info.hostname = "staging";           // Optional: staging, production, or custom URL
    info.uuid = "";                      // Optional: will be auto-generated if empty
    info.serialNumber = 0;               // Optional: device serial number

    // Use encrypt_tool to generate your encrypted key from your private key
    std::string encrypted_key = "your_encrypted_key_here";

    // Create game state object with encrypted key
    auto gs = scorbit::createGameState(encrypted_key, std::move(info));

    // Main game loop
    while (game_is_running) {
        // Update scores, modes, and player states
        update_game_state(gs);

        // Commit changes at the end of each frame
        gs.commit();

        // Optional: Add a small delay to control update frequency
        std::this_thread::sleep_for(std::chrono::microseconds(16667)); // ~60fps
    }
}
def game_loop():
    # Initialize game state with your device info
    info = scorbit.DeviceInfo()
    info.provider = "your_provider"      # Required: your provider name
    info.machine_id = 1234              # Required: your machine ID
    info.game_code_version = "1.0.0"    # Required: version tracking
    info.hostname = "staging"           # Optional: staging, production, or custom URL
    info.uuid = ""                      # Optional: will be auto-generated if empty
    info.serial_number = 0              # Optional: device serial number

    # Use encrypt_tool to generate your encrypted key from your private key
    encrypted_key = "your_encrypted_key_here"

    # Create game state object with encrypted key
    gs = scorbit.create_game_state(encrypted_key, info)

    # Main game loop
    while game_is_running:
        # Update scores, modes, and player states
        update_game_state(gs)

        # Commit changes at the end of each frame
        gs.commit()

        # Optional: Add a small delay to control update frequency
        time.sleep(0.016667)  # ~60fps

Key Concepts

1. Initialization

  • Create a game state object at startup with device info and encrypted key
  • Configure your device info with provider name and machine ID
  • Set up any necessary callbacks (e.g., logging)

2. State Updates

  • Update player scores
  • Manage active modes
  • Track current ball and player
  • Handle game start/end conditions

3. Commit Frequency

  • Call commit() at the end of each frame
  • Changes are only sent if state has been modified
  • Typical update rate is 60fps (every ~16.7ms)

4. Status Monitoring

  • Check connection status periodically (see Pairing & Status)
  • Avoid checking more frequently than once per second
  • Update UI indicators based on connection state

Logging

The SDK provides logging capabilities to help debug your integration. You can set up logging before creating your game state:

void loggerCallback(const char *message, sb_log_level_t level, const char *file, int line,
                    void *userData) {
    // Handle log messages - example implementation:
    printf("[%s] %s\n", 
        level == SB_DEBUG ? "DBG" :
        level == SB_INFO  ? "INF" :
        level == SB_WARN  ? "WRN" :
        level == SB_ERROR ? "ERR" : "UNK",
        message);
}

// Add logger before creating game state
sb_add_logger_callback(loggerCallback, NULL);
void loggerCallback(const std::string &message, scorbit::LogLevel level, 
                   const char *file, int line, void *userData) {
    // Handle log messages - example implementation:
    std::cout << "[" << (
        level == scorbit::LogLevel::Debug ? "DBG" :
        level == scorbit::LogLevel::Info  ? "INF" :
        level == scorbit::LogLevel::Warn  ? "WRN" :
        level == scorbit::LogLevel::Error ? "ERR" : "UNK"
    ) << "] " << message << std::endl;
}

// Add logger before creating game state
scorbit::addLoggerCallback(loggerCallback);
def logger_callback(message, level, file, line):
    # Handle log messages - example implementation:
    level_str = {
        scorbit.LogLevel.Debug: "DBG",
        scorbit.LogLevel.Info: "INF",
        scorbit.LogLevel.Warn: "WRN",
        scorbit.LogLevel.Error: "ERR"
    }.get(level, "UNK")
    print(f"[{level_str}] {message}")

# Add logger before creating game state
scorbit.add_logger_callback(logger_callback)

The logger callback receives the following parameters:

Parameter Type Description
message string The log message text
level enum Log severity (Debug, Info, Warning, Error)
file string Source file generating the log
line integer Line number in source file
userData pointer Optional context (C only)

The callback is thread-safe and can be used to route logs to your preferred destination (console, file, etc.).

Example Integration

Here's a more detailed example showing common game state updates, including scores, players, modes and ball tracking:

void update_game_state(sb_game_handle_t state) {
    // Handle game session state
    if (is_game_starting()) {
        sb_set_game_started(state);
    }

    if (is_game_active()) {
        // Update current player and ball
        sb_set_active_player(state, current_player);
        sb_set_current_ball(state, current_ball);

        // Update scores
        sb_set_score(state, 1, player1_score, 0);

        // Manage modes
        if (multiball_active) {
            sb_add_mode(state, "MB:Multiball");
        }
    }

    if (is_game_ending()) {
        sb_set_game_finished(state);
    }
}
void update_game_state(scorbit::GameState& gs) {
    // Handle game session state
    if (is_game_starting()) {
        gs.setGameStarted();
    }

    if (is_game_active()) {
        // Update current player and ball
        gs.setActivePlayer(current_player);
        gs.setCurrentBall(current_ball);

        // Update scores
        gs.setScore(1, player1_score);

        // Manage modes
        if (multiball_active) {
            gs.addMode("MB:Multiball");
        }
    }

    if (is_game_ending()) {
        gs.setGameFinished();
    }
}
def update_game_state(gs):
    # Handle game session state
    if is_game_starting():
        gs.set_game_started()

    if is_game_active():
        # Update current player and ball
        gs.set_active_player(current_player)
        gs.set_current_ball(current_ball)

        # Update scores
        gs.set_score(1, player1_score)

        # Manage modes
        if multiball_active:
            gs.add_mode("MB:Multiball")

    if is_game_ending():
        gs.set_game_finished()

Note

The game loop should run continuously while your game is active. Make sure to properly clean up resources when shutting down.

Tip

While the examples show a 60fps update rate, you can adjust this based on your needs. Just ensure you're calling commit() frequently enough to capture all important game state changes.