refactored to multiple games implementation
This commit is contained in:
555
basic1.cpp
555
basic1.cpp
@@ -44,10 +44,12 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "display/low_level_render.h"
|
||||
#include "display/low_level_gui.h"
|
||||
#include "display/low_level_display.h"
|
||||
#include "display/low_level_display_epaper.h"
|
||||
#include "display/low_level_touch.h"
|
||||
#include "input_manager.h"
|
||||
#include "game.h"
|
||||
#include "tic_tac_toe.h"
|
||||
|
||||
|
||||
// Binary info for RP2350 - ensures proper boot image structure
|
||||
@@ -130,52 +132,9 @@ bool is_refresh_in_progress() {
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// INPUT EVENT STRUCTURES
|
||||
// GAME CONFIGURATION
|
||||
// ============================================================================
|
||||
|
||||
// Input event types
|
||||
enum InputType {
|
||||
INPUT_NONE = 0,
|
||||
INPUT_TOUCH_DOWN,
|
||||
INPUT_TOUCH_MOVE,
|
||||
INPUT_TOUCH_UP,
|
||||
INPUT_BUTTON_0,
|
||||
INPUT_BUTTON_1,
|
||||
INPUT_GESTURE
|
||||
};
|
||||
|
||||
// Unified input event structure
|
||||
struct InputEvent {
|
||||
InputType type;
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
uint8_t gesture_code; // For gesture events
|
||||
uint8_t button_id; // For button events
|
||||
uint8_t pressure; // Touch pressure/weight
|
||||
bool valid; // Set to true if event is valid
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// GAME STATE AND CONFIGURATION
|
||||
// ============================================================================
|
||||
|
||||
// Game state - customize this for your game
|
||||
struct GameState {
|
||||
// Tic-Tac-Toe game state
|
||||
uint8_t board[3][3]; // 0=empty, 1=X, 2=O
|
||||
uint8_t current_player; // 1=X, 2=O
|
||||
uint8_t winner; // 0=none, 1=X wins, 2=O wins, 3=tie
|
||||
uint8_t selected_row; // Currently selected cell
|
||||
uint8_t selected_col;
|
||||
bool game_over;
|
||||
|
||||
// Game statistics
|
||||
uint32_t x_wins;
|
||||
uint32_t o_wins;
|
||||
uint32_t ties;
|
||||
uint32_t total_moves;
|
||||
};
|
||||
|
||||
// Game configuration - adjust these for your game
|
||||
struct GameConfig {
|
||||
uint32_t touch_debounce_ms; // Touch polling rate
|
||||
@@ -282,488 +241,9 @@ void refresh_screen(const uint8_t *buffer, LowLevelDisplay* display) {
|
||||
// INPUT PROCESSING
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* @brief Get human-readable gesture name
|
||||
*
|
||||
* @param gesture_code Gesture code from touch controller
|
||||
* @return Constant string with gesture name
|
||||
*/
|
||||
const char* get_gesture_name(uint8_t gesture_code) {
|
||||
switch(gesture_code) {
|
||||
case 0x10: return "Move Up";
|
||||
case 0x14: return "Move Right";
|
||||
case 0x18: return "Move Down";
|
||||
case 0x1C: return "Move Left";
|
||||
case 0x48: return "Zoom In";
|
||||
case 0x49: return "Zoom Out";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Process touch input and convert to InputEvent
|
||||
*
|
||||
* Reads touch data from controller and creates appropriate InputEvent.
|
||||
* Handles debouncing and filtering internally.
|
||||
*
|
||||
* @param config Game configuration
|
||||
* @param last_time Pointer to last touch time for debouncing
|
||||
* @return InputEvent structure (valid=false if no valid input)
|
||||
*/
|
||||
InputEvent process_touch_input(const GameConfig& config, uint32_t* last_time) {
|
||||
InputEvent event = {INPUT_NONE, 0, 0, 0, 0, 0, false};
|
||||
|
||||
// Check if touch interrupt flag is set
|
||||
if (!touch_interrupt_flag) {
|
||||
return event; // No touch event
|
||||
}
|
||||
|
||||
printf("Processing touch: flag=%d, event_down=%d\n", touch_interrupt_flag, touch_event_down);
|
||||
|
||||
// Don't clear the flag yet - we may still be processing continuous touch
|
||||
|
||||
// Check if touch is active
|
||||
if (!touch_event_down) {
|
||||
// Touch released - reset timing for next touch
|
||||
touch_interrupt_flag = false;
|
||||
*last_time = 0; // Reset so next touch is treated as new touch-down
|
||||
event.type = INPUT_TOUCH_UP;
|
||||
event.valid = true;
|
||||
printf("Touch UP\n");
|
||||
return event;
|
||||
}
|
||||
|
||||
// Touch is down - check debounce timing
|
||||
uint32_t now = to_ms_since_boot(get_absolute_time());
|
||||
if (now - *last_time < config.touch_debounce_ms) {
|
||||
return event; // Too soon, skip
|
||||
}
|
||||
|
||||
// Read touch data
|
||||
TouchData touch_data;
|
||||
if (!touch || !touch->read_touch(&touch_data)) {
|
||||
// Clear flag even if read failed to prevent getting stuck
|
||||
touch_interrupt_flag = false;
|
||||
printf("Touch read FAILED\n");
|
||||
return event; // Read failed
|
||||
}
|
||||
|
||||
// Clear the interrupt flag after successfully reading touch data
|
||||
// This allows the next touch interrupt to be detected
|
||||
touch_interrupt_flag = false;
|
||||
|
||||
printf("Touch DOWN at (%d,%d)\n", touch_data.points[0].x, touch_data.points[0].y);
|
||||
|
||||
// Populate event structure
|
||||
event.x = touch_data.points[0].x;
|
||||
event.y = touch_data.points[0].y;
|
||||
event.pressure = touch_data.points[0].pressure;
|
||||
event.gesture_code = touch_data.gesture;
|
||||
event.valid = true;
|
||||
|
||||
// Determine event type
|
||||
if (*last_time == 0) {
|
||||
event.type = INPUT_TOUCH_DOWN;
|
||||
} else {
|
||||
event.type = INPUT_TOUCH_MOVE;
|
||||
}
|
||||
|
||||
// Handle gesture events
|
||||
if (config.enable_gestures && touch_data.gesture != 0) {
|
||||
event.type = INPUT_GESTURE;
|
||||
if (config.debug_verbose) {
|
||||
printf("Gesture: 0x%02X (%s)\n", event.gesture_code, get_gesture_name(event.gesture_code));
|
||||
}
|
||||
}
|
||||
|
||||
*last_time = now;
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Process button input and convert to InputEvent
|
||||
*
|
||||
* Checks button flags and verifies button state with debouncing.
|
||||
* Clears flags after processing.
|
||||
*
|
||||
* @param config Game configuration
|
||||
* @return InputEvent structure (valid=false if no valid input)
|
||||
*/
|
||||
InputEvent process_button_input(const GameConfig& config) {
|
||||
InputEvent event = {INPUT_NONE, 0, 0, 0, 0, 0, false};
|
||||
|
||||
#ifdef BUTTON_KEY0_PIN
|
||||
// Check KEY0
|
||||
if (button_key0_pressed) {
|
||||
button_key0_pressed = false;
|
||||
sleep_ms(config.button_debounce_ms);
|
||||
|
||||
if (gpio_get(BUTTON_KEY0_PIN) == 0) { // Verify still pressed
|
||||
event.type = INPUT_BUTTON_0;
|
||||
event.button_id = 0;
|
||||
event.valid = true;
|
||||
|
||||
if (config.debug_verbose) {
|
||||
printf("Button KEY0 action triggered\n");
|
||||
}
|
||||
return event;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BUTTON_KEY1_PIN
|
||||
// Check KEY1
|
||||
if (button_key1_pressed) {
|
||||
button_key1_pressed = false;
|
||||
sleep_ms(config.button_debounce_ms);
|
||||
|
||||
if (gpio_get(BUTTON_KEY1_PIN) == 0) { // Verify still pressed
|
||||
event.type = INPUT_BUTTON_1;
|
||||
event.button_id = 1;
|
||||
event.valid = true;
|
||||
|
||||
if (config.debug_verbose) {
|
||||
printf("Button KEY1 action triggered\n");
|
||||
}
|
||||
return event;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// GAME LOGIC (Customize this section for your game!)
|
||||
// ============================================================================
|
||||
|
||||
// Game board dimensions (used for both drawing and touch detection)
|
||||
const int BOARD_SIZE = 200;
|
||||
const int CELL_SIZE = BOARD_SIZE / 3;
|
||||
const int BOARD_Y = 80; // Y position below title
|
||||
|
||||
/**
|
||||
* @brief Check if there's a winner on the board
|
||||
* @return 0=no winner, 1=X wins, 2=O wins, 3=tie
|
||||
*/
|
||||
uint8_t check_winner(const GameState* state) {
|
||||
// Check rows
|
||||
for (int row = 0; row < 3; row++) {
|
||||
if (state->board[row][0] != 0 &&
|
||||
state->board[row][0] == state->board[row][1] &&
|
||||
state->board[row][1] == state->board[row][2]) {
|
||||
return state->board[row][0];
|
||||
}
|
||||
}
|
||||
|
||||
// Check columns
|
||||
for (int col = 0; col < 3; col++) {
|
||||
if (state->board[0][col] != 0 &&
|
||||
state->board[0][col] == state->board[1][col] &&
|
||||
state->board[1][col] == state->board[2][col]) {
|
||||
return state->board[0][col];
|
||||
}
|
||||
}
|
||||
|
||||
// Check diagonals
|
||||
if (state->board[0][0] != 0 &&
|
||||
state->board[0][0] == state->board[1][1] &&
|
||||
state->board[1][1] == state->board[2][2]) {
|
||||
return state->board[0][0];
|
||||
}
|
||||
|
||||
if (state->board[0][2] != 0 &&
|
||||
state->board[0][2] == state->board[1][1] &&
|
||||
state->board[1][1] == state->board[2][0]) {
|
||||
return state->board[0][2];
|
||||
}
|
||||
|
||||
// Check for tie (board full)
|
||||
bool board_full = true;
|
||||
for (int row = 0; row < 3; row++) {
|
||||
for (int col = 0; col < 3; col++) {
|
||||
if (state->board[row][col] == 0) {
|
||||
board_full = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!board_full) break;
|
||||
}
|
||||
|
||||
if (board_full) return 3; // Tie
|
||||
return 0; // No winner yet
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize game state
|
||||
*
|
||||
* Called once at startup to set initial game values.
|
||||
* Customize this for your game.
|
||||
*
|
||||
* @param state Pointer to GameState to initialize
|
||||
*/
|
||||
void game_init(GameState* state) {
|
||||
// Clear the board
|
||||
for (int row = 0; row < 3; row++) {
|
||||
for (int col = 0; col < 3; col++) {
|
||||
state->board[row][col] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
state->current_player = 1; // X starts
|
||||
state->winner = 0;
|
||||
state->selected_row = 1; // Start in center
|
||||
state->selected_col = 1;
|
||||
state->game_over = false;
|
||||
state->total_moves = 0;
|
||||
|
||||
// Keep win statistics across games
|
||||
// state->x_wins, state->o_wins, state->ties remain unchanged
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update game state based on input event
|
||||
*
|
||||
* This is where your game logic goes.
|
||||
* Called whenever an input event occurs.
|
||||
*
|
||||
* @param state Pointer to GameState to update
|
||||
* @param input Input event to process
|
||||
* @param config Game configuration
|
||||
* @param renderer Renderer for drawing operations
|
||||
* @return true if screen needs refresh (drawing occurred)
|
||||
*/
|
||||
bool game_update(GameState* state, const InputEvent& input, const GameConfig& config, LowLevelRenderer* renderer) {
|
||||
bool needs_refresh = false;
|
||||
|
||||
switch (input.type) {
|
||||
case INPUT_TOUCH_DOWN: {
|
||||
// If game is over, restart on touch
|
||||
if (state->game_over) {
|
||||
game_init(state);
|
||||
needs_refresh = true;
|
||||
break;
|
||||
}
|
||||
|
||||
printf("Touch down at (%d,%d)\n", input.x, input.y);
|
||||
|
||||
// Calculate board position (must match game_draw!)
|
||||
int board_x = V_WIDTH - BOARD_SIZE - 20;
|
||||
|
||||
// Check if touch is within board
|
||||
if (input.x >= board_x && input.x < board_x + BOARD_SIZE &&
|
||||
input.y >= BOARD_Y && input.y < BOARD_Y + BOARD_SIZE) {
|
||||
|
||||
int touched_col = (input.x - board_x) / CELL_SIZE;
|
||||
int touched_row = (input.y - BOARD_Y) / CELL_SIZE;
|
||||
|
||||
// Clamp to valid range (safety check)
|
||||
if (touched_row >= 0 && touched_row < 3 && touched_col >= 0 && touched_col < 3) {
|
||||
// Place piece if cell is empty
|
||||
if (state->board[touched_row][touched_col] == 0) {
|
||||
state->board[touched_row][touched_col] = state->current_player;
|
||||
state->total_moves++;
|
||||
|
||||
// Check for winner
|
||||
state->winner = check_winner(state);
|
||||
if (state->winner != 0) {
|
||||
state->game_over = true;
|
||||
if (state->winner == 1) state->x_wins++;
|
||||
else if (state->winner == 2) state->o_wins++;
|
||||
else if (state->winner == 3) state->ties++;
|
||||
} else {
|
||||
// Switch player
|
||||
state->current_player = (state->current_player == 1) ? 2 : 1;
|
||||
}
|
||||
|
||||
needs_refresh = true;
|
||||
|
||||
if (config.debug_verbose) {
|
||||
printf("Touch at [%d,%d] (pixel %d,%d) by player %d\n",
|
||||
touched_row, touched_col, input.x, input.y,
|
||||
state->current_player == 1 ? 2 : 1);
|
||||
}
|
||||
} else if (config.debug_verbose) {
|
||||
printf("Cell [%d,%d] already occupied\n", touched_row, touched_col);
|
||||
}
|
||||
}
|
||||
} else if (config.debug_verbose) {
|
||||
printf("Touch outside board: %d,%d\n", input.x, input.y);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case INPUT_BUTTON_0:
|
||||
// KEY0: Move selection (for button-only boards)
|
||||
if (!state->game_over) {
|
||||
// Move to next cell, skipping occupied ones
|
||||
int attempts = 0;
|
||||
do {
|
||||
state->selected_col++;
|
||||
if (state->selected_col > 2) {
|
||||
state->selected_col = 0;
|
||||
state->selected_row++;
|
||||
if (state->selected_row > 2) {
|
||||
state->selected_row = 0;
|
||||
}
|
||||
}
|
||||
attempts++;
|
||||
// If we've tried all 9 cells, stop (game might be full)
|
||||
if (attempts >= 9) break;
|
||||
} while (state->board[state->selected_row][state->selected_col] != 0);
|
||||
|
||||
needs_refresh = true;
|
||||
if (config.debug_verbose) {
|
||||
printf("Selection moved to [%d,%d]\n", state->selected_row, state->selected_col);
|
||||
}
|
||||
} else {
|
||||
// Restart game
|
||||
game_init(state);
|
||||
needs_refresh = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case INPUT_BUTTON_1:
|
||||
// KEY1: Place piece at selected position
|
||||
if (!state->game_over) {
|
||||
if (state->board[state->selected_row][state->selected_col] == 0) {
|
||||
state->board[state->selected_row][state->selected_col] = state->current_player;
|
||||
state->total_moves++;
|
||||
|
||||
// Check for winner
|
||||
state->winner = check_winner(state);
|
||||
if (state->winner != 0) {
|
||||
state->game_over = true;
|
||||
if (state->winner == 1) state->x_wins++;
|
||||
else if (state->winner == 2) state->o_wins++;
|
||||
else if (state->winner == 3) state->ties++;
|
||||
} else {
|
||||
// Switch player
|
||||
state->current_player = (state->current_player == 1) ? 2 : 1;
|
||||
}
|
||||
|
||||
needs_refresh = true;
|
||||
|
||||
if (config.debug_verbose) {
|
||||
printf("Piece placed at [%d,%d]\n", state->selected_row, state->selected_col);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return needs_refresh;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Draw game graphics to screen buffer
|
||||
*
|
||||
* All initial UI drawing operations go here.
|
||||
* Called once at startup to create the initial screen.
|
||||
*
|
||||
* @param state Pointer to current GameState
|
||||
* @param renderer Renderer for drawing primitives
|
||||
* @param gui GUI system for widgets (optional)
|
||||
*/
|
||||
void game_draw(const GameState* state, LowLevelRenderer* renderer, LowLevelGUI* gui) {
|
||||
// Draw main window
|
||||
LowLevelWindow *w1 = gui->draw_new_window(10, 10, V_WIDTH - 20, V_HEIGHT - 20, "Tic-Tac-Toe");
|
||||
|
||||
renderer->set_font(&font_5x5_obj);
|
||||
|
||||
// Draw current player or game result
|
||||
if (state->game_over) {
|
||||
if (state->winner == 1) {
|
||||
renderer->draw_string(20, 40, "X WINS!", true);
|
||||
} else if (state->winner == 2) {
|
||||
renderer->draw_string(20, 40, "O WINS!", true);
|
||||
} else {
|
||||
renderer->draw_string(20, 40, "TIE GAME!", true);
|
||||
}
|
||||
renderer->draw_string(20, 55, "Touch or KEY0 to restart", true);
|
||||
} else {
|
||||
char turn_text[30];
|
||||
snprintf(turn_text, sizeof(turn_text), "Turn: %s", state->current_player == 1 ? "X" : "O");
|
||||
renderer->draw_string(20, 40, turn_text, true);
|
||||
renderer->draw_string(20, 55, "Touch cell or use keys", true);
|
||||
}
|
||||
|
||||
// Draw game board (use same layout as touch detection!)
|
||||
int board_x = V_WIDTH - BOARD_SIZE - 20;
|
||||
|
||||
// Draw current turn indicator (large, on left side)
|
||||
if (!state->game_over) {
|
||||
int indicator_x = 60;
|
||||
int indicator_y = V_HEIGHT / 2;
|
||||
int piece_offset = CELL_SIZE / 4;
|
||||
|
||||
if (state->current_player == 1) {
|
||||
// Draw large X
|
||||
renderer->draw_line(indicator_x - piece_offset, indicator_y - piece_offset,
|
||||
indicator_x + piece_offset, indicator_y + piece_offset, true, 4);
|
||||
renderer->draw_line(indicator_x + piece_offset, indicator_y - piece_offset,
|
||||
indicator_x - piece_offset, indicator_y + piece_offset, true, 4);
|
||||
} else {
|
||||
// Draw large O
|
||||
int piece_radius = CELL_SIZE / 4;
|
||||
renderer->draw_circle(indicator_x, indicator_y, piece_radius, true);
|
||||
renderer->draw_circle(indicator_x, indicator_y, piece_radius - 1, true);
|
||||
renderer->draw_circle(indicator_x, indicator_y, piece_radius - 2, true);
|
||||
renderer->draw_circle(indicator_x, indicator_y, piece_radius - 3, true);
|
||||
}
|
||||
}
|
||||
// Draw grid lines
|
||||
for (int i = 1; i < 3; i++) {
|
||||
// Vertical lines
|
||||
renderer->draw_line(board_x + i * CELL_SIZE, BOARD_Y,
|
||||
board_x + i * CELL_SIZE, BOARD_Y + BOARD_SIZE, true, 2);
|
||||
// Horizontal lines
|
||||
renderer->draw_line(board_x, BOARD_Y + i * CELL_SIZE,
|
||||
board_x + BOARD_SIZE, BOARD_Y + i * CELL_SIZE, true, 2);
|
||||
}
|
||||
|
||||
// Draw outer border
|
||||
renderer->draw_rectangle(board_x, BOARD_Y, BOARD_SIZE, BOARD_SIZE, true, 3);
|
||||
|
||||
// Draw X's and O's
|
||||
for (int row = 0; row < 3; row++) {
|
||||
for (int col = 0; col < 3; col++) {
|
||||
int cell_x = board_x + col * CELL_SIZE;
|
||||
int cell_y = BOARD_Y + row * CELL_SIZE;
|
||||
int center_x = cell_x + CELL_SIZE / 2;
|
||||
int center_y = cell_y + CELL_SIZE / 2;
|
||||
|
||||
// Highlight selected cell (for button navigation)
|
||||
if (!state->game_over && row == state->selected_row && col == state->selected_col) {
|
||||
renderer->draw_rectangle(cell_x + 5, cell_y + 5, CELL_SIZE - 10, CELL_SIZE - 10, true, 1);
|
||||
}
|
||||
|
||||
if (state->board[row][col] == 1) {
|
||||
// Draw X
|
||||
int offset = CELL_SIZE / 4;
|
||||
renderer->draw_line(center_x - offset, center_y - offset,
|
||||
center_x + offset, center_y + offset, true, 3);
|
||||
renderer->draw_line(center_x + offset, center_y - offset,
|
||||
center_x - offset, center_y + offset, true, 3);
|
||||
} else if (state->board[row][col] == 2) {
|
||||
// Draw O
|
||||
int radius = CELL_SIZE / 4;
|
||||
renderer->draw_circle(center_x, center_y, radius, true);
|
||||
renderer->draw_circle(center_x, center_y, radius - 1, true);
|
||||
renderer->draw_circle(center_x, center_y, radius - 2, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw statistics at bottom
|
||||
char stats[60];
|
||||
snprintf(stats, sizeof(stats), "X:%d O:%d Tie:%d Moves:%d",
|
||||
state->x_wins, state->o_wins, state->ties, state->total_moves);
|
||||
renderer->draw_string(20, V_HEIGHT - 40, stats, true);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// MAIN PROGRAM
|
||||
@@ -835,16 +315,17 @@ int main()
|
||||
.debug_verbose = false
|
||||
};
|
||||
|
||||
// Initialize game state
|
||||
GameState game_state;
|
||||
// Initialize statistics (persists across game restarts)
|
||||
game_state.x_wins = 0;
|
||||
game_state.o_wins = 0;
|
||||
game_state.ties = 0;
|
||||
game_init(&game_state);
|
||||
// Create InputManager for processing inputs
|
||||
InputManager input_manager(touch, &config);
|
||||
|
||||
// Create game instance (polymorphic - can swap for other games later)
|
||||
Game* current_game = new TicTacToeGame(V_WIDTH, V_HEIGHT, &renderer, &gui);
|
||||
|
||||
// Initialize game
|
||||
current_game->init();
|
||||
|
||||
// Draw initial game graphics
|
||||
game_draw(&game_state, &renderer, &gui);
|
||||
current_game->draw();
|
||||
|
||||
// Refresh the screen with the rendered GUI (async on Core 1)
|
||||
refresh_screen_async(bit_buffer, display);
|
||||
@@ -935,16 +416,16 @@ int main()
|
||||
bool needs_refresh = false;
|
||||
|
||||
// 1. Process button input first (higher priority)
|
||||
input = process_button_input(config);
|
||||
input = input_manager.process_button_input();
|
||||
if (input.valid) {
|
||||
needs_refresh = game_update(&game_state, input, config, &renderer);
|
||||
needs_refresh = current_game->update(input);
|
||||
}
|
||||
|
||||
// 2. Process touch input (if no button was pressed)
|
||||
if (!input.valid) {
|
||||
input = process_touch_input(config, &last_touch_time);
|
||||
input = input_manager.process_touch_input(&last_touch_time);
|
||||
if (input.valid) {
|
||||
needs_refresh = game_update(&game_state, input, config, &renderer);
|
||||
needs_refresh = current_game->update(input);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -952,7 +433,7 @@ int main()
|
||||
if (needs_refresh || pending_refresh) {
|
||||
// Clear buffer and redraw entire UI with updated state
|
||||
memset(bit_buffer, 0, V_WIDTH * V_HEIGHT / 8);
|
||||
game_draw(&game_state, &renderer, &gui);
|
||||
current_game->draw();
|
||||
|
||||
// Request async refresh (non-blocking - handled by Core 1)
|
||||
bool refresh_started = refresh_screen_async(bit_buffer, display);
|
||||
|
||||
Reference in New Issue
Block a user