From 0856301c41359e63b575a0f7d42bc5923ca51c54 Mon Sep 17 00:00:00 2001 From: Quinn Date: Wed, 29 Jan 2025 13:09:06 +0100 Subject: [PATCH] add collision --- src/game/game.c | 28 ++++----------- src/game/tetromino/placing.c | 70 ++++++++++++++++++++++++++++-------- src/game/tetromino/placing.h | 8 ++++- 3 files changed, 69 insertions(+), 37 deletions(-) diff --git a/src/game/game.c b/src/game/game.c index 3889a63..36f18f5 100644 --- a/src/game/game.c +++ b/src/game/game.c @@ -21,6 +21,8 @@ void game_init(GameData* const game_data) { for (uint8_t i = 0; i < ROWS; i++) game_data->row[i] = game_data->row_raw[i]; + game_data->selected = (SelectedShape){TETROMINO_L, 0, 0}; + // set a random seed using the system clock srand(time(NULL)); } @@ -68,31 +70,13 @@ static void clear_rows(Row* row) { } } -static void update_input(GameData* game_data, const uint8_t* keys) { - if (keys[SDL_SCANCODE_ESCAPE]) - stop(); - - if (keys[SDL_SCANCODE_DOWN] || keys[SDL_SCANCODE_S] || keys[SDL_SCANCODE_SPACE]) - game_data->selected.y++; - - if (keys[SDL_SCANCODE_LEFT] || keys[SDL_SCANCODE_A]) - game_data->selected.x--; - - if (keys[SDL_SCANCODE_RIGHT] || keys[SDL_SCANCODE_D]) - game_data->selected.x++; -} // called every time the game's state is updated void game_update(GameData* game_data, const uint8_t* keys) { - static int x = 0; - if (!x) { - x = 1; - game_data->selected = (SelectedShape){TETROMINO_L, 0, 0}; - } + if (keys[SDL_SCANCODE_ESCAPE]) + stop(); - update_input(game_data, keys); - - // tmp_set_random(game_data); - dbg_set_all(game_data); + place_update(game_data, keys); + // dbg_set_all(game_data); } diff --git a/src/game/tetromino/placing.c b/src/game/tetromino/placing.c index 0b74408..d4feb61 100644 --- a/src/game/tetromino/placing.c +++ b/src/game/tetromino/placing.c @@ -5,6 +5,7 @@ #include "../../window/colour.h" #include "../game.h" +#include "SDL_scancode.h" #include "shapes.h" // sets a shape to the screen @@ -27,6 +28,61 @@ static inline void set_shape(Row* row, const ShapeId id, const uint8_t pos_x, co set_shape_i(&row[pos_y], id, pos_x); // calls itself, but omitting the pos_y argument, instead opting for specifying the row } +static bool shape_intersects(const Row* rows, const ShapeId id, const uint8_t x, const uint8_t y) { + const Shape shape = shape_from_id(id); + + for (uint8_t y0 = 0; y0 < SHAPE_HEIGHT; y0++) { + const ShapeRow shape_row = shape_get_row(shape, y0); // get the shape row + if (shape_row == 0) continue; // if the row doesn't contain data; continue + + for (uint8_t x0 = 0; x0 < SHAPE_WIDTH; x0++) { + if (is_set(shape_row, x0) == false) continue; // if the bit isn't set at this index; continue + const uint8_t x1 = x + x0; + const uint8_t y1 = y + y0; + + if (x1 < 0 || x1 >= COLUMNS) return true; // if X is out of bounds + if (y1 < 0 || y1 >= ROWS) return true; // if Y is out of bounds + if (rows[y1][x1].packed != 0) return true; // if there is a block here + } + } + return false; +} + +void place_update(GameData* const game_data, const uint8_t* const keys) { + int8_t move = 0; + + if (keys[SDL_SCANCODE_LEFT] || keys[SDL_SCANCODE_A]) + move |= 1; + + if (keys[SDL_SCANCODE_RIGHT] || keys[SDL_SCANCODE_D]) + move |= 2; + + if (keys[SDL_SCANCODE_DOWN] || keys[SDL_SCANCODE_S] || keys[SDL_SCANCODE_SPACE]) + move |= 4; + + // set the shape if we moved vertically and collided + if (!!(move & 4)) { + const uint8_t y = game_data->selected.y + 1; + if (shape_intersects(game_data->row, game_data->selected.id, game_data->selected.x, y)) { + set_shape(game_data->row, game_data->selected.id, game_data->selected.x, y); + return; + } + + game_data->selected.y = y; + } + + // ignore if the movement cancles itself out + if ((move & 3) == 0 || (move & 3) == 3) + return; + + const uint8_t x = game_data->selected.x + ((move & 3) == 1 ? -1 : 1); + if (shape_intersects(game_data->row, game_data->selected.id, x, game_data->selected.y)) + return; + + game_data->selected.x = x; + printf("%i\n", x); +} + #ifdef DEBUG void dbg_set_all(GameData* game_data) { for (uint8_t i = 0; i < TETROMINO_COUNT; i++) @@ -34,17 +90,3 @@ void dbg_set_all(GameData* game_data) { set_shape(game_data->row, i | (r << 3), r * 4, i * 4); } #endif - -void tmp_set_random(GameData* game_data) { - static int finished = 0; - if (finished) - return; - - finished = 1; - for (uint8_t y = 0; y <= ROWS - SHAPE_HEIGHT; y += SHAPE_HEIGHT) { - for (uint8_t x = 0; x <= COLUMNS - SHAPE_WIDTH; x += SHAPE_WIDTH) { - const ShapeId id = (rand() % TETROMINO_COUNT) | ((rand() % 4) << 3); - set_shape(game_data->row, id, x, y); - } - } -} diff --git a/src/game/tetromino/placing.h b/src/game/tetromino/placing.h index f055761..6e8fff1 100644 --- a/src/game/tetromino/placing.h +++ b/src/game/tetromino/placing.h @@ -1,7 +1,13 @@ #pragma once +#include +#include + #include "../game.h" +#include "shapes.h" +void place_update(GameData* game_data, const uint8_t* keys); -void tmp_set_random(GameData* game_data); +#ifdef DEBUG void dbg_set_all(GameData* game_data); +#endif