commit 5db2e8fc7018f80a3ddb3a3aef6aeb6f83e080fd
parent 170043ec7675acc7c9042ba28cc4277d751391aa
Author: Matsuda Kenji <info@mtkn.jp>
Date: Sat, 31 Dec 2022 15:55:46 +0900
rename
Diffstat:
M | ex8/main.c | | | 7 | ------- |
M | ex8/main.h | | | 14 | ++++++++++++++ |
A | ex8/util.c | | | 227 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
3 files changed, 241 insertions(+), 7 deletions(-)
diff --git a/ex8/main.c b/ex8/main.c
@@ -381,13 +381,6 @@ swap_ll(struct OL *oi, struct OL *oj)
oj->o = tmp;
}
-int
-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);
-}
-
void
sort_ll(struct OL *ol, struct Object *player)
{
diff --git a/ex8/main.h b/ex8/main.h
@@ -41,10 +41,24 @@ struct Object {
int m;
};
+struct OH {
+ struct OL *first;
+};
+
+/*
+ * linked list which starts with OH and
+ * terminates with ->next == NULL
+ */
struct OL {
struct Object *o;
struct OL *next;
};
+struct OH *create_ol(void);
+void free_ol(struct OH *);
+void append_ol(struct OH *, struct Object *);
+void swap_ol(struct OL *, struct OL *);
+void sort_ol(struct OH *, struct Object *);
+int object_dist(struct Object *, struct Object *);
struct rect {
struct Point pp;
diff --git a/ex8/util.c b/ex8/util.c
@@ -0,0 +1,227 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "main.h"
+
+static int test_collision_rr(struct Object *, struct Object *);
+static void rect_next_tick(struct Object *, long);
+static void rect_handle_collision_mf(struct Object *, struct Object *);
+
+struct Object *
+create_object(float px, float py, float vx, float vy, float ax, float ay,
+ int w, int h, int m)
+{
+ struct Object *o;
+ o = (struct Object *)malloc(sizeof(struct Object));
+ o->pp.x = o->p.x = px;
+ o->pp.y = o->p.y = py;
+ o->v.x = vx;
+ o->v.y = vy;
+ o->a.x = ax;
+ o->a.y = ay;
+ o->shape = SRECTANGLE;
+ o->body.rectangle.w = w;
+ o->body.rectangle.h = h;
+ o->m = m;
+ return o;
+}
+
+/*
+ * 1 if collide, 0 if not
+ */
+int
+test_collision(struct Object *o1, struct Object *o2)
+{
+ if (o1->shape == SRECTANGLE && o2->shape == SRECTANGLE)
+ return test_collision_rr(o1, o2);
+ else {
+ fprintf(stderr, "test_collision for other shapes is not implemented yet\n");
+ return -1;
+ }
+}
+
+static int
+test_collision_rr(struct Object *o1, struct Object *o2)
+{
+ if (o1->shape != SRECTANGLE || o2->shape != SRECTANGLE) {
+ fprintf(stderr, "test_collision_rr: invalid objects\n");
+ return -1;
+ }
+ return o1->p.x < o2->p.x + o2->body.rectangle.w &&
+ o2->p.x < o1->p.x + o1->body.rectangle.w &&
+ o2->p.y < o1->p.y + o1->body.rectangle.h &&
+ o1->p.y < o2->p.y + o2->body.rectangle.h;
+}
+
+void
+next_tick(struct Object *o, long ndt)
+{
+ switch (o->shape) {
+ case SRECTANGLE:
+ rect_next_tick(o, ndt);
+ break;
+ default:
+ fprintf(stderr, "next_tick: not implemented for other shapes\n");
+ break;
+ }
+}
+
+static void
+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;
+ o->v.y += o->a.y * ndt / 1e9;
+ o->p.x += o->v.x * ndt / 1e9;
+ o->p.y += o->v.y * ndt / 1e9;
+}
+
+void
+handle_collision_mf(struct Object *om, struct Object *of)
+{
+ // TODO: too many testing?
+ if (!test_collision(om, of))
+ return;
+ if (om->shape == SRECTANGLE && of->shape == SRECTANGLE)
+ rect_handle_collision_mf(om, of);
+ else {
+ fprintf(stderr, "handle_collision_mf: not implemented for other shapes\n");
+ return;
+ }
+}
+
+/*
+ * Handle collision of a moving rect against fixed rect
+ */
+static void
+rect_handle_collision_mf(struct Object *om, struct Object *of)
+{
+ // TODO: too many testing?
+ if (!test_collision(om, of))
+ return;
+ if (om->pp.x + om->body.rectangle.w <= of->pp.x &&
+ of->p.x < om->p.x + om->body.rectangle.w) {
+ // collisioin from left to right
+ om->p.x = of->p.x - om->body.rectangle.w;
+ om->v.x = 0;
+ }
+ if (of->pp.x + of->body.rectangle.w <= om->pp.x &&
+ om->p.x < of->p.x + of->body.rectangle.w) {
+ // collision from right to left
+ om->p.x = of->p.x + of->body.rectangle.w;
+ om->v.x = 0;
+ }
+
+ if (om->pp.y + om->body.rectangle.h <= of->pp.y &&
+ of->p.y < om->p.y + om->body.rectangle.h) {
+ // collision from up to down
+ om->p.y = of->p.y - om->body.rectangle.h;
+ om->v.y = 0;
+ }
+ if (of->pp.y + of->body.rectangle.h <= om->pp.y &&
+ om->p.y < of->p.y + of->body.rectangle.h) {
+ // collision from down to up
+ om->p.y = of->p.y + of->body.rectangle.h;
+ om->v.y = 0;
+ }
+
+}
+
+/*
+ * Test if object o is not on top of one of fb (floor blocks).
+ * o: object to be tested, fb: floor blocks, num_f: count of fb.
+ */
+int
+object_is_falling(struct Object *o, struct Object *fb, int num_f)
+{
+ struct Object p = *o;
+
+ p.v.x = 0; p.v.y = 1;
+ p.a.x = 0; p.a.y = 0;
+
+ next_tick(&p, 1e9);
+
+ for (int i = 0; i < num_f; i++)
+ if (test_collision(&p, &fb[i]))
+ return 0;
+ return 1;
+}
+
+struct OH *
+create_ol(void)
+{
+ struct OH *oh;
+ oh = (struct OH *)malloc(sizeof(struct OH));
+ oh->first = NULL;
+ return oh;
+}
+
+void
+free_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;
+ }
+ free(oh);
+}
+
+void
+append_ol(struct OH *oh, struct Object *o)
+{
+ struct OL *cur;
+
+ if (oh->first == NULL) {
+ oh->first = (struct OL *)malloc(sizeof(struct OL));
+ cur = oh->first;
+ } else {
+ cur = oh->first;
+ while (cur->next != NULL)
+ cur = cur->next;
+ cur->next = (struct OL *)malloc(sizeof(struct OL));
+ cur = cur->next;
+ }
+ cur->o = o;
+ cur->next = NULL;
+}
+
+void
+swap_ol(struct OL *ol0, struct OL *ol1)
+{
+ struct Object *tmp;
+ tmp = ol0->o;
+ ol0->o = ol1->o;
+ ol1->o = tmp;
+}
+
+void
+sort_ol(struct OH *oh, struct Object *player)
+{
+ if (oh == NULL)
+ return;
+ struct OL *oi, *oj;
+ for (oi = oh->first; oi->next != NULL; oi = oi->next) {
+ for (oj = oi->next; oj != NULL; oj = oj->next) {
+ if (object_dist(oj->o, player) < object_dist(oi->o, player))
+ swap_ol(oi, oj);
+ }
+ }
+}
+
+int
+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);
+}