diff options
author | Richard Braun <rbraun@sceen.net> | 2025-05-14 00:47:02 +0200 |
---|---|---|
committer | Richard Braun <rbraun@sceen.net> | 2025-05-14 00:47:02 +0200 |
commit | f3c676a6a7b45888279f952f64fa3cbeb871b780 (patch) | |
tree | 5f938b57e6e3b1941c1f2727d3e086e611b27844 | |
parent | 7615f0310ca90ad2d6f89dece90d73267596dbf2 (diff) |
Erase rows (incomplete)
-rw-r--r-- | src/eetg.c | 83 | ||||
-rw-r--r-- | src/eetg.h | 4 | ||||
-rw-r--r-- | src/ei/ei.c | 4 | ||||
-rw-r--r-- | src/et/et.c | 126 | ||||
-rw-r--r-- | src/et/et.h | 6 |
5 files changed, 171 insertions, 52 deletions
@@ -202,6 +202,26 @@ eetg_layer_remove(struct eetg_layer *layer, struct eetg_object *object) return false; } +static struct eetg_object * +eetg_layer_lookup(struct eetg_layer *layer, int x, int y) +{ + assert(layer); + + for (struct eetg_object *object = layer->objects; + object; + object = object->next) { + char c; + + c = eetg_object_get_char(object, x, y); + + if ((c > 0) && (c != ' ')) { + return object; + } + } + + return NULL; +} + static void eetg_view_cell_set(struct eetg_view_cell *view_cell, char c, int color) @@ -309,12 +329,11 @@ eetg_world_clear(struct eetg_world *world) } void -eetg_world_register_collision_fn(struct eetg_world *world, - eetg_handle_collision_fn handle_collision_fn, - void *arg) +eetg_world_set_collision_fn(struct eetg_world *world, + eetg_handle_collision_fn handle_collision_fn, + void *arg) { assert(world); - assert(handle_collision_fn); world->handle_collision_fn = handle_collision_fn; world->handle_collision_fn_arg = arg; @@ -386,6 +405,27 @@ eetg_world_add(struct eetg_world *world, struct eetg_object *object, return hit; } +struct eetg_object * +eetg_world_lookup(struct eetg_world *world, int x, int y, int layer_id) +{ + assert(world); + + for (int i = ARRAY_SIZE(world->layers) - 1; i >= 0; i--) { + if ((layer_id < 0) || (i == layer_id)) { + struct eetg_layer *layer = &world->layers[i]; + struct eetg_object *object; + + object = eetg_layer_lookup(layer, x, y); + + if (object) { + return object; + } + } + } + + return NULL; +} + void eetg_world_remove(struct eetg_world *world, struct eetg_object *object) { @@ -664,31 +704,22 @@ eetg_world_render(struct eetg_world *world, bool sync) eetg_world_swap_views(world); } -void -eetg_object_init(struct eetg_object *object, int type, const char *sprite) +static void +eetg_object_compute_dimensions(struct eetg_object *object) { size_t width; char *ptr; assert(object); - object->world = NULL; - object->next = NULL; - object->sprite = sprite; - object->type = type; - object->x = 0; - object->y = 0; - object->color = EETG_FG_COLOR; - - ptr = strchr(sprite, '\n'); + ptr = strchr(object->sprite, '\n'); assert(ptr); - width = ptr - sprite; + width = ptr - object->sprite; assert(width <= INT_MAX); object->width = (int)width; object->height = 1; - object->layer_id = -1; for (;;) { char *next; @@ -712,6 +743,23 @@ eetg_object_init(struct eetg_object *object, int type, const char *sprite) } void +eetg_object_init(struct eetg_object *object, int type, const char *sprite) +{ + assert(object); + + object->world = NULL; + object->next = NULL; + object->sprite = sprite; + object->color = EETG_FG_COLOR; + object->type = type; + object->x = 0; + object->y = 0; + object->layer_id = -1; + + eetg_object_compute_dimensions(object); +} + +void eetg_object_set_color(struct eetg_object *object, int color) { assert(object); @@ -823,6 +871,7 @@ eetg_object_update(struct eetg_object *object) { assert(object); + eetg_object_compute_dimensions(object); return eetg_object_move(object, object->x, object->y); } @@ -96,10 +96,12 @@ struct eetg_world { void eetg_world_init(struct eetg_world *world, eetg_write_fn write_fn, void *arg); void eetg_world_clear(struct eetg_world *world); -void eetg_world_register_collision_fn(struct eetg_world *world, +void eetg_world_set_collision_fn(struct eetg_world *world, eetg_handle_collision_fn handle_collision_fn, void *arg); bool eetg_world_add(struct eetg_world *world, struct eetg_object *object, int x, int y, int layer_id); +struct eetg_object *eetg_world_lookup(struct eetg_world *world, + int x, int y, int layer_id); void eetg_world_remove(struct eetg_world *world, struct eetg_object *object); void eetg_world_render(struct eetg_world *world, bool sync); diff --git a/src/ei/ei.c b/src/ei/ei.c index f55e648..665ebf0 100644 --- a/src/ei/ei.c +++ b/src/ei/ei.c @@ -1103,9 +1103,7 @@ ei_game_init(struct ei_game *game, eetg_write_fn write_fn, void *arg) ei_game_reset_history(game); eetg_world_init(&game->world, write_fn, arg); - eetg_world_register_collision_fn(&game->world, - ei_game_handle_collision, - game); + eetg_world_set_collision_fn(&game->world, ei_game_handle_collision, game); eetg_object_init(&game->title, EI_TYPE_TITLE, EI_TITLE_SPRITE); eetg_object_set_color(&game->title, EETG_COLOR_BLUE); diff --git a/src/et/et.c b/src/et/et.c index f8758c4..bc1b673 100644 --- a/src/et/et.c +++ b/src/et/et.c @@ -192,6 +192,14 @@ et_piece_init(struct et_piece *piece) piece->type = -1; } +static struct et_piece * +et_piece_get(struct eetg_object *object) +{ + assert(eetg_object_get_type(object) == ET_TYPE_PIECE); + + return structof(object, struct et_piece, object); +} + static struct eetg_object * et_piece_get_object(struct et_piece *piece) { @@ -574,6 +582,40 @@ et_piece_move_right(struct et_piece *piece) eetg_object_get_y(object)); } +static bool +et_piece_erase_row(struct et_piece *piece, int row) +{ + struct eetg_object *object; + int width, height, src_index, dest_index; + char *src, *dest; + bool empty = false; + + assert(piece); + + object = &piece->object; + + row -= eetg_object_get_y(object); + width = eetg_object_get_width(object); + height = eetg_object_get_height(object); + + assert((row >= 0) && (row < eetg_object_get_height(object))); + + dest_index = row * (width + 1); + src_index = dest_index + width + 1; + src = &piece->sprite[src_index]; + dest = &piece->sprite[dest_index]; + + memmove(dest, src, ((height - row - 1) * (width + 1)) + 1); + + if (piece->sprite[0] == '\0') { + empty = true; + } else { + eetg_object_update(object); + } + + return empty; +} + static struct et_piece * et_game_alloc_piece(struct et_game *game) { @@ -747,35 +789,79 @@ et_game_switch_to_next_piece(struct et_game *game) } static bool +et_game_handle_collision(struct eetg_object *object1, + struct eetg_object *object2, + int x, int y, void *arg) +{ + (void)x; + (void)y; + (void)arg; + + if (et_has_type(object1, object2, ET_TYPE_BG)) { + return false; + } + + return true; +} + +static bool et_game_scan_row(struct et_game *game, int row) { -#if 0 - for (int i = 0; i < ET_FRAME_WIDTH; i += 2) { - int cell; + struct et_piece *pieces[ET_FRAME_WIDTH], *prev; + + for (int i = 0; i < (int)ARRAY_SIZE(pieces); i++) { + struct eetg_object *object; + + object = eetg_world_lookup(&game->world, ET_FRAME_X + (i * 2), row, 1); - cell = eetg_object_get_cell( + if (!object) { + return false; + } + + pieces[i] = et_piece_get(object); } -#endif - return false; + eetg_world_set_collision_fn(&game->world, NULL, NULL); + + for (int i = 0; i < (int)ARRAY_SIZE(pieces); i++) { + struct et_piece *piece = pieces[i]; + bool empty; + + if (piece == prev) { + continue; + } + + empty = et_piece_erase_row(piece, row); + + if (empty) { + eetg_world_remove(&game->world, et_piece_get_object(piece)); + /* TODO Free piece. */ + } else { + et_piece_move_down(piece); + } + + prev = piece; + } + + eetg_world_set_collision_fn(&game->world, et_game_handle_collision, game); + + return true; } static void et_game_scan_rows(struct et_game *game) { - int cleared_rows[4]; int nr_cleared_rows = 0; for (int i = 0; i < ET_FRAME_HEIGHT; i++) { bool cleared; - cleared = et_game_scan_row(game, i); + cleared = et_game_scan_row(game, ET_FRAME_Y + i); if (cleared) { - cleared_rows[nr_cleared_rows] = i; nr_cleared_rows++; - if (nr_cleared_rows == ARRAY_SIZE(cleared_rows)) { + if (nr_cleared_rows == 4) { break; } } @@ -847,22 +933,6 @@ et_game_start_lockdown(struct et_game *game, bool nodelay) } } -static bool -et_game_handle_collision(struct eetg_object *object1, - struct eetg_object *object2, - int x, int y, void *arg) -{ - (void)x; - (void)y; - (void)arg; - - if (et_has_type(object1, object2, ET_TYPE_BG)) { - return false; - } - - return true; -} - static void et_game_reset_history(struct et_game *game) { @@ -1017,9 +1087,7 @@ et_game_init(struct et_game *game, eetg_write_fn write_fn, void *arg) et_bag_init(&game->bag); eetg_world_init(&game->world, write_fn, arg); - eetg_world_register_collision_fn(&game->world, - et_game_handle_collision, - game); + eetg_world_set_collision_fn(&game->world, et_game_handle_collision, game); eetg_object_init(&game->title, ET_TYPE_TITLE, ET_TITLE_SPRITE); eetg_object_set_color(&game->title, EETG_COLOR_BLUE); diff --git a/src/et/et.h b/src/et/et.h index dce0e9a..2c2098e 100644 --- a/src/et/et.h +++ b/src/et/et.h @@ -54,8 +54,10 @@ /* * Take into account the following : - * - Square of the longest piece, with 2 characters per cell when horizontal - * - newlines + * - the longest piece is 4 squares long + * - tetromino squares are one character high, two characters wide + * - each row ends with a newline + * - all sprites are initially squares * - null terminating character */ #define ET_PIECE_SPRITE_SIZE ((((4 * 2) + 1) * 4) + 1) |