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 }