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 }