commit 0e9d36b4d1477c6c470d9602f17266d2fc9aacdf
parent 33fb14b033746c208b9acdc695ebc6722715f6e8
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Sun,  1 Jan 2023 13:21:40 +0900
add falling status
Diffstat:
3 files changed, 44 insertions(+), 11 deletions(-)
diff --git a/ex8/main.c b/ex8/main.c
@@ -116,7 +116,7 @@ game_play(void)
 	int fps_count = 0;
 #endif
 	struct timespec ts;
-	struct OH *blh[WORLD_WIDTH] = {0}; // block list header
+	struct OH *blh[WORLD_WIDTH]; // block list header
 	struct OL *blc;
 
 	for (int xi = 0; xi < WORLD_WIDTH; xi++)
@@ -141,8 +141,6 @@ game_play(void)
 	}
 
 	while (next_menu == GAME_PLAY){
-		clock_gettime(CLOCK_MONOTONIC, &ts);
-		t0 = ts.tv_nsec;
 		receive_events(key_state);
 		handle_inputs(key_state);
 
@@ -152,7 +150,7 @@ game_play(void)
 		for (int k = 0; k < SUB_TICK; k++) {
 			next_tick(player, 1e9 / FPS / SUB_TICK);
 
-			// game over when fall out of the screen
+			// game over when fall out of the world
 			if (player->p.y > WORLD_HEIGHT * BLOCK_SIZE) {
 				next_menu = GAME_OVER;
 				break;
@@ -170,11 +168,15 @@ game_play(void)
 			struct OH *collidings;
 			collidings = create_ol();
 
+			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++) {
 				blc = blh[xi]->first;
 				while (blc != NULL) {
+					if (is_on_floor_before(player, blc->o)) {
+						player_is_falling = 0;
+					}
 					if (test_collision(player, blc->o))
 						append_ol(collidings, blc->o);
 					blc = blc->next;
@@ -188,6 +190,7 @@ game_play(void)
 					blc = blc->next;
 				}
 			}
+			free_ol(collidings);
 		}
 
 		// fix fps
@@ -230,7 +233,7 @@ game_play(void)
 					strlen(status_string));
 	}
 	for (int xi = 0; xi < WORLD_WIDTH; xi++)
-		free_ol(blh[xi]);
+		free_obj_and_ol(blh[xi]);
 }
 
 void
@@ -322,13 +325,13 @@ handle_inputs(enum key_state key_state[])
 		next_menu = GAME_OVER;
 		return;
 	}
-	if (key_state[KEY_D] == KEY_DOWN) {
+	if (key_state[KEY_D] == KEY_DOWN && key_state[KEY_A] == KEY_UP) {
 		if (player->v.x > 0) {
 			player->a.x = 500;
 		} else {
 			player->a.x = 1000;
 		}
-	} else if (key_state[KEY_A] == KEY_DOWN) {
+	} else if (key_state[KEY_A] == KEY_DOWN && key_state[KEY_D] == KEY_UP) {
 		if (player->v.x > 0) {
 			player->a.x = -1000;
 		} else {
@@ -349,8 +352,9 @@ handle_inputs(enum key_state key_state[])
 	if (key_state[KEY_W] == KEY_DOWN)
 		player->v.y += -300;
 	*/
-	if (!player_is_falling && key_state[KEY_SPACE] == KEY_DOWN)
+	if (!player_is_falling && key_state[KEY_SPACE] == KEY_DOWN) {
 		player->v.y = -450;
+	}
 }
 
 void
diff --git a/ex8/main.h b/ex8/main.h
@@ -46,7 +46,7 @@ struct OH {
 };
 
 /*
- * linked list which starts with OH and 
+ * linked list which starts with OH and
  * terminates with ->next == NULL
  */
 struct OL {
@@ -55,6 +55,7 @@ struct OL {
 };
 struct OH *create_ol(void);
 void free_ol(struct OH *);
+void free_obj_and_ol(struct OH *);
 void append_ol(struct OH *, struct Object *);
 void swap_ol(struct OL *, struct OL *);
 void sort_ol(struct OH *, struct Object *);
@@ -84,6 +85,7 @@ void handle_collision_mf(struct Object *, struct Object *);
 int object_is_falling(struct Object *o, struct Object *fb, int num_f);
 struct Object *create_object(float, float, float, float, float, float,
                              int, int, int);
+int is_on_floor_before(struct Object *, struct Object *);
 /*
  * x.c
  */
diff --git a/ex8/util.c b/ex8/util.c
@@ -78,7 +78,7 @@ rect_next_tick(struct Object *o, long ndt)
 	if (o->shape != SRECTANGLE) {
 		fprintf(stderr, "rect_next_tick: invalid object shape\n");
 		return;
-	}		
+	}
 	o->pp.x = o->p.x;
     o->pp.y = o->p.y;
     o->v.x += o->a.x * ndt / 1e9;
@@ -176,7 +176,6 @@ free_ol(struct OH *oh)
 	ol0 = ol1 = oh->first;
 	while (ol1 != NULL) {
 		ol1 = ol0->next;
-		free(ol0->o);
 		free(ol0);
 		ol0 = ol1;
 	}
@@ -184,6 +183,22 @@ free_ol(struct OH *oh)
 }
 
 void
+free_obj_and_ol(struct OH *oh)
+{
+	if (oh == NULL)
+		return;
+	struct OL *ol0, *ol1;
+	ol0 = ol1 = oh->first;
+	while (ol1 != NULL) {
+		ol1 = ol0->next;
+		free(ol0->o);
+		free(ol0);
+		ol0 = ol1;
+	}
+
+}
+
+void
 append_ol(struct OH *oh, struct Object *o)
 {
     struct OL *cur;
@@ -231,3 +246,15 @@ object_dist(struct Object *o1, struct Object *o2)
     return (o1->p.x - o2->p.x) * (o1->p.x - o2->p.x) +
            (o1->p.y - o2->p.y) * (o1->p.y - o2->p.y);
 }
+
+int
+is_on_floor_before(struct Object *player, struct Object *floor)
+{
+	struct Object o = *player;
+	o.p.x = o.pp.x; o.p.y = o.pp.y;
+	o.v.x = 0; o.v.y = 5;
+	o.a.x = 0; o.a.y = 0;
+	next_tick(&o, 1e9);
+	int col = test_collision(&o, floor);
+	return col;
+}