xlib_playground

Xlib playground for experiments.
Log | Files | Refs

util.c (5607B)


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <stdint.h>
      4 
      5 #include "main.h"
      6 
      7 static int test_collision_rr(struct Object *, struct Object *);
      8 static void rect_next_tick(struct Object *, long);
      9 static void rect_handle_collision_mf(struct Object *, struct Object *);
     10 
     11 struct Object *
     12 create_object(enum object_type t, uint32_t color,
     13               float px, float py, float vx, float vy, float ax, float ay,
     14               int w, int h, int m)
     15 {
     16 	struct Object *o;
     17 	o = (struct Object *)malloc(sizeof(struct Object));
     18 	o->type = t;
     19 	o->color = color;
     20 	o->shape = SRECTANGLE;
     21 	o->pp.x = o->p.x = px;
     22 	o->pp.y = o->p.y = py;
     23 	o->v.x = vx;
     24 	o->v.y = vy;
     25 	o->a.x = ax;
     26 	o->a.y = ay;
     27 	o->body.rectangle.w = w;
     28 	o->body.rectangle.h = h;
     29 	o->m = m;
     30 	return o;
     31 }
     32 
     33 void
     34 free_object(struct Object *o)
     35 {
     36 	free(o);
     37 }
     38 
     39 /*
     40  * 1 if collide, 0 if not
     41  */
     42 int
     43 test_collision(struct Object *o1, struct Object *o2)
     44 {
     45 	if (o1->shape == SRECTANGLE && o2->shape == SRECTANGLE)
     46 		return test_collision_rr(o1, o2);
     47 	else {
     48 		fprintf(stderr, "test_collision for other shapes is not implemented yet\n");
     49 		return -1;
     50 	}
     51 }
     52 
     53 static int
     54 test_collision_rr(struct Object *o1, struct Object *o2)
     55 {
     56 	if (o1->shape != SRECTANGLE || o2->shape != SRECTANGLE) {
     57 		fprintf(stderr, "test_collision_rr: invalid objects\n");
     58 		return -1;
     59 	}
     60 	return o1->p.x < o2->p.x + o2->body.rectangle.w &&
     61 		   o2->p.x < o1->p.x + o1->body.rectangle.w &&
     62 	       o2->p.y < o1->p.y + o1->body.rectangle.h &&
     63 		   o1->p.y < o2->p.y + o2->body.rectangle.h;
     64 }
     65 
     66 void
     67 next_tick(struct Object *o, long ndt)
     68 {
     69 	switch (o->shape) {
     70 	case SRECTANGLE:
     71 		rect_next_tick(o, ndt);
     72 		break;
     73 	default:
     74 		fprintf(stderr, "next_tick: not implemented for other shapes\n");
     75 		break;
     76 	}
     77 }
     78 
     79 static void
     80 rect_next_tick(struct Object *o, long ndt)
     81 {
     82 	if (o->shape != SRECTANGLE) {
     83 		fprintf(stderr, "rect_next_tick: invalid object shape\n");
     84 		return;
     85 	}
     86 	o->pp.x = o->p.x;
     87     o->pp.y = o->p.y;
     88     o->v.x += o->a.x * ndt / 1e9;
     89     o->v.y += o->a.y * ndt / 1e9;
     90     o->p.x += o->v.x * ndt / 1e9;
     91     o->p.y += o->v.y * ndt / 1e9;
     92 }
     93 
     94 void
     95 handle_collision_mf(struct Object *om, struct Object *of)
     96 {
     97 	// TODO: too many testing?
     98 	if (!test_collision(om, of))
     99 		return;
    100 	if (om->shape == SRECTANGLE && of->shape == SRECTANGLE)
    101 		rect_handle_collision_mf(om, of);
    102 	else {
    103 		fprintf(stderr, "handle_collision_mf: not implemented for other shapes\n");
    104 		return;
    105 	}
    106 }
    107 
    108 /*
    109  * Handle collision of a moving rect against fixed rect
    110  */
    111 static void
    112 rect_handle_collision_mf(struct Object *om, struct Object *of)
    113 {
    114 	// TODO: too many testing?
    115     if (!test_collision(om, of))
    116         return;
    117     if (om->pp.x + om->body.rectangle.w <= of->pp.x &&
    118         of->p.x < om->p.x + om->body.rectangle.w) {
    119         // collisioin from left to right
    120         om->p.x = of->p.x - om->body.rectangle.w;
    121         om->v.x = 0;
    122     }
    123     if (of->pp.x + of->body.rectangle.w <= om->pp.x &&
    124         om->p.x < of->p.x + of->body.rectangle.w) {
    125         // collision from right to left
    126         om->p.x = of->p.x + of->body.rectangle.w;
    127         om->v.x = 0;
    128     }
    129 
    130     if (om->pp.y + om->body.rectangle.h <= of->pp.y &&
    131         of->p.y < om->p.y + om->body.rectangle.h) {
    132         // collision from up to down
    133         om->p.y = of->p.y - om->body.rectangle.h;
    134         om->v.y = 0;
    135     }
    136     if (of->pp.y + of->body.rectangle.h <= om->pp.y &&
    137         om->p.y < of->p.y + of->body.rectangle.h) {
    138         // collision from down to up
    139         om->p.y = of->p.y + of->body.rectangle.h;
    140         om->v.y = 0;
    141     }
    142 
    143 }
    144 
    145 /*
    146  * Test if object o is not on top of one of fb (floor blocks).
    147  * o: object to be tested, fb: floor blocks, num_f: count of fb.
    148  */
    149 int
    150 object_is_falling(struct Object *o, struct Object *fb, int num_f)
    151 {
    152 	struct Object p = *o;
    153 
    154 	p.v.x = 0; p.v.y = 1;
    155 	p.a.x = 0; p.a.y = 0;
    156 
    157 	next_tick(&p, 1e9);
    158 
    159 	for (int i = 0; i < num_f; i++)
    160 		if (test_collision(&p, &fb[i]))
    161 			return 0;
    162 	return 1;
    163 }
    164 
    165 struct OL *
    166 create_ol(void)
    167 {
    168 	struct OL *ol;
    169 	ol = (struct OL *)malloc(sizeof(struct OL));
    170 	ol->next = NULL;
    171 	ol->o = NULL;
    172 	return ol;
    173 }
    174 
    175 void
    176 free_ol(struct OL *ol)
    177 {
    178 	struct OL *p, *q;
    179 	for (p = q = ol; q != NULL; p = q) {
    180 		q = p->next;
    181 		free(p); // asume that p->o is freed elsewhere
    182 	}
    183 }
    184 
    185 void
    186 free_obj_and_ol(struct OL *ol)
    187 {
    188 	struct OL *p, *q;
    189 	for (p = q = ol; q != NULL; p = q) {
    190 		q = p->next;
    191 		free(p->o);
    192 		free(p);
    193 	}
    194 }
    195 
    196 struct OL *
    197 addfront_ol(struct OL *ol, struct Object *o)
    198 {
    199     struct OL *nol;
    200 	nol = (struct OL *)malloc(sizeof(struct OL));
    201 	nol->next = ol;
    202 	nol->o = o;
    203 	return nol;
    204 }
    205 
    206 void
    207 swap_ol(struct OL *p, struct OL *q)
    208 {
    209 	struct Object *tmp;
    210 	tmp = p->o;
    211 	p->o = q->o;
    212 	q->o = tmp;
    213 }
    214 
    215 void
    216 sort_ol(struct OL *ol, struct Object *player)
    217 {
    218     struct OL *p, *q;
    219     for (p = ol; p != NULL && p->next != NULL; p = p->next) {
    220         for (q = p->next; q != NULL; q = q->next) {
    221             if (object_dist(q->o, player) < object_dist(p->o, player))
    222                 swap_ol(p, q);
    223         }
    224     }
    225 }
    226 
    227 int
    228 object_dist(struct Object *o1, struct Object *o2)
    229 {
    230     return (o1->p.x - o2->p.x) * (o1->p.x - o2->p.x) +
    231            (o1->p.y - o2->p.y) * (o1->p.y - o2->p.y);
    232 }
    233 
    234 int
    235 is_on_floor_before(struct Object *player, struct Object *floor)
    236 {
    237 	struct Object o = *player;
    238 	o.p.x = o.pp.x; o.p.y = o.pp.y;
    239 	o.v.x = 0; o.v.y = 5;
    240 	o.a.x = 0; o.a.y = 0;
    241 	next_tick(&o, 1e9);
    242 	int col = test_collision(&o, floor);
    243 	return col;
    244 }
    245 
    246 void handle_collision(struct Object *o0, struct Object *o1) {
    247 	(* col_func[o0->type][o1->type])(o0, o1);
    248 }
    249 
    250 void print_ol(struct OL *ol) {
    251 	for (; ol != NULL; ol = ol->next) {
    252 		printf("(%3.0f, %3.0f)%s", ol->o->p.x, ol->o->p.y,
    253 			ol->next == NULL ? "\n" : "->");
    254 	}
    255 }