+
+
+static float
+sprite_mass(Sprite *s)
+{
+ if(s->type == SHIP) return s->area;
+ else if(s->type == ROCK) return 3*s->area;
+ else return 0;
+}
+
+void
+bounce(Sprite *a, Sprite *b)
+{
+ float x, y, n;
+ float va, vb;
+ float ma, mb, mr;
+
+ // (x, y) is unit vector pointing from A's center to B's center.
+ x = (b->x + b->w / 2) - (a->x + a->w / 2);
+ y = (b->y + b->h / 2) - (a->y + a->h / 2);
+ n = sqrt(x*x + y*y); x /= n; y /= n;
+
+ // velocities along (x, y), or 0 if already moving away.
+ va = max(x*a->dx + y*a->dy, 0);
+ vb = min(x*b->dx + y*b->dy, 0);
+
+ // mass ratio
+ ma = sprite_mass(a); mb = sprite_mass(b);
+ if(ma && mb) mr = mb/ma; else mr = 1;
+
+ a->dx += x*(mb*vb - ma*va)/ma; a->dy += y*(mb*vb - ma*va)/ma;
+ b->dx += x*(ma*va - mb*vb)/mb; b->dy += y*(ma*va - mb*vb)/mb;
+}