6 load_sprite(Sprite *s, char *filename)
8 s->image = load_image(filename);
9 if(s->image) get_shape(s);
17 uint32_t bits = 0, bit, *p;
19 if(s->image->format->BytesPerPixel != 2) {
20 fprintf(stderr, "get_shape(): not a 16-bit image!\n");
24 s->w = s->image->w; s->h = s->image->h;
25 s->mask_w = ((s->image->w+31)>>5);
26 s->mask = malloc(4*s->mask_w*s->h);
28 fprintf(stderr, "get_shape(): can't allocate bitmask.\n");
32 SDL_LockSurface(s->image);
33 px = s->image->pixels;
34 transp = s->image->format->colorkey;
36 for(y=0; y<s->image->h; y++) {
38 for(x=0; x<s->image->w; x++) {
39 if(!bit) { bits = 0; bit = 0x80000000; }
40 if(*px++ != transp) { bits |= bit; }
42 if(!bit || x == s->image->w - 1) { *(p++) = bits; }
44 px = (uint16_t *) ((uint8_t *) px + s->image->pitch - 2*s->image->w);
46 SDL_UnlockSurface(s->image);
50 line_collide(int xov, unsigned bit, uint32_t *amask, uint32_t *bmask)
52 int i, words = (xov-1) >> 5;
55 for(i=0; i<words; i++) {
56 abits = *amask++ << bit;
57 abits |= *amask >> (32-bit);
58 if(abits & *bmask++) return true;
60 abits = *amask << bit;
61 if(abits & *bmask) return true;
67 mask_collide(int xov, int yov, Sprite *a, Sprite *b)
70 int xoffset = a->w - xov;
71 int word = xoffset >> 5, bit = xoffset & 31;
72 uint32_t *amask = a->mask, *bmask = b->mask;
75 amask = a->mask + ((a->h - yov) * a->mask_w) + word;
80 bmask = b->mask + ((b->h - yov) * b->mask_w) + word;
83 for(y=0; y<yov; y++) {
84 if(line_collide(xov, bit, amask, bmask)) return 1;
85 amask += a->mask_w; bmask += b->mask_w;
92 collide(Sprite *a, Sprite *b)
96 if(b->x < a->x) { Sprite *tmp = a; a = b; b = tmp; }
101 xov = max(min(a->w - dx, b->w), 0);
103 if(dy >= 0) yov = max(min(a->h - dy, b->h), 0);
104 else yov = -max(min(a->h - -dy, b->h), 0);
106 if(xov == 0 || yov == 0) return false;
107 else return mask_collide(xov, yov, a, b);
111 pixel_collide(Sprite *s, int x, int y)
115 if(x < s->x || y < s->y || x >= s->x + s->w || y >= s->y + s->h) return 0;
117 x -= s->x; y -= s->y;
118 pmask = 0x80000000 >> (x&0x1f);
119 return s->mask[(y*s->mask_w) + (x>>5)] & pmask;