xlib_playground

Xlib playground for experiments.
Log | Files | Refs

commit 2b6d9e9f22b9fe2d981836465008e53c456df965
parent 8a7689e031500c1675b74eac30a4260cfe77af90
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Tue, 10 Jan 2023 10:31:14 +0900

Change to use a single list for all objects

Collision handling is done in bruteforce method.
I need to implement collision handling so that closer objects are
handled before distant pairs.

Diffstat:
Mex9/main.c | 88++++++++++++++++++++++++++++---------------------------------------------------
Mex9/object.c | 12++++++++++--
Mex9/object.h | 4+++-
3 files changed, 44 insertions(+), 60 deletions(-)

diff --git a/ex9/main.c b/ex9/main.c @@ -133,26 +133,23 @@ game_play(void) int fps_count = 0; #endif struct timespec ts; - struct List *bl[WORLD_WIDTH]; // block list header - struct List *fl; // flag + struct List *bl; // block list struct List *olp; int scroll_dst = 0; - for (int xi = 0; xi < WORLD_WIDTH; xi++) - bl[xi] = NULL; - fl = NULL; + bl = NULL; for (int i = 0; i < NUM_OBJ_TYPE; i++) for (int j = 0; j < NUM_OBJ_TYPE; j++) - col_func[i][j] = &handle_collision_mf; + col_func[i][j] = NULL; col_func[TPLAYER][TFLAG] = col_func[TFLAG][TPLAYER] = &col_pf; - col_func[TPLAYER][TBLOCK] = col_func[TFLAG][TPLAYER] = &col_pb; + col_func[TPLAYER][TBLOCK] = col_func[TBLOCK][TPLAYER] = &col_pb; + /* load world into bl */ for (int i = 0; i < WORLD_WIDTH * WORLD_HEIGHT; i++) { if (world_map[i] == 'b') { - int xi = i % WORLD_WIDTH; // TODO: don't forget to free these things. - olp = laddfront(bl[xi], create_object(TBLOCK, 0x00FF00, + olp = laddfront(bl, create_object(TBLOCK, 0x00FF00, i % WORLD_WIDTH * BLOCK_SIZE, i / WORLD_WIDTH * BLOCK_SIZE, 0, 0, 0, 0, @@ -161,7 +158,7 @@ game_play(void) if (olp == NULL) { fprintf(stderr, "error: adding item to list bl\n"); } else { - bl[xi] = olp; + bl = olp; } } else if (world_map[i] == 'p') { player = create_object(TPLAYER, 0x0000FF, @@ -170,12 +167,15 @@ game_play(void) 0, 0, 0, GRAVITY, BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE * BLOCK_SIZE); - if (player == NULL) { + olp = laddfront(bl, player); + if (player == NULL || olp == NULL) { fprintf(stderr, "error: creating player\n"); exit(1); + } else { + bl = olp; } } else if (world_map[i] == 'f') { - olp = laddfront(fl, create_object(TFLAG, 0xFFFF00, + olp = laddfront(bl, create_object(TFLAG, 0xFFFF00, i % WORLD_WIDTH * BLOCK_SIZE, i / WORLD_WIDTH * BLOCK_SIZE, 0, 0, 0, 0, @@ -184,11 +184,11 @@ game_play(void) if (olp == NULL) { fprintf(stderr, "error: adding item to list fl\n"); } else { - fl = olp; + bl = olp; } } } - + //lprint(bl, (void (*)(void *))&oprint); while (next_menu == GAME_PLAY){ receive_events(key_state); handle_inputs(key_state); @@ -227,34 +227,17 @@ game_play(void) scroll_dst = 0; } - struct List *collidings = NULL; - + // TODO: state of object should be contained in object itself. player_is_falling = 1; - for (int xi = (int) player->p.x / BLOCK_SIZE; - xi <= (int) player->p.x / BLOCK_SIZE + 1 && - xi < WORLD_WIDTH; - xi++) { - for (olp = bl[xi]; olp != NULL; olp = olp->next) { - if (is_on_floor_before(player, (struct Object *)olp->item)) { - player_is_falling = 0; - } - if (test_collision(player, (struct Object *)olp->item)) - collidings = laddfront(collidings, olp->item); - } - } - if (collidings != NULL) { - sort_list_dist(collidings, player); - for (olp = collidings; olp != NULL; olp = olp->next) { - handle_collision(player, (struct Object *)olp->item); + for (olp = bl; olp != NULL; olp = olp->next) { + if (olp->item == player) + continue; + if (is_on_floor_before(player, (struct Object *)olp->item)) { + player_is_falling = 0; } } - lfree(collidings); - - // collision aganst the goal flag - for (olp = fl; olp != NULL; olp = olp->next){ - handle_collision(player, (struct Object *)olp->item); - } + lhandle_collision(bl); } // fix fps @@ -277,28 +260,14 @@ game_play(void) #endif x_clear_area(); - for (int xi = scroll_dst / BLOCK_SIZE; - xi < (WIN_WIDTH + scroll_dst) / BLOCK_SIZE + 1 && - xi < WORLD_WIDTH; xi++) { - for (olp = bl[xi]; olp != NULL; olp = olp->next) { - draw_object_scroll((struct Object *)olp->item, scroll_dst); - } + // TODO: disable drawing outside of window. + for (olp = bl; olp != NULL; olp = olp->next) { + draw_object_scroll((struct Object *)olp->item, scroll_dst); } draw_object_scroll(player, scroll_dst); - for (olp = fl; olp != NULL; olp = olp->next) { - if (0 <= ((struct Object *)olp->item)->p.x - scroll_dst && - ((struct Object *)olp->item)->p.x - scroll_dst < WIN_WIDTH) { - draw_object_scroll((struct Object *)olp->item, scroll_dst); - } else { - break; - } - } - } - for (int xi = 0; xi < WORLD_WIDTH; xi++) - lfreei(bl[xi], (void (*)(void *))&free_object); - lfreei(fl, (void (*)(void *))&free_object); + lfreei(bl, (void (*)(void *))&free_object); } void @@ -448,8 +417,13 @@ void col_pf(struct Object *o0, struct Object *o1) { } void col_pb(struct Object *op, struct Object *ob) { + if (op->type == TBLOCK && ob->type == TPLAYER) { + col_pb(ob, op); + return; + } if (op->type != TPLAYER || ob->type != TBLOCK) { - fprintf(stderr, "col_pb: invalid object type\n"); + fprintf(stderr, "col_pb: invalid object type: [%d, %d]\n", + op->type, ob->type); return; } handle_collision_mf(op, ob); diff --git a/ex9/object.c b/ex9/object.c @@ -183,18 +183,26 @@ is_on_floor_before(struct Object *player, struct Object *floor) } void -handle_collision(struct Object *o0, struct Object *o1) +ohandle_collision(struct Object *o0, struct Object *o1) { + if (col_func[o0->type][o1->type] == NULL) + return; (* col_func[o0->type][o1->type])(o0, o1); } void +oprint(struct Object *o) +{ + printf("[%d: (%4.0f, %4.0f)]", o->type, o->p.x, o->p.y); +} + +void lhandle_collision(struct List *o) { struct List *p, *q; for (p = o; p != NULL && p->next != NULL; p = p->next) { for (q = p->next; q != NULL; q = q->next) { - handle_collision((struct Object *)p, (struct Object *)q); + ohandle_collision((struct Object *)p->item, (struct Object *)q->item); } } return; diff --git a/ex9/object.h b/ex9/object.h @@ -53,7 +53,7 @@ struct Object { extern void (* col_func[NUM_OBJ_TYPE][NUM_OBJ_TYPE])(struct Object *, struct Object *); int object_dist(struct Object *, struct Object *); -void handle_collision(struct Object *, struct Object *); +void ohandle_collision(struct Object *, struct Object *); int test_collision(struct Object *, struct Object *); // 1 if collide, 0 if not void next_tick(struct Object *o, long); void handle_collision_mf(struct Object *, struct Object *); @@ -63,4 +63,6 @@ struct Object *create_object(enum object_type, uint32_t, int, int, int); void free_object(struct Object *); int is_on_floor_before(struct Object *, struct Object *); +void oprint(struct Object *); + void lhandle_collision(struct List *);