From d0ba27ee0fba5412c6b559ff15f44cd511169b07 Mon Sep 17 00:00:00 2001 From: Quinn Date: Wed, 29 Jan 2025 11:56:07 +0100 Subject: [PATCH] optimize clearing lines by using pointers to define the row order --- src/game/game.c | 68 +++++++++++++++++++++++++----------- src/game/game.h | 13 ++++--- src/game/tetromino/placing.c | 2 +- src/main.c | 4 +-- src/window/renderer.c | 4 +-- 5 files changed, 59 insertions(+), 32 deletions(-) diff --git a/src/game/game.c b/src/game/game.c index 05a17aa..27c1507 100644 --- a/src/game/game.c +++ b/src/game/game.c @@ -3,7 +3,9 @@ #include #include #include +#include #include +#include #include "../main.h" #include "../window/colour.h" @@ -11,32 +13,58 @@ #include "tetromino/placing.h" -static void clear_row(Row* row, uint8_t y) { - // move the rows down from the specified height - for (; y > 0; y--) - memcpy(row[y].columns, row[y - 1].columns, COLUMNS * sizeof(Colour)); +void game_init(GameData* const game_data) { + // zero-initialize the game data + *game_data = (GameData){0}; - memset(row[0].columns, NONE, sizeof(Colour)); + // write the pointer information for the rows + for (uint8_t i = 0; i < ROWS; i++) + game_data->row[i] = game_data->row_raw[i]; + + // set a random seed using the system clock + srand(time(NULL)); +} + +static bool is_filled(CRow row) { + for (uint8_t x = 0; x < COLUMNS; x++) { + if (row[x].packed == NONE) { + return false; + } + } + + return true; +} + +static inline void set_row(Row* rows, const uint8_t y, Row row) { + rows[(ROWS - 1) - y] = row; } static void clear_rows(Row* row) { - // start at the lowest row - // integer will wrap - for (uint8_t y = ROWS - 1; y < ROWS; y--) { - Row* crow = &row[y]; // the current row - bool nfilled = false; // whether this row is filled + uint8_t filled_rows = 0; - // loop through all the columns or till nfilled is true - for (uint8_t x = 0; x < COLUMNS; x++) { - if (crow->columns[x].packed == NONE) { - nfilled = true; - break; - } + // loop through each row + for (uint8_t y = 0; y < ROWS; y++) { + // zero out the row instead if we've reached the top rows + if ((ROWS - y) <= filled_rows) { + for (uint8_t x = 0; x < COLUMNS; x++) + row[filled_rows--][x].packed = 0; // use filled_rows as the y index and decrease them as we go. + continue; } - // continue if the row isn;t filled - if (!nfilled) - clear_row(crow, y); + // get the row we currently need to check + Row crow = filled_rows > 0 + ? row[y + filled_rows] + : row[y]; + + // set the current y to the current row + Row row_cache = row[y]; + set_row(row, y, crow); + + if (!is_filled(crow)) continue; + + // write the cached row to the top if we know that the current row pointer will be lost + row[filled_rows] = row_cache; + filled_rows++; } } @@ -66,5 +94,5 @@ void game_update(GameData* game_data, const uint8_t* keys) { update_input(game_data, keys); // tmp_set_random(game_data); - // tmp_set_all(game_data); + tmp_set_all(game_data); } diff --git a/src/game/game.h b/src/game/game.h index 37d70df..bf680c4 100644 --- a/src/game/game.h +++ b/src/game/game.h @@ -15,15 +15,14 @@ typedef struct { uint8_t y; } SelectedShape; -typedef struct { - Colour columns[COLUMNS]; -} Row; - +typedef const Colour* CRow; +typedef Colour* Row; typedef struct { SelectedShape selected; - Row row[ROWS]; + Colour* row[ROWS]; // stores how to interpert the raw level data + Colour row_raw[ROWS][COLUMNS]; // stores the raw level data } GameData; -// updates the game's state -void game_update(GameData* game_data, const uint8_t* keys); +void game_init(GameData* game_data); // initializes the game +void game_update(GameData* game_data, const uint8_t* keys); // updates the game's state diff --git a/src/game/tetromino/placing.c b/src/game/tetromino/placing.c index 9cc294c..31e3a5c 100644 --- a/src/game/tetromino/placing.c +++ b/src/game/tetromino/placing.c @@ -19,7 +19,7 @@ static void set_shape_i(Row* row, const ShapeId id, const uint8_t pos_x) { for (uint8_t x = 0; x < SHAPE_WIDTH; x++) if (is_set(shape_row, x)) - row[y].columns[x + pos_x] = colour; + row[y][x + pos_x] = colour; } } diff --git a/src/main.c b/src/main.c index 5710099..80201bf 100644 --- a/src/main.c +++ b/src/main.c @@ -43,8 +43,8 @@ static void init(void) { return; } - // set a random seed using the system clock - srand(time(NULL)); + // initialize the game + game_init(&game_data); // initialize audio // AudioDevice* audio_device = audio_device_init(32000, AUDIO_S16, 1, 4096); diff --git a/src/window/renderer.c b/src/window/renderer.c index ce2bc0a..a7d7e17 100644 --- a/src/window/renderer.c +++ b/src/window/renderer.c @@ -74,8 +74,8 @@ void renderer_update(const RenderData* render_data) { Row row = data->row[y]; for (uint8_t x = 0; x < COLUMNS; x++) { - if (row.columns[x].packed != 0) { - set_colour(renderer, row.columns[x]); + if (row[x].packed != 0) { + set_colour(renderer, row[x]); success |= draw_block(renderer, x, y); } }