xlib_playground

Xlib playground for experiments.
Log | Files | Refs

util.c (5616B)


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