physics.c (3314B)
1 #include <stdio.h> 2 3 #include "main.h" 4 5 static int test_collision_rr(struct Object *, struct Object *); 6 static void rect_next_tick(struct Object *, long); 7 static void rect_handle_collision_mf(struct Object *, struct Object *); 8 9 /* 10 * 1 if collide, 0 if not 11 */ 12 int 13 test_collision(struct Object *o1, struct Object *o2) 14 { 15 if (o1->shape == SRECTANGLE && o2->shape == SRECTANGLE) 16 return test_collision_rr(o1, o2); 17 else { 18 fprintf(stderr, "test_collision for other shapes is not implemented yet\n"); 19 return -1; 20 } 21 } 22 23 static int 24 test_collision_rr(struct Object *o1, struct Object *o2) 25 { 26 if (o1->shape != SRECTANGLE || o2->shape != SRECTANGLE) { 27 fprintf(stderr, "test_collision_rr: invalid objects\n"); 28 return -1; 29 } 30 return o1->p.x < o2->p.x + o2->body.rectangle.w && 31 o2->p.x < o1->p.x + o1->body.rectangle.w && 32 o2->p.y < o1->p.y + o1->body.rectangle.h && 33 o1->p.y < o2->p.y + o2->body.rectangle.h; 34 } 35 36 void 37 next_tick(struct Object *o, long ndt) 38 { 39 switch (o->shape) { 40 case SRECTANGLE: 41 rect_next_tick(o, ndt); 42 break; 43 default: 44 fprintf(stderr, "next_tick: not implemented for other shapes\n"); 45 break; 46 } 47 } 48 49 static void 50 rect_next_tick(struct Object *o, long ndt) 51 { 52 if (o->shape != SRECTANGLE) { 53 fprintf(stderr, "rect_next_tick: invalid object shape\n"); 54 return; 55 } 56 o->pp.x = o->p.x; 57 o->pp.y = o->p.y; 58 o->v.x += o->a.x * ndt / 1e9; 59 o->v.y += o->a.y * ndt / 1e9; 60 o->p.x += o->v.x * ndt / 1e9; 61 o->p.y += o->v.y * ndt / 1e9; 62 } 63 64 void 65 handle_collision_mf(struct Object *om, struct Object *of) 66 { 67 // TODO: too many testing? 68 if (!test_collision(om, of)) 69 return; 70 if (om->shape == SRECTANGLE && of->shape == SRECTANGLE) 71 rect_handle_collision_mf(om, of); 72 else { 73 fprintf(stderr, "handle_collision_mf: not implemented for other shapes\n"); 74 return; 75 } 76 } 77 78 /* 79 * Handle collision of a moving rect against fixed rect 80 */ 81 static void 82 rect_handle_collision_mf(struct Object *om, struct Object *of) 83 { 84 // TODO: too many testing? 85 if (!test_collision(om, of)) 86 return; 87 if (om->pp.x + om->body.rectangle.w <= of->pp.x && 88 of->p.x < om->p.x + om->body.rectangle.w) { 89 // collisioin from left to right 90 om->p.x = of->p.x - om->body.rectangle.w; 91 om->v.x = 0; 92 } 93 if (of->pp.x + of->body.rectangle.w <= om->pp.x && 94 om->p.x < of->p.x + of->body.rectangle.w) { 95 // collision from right to left 96 om->p.x = of->p.x + of->body.rectangle.w; 97 om->v.x = 0; 98 } 99 100 if (om->pp.y + om->body.rectangle.h <= of->pp.y && 101 of->p.y < om->p.y + om->body.rectangle.h) { 102 // collision from up to down 103 om->p.y = of->p.y - om->body.rectangle.h; 104 om->v.y = 0; 105 } 106 if (of->pp.y + of->body.rectangle.h <= om->pp.y && 107 om->p.y < of->p.y + of->body.rectangle.h) { 108 // collision from down to up 109 om->p.y = of->p.y + of->body.rectangle.h; 110 om->v.y = 0; 111 } 112 113 } 114 115 /* 116 * Test if object o is not on top of one of fb (floor blocks). 117 * o: object to be tested, fb: floor blocks, num_f: count of fb. 118 */ 119 int 120 object_is_falling(struct Object *o, struct Object *fb, int num_f) 121 { 122 struct Object p = *o; 123 124 p.v.x = 0; p.v.y = 1; 125 p.a.x = 0; p.a.y = 0; 126 127 next_tick(&p, 1e9); 128 129 for (int i = 0; i < num_f; i++) 130 if (test_collision(&p, &fb[i])) 131 return 0; 132 return 1; 133 }