+ if(x < s->x || y < s->y || x >= s->x + s->w || y >= s->y + s->h) return 0;
+
+ x -= s->x; y -= s->y;
+ pmask = 0x80000000 >> (x&0x1f);
+ return s->mask[(y*s->mask_w) + (x>>5)] & pmask;
+}
+
+Sprite *
+pixel_hit_in_square(Sprite *r, float x, float y)
+{
+ for(; r; r=r->next) {
+ if(COLLIDES(r) && pixel_collide(r, x, y)) return r;
+ }
+ return 0;
+}
+
+Sprite *
+pixel_collides(float x, float y)
+{
+ int l, t;
+ Sprite **sq;
+ Sprite *ret;
+
+ l = (x + grid_size) / grid_size; t = (y + grid_size) / grid_size;
+ sq = &sprites[set][l + t*gw];
+ if((ret = pixel_hit_in_square(*sq, x, y))) return ret;
+ if(l > 0 && (ret = pixel_hit_in_square(*(sq-1), x, y))) return ret;
+ if(t > 0 && (ret = pixel_hit_in_square(*(sq-gw), x, y))) return ret;
+ if(l > 0 && t > 0 && (ret = pixel_hit_in_square(*(sq-1-gw), x, y))) return ret;
+ return 0;
+}
+
+
+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, vc;
+ float ma, mb;
+
+ // (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 = x*a->dx + y*a->dy;
+ vb = x*b->dx + y*b->dy;
+ if(vb-va > 0) return;
+
+ ma = sprite_mass(a); mb = sprite_mass(b);
+ vc = (va*ma + vb*mb) / (ma+mb);