X-Git-Url: https://jasonwoof.com/gitweb/?p=vor.git;a=blobdiff_plain;f=sprite.c;h=1609368d324ab653070e6315e90d75b2260ed774;hp=a772668b104254a65b57153b3b52d65d136be1db;hb=e06676edd300c8a85d2e6715427e7e22e55c7670;hpb=22c206a9ad669ebf46c38ce78079a6be4238e0d9 diff --git a/sprite.c b/sprite.c index a772668..1609368 100644 --- a/sprite.c +++ b/sprite.c @@ -33,6 +33,7 @@ get_shape(Sprite *s) uint16_t *px, transp; uint32_t bits = 0, bit, *p; + s->area = 0; if(s->image->format->BytesPerPixel != 2) { fprintf(stderr, "get_shape(): not a 16-bit image!\n"); exit(1); @@ -55,7 +56,7 @@ get_shape(Sprite *s) bit = 0; for(x=0; ximage->w; x++) { if(!bit) { bits = 0; bit = 0x80000000; } - if(*px++ != transp) { bits |= bit; } + if(*px++ != transp) { bits |= bit; s->area++; } bit >>= 1; if(!bit || x == s->image->w - 1) { *(p++) = bits; } } @@ -110,10 +111,25 @@ square(int x, int y, int set) void add_sprite(Sprite *s) { + if(s->type < 0) s->type = -s->type; insert_sprite(square(s->x, s->y, set), s); } void +reset_sprites(void) +{ + int i; + + for(i=0; itype < 0) s->type = -s->type; + insert_sprite(&free_sprites[s->type], s); + if(s->type > 0) s->type = -s->type; + } +} + +void move_sprite(Sprite *s) { // move it. @@ -127,8 +143,9 @@ sort_sprite(Sprite *s) // clip it, or sort it into the other set of sprites. if(s->x + s->w < 0 || s->x >= XSIZE || s->y + s->h < 0 || s->y >= YSIZE) { + if(s->type < 0) s->type = -s->type; insert_sprite(&free_sprites[s->type], s); - s->type = NONE; + if(s->type > 0) s->type = -s->type; } else insert_sprite(square(s->x, s->y, 1-set), s); } @@ -138,7 +155,7 @@ move_sprites(void) int sq; Sprite **head; - // Move all the sprites (position and set) + // Move all the sprites for(sq=0; sqtype < 0 || b->type < 0) return false; + if(b->x < a->x) { Sprite *tmp = a; a = b; b = tmp; } dx = b->x - a->x; @@ -211,6 +230,28 @@ collide(Sprite *a, Sprite *b) else return mask_collide(xov, yov, a, b); } +void +collide_with_list(Sprite *s, Sprite *list) +{ + for(; list; list=list->next) + if(collide(s, list)) do_collision(s, list); +} + +void +collisions(void) +{ + int i, end = gw*gh; + Sprite *s; + for(i=0; inext) { + collide_with_list(s, s->next); + if(i+1 < end) collide_with_list(s, sprites[set][i+1]); + if(i+gw < end) collide_with_list(s, sprites[set][i+gw]); + if(i+gw+1 < end) collide_with_list(s, sprites[set][i+gw+1]); + } + } +} + Sprite * hit_in_square(Sprite *r, Sprite *s) { @@ -265,7 +306,7 @@ int pixel_hit_in_square(Sprite *r, float x, float y) { for(; r; r=r->next) { - if(pixel_collide(r, x, y)) return 1; + if(r->type >= 0 && pixel_collide(r, x, y)) return 1; } return 0; } @@ -285,19 +326,35 @@ pixel_collides(float x, float y) return false; } + +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 na, nb; + 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; - na = (x*a->dx + y*a->dy); // sqrt(a->dx*a->dx + a->dy*a->dy); - nb = (x*b->dx + y*b->dy); // sqrt(b->dx*b->dx + b->dy*b->dy); + // 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*(nb-na); a->dy += y*(nb-na); - b->dx += x*(na-nb); b->dy += y*(na-nb); + 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; }