xlib_playground

Xlib playground for experiments.
Log | Files | Refs

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 }