xlib_playground

Xlib playground for experiments.
Log | Files | Refs

commit 5db2e8fc7018f80a3ddb3a3aef6aeb6f83e080fd
parent 170043ec7675acc7c9042ba28cc4277d751391aa
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Sat, 31 Dec 2022 15:55:46 +0900

rename

Diffstat:
Mex8/main.c | 7-------
Mex8/main.h | 14++++++++++++++
Aex8/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); +}