From 5c8f059629c2127848ce4051296d2f5897bf5c0f Mon Sep 17 00:00:00 2001 From: Joshua Grams Date: Wed, 22 Mar 2006 14:02:58 +0000 Subject: [PATCH] moved grid stuff from rocks.c to sprite.c --- Makefile | 2 +- common.h | 2 + main.c | 39 ++++------- rocks.c | 231 +++++++++----------------------------------------------------- rocks.h | 8 +-- sprite.c | 183 ++++++++++++++++++++++++++++++++++++++++++++++--- sprite.h | 54 ++++++++++++--- 7 files changed, 270 insertions(+), 249 deletions(-) diff --git a/Makefile b/Makefile index 77460c4..650a98b 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ DATA_PREFIX := /usr/share/vor PROGRAM_PREFIX := /usr/games/bin -CFLAGS := -Wall +CFLAGS := -Wall -ggdb LDFLAGS := paths := -DDATA_PREFIX=\"$(DATA_PREFIX)\" diff --git a/common.h b/common.h index 59268ae..28d9ea0 100644 --- a/common.h +++ b/common.h @@ -4,6 +4,8 @@ #include #include +#define NONE (~0) + #ifndef max #define max(a, b) ((a) > (b) ? (a) : (b)) #endif diff --git a/main.c b/main.c index d57aa3b..097969c 100644 --- a/main.c +++ b/main.c @@ -203,7 +203,7 @@ draw_bang_dots(SDL_Surface *s) } // check collisions - if(pixel_hit_rocks(bdot[i].x, bdot[i].y)) { bdot[i].active = 0; continue; } + if(pixel_collides(bdot[i].x, bdot[i].y)) { bdot[i].active = 0; continue; } pixel = pixels + row_inc*(int)(bdot[i].y) + (int)(bdot[i].x); if(bdot[i].c) c = bdot[i].c; else c = heatcolor[(int)(bdot[i].life)*3]; @@ -268,7 +268,7 @@ draw_engine_dots(SDL_Surface *s) { edot[i].active = 0; continue; } - if(pixel_hit_rocks(edot[i].x, edot[i].y)) { edot[i].active = 0; continue; } + if(pixel_collides(edot[i].x, edot[i].y)) { edot[i].active = 0; continue; } heatindex = edot[i].life * 6; c = heatindex>3*W ? heatcolor[3*W-1] : heatcolor[heatindex]; pixels[row_inc*(int)(edot[i].y) + (int)(edot[i].x)] = c; @@ -311,6 +311,12 @@ load_image(char *filename) return img; } +void +load_ship(void) +{ + load_sprite(SPRITE(&ship), "sprites/ship.png"); +} + int init(void) { @@ -367,9 +373,6 @@ init(void) { NULLERROR(surf_b_game = load_image("banners/game.png")); NULLERROR(surf_b_over = load_image("banners/over.png")); - // Load the spaceship graphic. - load_sprite(SPRITE(&ship), "sprites/ship.png"); - // Load the life indicator (small ship) graphic. NULLERROR(surf_life = load_image("indicators/life.png")); @@ -384,7 +387,7 @@ init(void) { init_engine_dots(); init_dust(); - init_rocks(); + init_sprites(); // Remove the mouse cursor #ifdef SDL_DISABLE @@ -411,11 +414,7 @@ draw() { drawdots(surf_screen); // Draw ship - if(state == GAMEPLAY ) { - dest.x = ship.x; - dest.y = ship.y; - SDL_BlitSurface(ship.image,NULL,surf_screen,&dest); - } + if(state == GAMEPLAY) draw_sprite(SPRITE(&ship)); draw_rocks(); @@ -511,7 +510,7 @@ draw() { } if(state == GAMEPLAY) { - bang = hit_rocks(SPRITE(&ship)); + bang = collides(SPRITE(&ship)); } ms_frame = SDL_GetTicks() - ms_end; @@ -579,16 +578,10 @@ gameloop() { } else { if(state == DEAD_PAUSE) { float blast_radius; - int fixonly; - - if(state_timeout < DEAD_PAUSE_LENGTH - 20.0) { - blast_radius = BLAST_RADIUS * 1.3; - fixonly = 1; - } else { + if(state_timeout >= DEAD_PAUSE_LENGTH - 20.0) { blast_radius = BLAST_RADIUS * (DEAD_PAUSE_LENGTH - state_timeout) / 20.0; - fixonly = 0; + blast_rocks(bangx, bangy, blast_radius); } - blast_rocks(bangx, bangy, blast_radius, fixonly); if(bangx < 60) bangx = 60; } @@ -613,14 +606,12 @@ gameloop() { xscroll = screendx * t_frame; yscroll = screendy * t_frame; - ship.x += ship.dx*t_frame - xscroll; - ship.y += ship.dy*t_frame - yscroll; - // move bang center bangx += bangdx*t_frame - xscroll; bangy += bangdy*t_frame - yscroll; - move_rocks(); + move_sprite(SPRITE(&ship)); + move_sprites(); // BOUNCE X diff --git a/rocks.c b/rocks.c index 86c76e7..89efb6e 100644 --- a/rocks.c +++ b/rocks.c @@ -9,24 +9,16 @@ #include "globals.h" #include "mt.h" #include "rocks.h" +#include "sprite.h" -struct rock rocks[MAXROCKS]; -Sprite *free_rocks; - -Sprite **rock_buckets[2]; -int n_buckets; -// we have two sets of buckets -- this variable tells which we are using. -int p; -int bw, bh; -int grid_size; - +static struct rock rocks[MAXROCKS]; static struct rock prototypes[NROCKS]; // timers for rock generation. static float rtimers[4]; -uint32_t nrocks; -float nrocks_timer; +uint32_t nrocks = I_ROCKS; +float nrocks_timer = 0; float nrocks_inc_ticks = 2*60*20/(F_ROCKS-I_ROCKS); // constants for rock generation. @@ -35,86 +27,33 @@ float nrocks_inc_ticks = 2*60*20/(F_ROCKS-I_ROCKS); #define RDX 2.5 // range for rock dx values (+/-) #define RDY 2.5 // range for rock dy values (+/-) -static inline Sprite ** -bucket(int x, int y, int p) -{ - int b = (x+grid_size)/grid_size + bw*((y+grid_size)/grid_size); - return &rock_buckets[p][b]; -} - -void -init_buckets(void) -{ - int scr_grid_w = (XSIZE+2*grid_size-1) / grid_size; - int scr_grid_h = (YSIZE+2*grid_size-1) / grid_size; - bw = 1 + scr_grid_w + 1; - bh = 1 + scr_grid_h + 1; - n_buckets = bw * bh; - - rock_buckets[0] = malloc(n_buckets * sizeof(struct rock *)); - rock_buckets[1] = malloc(n_buckets * sizeof(struct rock *)); - if(!rock_buckets[0] || !rock_buckets[1]) { - fprintf(stderr, "Can't allocate rock buckets.\n"); - exit(1); - } - p = 0; -} - -static inline void -insert_sprite(Sprite **head, Sprite *this) -{ - this->next = *head; - *head = this; -} - -static inline Sprite * -remove_sprite(Sprite **head) -{ - Sprite *this = *head; - *head = this->next; - return this; -} - void reset_rocks(void) { - int i; - - for(i=0; i= 1) { rtimers[i] -= 1; - if(!free_rocks) return; // sorry, we ran out of rocks! - r = (struct rock *) remove_sprite(&free_rocks); + if(!free_sprites[ROCK_SPRITE]) return; // sorry, we ran out of rocks! + r = (struct rock *) remove_sprite(&free_sprites[ROCK_SPRITE]); type = urnd() % NROCKS; *r = prototypes[type]; r->type = type; @@ -246,143 +185,39 @@ new_rocks(void) r->dy = weighted_rnd_range(rmin[i], rmax[i]) + screendy; break; } - insert_sprite(bucket(r->x, r->y, p), SPRITE(r)); + add_sprite(SPRITE(r)); } } } -void -move_rocks(void) -{ - int b; - Sprite *r, **head; - - // Move all the rocks - for(b=0; bx += (r->dx - screendx)*t_frame; - r->y += (r->dy - screendy)*t_frame; - - // clip it, or sort it into the other bucket set - // (either way we move it out of this list). - if(r->x + r->image->w < 0 || r->x >= XSIZE - || r->y + r->image->h < 0 || r->y >= YSIZE) { - insert_sprite(&free_rocks, remove_sprite(head)); - r->image = NULL; - } else insert_sprite(bucket(r->x, r->y, 1-p), remove_sprite(head)); - } - } - p = 1-p; // switch current set of buckets. -} void draw_rocks(void) { int i; - SDL_Rect dest; - - for(i=0; inext) { - if(collide(r, s)) return true; - } - return false; -} - -int -hit_rocks(Sprite *s) -{ - int l, r, t, b; - Sprite **bucket; - - l = (s->x + grid_size) / grid_size; - r = (s->x + s->w + grid_size) / grid_size; - t = (s->y + grid_size) / grid_size; - b = (s->y + s->h + grid_size) / grid_size; - bucket = &rock_buckets[p][l + t*bw]; - - if(hit_in_bucket(*bucket, s)) return true; - if(l > 0 && hit_in_bucket(*(bucket-1), s)) return true; - if(t > 0 && hit_in_bucket(*(bucket-bw), s)) return true; - if(l > 0 && t > 0 && hit_in_bucket(*(bucket-1-bw), s)) return true; - - if(r > l) { - if(hit_in_bucket(*(bucket+1), s)) return true; - if(t > 0 && hit_in_bucket(*(bucket+1-bw), s)) return true; - } - if(b > t) { - if(hit_in_bucket(*(bucket+bw), s)) return true; - if(l > 0 && hit_in_bucket(*(bucket-1+bw), s)) return true; - } - if(r > l && b > t && hit_in_bucket(*(bucket+1+bw), s)) return true; - return false; -} - -int -pixel_hit_in_bucket(Sprite *r, float x, float y) -{ - for(; r; r=r->next) { - if(pixel_collide(r, x, y)) return 1; - } - return 0; -} - -int -pixel_hit_rocks(float x, float y) -{ - int ix, iy; - int l, t; - Sprite **bucket; - - ix = x + grid_size; iy = y + grid_size; - l = ix / grid_size; t = iy / grid_size; - bucket = &rock_buckets[p][l + t*bw]; - if(pixel_hit_in_bucket(*bucket, x, y)) return true; - if(l > 0 && pixel_hit_in_bucket(*(bucket-1), x, y)) return true; - if(t > 0 && pixel_hit_in_bucket(*(bucket-bw), x, y)) return true; - if(l > 0 && t > 0 && pixel_hit_in_bucket(*(bucket-1-bw), x, y)) return true; - return false; + for(i=0; inext) { - if(r->x <= 0) continue; - - // This makes it so your explosion from dying magically doesn't leave - // any rocks that aren't moving much on the x axis. If onlyslow is set, - // only rocks that are barely moving will be pushed. - if(onlyslow && (r->dx - screendx < -4 || r->dx - screendx > 3)) continue; - - dx = r->x - x; - dy = r->y - y; - - n = sqrt(dx*dx + dy*dy); - if(n < radius) { - n *= 15; - r->dx += 54.0*dx/n; - r->dy += 54.0*dy/n; - } + for(i=0; ix <= 0) continue; + + dx = r->x - x; + dy = r->y - y; + + n = sqrt(dx*dx + dy*dy); + if(n < radius) { + n *= 15; + r->dx += 54.0*dx/n; + r->dy += 54.0*dy/n; } } } diff --git a/rocks.h b/rocks.h index ab5df75..1fbff53 100644 --- a/rocks.h +++ b/rocks.h @@ -1,13 +1,9 @@ #include "sprite.h" -int init_rocks(void); +void load_rocks(void); void reset_rocks(void); void new_rocks(void); -void move_rocks(void); void draw_rocks(void); -int hit_rocks(Sprite *s); -int pixel_hit_rocks(float x, float y); - -void blast_rocks(float x, float y, float radius, int onlyslow); +void blast_rocks(float x, float y, float radius); diff --git a/sprite.c b/sprite.c index 760af11..38dae30 100644 --- a/sprite.c +++ b/sprite.c @@ -1,15 +1,31 @@ #include +#include +#include "config.h" #include "common.h" +#include "globals.h" #include "sprite.h" +#include "rocks.h" -void -load_sprite(Sprite *s, char *filename) -{ - s->image = load_image(filename); - if(s->image) get_shape(s); -} +SDL_Surface *load_image(char *filename); +void load_ship(void); -void +// 2 sets of sprites, sorted by position +static Sprite **sprites[2] = { NULL, NULL }; + +// which set are we using? +static int set = 0; + +// size of squares into which sprites are sorted. +static int grid_size = 0; + +// screen size in grid squares. +static int gw = 0, gh = 0; + +// lists of free sprites, by type. +Sprite *free_sprites[N_TYPES]; + + +static void get_shape(Sprite *s) { int x, y; @@ -22,8 +38,9 @@ get_shape(Sprite *s) } s->w = s->image->w; s->h = s->image->h; - s->mask_w = ((s->image->w+31)>>5); - s->mask = malloc(4*s->mask_w*s->h); + grid_size = max(grid_size, max(s->w, s->h)); + s->mask_w = ((s->w+31)>>5); + s->mask = malloc(s->mask_w*s->h*sizeof(uint32_t)); if(!s->mask) { fprintf(stderr, "get_shape(): can't allocate bitmask.\n"); exit(1); @@ -46,6 +63,92 @@ get_shape(Sprite *s) SDL_UnlockSurface(s->image); } + +void +load_sprite(Sprite *s, char *filename) +{ + s->image = load_image(filename); + if(s->image) get_shape(s); +} + + +static void +load_sprites(void) +{ + load_ship(); + load_rocks(); +} + + +void +init_sprites(void) +{ + load_sprites(); + + grid_size = grid_size * 3 / 2; + gw = (XSIZE-1 + 2*grid_size) / grid_size; + gh = (YSIZE-1 + 2*grid_size) / grid_size; + + sprites[0] = malloc(2 * gw * gh * sizeof(Sprite *)); + sprites[1] = (void *)sprites[0] + gw * gh * sizeof(Sprite *); + if(!sprites[0]) { + fprintf(stderr, "init_sprites(): can't allocate grid squares.\n"); + exit(1); + } + memset(sprites[0], 0, 2 * gw * gh * sizeof(Sprite *)); + set = 0; +} + +static inline Sprite ** +square(int x, int y, int set) +{ + int b = (x+grid_size)/grid_size + gw*((y+grid_size)/grid_size); + return &sprites[set][b]; +} + +void +add_sprite(Sprite *s) +{ + insert_sprite(square(s->x, s->y, set), s); +} + +void +move_sprite(Sprite *s) +{ + // move it. + s->x += (s->dx - screendx)*t_frame; + s->y += (s->dy - screendy)*t_frame; +} + +void +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) { + insert_sprite(&free_sprites[s->type], s); + s->type = NONE; + } else insert_sprite(square(s->x, s->y, 1-set), s); +} + +void +move_sprites(void) +{ + int sq; + Sprite **head; + + // Move all the sprites (position and set) + for(sq=0; sqnext) { + if(collide(r, s)) return true; + } + return false; +} + +int +collides(Sprite *s) +{ + int l, r, t, b; + Sprite **sq; + + l = (s->x + grid_size) / grid_size; + r = (s->x + s->w + grid_size) / grid_size; + t = (s->y + grid_size) / grid_size; + b = (s->y + s->h + grid_size) / grid_size; + sq = &sprites[set][l + t*gw]; + + if(hit_in_square(*sq, s)) return true; + if(l > 0 && hit_in_square(*(sq-1), s)) return true; + if(t > 0 && hit_in_square(*(sq-gw), s)) return true; + if(l > 0 && t > 0 && hit_in_square(*(sq-1-gw), s)) return true; + + if(r > l) { + if(hit_in_square(*(sq+1), s)) return true; + if(t > 0 && hit_in_square(*(sq+1-gw), s)) return true; + } + if(b > t) { + if(hit_in_square(*(sq+gw), s)) return true; + if(l > 0 && hit_in_square(*(sq-1+gw), s)) return true; + } + if(r > l && b > t && hit_in_square(*(sq+1+gw), s)) return true; + return false; +} + +int pixel_collide(Sprite *s, int x, int y) { uint32_t pmask; @@ -118,3 +259,27 @@ pixel_collide(Sprite *s, int x, int y) pmask = 0x80000000 >> (x&0x1f); return s->mask[(y*s->mask_w) + (x>>5)] & pmask; } + +int +pixel_hit_in_square(Sprite *r, float x, float y) +{ + for(; r; r=r->next) { + if(pixel_collide(r, x, y)) return 1; + } + return 0; +} + +int +pixel_collides(float x, float y) +{ + int l, t; + Sprite **sq; + + l = (x + grid_size) / grid_size; t = (y + grid_size) / grid_size; + sq = &sprites[set][l + t*gw]; + if(pixel_hit_in_square(*sq, x, y)) return true; + if(l > 0 && pixel_hit_in_square(*(sq-1), x, y)) return true; + if(t > 0 && pixel_hit_in_square(*(sq-gw), x, y)) return true; + if(l > 0 && t > 0 && pixel_hit_in_square(*(sq-1-gw), x, y)) return true; + return false; +} diff --git a/sprite.h b/sprite.h index 7df8631..4c0cefd 100644 --- a/sprite.h +++ b/sprite.h @@ -1,5 +1,5 @@ -#ifndef VOR_SHAPE_H -#define VOR_SHAPE_H +#ifndef VOR_SPRITE_H +#define VOR_SPRITE_H #include #include @@ -11,9 +11,10 @@ typedef struct sprite Sprite; #define BASE_SPRITE 0 #define SHIP_SPRITE 1 #define ROCK_SPRITE 2 +#define N_TYPES 3 struct sprite { - uint8_t type; + int8_t type; Sprite *next; float x, y; float dx, dy; @@ -23,17 +24,23 @@ struct sprite { uint32_t *mask; }; -void get_shape(Sprite *s); -int collide(Sprite *r, Sprite *s); -int pixel_collide(Sprite *s, int x, int y); +Sprite *free_sprites[N_TYPES]; // lists of free sprites, by type. +void init_sprites(void); +void add_sprite(Sprite *s); +void move_sprite(Sprite *s); +void move_sprites(void); + +int collides(Sprite *s); +int pixel_collides(float x, float y); +void load_sprite(Sprite *sprite, char *filename); // extended sprites struct ship { // core sprite fields - uint8_t sprite_type; + int8_t sprite_type; struct ship *next; float x, y; float dx, dy; @@ -48,7 +55,7 @@ struct ship { struct rock { // core sprite fields - uint8_t sprite_type; + int8_t sprite_type; struct rock *next; float x, y; float dx, dy; @@ -60,7 +67,32 @@ struct rock { int type; }; -SDL_Surface *load_image(char *filename); -void load_sprite(Sprite *sprite, char *filename); -#endif // VOR_SHAPE_H + +static inline void +insert_sprite(Sprite **head, Sprite *s) +{ + s->next = *head; + *head = s; +} + + +static inline Sprite * +remove_sprite(Sprite **head) +{ + Sprite *s = *head; + *head = s->next; + return s; +} + + +static inline void +draw_sprite(Sprite *s) +{ + SDL_Rect dest; + if(s->type == NONE) return; + dest.x = s->x; dest.y = s->y; + SDL_BlitSurface(s->image, NULL, surf_screen, &dest); +} + +#endif // VOR_SPRITE_H -- 1.7.10.4