xlib_playground

Xlib playground for experiments.
Log | Files | Refs

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 }