physics.c (3738B)
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 /* 30 * 1 if collide, 0 if not 31 */ 32 int 33 test_collision(struct Object *o1, struct Object *o2) 34 { 35 if (o1->shape == SRECTANGLE && o2->shape == SRECTANGLE) 36 return test_collision_rr(o1, o2); 37 else { 38 fprintf(stderr, "test_collision for other shapes is not implemented yet\n"); 39 return -1; 40 } 41 } 42 43 static int 44 test_collision_rr(struct Object *o1, struct Object *o2) 45 { 46 if (o1->shape != SRECTANGLE || o2->shape != SRECTANGLE) { 47 fprintf(stderr, "test_collision_rr: invalid objects\n"); 48 return -1; 49 } 50 return o1->p.x < o2->p.x + o2->body.rectangle.w && 51 o2->p.x < o1->p.x + o1->body.rectangle.w && 52 o2->p.y < o1->p.y + o1->body.rectangle.h && 53 o1->p.y < o2->p.y + o2->body.rectangle.h; 54 } 55 56 void 57 next_tick(struct Object *o, long ndt) 58 { 59 switch (o->shape) { 60 case SRECTANGLE: 61 rect_next_tick(o, ndt); 62 break; 63 default: 64 fprintf(stderr, "next_tick: not implemented for other shapes\n"); 65 break; 66 } 67 } 68 69 static void 70 rect_next_tick(struct Object *o, long ndt) 71 { 72 if (o->shape != SRECTANGLE) { 73 fprintf(stderr, "rect_next_tick: invalid object shape\n"); 74 return; 75 } 76 o->pp.x = o->p.x; 77 o->pp.y = o->p.y; 78 o->v.x += o->a.x * ndt / 1e9; 79 o->v.y += o->a.y * ndt / 1e9; 80 o->p.x += o->v.x * ndt / 1e9; 81 o->p.y += o->v.y * ndt / 1e9; 82 } 83 84 void 85 handle_collision_mf(struct Object *om, struct Object *of) 86 { 87 // TODO: too many testing? 88 if (!test_collision(om, of)) 89 return; 90 if (om->shape == SRECTANGLE && of->shape == SRECTANGLE) 91 rect_handle_collision_mf(om, of); 92 else { 93 fprintf(stderr, "handle_collision_mf: not implemented for other shapes\n"); 94 return; 95 } 96 } 97 98 /* 99 * Handle collision of a moving rect against fixed rect 100 */ 101 static void 102 rect_handle_collision_mf(struct Object *om, struct Object *of) 103 { 104 // TODO: too many testing? 105 if (!test_collision(om, of)) 106 return; 107 if (om->pp.x + om->body.rectangle.w <= of->pp.x && 108 of->p.x < om->p.x + om->body.rectangle.w) { 109 // collisioin from left to right 110 om->p.x = of->p.x - om->body.rectangle.w; 111 om->v.x = 0; 112 } 113 if (of->pp.x + of->body.rectangle.w <= om->pp.x && 114 om->p.x < of->p.x + of->body.rectangle.w) { 115 // collision from right to left 116 om->p.x = of->p.x + of->body.rectangle.w; 117 om->v.x = 0; 118 } 119 120 if (om->pp.y + om->body.rectangle.h <= of->pp.y && 121 of->p.y < om->p.y + om->body.rectangle.h) { 122 // collision from up to down 123 om->p.y = of->p.y - om->body.rectangle.h; 124 om->v.y = 0; 125 } 126 if (of->pp.y + of->body.rectangle.h <= om->pp.y && 127 om->p.y < of->p.y + of->body.rectangle.h) { 128 // collision from down to up 129 om->p.y = of->p.y + of->body.rectangle.h; 130 om->v.y = 0; 131 } 132 133 } 134 135 /* 136 * Test if object o is not on top of one of fb (floor blocks). 137 * o: object to be tested, fb: floor blocks, num_f: count of fb. 138 */ 139 int 140 object_is_falling(struct Object *o, struct Object *fb, int num_f) 141 { 142 struct Object p = *o; 143 144 p.v.x = 0; p.v.y = 1; 145 p.a.x = 0; p.a.y = 0; 146 147 next_tick(&p, 1e9); 148 149 for (int i = 0; i < num_f; i++) 150 if (test_collision(&p, &fb[i])) 151 return 0; 152 return 1; 153 }