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:
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 *);