From f3887c5ba3c117c7a3c2cc74e9ebdcce162a53fc Mon Sep 17 00:00:00 2001 From: Joshua Grams Date: Mon, 11 Jul 2005 17:13:54 +0000 Subject: [PATCH 01/16] Rocks now sorted on a grid to speed collision checking. --- mt.h | 2 +- rocks.c | 273 +++++++++++++++++++++++++++++++++++++-------------------------- 2 files changed, 161 insertions(+), 114 deletions(-) diff --git a/mt.h b/mt.h index f7ac92a..46c2a1c 100644 --- a/mt.h +++ b/mt.h @@ -4,7 +4,7 @@ #include void init_mt(uint32_t s); -uint32_t irnd(void); // [0, 0xfffffff] +uint32_t urnd(void); // [0, 0xfffffff] float frnd(void); // [0, 1) float crnd(void); // [-0.5, 0.5) diff --git a/rocks.c b/rocks.c index bee1ca5..a2aa31e 100644 --- a/rocks.c +++ b/rocks.c @@ -12,14 +12,19 @@ #include "shape.h" struct rock_struct { + struct rock_struct *next; float x,y,dx,dy; - int active; SDL_Surface *image; struct shape *shape; int type_number; }; -struct rock_struct rock[MAXROCKS], *rockptr = rock; +struct rock_struct rocks[MAXROCKS], *free_rocks; + +struct rock_struct **rock_buckets[2]; +int n_buckets, p; +int bw, bh; +int grid_size; SDL_Surface *surf_rock[NROCKS]; struct shape rock_shapes[NROCKS]; @@ -37,39 +42,77 @@ 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 int bucket(int x, int y) { return (1+x/grid_size) + bw*(1+y/grid_size); } + +void +init_buckets(void) +{ + bw = (XSIZE+2*grid_size-1) / grid_size; + bh = (YSIZE+2*grid_size-1) / grid_size; + n_buckets = bw * bh; + + rock_buckets[0] = malloc(n_buckets * sizeof(struct rock_struct *)); + rock_buckets[1] = malloc(n_buckets * sizeof(struct rock_struct *)); + if(!rock_buckets[0] || !rock_buckets[1]) { + fprintf(stderr, "Can't allocate rock buckets.\n"); + exit(1); + } + p = 0; +} + +void +sort_rock(struct rock_struct *q, struct rock_struct *r, int p) +{ + int b = bucket(r->x, r->y); + q->next = r->next; // remove from old list + r->next = rock_buckets[p][b]; // insert into new list + rock_buckets[p][b] = r; +} + +void +reset_rocks(void) +{ + int i; + + for(i=0; i= 1) { rtimers[i] -= 1; - j=0; - while(rockptr->active && j= MAXROCKS) rockptr = rock; - j++; - } - if(!rockptr->active) { - rockptr->type_number = random() % NROCKS; - rockptr->image = surf_rock[rockptr->type_number]; - rockptr->shape = &rock_shapes[rockptr->type_number]; - switch(i) { - case RIGHT: - rockptr->x = XSIZE; - rockptr->y = frnd()*(YSIZE + rockptr->image->h); - - rockptr->dx = -weighted_rnd_range(rmin[i], rmax[i]) + screendx; - rockptr->dy = RDY*crnd(); - break; - case LEFT: - rockptr->x = -rockptr->image->w; - rockptr->y = frnd()*(YSIZE + rockptr->image->h); - - rockptr->dx = weighted_rnd_range(rmin[i], rmax[i]) + screendx; - rockptr->dy = RDY*crnd(); - break; - case BOTTOM: - rockptr->x = frnd()*(XSIZE + rockptr->image->w); - rockptr->y = YSIZE; - - rockptr->dx = RDX*crnd(); - rockptr->dy = -weighted_rnd_range(rmin[i], rmax[i]) + screendy; - break; - case TOP: - rockptr->x = frnd()*(XSIZE + rockptr->image->w); - rockptr->y = -rockptr->image->h; - - rockptr->dx = RDX*crnd(); - rockptr->dy = weighted_rnd_range(rmin[i], rmax[i]) + screendy; - break; - } - - rockptr->active = 1; + if(!free_rocks) return; // sorry, we ran out of rocks! + r = free_rocks; + r->type_number = urnd() % NROCKS; + r->image = surf_rock[r->type_number]; + r->shape = &rock_shapes[r->type_number]; + switch(i) { + case RIGHT: + r->x = XSIZE; + r->y = frnd()*(YSIZE + r->image->h); + + r->dx = -weighted_rnd_range(rmin[i], rmax[i]) + screendx; + r->dy = RDY*crnd(); + break; + case LEFT: + r->x = -r->image->w; + r->y = frnd()*(YSIZE + r->image->h); + + r->dx = weighted_rnd_range(rmin[i], rmax[i]) + screendx; + r->dy = RDY*crnd(); + break; + case BOTTOM: + r->x = frnd()*(XSIZE + r->image->w); + r->y = YSIZE; + + r->dx = RDX*crnd(); + r->dy = -weighted_rnd_range(rmin[i], rmax[i]) + screendy; + break; + case TOP: + r->x = frnd()*(XSIZE + r->image->w); + r->y = -r->image->h; + + r->dx = RDX*crnd(); + r->dy = weighted_rnd_range(rmin[i], rmax[i]) + screendy; + break; } + sort_rock((struct rock_struct *)&free_rocks, r, p); } } } @@ -206,73 +245,78 @@ new_rocks(void) void move_rocks(void) { - int i; + int b; + struct rock_struct *q,*r; // Move all the rocks - for(i = 0; i < MAXROCKS; i++) { - if(rock[i].active) { + for(b=0; bnext; + while(r) { // move - rock[i].x += (rock[i].dx-screendx)*t_frame; - rock[i].y += (rock[i].dy-screendy)*t_frame; + r->x += (r->dx - screendx)*t_frame; + r->y += (r->dy - screendy)*t_frame; + // clip - if(rock[i].x < -rock[i].image->w || rock[i].x >= XSIZE - || rock[i].y < -rock[i].image->h || rock[i].y >= YSIZE) { - rock[i].active = 0; - } + if(r->x + r->image->w < 0 || r->x >= XSIZE + || r->y + r->image->h < 0 || r->y >= YSIZE) { + q->next = r->next; + r->next = free_rocks; free_rocks = r; + r->image = NULL; + } else sort_rock(q,r,1-p); + if(q->next == r) q = q->next; + if(q) r = q->next; else r = NULL; } } + p = 1-p; // switch current set of buckets. } void draw_rocks(void) { int i; - SDL_Rect src, dest; - - src.x = 0; src.y = 0; - - for(i = 0; iw; - src.h = rock[i].image->h; + SDL_Rect dest; - dest.w = src.w; - dest.h = src.h; - dest.x = (int) rock[i].x; - dest.y = (int) rock[i].y; + for(i=0; inext) { + if(collide(x - r->x, y - r->y, r->shape, shape)) return 1; } + return 0; } int hit_rocks(float x, float y, struct shape *shape) { - int i; - - for(i=0; iw)/grid_size - (int)x/grid_size; + int bdy = ((int)y+shape->h)/grid_size - (int)y/grid_size; + if(hit_in_bucket(b, x, y, shape)) return 1; + if(bdx && hit_in_bucket(b+1, x, y, shape)) return 1; + if(bdy && hit_in_bucket(b+bw, x, y, shape)) return 1; + if(bdx && bdy && hit_in_bucket(b+bw+1, x, y, shape)) return 1; return 0; } int pixel_hit_rocks(float x, float y) { - int i; - float xoff, yoff; + int b; + struct rock_struct *r; - for(i=0; inext) { + if(x < r->x || y < r->y) continue; + if(pixel_collide(x - r->x, y - r->y, r->shape)) return 1; } return 0; } @@ -280,27 +324,30 @@ pixel_hit_rocks(float x, float y) void blast_rocks(float x, float y, float radius, int onlyslow) { - int i; + int b; + struct rock_struct *r; float dx, dy, n; if(onlyslow) return; - 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 && (rock[i].dx-screendx < -4 || rock[i].dx-screendx > 3)) 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 = rock[i].x - x; - dy = rock[i].y - y; + dx = r->x - x; + dy = r->y - y; - n = sqrt(dx*dx + dy*dy); - if(n < radius) { - n *= 15; - rock[i].dx += 54.0*dx/n; - rock[i].dy += 54.0*dy/n; + n = sqrt(dx*dx + dy*dy); + if(n < radius) { + n *= 15; + r->dx += 54.0*dx/n; + r->dy += 54.0*dy/n; + } } } } -- 1.7.10.4 From a77978e0c9bc91ea3d7b192ce136621e78d4ec5b Mon Sep 17 00:00:00 2001 From: Joshua Grams Date: Mon, 11 Jul 2005 18:21:34 +0000 Subject: [PATCH 02/16] fixed 2 more dot collision bugs (last ones?) --- main.c | 16 ++++++++++------ rocks.c | 16 ++++++++++++---- shape.c | 4 ++-- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/main.c b/main.c index 8d131be..b4972a2 100644 --- a/main.c +++ b/main.c @@ -193,20 +193,24 @@ draw_bang_dots(SDL_Surface *s) for(i=0; i= XSIZE || bdot[i].y < 0 || bdot[i].y >= YSIZE) { bdot[i].active = 0; continue; } + + // check collisions if(pixel_hit_rocks(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]; *pixel = c; - bdot[i].life -= bdot[i].decay; - bdot[i].x += bdot[i].dx*t_frame - xscroll; - bdot[i].y += bdot[i].dy*t_frame - yscroll; - - if(bdot[i].life<0) bdot[i].active = 0; } } diff --git a/rocks.c b/rocks.c index a2aa31e..e098fa0 100644 --- a/rocks.c +++ b/rocks.c @@ -308,12 +308,9 @@ hit_rocks(float x, float y, struct shape *shape) } int -pixel_hit_rocks(float x, float y) +pixel_hit_in_bucket(int b, float x, float y) { - int b; struct rock_struct *r; - - b = bucket(x, y); for(r=rock_buckets[p][b]; r; r=r->next) { if(x < r->x || y < r->y) continue; if(pixel_collide(x - r->x, y - r->y, r->shape)) return 1; @@ -321,6 +318,17 @@ pixel_hit_rocks(float x, float y) return 0; } +int +pixel_hit_rocks(float x, float y) +{ + int b = bucket(x, y); + if(pixel_hit_in_bucket(b, x, y)) return 1; + if(pixel_hit_in_bucket(b-1, x, y)) return 1; + if(pixel_hit_in_bucket(b-bw, x, y)) return 1; + if(pixel_hit_in_bucket(b-bw-1, x, y)) return 1; + return 0; +} + void blast_rocks(float x, float y, float radius, int onlyslow) { diff --git a/shape.c b/shape.c index 5aa7fb7..92729e9 100644 --- a/shape.c +++ b/shape.c @@ -116,6 +116,6 @@ pixel_collide(unsigned int xoff, unsigned int yoff, struct shape *r) if(xoff >= r->w || yoff >= r->h) return 0; - pmask = 1 << (xoff & 31); xoff >>= 5; - return r->mask[yoff*r->mw + xoff] & pmask; + pmask = 1 << (32 - (xoff&0x1f)); + return r->mask[(yoff*r->mw) + (xoff>>5)] & pmask; } -- 1.7.10.4 From 2b5dd5bc0eb1739dd744de6f565d0f3a7ae02c95 Mon Sep 17 00:00:00 2001 From: Joshua Grams Date: Mon, 11 Jul 2005 18:39:39 +0000 Subject: [PATCH 03/16] oops, have to check all 9 buckets. maybe I should consider doing the 4 resort/check cycles instead... --- rocks.c | 14 ++++++++++++-- shape.c | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/rocks.c b/rocks.c index e098fa0..f68a57a 100644 --- a/rocks.c +++ b/rocks.c @@ -301,8 +301,18 @@ hit_rocks(float x, float y, struct shape *shape) int bdx = ((int)x+shape->w)/grid_size - (int)x/grid_size; int bdy = ((int)y+shape->h)/grid_size - (int)y/grid_size; if(hit_in_bucket(b, x, y, shape)) return 1; - if(bdx && hit_in_bucket(b+1, x, y, shape)) return 1; - if(bdy && hit_in_bucket(b+bw, x, y, shape)) return 1; + if(hit_in_bucket(b-1, x, y, shape)) return 1; + if(hit_in_bucket(b-bw, x, y, shape)) return 1; + if(hit_in_bucket(b-bw-1, x, y, shape)) return 1; + + if(bdx) { + if(hit_in_bucket(b+1, x, y, shape)) return 1; + if(hit_in_bucket(b+1-bw, x, y, shape)) return 1; + } + if(bdy) { + if(hit_in_bucket(b+bw, x, y, shape)) return 1; + if(hit_in_bucket(b+bw-1, x, y, shape)) return 1; + } if(bdx && bdy && hit_in_bucket(b+bw+1, x, y, shape)) return 1; return 0; } diff --git a/shape.c b/shape.c index 92729e9..75424ef 100644 --- a/shape.c +++ b/shape.c @@ -116,6 +116,6 @@ pixel_collide(unsigned int xoff, unsigned int yoff, struct shape *r) if(xoff >= r->w || yoff >= r->h) return 0; - pmask = 1 << (32 - (xoff&0x1f)); + pmask = 0x80000000 >> (xoff&0x1f); return r->mask[(yoff*r->mw) + (xoff>>5)] & pmask; } -- 1.7.10.4 From af711b4e66c96c112086a442ea09094643bd8d71 Mon Sep 17 00:00:00 2001 From: Joshua Grams Date: Wed, 4 Jan 2006 23:37:51 +0000 Subject: [PATCH 04/16] * rocks.c: refactored stuff and fixed linked-list bug (I think). * file.c (add_path): renamed to add_data_path, changed all callers. * main.c (load_image): new function - changed all image loads. * mt.c (frnd, crnd): converted literals to standard constants. * mt.h: including inttypes.h instead of the less common stdint.h. --- file.c | 47 +++++++++++++++++++++--------- file.h | 2 +- main.c | 55 +++++++++++++++++++++-------------- mt.c | 7 +++-- mt.h | 2 +- rocks.c | 98 +++++++++++++++++++++++++++++++++------------------------------ shape.c | 2 +- sound.c | 19 +++++++++---- 8 files changed, 139 insertions(+), 93 deletions(-) diff --git a/file.c b/file.c index 45532d3..ee14299 100644 --- a/file.c +++ b/file.c @@ -32,11 +32,26 @@ char *g_score_file; mode_t g_score_mask; char * -add_path(char *filename) +add_path(char *path, char *file) { - static char r[MAX_PATH_LEN]; - snprintf(r, MAX_PATH_LEN, "%s/%s", g_data_dir, filename); - return r; + char *s; + size_t plen, flen; + + if(!path || !file) return NULL; + plen = strlen(path); + flen = strlen(file); + s = malloc(2+plen+flen); + if(!s) return NULL; + memcpy(s, path, plen); + s[plen] = '/'; + memcpy(s+plen+1, file, flen+1); + return s; +} + +char * +add_data_path(char *filename) +{ + return add_path(g_data_dir, filename); } int @@ -81,13 +96,18 @@ find_data_dir(void) int find_score_file(void) { - g_score_file = malloc(MAX_PATH_LEN); - snprintf(g_score_file, MAX_PATH_LEN, - "%s/.vor-scores", getenv("HOME")); - g_score_mask = 0177; - if(is_file(g_score_file)) return true; - - return false; + char *dir, *s; + + /* in case we get called twice */ + if(g_score_file) return true; + + dir = getenv("HOME"); if(!dir) return false; + s = add_path(dir, ".vor-scores"); + if(s) { + g_score_file = s; + g_score_mask = 0177; + return is_file(s); + } else return false; } int @@ -103,13 +123,12 @@ FILE * open_score_file(char *mode) { mode_t old_mask; - FILE *f = NULL; + FILE *f; - if(!g_score_file) return f; + if(!g_score_file) return NULL; old_mask = umask(g_score_mask); f = fopen(g_score_file, mode); - umask(old_mask); return f; } diff --git a/file.h b/file.h index 14092ce..f9249e9 100644 --- a/file.h +++ b/file.h @@ -26,7 +26,7 @@ extern char *g_data_dir; extern char *g_score_file; extern mode_t g_score_mode; -char *add_path(char *filename); +char *add_data_path(char *filename); int is_dir(char *dirname); int is_file(char *filename); int find_data_dir(void); diff --git a/main.c b/main.c index b4972a2..a0b50cc 100644 --- a/main.c +++ b/main.c @@ -298,11 +298,27 @@ drawdots(SDL_Surface *s) { SDL_UnlockSurface(s); } +SDL_Surface * +load_image(char *filename) +{ + SDL_Surface *tmp, *img = NULL; + char *s = add_data_path(filename); + if(s) { + tmp = IMG_Load(s); + free(s); + if(tmp) { + img = SDL_DisplayFormat(tmp); + SDL_FreeSurface(tmp); + } + } + return img; +} + int init(void) { int i; - SDL_Surface *temp; + char *s; Uint32 flag; // Where are our data files? @@ -347,32 +363,27 @@ init(void) { } // Load the banners - NULLERROR(temp = IMG_Load(add_path("banners/variations.png"))); - NULLERROR(surf_b_variations = SDL_DisplayFormat(temp)); + NULLERROR(surf_b_variations = load_image("banners/variations.png")); + NULLERROR(surf_b_on = load_image("banners/on.png")); + NULLERROR(surf_b_rockdodger = load_image("banners/rockdodger.png")); - NULLERROR(temp = IMG_Load(add_path("banners/on.png"))); - NULLERROR(surf_b_on = SDL_DisplayFormat(temp)); - - NULLERROR(temp = IMG_Load(add_path("banners/rockdodger.png"))); - NULLERROR(surf_b_rockdodger = SDL_DisplayFormat(temp)); - - NULLERROR(temp = IMG_Load(add_path("banners/game.png"))); - NULLERROR(surf_b_game = SDL_DisplayFormat(temp)); - - NULLERROR(temp = IMG_Load(add_path("banners/over.png"))); - NULLERROR(surf_b_over = SDL_DisplayFormat(temp)); - - surf_font_big = IMG_Load(add_path(BIG_FONT_FILE)); - g_font = SFont_InitFont(surf_font_big); + NULLERROR(surf_b_game = load_image("banners/game.png")); + NULLERROR(surf_b_over = load_image("banners/over.png")); // Load the spaceship graphic. - NULLERROR(temp = IMG_Load(add_path("sprites/ship.png"))); - NULLERROR(surf_ship = SDL_DisplayFormat(temp)); + NULLERROR(surf_ship = load_image("sprites/ship.png")); get_shape(surf_ship, &shipshape); // Load the life indicator (small ship) graphic. - NULLERROR(temp = IMG_Load(add_path("indicators/life.png"))); - NULLERROR(surf_life = SDL_DisplayFormat(temp)); + NULLERROR(surf_life = load_image("indicators/life.png")); + + // Load the font image + s = add_data_path(BIG_FONT_FILE); + if(s) { + NULLERROR(surf_font_big = IMG_Load(s)); + free(s); + g_font = SFont_InitFont(surf_font_big); + } init_engine_dots(); init_dust(); @@ -528,7 +539,7 @@ draw() { int gameloop() { - Uint8 *keystate; + Uint8 *keystate = SDL_GetKeyState(NULL); float tmp; diff --git a/mt.c b/mt.c index ff3a7c9..816de6e 100644 --- a/mt.c +++ b/mt.c @@ -1,6 +1,9 @@ /* mt.c - A C program for MT199937, with initialization improved 2002-02-10. ----- + 2006-01-14 - Switched include from stdint.h to inttypes.h, + fixed a warning from gcc -Wall. --Josh + ----- 2003-07-01 - Stripped out stuff I didn't need, converted to stdint.h types, changed source formatting a bit. --Josh ----- @@ -125,11 +128,11 @@ urnd(void) float frnd(void) { - return urnd()/(float)0x100000000UL; + return urnd()/(1.0 + UINT32_MAX); } float crnd(void) { - return (urnd()-0x80000000)/(float)0x100000000UL; + return (urnd()-INT32_MIN)/(1.0 + UINT32_MAX); } diff --git a/mt.h b/mt.h index 46c2a1c..0edff68 100644 --- a/mt.h +++ b/mt.h @@ -1,7 +1,7 @@ #ifndef VOR_MT_H #define VOR_MT_H -#include +#include void init_mt(uint32_t s); uint32_t urnd(void); // [0, 0xfffffff] diff --git a/rocks.c b/rocks.c index f68a57a..a594547 100644 --- a/rocks.c +++ b/rocks.c @@ -11,6 +11,8 @@ #include "rocks.h" #include "shape.h" +SDL_Surface *load_image(char *filename); + struct rock_struct { struct rock_struct *next; float x,y,dx,dy; @@ -22,7 +24,9 @@ struct rock_struct { struct rock_struct rocks[MAXROCKS], *free_rocks; struct rock_struct **rock_buckets[2]; -int n_buckets, p; +int n_buckets; +// we have two sets of buckets -- this variable tells which we are using. +int p; int bw, bh; int grid_size; @@ -37,12 +41,17 @@ float nrocks_timer; float nrocks_inc_ticks = 2*60*20/(F_ROCKS-I_ROCKS); // constants for rock generation. -#define KH (32.0*20) // 32 s for a speed=1 rock to cross the screen horizontally. -#define KV (24.0*20) // 24 s for a speed=1 rock to cross the screen vertically. +#define KH (32*20) // 32 s for a speed=1 rock to cross the screen horizontally. +#define KV (24*20) // 24 s for a speed=1 rock to cross the screen vertically. #define RDX 2.5 // range for rock dx values (+/-) #define RDY 2.5 // range for rock dy values (+/-) -static inline int bucket(int x, int y) { return (1+x/grid_size) + bw*(1+y/grid_size); } +static inline struct rock_struct ** +bucket(int x, int y, int p) +{ + int b = (1+x/grid_size) + bw*(1+y/grid_size); + return &rock_buckets[p][b]; +} void init_buckets(void) @@ -61,12 +70,11 @@ init_buckets(void) } void -sort_rock(struct rock_struct *q, struct rock_struct *r, int p) +transfer_rock(struct rock_struct *r, struct rock_struct **from, struct rock_struct **to) { - int b = bucket(r->x, r->y); - q->next = r->next; // remove from old list - r->next = rock_buckets[p][b]; // insert into new list - rock_buckets[p][b] = r; + *from = r->next; + r->next = *to; + *to = r; } void @@ -86,18 +94,18 @@ reset_rocks(void) nrocks_timer = 0; } +#define ROCK_LEN sizeof("sprites/rockXX.png") + int init_rocks(void) { int i; - char a[MAX_PATH_LEN]; - SDL_Surface *temp; + char a[ROCK_LEN]; int maxw=0, maxh=0; for(i = 0; idy = weighted_rnd_range(rmin[i], rmax[i]) + screendy; break; } - sort_rock((struct rock_struct *)&free_rocks, r, p); + transfer_rock(r, &free_rocks, bucket(r->x, r->y, p)); } } } @@ -246,25 +254,26 @@ void move_rocks(void) { int b; - struct rock_struct *q,*r; + struct rock_struct **head; + struct rock_struct *r; // Move all the rocks for(b=0; bnext; - while(r) { + head=&rock_buckets[p][b]; r=*head; + while(*head) { + r=*head; + // move r->x += (r->dx - screendx)*t_frame; r->y += (r->dy - screendy)*t_frame; - // clip + // clip or resort into 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) { - q->next = r->next; - r->next = free_rocks; free_rocks = r; + transfer_rock(r, head, &free_rocks); r->image = NULL; - } else sort_rock(q,r,1-p); - if(q->next == r) q = q->next; - if(q) r = q->next; else r = NULL; + } else transfer_rock(r, head, bucket(r->x, r->y, 1-p)); } } p = 1-p; // switch current set of buckets. @@ -284,11 +293,9 @@ draw_rocks(void) } int -hit_in_bucket(int b, float x, float y, struct shape *shape) +hit_in_bucket(struct rock_struct *r, float x, float y, struct shape *shape) { - struct rock_struct *r; - - for(r=rock_buckets[p][b]; r; r=r->next) { + for(; r; r=r->next) { if(collide(x - r->x, y - r->y, r->shape, shape)) return 1; } return 0; @@ -297,31 +304,30 @@ hit_in_bucket(int b, float x, float y, struct shape *shape) int hit_rocks(float x, float y, struct shape *shape) { - int b = bucket(x, y); + struct rock_struct **b = bucket(x, y, p); int bdx = ((int)x+shape->w)/grid_size - (int)x/grid_size; int bdy = ((int)y+shape->h)/grid_size - (int)y/grid_size; - if(hit_in_bucket(b, x, y, shape)) return 1; - if(hit_in_bucket(b-1, x, y, shape)) return 1; - if(hit_in_bucket(b-bw, x, y, shape)) return 1; - if(hit_in_bucket(b-bw-1, x, y, shape)) return 1; + if(hit_in_bucket(*b, x, y, shape)) return 1; + if(hit_in_bucket(*(b-1), x, y, shape)) return 1; + if(hit_in_bucket(*(b-bw), x, y, shape)) return 1; + if(hit_in_bucket(*(b-bw-1), x, y, shape)) return 1; if(bdx) { - if(hit_in_bucket(b+1, x, y, shape)) return 1; - if(hit_in_bucket(b+1-bw, x, y, shape)) return 1; + if(hit_in_bucket(*(b+1), x, y, shape)) return 1; + if(hit_in_bucket(*(b+1-bw), x, y, shape)) return 1; } if(bdy) { - if(hit_in_bucket(b+bw, x, y, shape)) return 1; - if(hit_in_bucket(b+bw-1, x, y, shape)) return 1; + if(hit_in_bucket(*(b+bw), x, y, shape)) return 1; + if(hit_in_bucket(*(b+bw-1), x, y, shape)) return 1; } - if(bdx && bdy && hit_in_bucket(b+bw+1, x, y, shape)) return 1; + if(bdx && bdy && hit_in_bucket(*(b+bw+1), x, y, shape)) return 1; return 0; } int -pixel_hit_in_bucket(int b, float x, float y) +pixel_hit_in_bucket(struct rock_struct *r, float x, float y) { - struct rock_struct *r; - for(r=rock_buckets[p][b]; r; r=r->next) { + for(; r; r=r->next) { if(x < r->x || y < r->y) continue; if(pixel_collide(x - r->x, y - r->y, r->shape)) return 1; } @@ -331,11 +337,11 @@ pixel_hit_in_bucket(int b, float x, float y) int pixel_hit_rocks(float x, float y) { - int b = bucket(x, y); - if(pixel_hit_in_bucket(b, x, y)) return 1; - if(pixel_hit_in_bucket(b-1, x, y)) return 1; - if(pixel_hit_in_bucket(b-bw, x, y)) return 1; - if(pixel_hit_in_bucket(b-bw-1, x, y)) return 1; + struct rock_struct **b = bucket(x, y, p); + if(pixel_hit_in_bucket(*b, x, y)) return 1; + if(pixel_hit_in_bucket(*(b-1), x, y)) return 1; + if(pixel_hit_in_bucket(*(b-bw), x, y)) return 1; + if(pixel_hit_in_bucket(*(b-bw-1), x, y)) return 1; return 0; } diff --git a/shape.c b/shape.c index 75424ef..f29bd6e 100644 --- a/shape.c +++ b/shape.c @@ -7,7 +7,7 @@ get_shape(SDL_Surface *img, struct shape *s) { int x, y; uint16_t *px, transp; - uint32_t bits, bit, *p; + uint32_t bits = 0, bit, *p; if(img->format->BytesPerPixel != 2) { fprintf(stderr, "get_shape(): not a 16-bit image!\n"); diff --git a/sound.c b/sound.c index 1a69535..3794bef 100644 --- a/sound.c +++ b/sound.c @@ -18,7 +18,7 @@ int audio_rate; Uint16 audio_format; int audio_channels; -char *add_path(char *); +char *add_data_path(char *); char *wav_file[] = { "sounds/booom.wav", "sounds/cboom.wav", @@ -32,11 +32,11 @@ char *tune_file[] = { "music/4est_fulla3s.mod" }; +// Return 1 if the sound is ready to roll, and 0 if not. int init_sound() { - // Return 1 if the sound is ready to roll, and 0 if not. - int i; + char *s; // Initialise output with SDL_mixer if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, AUDIO_S16, MIX_DEFAULT_CHANNELS, 4096) < 0) { @@ -46,14 +46,21 @@ init_sound() { // Preload all the tunes into memory for (i=0; i Date: Thu, 5 Jan 2006 00:09:57 +0000 Subject: [PATCH 05/16] * rocks.c (init_buckets): oops, we weren't allocating big enough arrays. --- rocks.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/rocks.c b/rocks.c index a594547..0a71ebf 100644 --- a/rocks.c +++ b/rocks.c @@ -56,8 +56,10 @@ bucket(int x, int y, int p) void init_buckets(void) { - bw = (XSIZE+2*grid_size-1) / grid_size; - bh = (YSIZE+2*grid_size-1) / grid_size; + 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_struct *)); -- 1.7.10.4 From ecb22d95c5c67e92873ba1f518711dcf3e86f181 Mon Sep 17 00:00:00 2001 From: Joshua Grams Date: Thu, 5 Jan 2006 03:40:56 +0000 Subject: [PATCH 06/16] * rocks.c (bucket): rewrote to work with either division rounding mode (symmetric or floored). (hit_rocks): rewrote to check validity of all buckets before using them. --- rocks.c | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/rocks.c b/rocks.c index 0a71ebf..428c697 100644 --- a/rocks.c +++ b/rocks.c @@ -49,7 +49,7 @@ float nrocks_inc_ticks = 2*60*20/(F_ROCKS-I_ROCKS); static inline struct rock_struct ** bucket(int x, int y, int p) { - int b = (1+x/grid_size) + bw*(1+y/grid_size); + int b = (x+grid_size)/grid_size + bw*((y+grid_size)/grid_size); return &rock_buckets[p][b]; } @@ -269,7 +269,7 @@ move_rocks(void) r->x += (r->dx - screendx)*t_frame; r->y += (r->dy - screendy)*t_frame; - // clip or resort into other bucket set + // 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) { @@ -306,24 +306,30 @@ hit_in_bucket(struct rock_struct *r, float x, float y, struct shape *shape) int hit_rocks(float x, float y, struct shape *shape) { - struct rock_struct **b = bucket(x, y, p); - int bdx = ((int)x+shape->w)/grid_size - (int)x/grid_size; - int bdy = ((int)y+shape->h)/grid_size - (int)y/grid_size; - if(hit_in_bucket(*b, x, y, shape)) return 1; - if(hit_in_bucket(*(b-1), x, y, shape)) return 1; - if(hit_in_bucket(*(b-bw), x, y, shape)) return 1; - if(hit_in_bucket(*(b-bw-1), x, y, shape)) return 1; - - if(bdx) { - if(hit_in_bucket(*(b+1), x, y, shape)) return 1; - if(hit_in_bucket(*(b+1-bw), x, y, shape)) return 1; + int ix, iy; + int l, r, t, b; + struct rock_struct **bucket; + + ix = x + grid_size; iy = y + grid_size; + l = ix / grid_size; r = (ix+shape->w)/grid_size; + t = iy / grid_size; b = (iy+shape->h)/grid_size; + bucket = &rock_buckets[p][l + t*bw]; + + if(hit_in_bucket(*bucket, x, y, shape)) return true; + if(l && hit_in_bucket(*(bucket-1), x, y, shape)) return true; + if(r && hit_in_bucket(*(bucket-bw), x, y, shape)) return true; + if(l && r && hit_in_bucket(*(bucket-(1+bw)), x, y, shape)) return true; + + if(r > l) { + if(hit_in_bucket(*(bucket+1), x, y, shape)) return true; + if(hit_in_bucket(*(bucket+1-bw), x, y, shape)) return true; } - if(bdy) { - if(hit_in_bucket(*(b+bw), x, y, shape)) return 1; - if(hit_in_bucket(*(b+bw-1), x, y, shape)) return 1; + if(t > b) { + if(hit_in_bucket(*(bucket+bw), x, y, shape)) return true; + if(hit_in_bucket(*(bucket+bw-1), x, y, shape)) return true; } - if(bdx && bdy && hit_in_bucket(*(b+bw+1), x, y, shape)) return 1; - return 0; + if(r > l && t > b && hit_in_bucket(*(bucket+bw+1), x, y, shape)) return true; + return false; } int -- 1.7.10.4 From da1d3fc11c5663c03da7e9cfb9c9a9e616e692ac Mon Sep 17 00:00:00 2001 From: Joshua Grams Date: Thu, 5 Jan 2006 03:47:00 +0000 Subject: [PATCH 07/16] * rocks.c (hit_rocks): oops, had r(ight) where I should have had t(op). (pixel_hit_rocks): added bucket validity checks. --- rocks.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/rocks.c b/rocks.c index 428c697..d395d5d 100644 --- a/rocks.c +++ b/rocks.c @@ -317,8 +317,8 @@ hit_rocks(float x, float y, struct shape *shape) if(hit_in_bucket(*bucket, x, y, shape)) return true; if(l && hit_in_bucket(*(bucket-1), x, y, shape)) return true; - if(r && hit_in_bucket(*(bucket-bw), x, y, shape)) return true; - if(l && r && hit_in_bucket(*(bucket-(1+bw)), x, y, shape)) return true; + if(t && hit_in_bucket(*(bucket-bw), x, y, shape)) return true; + if(l && t && hit_in_bucket(*(bucket-(1+bw)), x, y, shape)) return true; if(r > l) { if(hit_in_bucket(*(bucket+1), x, y, shape)) return true; @@ -345,12 +345,18 @@ pixel_hit_in_bucket(struct rock_struct *r, float x, float y) int pixel_hit_rocks(float x, float y) { - struct rock_struct **b = bucket(x, y, p); - if(pixel_hit_in_bucket(*b, x, y)) return 1; - if(pixel_hit_in_bucket(*(b-1), x, y)) return 1; - if(pixel_hit_in_bucket(*(b-bw), x, y)) return 1; - if(pixel_hit_in_bucket(*(b-bw-1), x, y)) return 1; - return 0; + int ix, iy; + int l, t; + struct rock_struct **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 && pixel_hit_in_bucket(*(bucket-1), x, y)) return true; + if(t && pixel_hit_in_bucket(*(bucket-bw), x, y)) return true; + if(l && t && pixel_hit_in_bucket(*(bucket-(bw+1)), x, y)) return true; + return false; } void -- 1.7.10.4 From cd7fb220b16a73c15ff9dff7a5627bf78478875f Mon Sep 17 00:00:00 2001 From: Joshua Grams Date: Thu, 5 Jan 2006 04:12:20 +0000 Subject: [PATCH 08/16] * rocks.c (hit_rock, pixel_hit_rock): fix more possible bugs. --- rocks.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/rocks.c b/rocks.c index d395d5d..114e22f 100644 --- a/rocks.c +++ b/rocks.c @@ -316,19 +316,19 @@ hit_rocks(float x, float y, struct shape *shape) bucket = &rock_buckets[p][l + t*bw]; if(hit_in_bucket(*bucket, x, y, shape)) return true; - if(l && hit_in_bucket(*(bucket-1), x, y, shape)) return true; - if(t && hit_in_bucket(*(bucket-bw), x, y, shape)) return true; - if(l && t && hit_in_bucket(*(bucket-(1+bw)), x, y, shape)) return true; + if(l > 0 && hit_in_bucket(*(bucket-1), x, y, shape)) return true; + if(t > 0 && hit_in_bucket(*(bucket-bw), x, y, shape)) return true; + if(l > 0 && t > 0 && hit_in_bucket(*(bucket-1-bw), x, y, shape)) return true; if(r > l) { if(hit_in_bucket(*(bucket+1), x, y, shape)) return true; - if(hit_in_bucket(*(bucket+1-bw), x, y, shape)) return true; + if(t > 0 && hit_in_bucket(*(bucket+1-bw), x, y, shape)) return true; } - if(t > b) { + if(b > t) { if(hit_in_bucket(*(bucket+bw), x, y, shape)) return true; - if(hit_in_bucket(*(bucket+bw-1), x, y, shape)) return true; + if(l > 0 && hit_in_bucket(*(bucket-1+bw), x, y, shape)) return true; } - if(r > l && t > b && hit_in_bucket(*(bucket+bw+1), x, y, shape)) return true; + if(r > l && b > t && hit_in_bucket(*(bucket+1+bw), x, y, shape)) return true; return false; } @@ -353,9 +353,9 @@ pixel_hit_rocks(float x, float y) 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 && pixel_hit_in_bucket(*(bucket-1), x, y)) return true; - if(t && pixel_hit_in_bucket(*(bucket-bw), x, y)) return true; - if(l && t && pixel_hit_in_bucket(*(bucket-(bw+1)), 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; } -- 1.7.10.4 From 0bbc23a37289ca20b8681229ccf74edfb6261d4e Mon Sep 17 00:00:00 2001 From: Joshua Grams Date: Thu, 2 Feb 2006 22:38:39 +0000 Subject: [PATCH 09/16] minor rearrangements and the beginnings of a Windows port. --- INSTALL | 1 - common.h | 17 ++++++----------- file.c | 47 +++++++++++++++++++++++++++++++++++------------ file.h | 22 ++++++++++++---------- main.c | 14 +++++--------- 5 files changed, 58 insertions(+), 43 deletions(-) diff --git a/INSTALL b/INSTALL index aa22cc8..607ea94 100644 --- a/INSTALL +++ b/INSTALL @@ -28,4 +28,3 @@ INSTALLING before building. If you change these settings in the Makefile after building, you'll have to "make clean" and build again before installing. - diff --git a/common.h b/common.h index 069f677..59268ae 100644 --- a/common.h +++ b/common.h @@ -1,17 +1,8 @@ #ifndef VOR_COMMON_H #define VOR_COMMON_H -#ifndef NULL -#define NULL 0 -#endif - -#ifndef true -#define true 1 -#endif - -#ifndef false -#define false 0 -#endif +#include +#include #ifndef max #define max(a, b) ((a) > (b) ? (a) : (b)) @@ -28,4 +19,8 @@ #define CONDERROR(a) if((a)) {initerror = strdup(SDL_GetError());return 1;} #define NULLERROR(a) CONDERROR((a) == NULL) +#ifdef WIN32 +# include +#endif + #endif // VOR_COMMON_H diff --git a/file.c b/file.c index ee14299..4b7872a 100644 --- a/file.c +++ b/file.c @@ -19,7 +19,9 @@ #include #include #include -#include +#ifndef WIN32 +# include +#endif #include #include @@ -43,7 +45,7 @@ add_path(char *path, char *file) s = malloc(2+plen+flen); if(!s) return NULL; memcpy(s, path, plen); - s[plen] = '/'; + s[plen] = PATH_SEPARATOR; memcpy(s+plen+1, file, flen+1); return s; } @@ -54,7 +56,29 @@ add_data_path(char *filename) return add_path(g_data_dir, filename); } -int +#ifdef WIN32 + +bool +is_dir(char *dirname) +{ + WIN32_FILE_ATTRIBUTE_DATA buf; + if(!GetFileAttributesEx(dirname, GetFileExInfoStandard, &buf)) + return false; + return buf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; +} + +bool +is_file(char *filename) +{ + WIN32_FILE_ATTRIBUTE_DATA buf; + if(!GetFileAttributesEx(filename, GetFileExInfoStandard, &buf)) + return false; + return buf.dwFileAttributes & FILE_ATTRIBUTE_NORMAL; +} + +#else /* !WIN32 */ + +bool is_dir(char *dirname) { struct stat buf; @@ -62,7 +86,7 @@ is_dir(char *dirname) return S_ISDIR(buf.st_mode); } -int +bool is_file(char *filename) { struct stat buf; @@ -70,13 +94,15 @@ is_file(char *filename) return S_ISREG(buf.st_mode); } -int +#endif /* !WIN32 */ + +bool find_data_dir(void) { int i; char *data_options[3] = { - "./data", getenv("VOR_DATA"), + "data", DATA_PREFIX }; @@ -93,7 +119,7 @@ find_data_dir(void) return false; } -int +bool find_score_file(void) { char *dir, *s; @@ -110,13 +136,10 @@ find_score_file(void) } else return false; } -int +bool find_files(void) { - int r; - r = find_data_dir(); - find_score_file(); - return r; + return find_data_dir() && find_score_file(); } FILE * diff --git a/file.h b/file.h index f9249e9..f376213 100644 --- a/file.h +++ b/file.h @@ -19,19 +19,21 @@ #ifndef VOR_FILE_H #define VOR_FILE_H +#include #include -#include - -extern char *g_data_dir; -extern char *g_score_file; -extern mode_t g_score_mode; char *add_data_path(char *filename); -int is_dir(char *dirname); -int is_file(char *filename); -int find_data_dir(void); -int find_score_file(void); -int find_files(void); +bool is_dir(char *dirname); +bool is_file(char *filename); +bool find_data_dir(void); +bool find_score_file(void); +bool find_files(void); FILE *open_score_file(char *mode); +#ifdef WIN32 +# define PATH_SEPARATOR '\\' +#else +# define PATH_SEPARATOR '/' +#endif + #endif // VOR_FILE_H diff --git a/main.c b/main.c index a0b50cc..b5dc64d 100644 --- a/main.c +++ b/main.c @@ -329,7 +329,7 @@ init(void) { // Initialize SDL with audio and video if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0) { opt_sound = 0; - printf ("Can't open sound, starting without it\n"); + fputs("Can't open sound, starting without it\n", stderr); atexit(SDL_Quit); } else { atexit(SDL_Quit); @@ -600,14 +600,10 @@ gameloop() { new_rocks(); - // INERTIA - shipx += shipdx*t_frame; - shipy += shipdy*t_frame; - // SCROLLING - tmp = (shipy-YSCROLLTO)/25 + (shipdy-screendy); + tmp = (shipy+shipdy*t_frame-YSCROLLTO)/25 + (shipdy-screendy); screendy += tmp * t_frame/12; - tmp = (shipx-XSCROLLTO)/25 + (shipdx-screendx); + tmp = (shipx+shipdx*t_frame-XSCROLLTO)/25 + (shipdx-screendx); screendx += tmp * t_frame/12; // taper off so we don't hit the barrier abruptly. // (if we would hit in < 2 seconds, adjust to 2 seconds). @@ -621,8 +617,8 @@ gameloop() { xscroll = screendx * t_frame; yscroll = screendy * t_frame; - shipx -= xscroll; - shipy -= yscroll; + shipx += shipdx*t_frame - xscroll; + shipy += shipdy*t_frame - yscroll; // move bang center bangx += bangdx*t_frame - xscroll; -- 1.7.10.4 From a7afb8a944789a03012c2c661d05895e95ac78c8 Mon Sep 17 00:00:00 2001 From: Jason Woofenden Date: Thu, 16 Mar 2006 00:55:46 +0000 Subject: [PATCH 10/16] commented DEAD_PAUSE_LENGTH and updated URL --- config.h | 4 ++++ main.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/config.h b/config.h index 5c7729c..da4c6a5 100644 --- a/config.h +++ b/config.h @@ -36,6 +36,10 @@ // radius^2 (pixels) which will be cleared of rocks when you die #define BLAST_RADIUS 300 + +// time (in 1/60ths of a seccond) between when you blow up, and when your next +// ship appears. Make it at least 20.0 so the explosion has time to push the +// rocks away. #define DEAD_PAUSE_LENGTH 40.0 #define MAX_PATH_LEN 1024 diff --git a/main.c b/main.c index b5dc64d..fb2b755 100644 --- a/main.c +++ b/main.c @@ -105,7 +105,7 @@ float state_timeout = 600.0; #define NSEQUENCE 2 char *sequence[] = { "Press SPACE to start", - "http://herkamire.com/jason/vor" + "http://jasonwoof.org/vor" }; int bangdotlife, nbangdots; -- 1.7.10.4 From c633a2e26924f5210aa8094593f5f003cee70a48 Mon Sep 17 00:00:00 2001 From: Joshua Grams Date: Tue, 21 Mar 2006 12:43:36 +0000 Subject: [PATCH 11/16] refactoring towards sprites, updated todo --- main.c | 94 ++++++++++++++++++++++++++++++++------------------------------- rocks.c | 54 ++++++++++++++++-------------------- shape.h | 58 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 128 insertions(+), 78 deletions(-) diff --git a/main.c b/main.c index fb2b755..3f66ce0 100644 --- a/main.c +++ b/main.c @@ -51,7 +51,6 @@ SDL_Surface *surf_b_rockdodger, // "rockdodger" banner *surf_b_game, // Title element "game" *surf_b_over, // Title element "over" - *surf_ship, // Spaceship element *surf_life, // Indicator of number of ships remaining *surf_rock[NROCKS], // THE ROCKS *surf_font_big; // The big font @@ -67,9 +66,8 @@ struct bangdots bdot[MAXBANGDOTS], *bdotptr = bdot; char topline[1024]; char *initerror = ""; -struct shape shipshape; -float shipx = XSIZE/2, shipy = YSIZE/2; // X position, 0..XSIZE -float shipdx = SCREENDXMIN, shipdy = 0.0; // Change in X position per tick. +struct ship ship = { SHIP_SPRITE, NULL, XSIZE/2, YSIZE/2, SCREENDXMIN, 0.0 }; + float screendx = SCREENDXMIN, screendy = 0.0; float xscroll, yscroll; float back_dist; @@ -81,8 +79,7 @@ int ms_end; // end of this frame (milliseconds) float bangx, bangy, bangdx, bangdy; -int nships,score; -int jets = 0; +int score; float fadetimer = 0, faderate; @@ -223,8 +220,8 @@ new_engine_dots(int n, int dir) { float hx, hy; // half ship width/height. static const int s[4] = { 2, 1, 0, 1 }; - hx = surf_ship->w / 2; - hy = surf_ship->h / 2; + hx = ship.image->w / 2; + hy = ship.image->h / 2; for(i = 0; iactive == 0) { @@ -234,15 +231,15 @@ new_engine_dots(int n, int dir) { dy = r * -sin(a); // screen y is "backwards". dotptr->active = 1; - dotptr->x = shipx + s[dir]*hx + (frnd()-0.5)*3; - dotptr->y = shipy + s[(dir+1)&3]*hy + (frnd()-0.5)*3; + dotptr->x = ship.x + s[dir]*hx + (frnd()-0.5)*3; + dotptr->y = ship.y + s[(dir+1)&3]*hy + (frnd()-0.5)*3; if(dir&1) { - dotptr->dx = shipdx + 2*dx; - dotptr->dy = shipdy + 20*dy; + dotptr->dx = ship.dx + 2*dx; + dotptr->dy = ship.dy + 20*dy; dotptr->life = 60 * fabs(dy); } else { - dotptr->dx = shipdx + 20*dx; - dotptr->dy = shipdy + 2*dy; + dotptr->dx = ship.dx + 20*dx; + dotptr->dy = ship.dy + 2*dy; dotptr->life = 60 * fabs(dx); } @@ -284,7 +281,7 @@ drawdots(SDL_Surface *s) { // Create engine dots out the side we're moving from for(m = 0; m<4; m++) { - if(jets & 1<w + 10); dest.y = 20; SDL_BlitSurface(surf_life, NULL, surf_screen, &dest); @@ -515,7 +517,7 @@ draw() { } if(state == GAMEPLAY) { - bang = hit_rocks(shipx, shipy, &shipshape); + bang = hit_rocks(ship.x, ship.y, ship.shape); } ms_frame = SDL_GetTicks() - ms_end; @@ -601,9 +603,9 @@ gameloop() { new_rocks(); // SCROLLING - tmp = (shipy+shipdy*t_frame-YSCROLLTO)/25 + (shipdy-screendy); + tmp = (ship.y+ship.dy*t_frame-YSCROLLTO)/25 + (ship.dy-screendy); screendy += tmp * t_frame/12; - tmp = (shipx+shipdx*t_frame-XSCROLLTO)/25 + (shipdx-screendx); + tmp = (ship.x+ship.dx*t_frame-XSCROLLTO)/25 + (ship.dx-screendx); screendx += tmp * t_frame/12; // taper off so we don't hit the barrier abruptly. // (if we would hit in < 2 seconds, adjust to 2 seconds). @@ -617,8 +619,8 @@ gameloop() { xscroll = screendx * t_frame; yscroll = screendy * t_frame; - shipx += shipdx*t_frame - xscroll; - shipy += shipdy*t_frame - yscroll; + ship.x += ship.dx*t_frame - xscroll; + ship.y += ship.dy*t_frame - yscroll; // move bang center bangx += bangdx*t_frame - xscroll; @@ -628,30 +630,30 @@ gameloop() { // BOUNCE X - if(shipx<0 || shipx>XSIZE-surf_ship->w) { + if(ship.x<0 || ship.x>XSIZE-ship.image->w) { // BOUNCE from left and right wall - shipx -= (shipdx-screendx)*t_frame; - shipdx = screendx - (shipdx-screendx)*opt_bounciness; + ship.x -= (ship.dx-screendx)*t_frame; + ship.dx = screendx - (ship.dx-screendx)*opt_bounciness; } // BOUNCE Y - if(shipy<0 || shipy>YSIZE-surf_ship->h) { + if(ship.y<0 || ship.y>YSIZE-ship.image->h) { // BOUNCE from top and bottom wall - shipy -= (shipdy-screendy)*t_frame; - shipdy = screendy - (shipdy-screendy)*opt_bounciness; + ship.y -= (ship.dy-screendy)*t_frame; + ship.dy = screendy - (ship.dy-screendy)*opt_bounciness; } if(draw() && state == GAMEPLAY) { // Died play_sound(SOUND_BANG); // Play the explosion sound - bangx = shipx; bangy = shipy; bangdx = shipdx; bangdy = shipdy; - new_bang_dots(shipx,shipy,shipdx,shipdy,surf_ship); - shipdx *= 0.5; shipdy *= 0.5; - if(shipdx < SCREENDXMIN) shipdx = SCREENDXMIN; - if(--nships <= 0) { + bangx = ship.x; bangy = ship.y; bangdx = ship.dx; bangdy = ship.dy; + new_bang_dots(ship.x,ship.y,ship.dx,ship.dy,ship.image); + ship.dx *= 0.5; ship.dy *= 0.5; + if(ship.dx < SCREENDXMIN) ship.dx = SCREENDXMIN; + if(--ship.lives <= 0) { state = GAME_OVER; - shipdx = SCREENDXMIN; shipdy = 0; + ship.dx = SCREENDXMIN; ship.dy = 0; state_timeout = 200.0; fadetimer = 0.0; faderate = t_frame; @@ -670,17 +672,17 @@ gameloop() { reset_rocks(); - nships = 4; + ship.lives = 4; score = 0; state = GAMEPLAY; play_tune(TUNE_GAMEPLAY); - shipx = XSIZE/2.2; shipy = YSIZE/2; - shipdx = screendx; shipdy = screendy; + ship.x = XSIZE/2.2; ship.y = YSIZE/2; + ship.dx = screendx; ship.dy = screendy; } - jets = 0; + ship.jets = 0; } else { SDL_PumpEvents(); keystate = SDL_GetKeyState(NULL); @@ -688,10 +690,10 @@ gameloop() { if(state == GAMEPLAY) { if(!paused) { - if(keystate[SDLK_LEFT] | keystate[SDLK_h]) { shipdx -= 1.5*t_frame; jets |= 1<<0;} - if(keystate[SDLK_DOWN] | keystate[SDLK_t]) { shipdy += 1.5*t_frame; jets |= 1<<1;} - if(keystate[SDLK_RIGHT] | keystate[SDLK_n]) { shipdx += 1.5*t_frame; jets |= 1<<2;} - if(keystate[SDLK_UP] | keystate[SDLK_c]) { shipdy -= 1.5*t_frame; jets |= 1<<3;} + if(keystate[SDLK_LEFT] | keystate[SDLK_h]) { ship.dx -= 1.5*t_frame; ship.jets |= 1<<0;} + if(keystate[SDLK_DOWN] | keystate[SDLK_t]) { ship.dy += 1.5*t_frame; ship.jets |= 1<<1;} + if(keystate[SDLK_RIGHT] | keystate[SDLK_n]) { ship.dx += 1.5*t_frame; ship.jets |= 1<<2;} + if(keystate[SDLK_UP] | keystate[SDLK_c]) { ship.dy -= 1.5*t_frame; ship.jets |= 1<<3;} if(keystate[SDLK_3]) { SDL_SaveBMP(surf_screen, "snapshot.bmp"); } } diff --git a/rocks.c b/rocks.c index 114e22f..82f29bf 100644 --- a/rocks.c +++ b/rocks.c @@ -13,17 +13,9 @@ SDL_Surface *load_image(char *filename); -struct rock_struct { - struct rock_struct *next; - float x,y,dx,dy; - SDL_Surface *image; - struct shape *shape; - int type_number; -}; +struct rock rocks[MAXROCKS], *free_rocks; -struct rock_struct rocks[MAXROCKS], *free_rocks; - -struct rock_struct **rock_buckets[2]; +struct rock **rock_buckets[2]; int n_buckets; // we have two sets of buckets -- this variable tells which we are using. int p; @@ -46,7 +38,7 @@ 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 struct rock_struct ** +static inline struct rock ** bucket(int x, int y, int p) { int b = (x+grid_size)/grid_size + bw*((y+grid_size)/grid_size); @@ -62,8 +54,8 @@ init_buckets(void) bh = 1 + scr_grid_h + 1; n_buckets = bw * bh; - rock_buckets[0] = malloc(n_buckets * sizeof(struct rock_struct *)); - rock_buckets[1] = malloc(n_buckets * sizeof(struct rock_struct *)); + 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); @@ -72,10 +64,10 @@ init_buckets(void) } void -transfer_rock(struct rock_struct *r, struct rock_struct **from, struct rock_struct **to) +transfer_rock(struct rock *r, struct rock **from, struct rock **to) { - *from = r->next; - r->next = *to; + *from = &r->next->rock; + r->next = SPRITE(*to); *to = r; } @@ -86,7 +78,7 @@ reset_rocks(void) for(i=0; itype_number = urnd() % NROCKS; - r->image = surf_rock[r->type_number]; - r->shape = &rock_shapes[r->type_number]; + r->type = urnd() % NROCKS; + r->image = surf_rock[r->type]; + r->shape = &rock_shapes[r->type]; switch(i) { case RIGHT: r->x = XSIZE; @@ -256,8 +248,8 @@ void move_rocks(void) { int b; - struct rock_struct **head; - struct rock_struct *r; + struct rock **head; + struct rock *r; // Move all the rocks for(b=0; bnext) { + for(; r; r=&r->next->rock) { if(collide(x - r->x, y - r->y, r->shape, shape)) return 1; } return 0; @@ -308,7 +300,7 @@ hit_rocks(float x, float y, struct shape *shape) { int ix, iy; int l, r, t, b; - struct rock_struct **bucket; + struct rock **bucket; ix = x + grid_size; iy = y + grid_size; l = ix / grid_size; r = (ix+shape->w)/grid_size; @@ -333,9 +325,9 @@ hit_rocks(float x, float y, struct shape *shape) } int -pixel_hit_in_bucket(struct rock_struct *r, float x, float y) +pixel_hit_in_bucket(struct rock *r, float x, float y) { - for(; r; r=r->next) { + for(; r; r=&r->next->rock) { if(x < r->x || y < r->y) continue; if(pixel_collide(x - r->x, y - r->y, r->shape)) return 1; } @@ -347,7 +339,7 @@ pixel_hit_rocks(float x, float y) { int ix, iy; int l, t; - struct rock_struct **bucket; + struct rock **bucket; ix = x + grid_size; iy = y + grid_size; l = ix / grid_size; t = iy / grid_size; @@ -363,13 +355,13 @@ void blast_rocks(float x, float y, float radius, int onlyslow) { int b; - struct rock_struct *r; + struct rock *r; float dx, dy, n; if(onlyslow) return; for(b=0; bnext) { + for(r=rock_buckets[p][b]; r; r=&r->next->rock) { if(r->x <= 0) continue; // This makes it so your explosion from dying magically doesn't leave diff --git a/shape.h b/shape.h index 9f7371d..c2d0a8e 100644 --- a/shape.h +++ b/shape.h @@ -2,7 +2,10 @@ #define VOR_SHAPE_H #include -#include +#include + + +// Shape stuff struct shape { int w, h; @@ -15,4 +18,57 @@ void get_shape(SDL_Surface *img, struct shape *s); int collide(int xdiff, int ydiff, struct shape *r, struct shape *s); int pixel_collide(unsigned int xoff, unsigned int yoff, struct shape *r); + + +// Sprite stuff + +typedef union sprite Sprite; + +#define SPRITE(x) ((Sprite *) (x)) + +struct base_sprite { + uint8_t type; + Sprite *next; + float x, y; + float dx, dy; + SDL_Surface *image; + struct shape *shape; +}; + +struct rock { + // core sprite fields + uint8_t sprite_type; + Sprite *next; + float x, y; + float dx, dy; + SDL_Surface *image; + struct shape *shape; + // ROCK extras + int type; +}; + +struct ship { + // core sprite fields + uint8_t sprite_type; + Sprite *next; + float x, y; + float dx, dy; + SDL_Surface *image; + struct shape *shape; + // SHIP extras + int lives; + int jets; +}; + +union sprite { + uint8_t type; + struct base_sprite sprite; + struct rock rock; + struct ship ship; +}; + +#define BASE_SPRITE 0 +#define SHIP_SPRITE 1 +#define ROCK_SPRITE 2 + #endif // VOR_SHAPE_H -- 1.7.10.4 From f33f1a05297ce0156030f0f78ecf5b84e00d424c Mon Sep 17 00:00:00 2001 From: Joshua Grams Date: Tue, 21 Mar 2006 13:21:50 +0000 Subject: [PATCH 12/16] renamed shape files to sprite, added todo list to svn. --- Makefile | 2 +- globals.h | 8 +--- main.c | 2 +- rocks.c | 1 - rocks.h | 2 +- shape.c | 121 ------------------------------------------------------------- shape.h | 74 ------------------------------------- sprite.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ sprite.h | 74 +++++++++++++++++++++++++++++++++++++ todo | 12 ++++++ 10 files changed, 211 insertions(+), 206 deletions(-) delete mode 100644 shape.c delete mode 100644 shape.h create mode 100644 sprite.c create mode 100644 sprite.h create mode 100644 todo diff --git a/Makefile b/Makefile index f8f4dd7..b3d8333 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ sdl-ldflags := $(shell sdl-config --libs) ldflags := $(sdl-ldflags) -lSDL_image -lSDL_mixer $(LDFLAGS) cflags := $(sdl-cflags) $(paths) $(CFLAGS) -my_objects := args.o dust.o file.o mt.o rocks.o score.o shape.o sound.o +my_objects := args.o dust.o file.o mt.o rocks.o score.o sprite.o sound.o my_objects += main.o libs := SFont.o objects := $(libs) $(my_objects) diff --git a/globals.h b/globals.h index bf5e1da..11ae5c4 100644 --- a/globals.h +++ b/globals.h @@ -2,7 +2,6 @@ #define VOR_GLOBALS_H #include -#include "shape.h" #include "SFont.h" struct bangdots { @@ -40,8 +39,6 @@ extern SDL_Surface extern SFont_Font *g_font; -extern uint32_t area; - // Structure global variables extern struct enginedots edot[MAXENGINEDOTS], *dotptr; extern struct bangdots bdot[MAXBANGDOTS], *bdotptr; @@ -50,9 +47,6 @@ extern struct bangdots bdot[MAXBANGDOTS], *bdotptr; extern char topline[1024]; extern char *initerror; -extern struct shape shipshape; -extern float shipx,shipy; // ship position on screen -extern float shipdx,shipdy; // ship speed (pixels/tick) extern float screendx, screendy; extern float xscroll, yscroll; extern float yscroll; @@ -62,7 +56,7 @@ extern float scrollvel; // All speeds are pixels/tick, with 20 ticks per second. extern float t_frame; // length of this frame (in ticks = 1/20th second) -extern int nships,score; +extern int score; extern float fadetimer, faderate; extern int pausedown, paused; diff --git a/main.c b/main.c index 3f66ce0..ae52bd7 100644 --- a/main.c +++ b/main.c @@ -39,7 +39,7 @@ #include "mt.h" #include "rocks.h" #include "score.h" -#include "shape.h" +#include "sprite.h" #include "sound.h" // ************************************* VARS diff --git a/rocks.c b/rocks.c index 82f29bf..8cb7987 100644 --- a/rocks.c +++ b/rocks.c @@ -9,7 +9,6 @@ #include "globals.h" #include "mt.h" #include "rocks.h" -#include "shape.h" SDL_Surface *load_image(char *filename); diff --git a/rocks.h b/rocks.h index 52c8cab..40f26bd 100644 --- a/rocks.h +++ b/rocks.h @@ -1,4 +1,4 @@ -#include "shape.h" +#include "sprite.h" int init_rocks(void); void reset_rocks(void); diff --git a/shape.c b/shape.c deleted file mode 100644 index f29bd6e..0000000 --- a/shape.c +++ /dev/null @@ -1,121 +0,0 @@ -#include -#include "common.h" -#include "shape.h" - -void -get_shape(SDL_Surface *img, struct shape *s) -{ - int x, y; - uint16_t *px, transp; - uint32_t bits = 0, bit, *p; - - if(img->format->BytesPerPixel != 2) { - fprintf(stderr, "get_shape(): not a 16-bit image!\n"); - exit(1); - } - - s->area = 0; - s->w = img->w; s->h = img->h; - s->mw = ((img->w+31)>>5); - s->mask = malloc(4*s->mw*s->h); - if(!s->mask) { - fprintf(stderr, "can't malloc bitmask"); - exit(1); - } - - SDL_LockSurface(img); - px = img->pixels; - transp = img->format->colorkey; - p = s->mask; - for(y=0; yh; y++) { - bit = 0; - for(x=0; xw; x++) { - if(!bit) { bits = 0; bit = 0x80000000; } - if(*px++ != transp) { bits |= bit; s->area++; } - bit >>= 1; - if(!bit || x == img->w - 1) { *(p++) = bits; } - } - px = (uint16_t *) ((uint8_t *) px + img->pitch - 2*img->w); - } - SDL_UnlockSurface(img); -} - -int -line_collide(int xov, struct shape *r, uint32_t *rbits, struct shape *s, uint32_t *sbits) -{ - int lshift, n, i, ret = 0; - uint32_t lbits; - struct shape *st; - uint32_t *bt; - - - if(xov < 0) { - st = r; r = s; s = st; - bt = rbits; rbits = sbits; sbits = bt; - xov = -xov; - } - - - lshift = (r->w - xov) & 31; - rbits += (r->w - xov) >> 5; - n = (xov + 31) >> 5; - for(i=0; i> (32 - lshift); - if(lbits & *sbits++) ret = 1; - } - lbits = *rbits << lshift; - if(lbits & *sbits) ret = 1; - - return ret; -} - -int -mask_collide(int xov, int yov, struct shape *r, struct shape *s) -{ - int y, ry, sy; - uint32_t *rbits, *sbits; - - if(yov > 0) { - ry = r->h - yov; sy = 0; - rbits = r->mask + (r->h - yov) * r->mw; - sbits = s->mask; - } else { - ry = 0; sy = s->h + yov; - rbits = r->mask; - sbits = s->mask + (s->h + yov) * s->mw; - } - - for(y=0; ymw; sbits += s->mw; - } - - return 0; -} - -int -collide(int xdiff, int ydiff, struct shape *r, struct shape *s) -{ - int xov, yov; - - if(xdiff >= 0) xov = max(min(r->w-xdiff, s->w), 0); - else xov = min(-min(s->w+xdiff, r->w), 0); - - if(ydiff >= 0) yov = max(min(r->h-ydiff, s->h), 0); - else yov = min(-min(s->h+ydiff, r->h), 0); - - if(xov == 0 || yov == 0) return 0; // bboxes hit? - else return mask_collide(xov, yov, r, s); -} - -int -pixel_collide(unsigned int xoff, unsigned int yoff, struct shape *r) -{ - uint32_t pmask; - - if(xoff >= r->w || yoff >= r->h) return 0; - - pmask = 0x80000000 >> (xoff&0x1f); - return r->mask[(yoff*r->mw) + (xoff>>5)] & pmask; -} diff --git a/shape.h b/shape.h deleted file mode 100644 index c2d0a8e..0000000 --- a/shape.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef VOR_SHAPE_H -#define VOR_SHAPE_H - -#include -#include - - -// Shape stuff - -struct shape { - int w, h; - int mw; // mask width (number of uint32's) - uint32_t *mask; - uint32_t area; -}; - -void get_shape(SDL_Surface *img, struct shape *s); -int collide(int xdiff, int ydiff, struct shape *r, struct shape *s); -int pixel_collide(unsigned int xoff, unsigned int yoff, struct shape *r); - - - -// Sprite stuff - -typedef union sprite Sprite; - -#define SPRITE(x) ((Sprite *) (x)) - -struct base_sprite { - uint8_t type; - Sprite *next; - float x, y; - float dx, dy; - SDL_Surface *image; - struct shape *shape; -}; - -struct rock { - // core sprite fields - uint8_t sprite_type; - Sprite *next; - float x, y; - float dx, dy; - SDL_Surface *image; - struct shape *shape; - // ROCK extras - int type; -}; - -struct ship { - // core sprite fields - uint8_t sprite_type; - Sprite *next; - float x, y; - float dx, dy; - SDL_Surface *image; - struct shape *shape; - // SHIP extras - int lives; - int jets; -}; - -union sprite { - uint8_t type; - struct base_sprite sprite; - struct rock rock; - struct ship ship; -}; - -#define BASE_SPRITE 0 -#define SHIP_SPRITE 1 -#define ROCK_SPRITE 2 - -#endif // VOR_SHAPE_H diff --git a/sprite.c b/sprite.c new file mode 100644 index 0000000..ca3e937 --- /dev/null +++ b/sprite.c @@ -0,0 +1,121 @@ +#include +#include "common.h" +#include "sprite.h" + +void +get_shape(SDL_Surface *img, struct shape *s) +{ + int x, y; + uint16_t *px, transp; + uint32_t bits = 0, bit, *p; + + if(img->format->BytesPerPixel != 2) { + fprintf(stderr, "get_shape(): not a 16-bit image!\n"); + exit(1); + } + + s->area = 0; + s->w = img->w; s->h = img->h; + s->mw = ((img->w+31)>>5); + s->mask = malloc(4*s->mw*s->h); + if(!s->mask) { + fprintf(stderr, "can't malloc bitmask"); + exit(1); + } + + SDL_LockSurface(img); + px = img->pixels; + transp = img->format->colorkey; + p = s->mask; + for(y=0; yh; y++) { + bit = 0; + for(x=0; xw; x++) { + if(!bit) { bits = 0; bit = 0x80000000; } + if(*px++ != transp) { bits |= bit; s->area++; } + bit >>= 1; + if(!bit || x == img->w - 1) { *(p++) = bits; } + } + px = (uint16_t *) ((uint8_t *) px + img->pitch - 2*img->w); + } + SDL_UnlockSurface(img); +} + +int +line_collide(int xov, struct shape *r, uint32_t *rbits, struct shape *s, uint32_t *sbits) +{ + int lshift, n, i, ret = 0; + uint32_t lbits; + struct shape *st; + uint32_t *bt; + + + if(xov < 0) { + st = r; r = s; s = st; + bt = rbits; rbits = sbits; sbits = bt; + xov = -xov; + } + + + lshift = (r->w - xov) & 31; + rbits += (r->w - xov) >> 5; + n = (xov + 31) >> 5; + for(i=0; i> (32 - lshift); + if(lbits & *sbits++) ret = 1; + } + lbits = *rbits << lshift; + if(lbits & *sbits) ret = 1; + + return ret; +} + +int +mask_collide(int xov, int yov, struct shape *r, struct shape *s) +{ + int y, ry, sy; + uint32_t *rbits, *sbits; + + if(yov > 0) { + ry = r->h - yov; sy = 0; + rbits = r->mask + (r->h - yov) * r->mw; + sbits = s->mask; + } else { + ry = 0; sy = s->h + yov; + rbits = r->mask; + sbits = s->mask + (s->h + yov) * s->mw; + } + + for(y=0; ymw; sbits += s->mw; + } + + return 0; +} + +int +collide(int xdiff, int ydiff, struct shape *r, struct shape *s) +{ + int xov, yov; + + if(xdiff >= 0) xov = max(min(r->w-xdiff, s->w), 0); + else xov = min(-min(s->w+xdiff, r->w), 0); + + if(ydiff >= 0) yov = max(min(r->h-ydiff, s->h), 0); + else yov = min(-min(s->h+ydiff, r->h), 0); + + if(xov == 0 || yov == 0) return 0; // bboxes hit? + else return mask_collide(xov, yov, r, s); +} + +int +pixel_collide(unsigned int xoff, unsigned int yoff, struct shape *r) +{ + uint32_t pmask; + + if(xoff >= r->w || yoff >= r->h) return 0; + + pmask = 0x80000000 >> (xoff&0x1f); + return r->mask[(yoff*r->mw) + (xoff>>5)] & pmask; +} diff --git a/sprite.h b/sprite.h new file mode 100644 index 0000000..c2d0a8e --- /dev/null +++ b/sprite.h @@ -0,0 +1,74 @@ +#ifndef VOR_SHAPE_H +#define VOR_SHAPE_H + +#include +#include + + +// Shape stuff + +struct shape { + int w, h; + int mw; // mask width (number of uint32's) + uint32_t *mask; + uint32_t area; +}; + +void get_shape(SDL_Surface *img, struct shape *s); +int collide(int xdiff, int ydiff, struct shape *r, struct shape *s); +int pixel_collide(unsigned int xoff, unsigned int yoff, struct shape *r); + + + +// Sprite stuff + +typedef union sprite Sprite; + +#define SPRITE(x) ((Sprite *) (x)) + +struct base_sprite { + uint8_t type; + Sprite *next; + float x, y; + float dx, dy; + SDL_Surface *image; + struct shape *shape; +}; + +struct rock { + // core sprite fields + uint8_t sprite_type; + Sprite *next; + float x, y; + float dx, dy; + SDL_Surface *image; + struct shape *shape; + // ROCK extras + int type; +}; + +struct ship { + // core sprite fields + uint8_t sprite_type; + Sprite *next; + float x, y; + float dx, dy; + SDL_Surface *image; + struct shape *shape; + // SHIP extras + int lives; + int jets; +}; + +union sprite { + uint8_t type; + struct base_sprite sprite; + struct rock rock; + struct ship ship; +}; + +#define BASE_SPRITE 0 +#define SHIP_SPRITE 1 +#define ROCK_SPRITE 2 + +#endif // VOR_SHAPE_H diff --git a/todo b/todo new file mode 100644 index 0000000..d1b9de2 --- /dev/null +++ b/todo @@ -0,0 +1,12 @@ +**** Finish porting to Windows (should be only file.c and args.c, I think) + +*** Switch over to sprites rather than totally separate structures. +* Rocks collide with each other? + +*** Add a scripting language and separate game logic from the engine. + Forth? Scheme? Lua? + +** Switch to a TTF font and all ray-traced graphics +* Then we can run at the native screen size + +* Deltas on high score display? -- 1.7.10.4 From f8a464d8eed8cf611c0c3f80166d2a650efb1485 Mon Sep 17 00:00:00 2001 From: Joshua Grams Date: Tue, 21 Mar 2006 17:33:25 +0000 Subject: [PATCH 13/16] Updated collide to take two sprites. removed references to stdint.h (using inttypes.h where necessary). Makefile: update header dependencies. --- Makefile | 20 +++++++++++++++++++- dust.h | 2 -- main.c | 14 ++++---------- rocks.c | 37 ++++++++++++++++++------------------- rocks.h | 2 +- score.c | 1 - score.h | 2 +- sprite.c | 40 ++++++++++++++++++++++++++++++---------- sprite.h | 13 ++++++++----- 9 files changed, 81 insertions(+), 50 deletions(-) diff --git a/Makefile b/Makefile index b3d8333..77460c4 100644 --- a/Makefile +++ b/Makefile @@ -63,7 +63,25 @@ program: vor $(my_objects): config.h -main.o file.o: file.h +SFont.o: SFont.h + +args.o: args.h + +dust.o: globals.h dust.h mt.h + +file.o: file.h common.h + +main.o: args.h common.h dust.h file.h globals.h mt.h rocks.h score.h sprite.h sound.h + +mt.o: mt.h + +rocks.o: rocks.h common.h file.h globals.h mt.h + +score.o: score.h common.h file.h + +sound.o: sound.h args.h common.h + +sprite.o: sprite.h common.h vor: $(objects) @echo linking $@ from $^ diff --git a/dust.h b/dust.h index b8e0de1..984587b 100644 --- a/dust.h +++ b/dust.h @@ -1,8 +1,6 @@ #ifndef VOR_DUST_H #define VOR_DUST_H -#include - /* * Dust motes are harmless background items. They are created when the * program is initialized, and are simply wrapped whenever they hit the diff --git a/main.c b/main.c index ae52bd7..d57aa3b 100644 --- a/main.c +++ b/main.c @@ -21,8 +21,8 @@ #include #include -#include -#include +#include +#include #include #include #include @@ -368,13 +368,7 @@ init(void) { NULLERROR(surf_b_over = load_image("banners/over.png")); // Load the spaceship graphic. - ship.shape = malloc(sizeof(struct shape)); - if(!ship.shape) { - fprintf(stderr, "can't allocate ship shape.\n"); - exit(1); - } - NULLERROR(ship.image = load_image("sprites/ship.png")); - get_shape(ship.image, ship.shape); + load_sprite(SPRITE(&ship), "sprites/ship.png"); // Load the life indicator (small ship) graphic. NULLERROR(surf_life = load_image("indicators/life.png")); @@ -517,7 +511,7 @@ draw() { } if(state == GAMEPLAY) { - bang = hit_rocks(ship.x, ship.y, ship.shape); + bang = hit_rocks(SPRITE(&ship)); } ms_frame = SDL_GetTicks() - ms_end; diff --git a/rocks.c b/rocks.c index 8cb7987..d01d794 100644 --- a/rocks.c +++ b/rocks.c @@ -10,8 +10,6 @@ #include "mt.h" #include "rocks.h" -SDL_Surface *load_image(char *filename); - struct rock rocks[MAXROCKS], *free_rocks; struct rock **rock_buckets[2]; @@ -286,40 +284,41 @@ draw_rocks(void) } int -hit_in_bucket(struct rock *r, float x, float y, struct shape *shape) +hit_in_bucket(struct rock *r, Sprite *s) { for(; r; r=&r->next->rock) { - if(collide(x - r->x, y - r->y, r->shape, shape)) return 1; + if(collide(SPRITE(r), s)) return true; } - return 0; + return false; } int -hit_rocks(float x, float y, struct shape *shape) +hit_rocks(Sprite *s) { - int ix, iy; + struct base_sprite *sp = &s->sprite; int l, r, t, b; struct rock **bucket; - ix = x + grid_size; iy = y + grid_size; - l = ix / grid_size; r = (ix+shape->w)/grid_size; - t = iy / grid_size; b = (iy+shape->h)/grid_size; + l = (sp->x + grid_size) / grid_size; + r = (sp->x + sp->shape->w + grid_size) / grid_size; + t = (sp->y + grid_size) / grid_size; + b = (sp->y + sp->shape->h + grid_size) / grid_size; bucket = &rock_buckets[p][l + t*bw]; - if(hit_in_bucket(*bucket, x, y, shape)) return true; - if(l > 0 && hit_in_bucket(*(bucket-1), x, y, shape)) return true; - if(t > 0 && hit_in_bucket(*(bucket-bw), x, y, shape)) return true; - if(l > 0 && t > 0 && hit_in_bucket(*(bucket-1-bw), x, y, shape)) return true; + 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), x, y, shape)) return true; - if(t > 0 && hit_in_bucket(*(bucket+1-bw), x, y, shape)) return true; + 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), x, y, shape)) return true; - if(l > 0 && hit_in_bucket(*(bucket-1+bw), x, y, shape)) return true; + 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), x, y, shape)) return true; + if(r > l && b > t && hit_in_bucket(*(bucket+1+bw), s)) return true; return false; } diff --git a/rocks.h b/rocks.h index 40f26bd..ab5df75 100644 --- a/rocks.h +++ b/rocks.h @@ -7,7 +7,7 @@ void new_rocks(void); void move_rocks(void); void draw_rocks(void); -int hit_rocks(float x, float y, struct shape *shape); +int hit_rocks(Sprite *s); int pixel_hit_rocks(float x, float y); void blast_rocks(float x, float y, float radius, int onlyslow); diff --git a/score.c b/score.c index 31025a9..5738e72 100644 --- a/score.c +++ b/score.c @@ -18,7 +18,6 @@ #include #include -#include #include #include #include diff --git a/score.h b/score.h index 478afca..0778033 100644 --- a/score.h +++ b/score.h @@ -20,7 +20,7 @@ #define VOR_SCORE_H #include -#include +#include #include #define N_SCORES 8 diff --git a/sprite.c b/sprite.c index ca3e937..9a9d953 100644 --- a/sprite.c +++ b/sprite.c @@ -3,6 +3,22 @@ #include "sprite.h" void +load_sprite(Sprite *sprite, char *filename) +{ + struct base_sprite *spr = &sprite->sprite; + spr->image = load_image(filename); + if(!spr->image) return; + if(!spr->shape) { + spr->shape = malloc(sizeof(struct shape)); + if(!spr->shape) { + fprintf(stderr, "load_sprite(): can't allocate shape structure.\n"); + exit(1); + } + get_shape(spr->image, spr->shape); + } +} + +void get_shape(SDL_Surface *img, struct shape *s) { int x, y; @@ -19,7 +35,7 @@ get_shape(SDL_Surface *img, struct shape *s) s->mw = ((img->w+31)>>5); s->mask = malloc(4*s->mw*s->h); if(!s->mask) { - fprintf(stderr, "can't malloc bitmask"); + fprintf(stderr, "get_shape(): can't allocate bitmask.\n"); exit(1); } @@ -40,7 +56,7 @@ get_shape(SDL_Surface *img, struct shape *s) SDL_UnlockSurface(img); } -int +static int line_collide(int xov, struct shape *r, uint32_t *rbits, struct shape *s, uint32_t *sbits) { int lshift, n, i, ret = 0; @@ -70,7 +86,7 @@ line_collide(int xov, struct shape *r, uint32_t *rbits, struct shape *s, uint32_ return ret; } -int +static int mask_collide(int xov, int yov, struct shape *r, struct shape *s) { int y, ry, sy; @@ -95,18 +111,22 @@ mask_collide(int xov, int yov, struct shape *r, struct shape *s) } int -collide(int xdiff, int ydiff, struct shape *r, struct shape *s) +collide(Sprite *r, Sprite *s) { + struct shape *rs = r->sprite.shape; + struct shape *ss = s->sprite.shape; + int dx = s->sprite.x - r->sprite.x; + int dy = s->sprite.y - r->sprite.y; int xov, yov; - if(xdiff >= 0) xov = max(min(r->w-xdiff, s->w), 0); - else xov = min(-min(s->w+xdiff, r->w), 0); + if(dx >= 0) xov = max(min(rs->w - dx, ss->w), 0); + else xov = -max(min(ss->w + dx, rs->w), 0); - if(ydiff >= 0) yov = max(min(r->h-ydiff, s->h), 0); - else yov = min(-min(s->h+ydiff, r->h), 0); + if(dy >= 0) yov = max(min(rs->h - dy, ss->h), 0); + else yov = -max(min(ss->h + dy, rs->h), 0); - if(xov == 0 || yov == 0) return 0; // bboxes hit? - else return mask_collide(xov, yov, r, s); + if(xov == 0 || yov == 0) return false; + else return mask_collide(xov, yov, rs, ss); } int diff --git a/sprite.h b/sprite.h index c2d0a8e..939de08 100644 --- a/sprite.h +++ b/sprite.h @@ -1,9 +1,11 @@ #ifndef VOR_SHAPE_H #define VOR_SHAPE_H -#include +#include #include +typedef union sprite Sprite; + // Shape stuff @@ -15,15 +17,13 @@ struct shape { }; void get_shape(SDL_Surface *img, struct shape *s); -int collide(int xdiff, int ydiff, struct shape *r, struct shape *s); -int pixel_collide(unsigned int xoff, unsigned int yoff, struct shape *r); +int collide(Sprite *r, Sprite *s); +int pixel_collide(unsigned int xdiff, unsigned int ydiff, struct shape *r); // Sprite stuff -typedef union sprite Sprite; - #define SPRITE(x) ((Sprite *) (x)) struct base_sprite { @@ -71,4 +71,7 @@ union sprite { #define SHIP_SPRITE 1 #define ROCK_SPRITE 2 +SDL_Surface *load_image(char *filename); +void load_sprite(Sprite *sprite, char *filename); + #endif // VOR_SHAPE_H -- 1.7.10.4 From 3f9238432d3b902a7744ad5a61f61995d67267a5 Mon Sep 17 00:00:00 2001 From: Joshua Grams Date: Tue, 21 Mar 2006 21:25:16 +0000 Subject: [PATCH 14/16] ditched the separate shape struct. --- rocks.c | 56 +++++++++++++------------- sprite.c | 133 ++++++++++++++++++++++++++------------------------------------ sprite.h | 69 ++++++++++++++------------------ 3 files changed, 113 insertions(+), 145 deletions(-) diff --git a/rocks.c b/rocks.c index d01d794..a32652a 100644 --- a/rocks.c +++ b/rocks.c @@ -19,11 +19,10 @@ int p; int bw, bh; int grid_size; -SDL_Surface *surf_rock[NROCKS]; -struct shape rock_shapes[NROCKS]; +static struct rock prototypes[NROCKS]; // timers for rock generation. -float rtimers[4]; +static float rtimers[4]; uint32_t nrocks; float nrocks_timer; @@ -63,8 +62,8 @@ init_buckets(void) void transfer_rock(struct rock *r, struct rock **from, struct rock **to) { - *from = &r->next->rock; - r->next = SPRITE(*to); + *from = r->next; + r->next = *to; *to = r; } @@ -74,8 +73,11 @@ reset_rocks(void) int i; for(i=0; i= 1) { rtimers[i] -= 1; if(!free_rocks) return; // sorry, we ran out of rocks! - r = free_rocks; - r->type = urnd() % NROCKS; - r->image = surf_rock[r->type]; - r->shape = &rock_shapes[r->type]; + r = free_rocks; free_rocks = r->next; + type = urnd() % NROCKS; + *r = prototypes[type]; + r->type = type; switch(i) { case RIGHT: r->x = XSIZE; @@ -236,7 +237,8 @@ new_rocks(void) r->dy = weighted_rnd_range(rmin[i], rmax[i]) + screendy; break; } - transfer_rock(r, &free_rocks, bucket(r->x, r->y, p)); + tmp = bucket(r->x, r->y, p); + r->next = *tmp; *tmp = r; } } } @@ -286,7 +288,7 @@ draw_rocks(void) int hit_in_bucket(struct rock *r, Sprite *s) { - for(; r; r=&r->next->rock) { + for(; r; r=r->next) { if(collide(SPRITE(r), s)) return true; } return false; @@ -295,14 +297,13 @@ hit_in_bucket(struct rock *r, Sprite *s) int hit_rocks(Sprite *s) { - struct base_sprite *sp = &s->sprite; int l, r, t, b; struct rock **bucket; - l = (sp->x + grid_size) / grid_size; - r = (sp->x + sp->shape->w + grid_size) / grid_size; - t = (sp->y + grid_size) / grid_size; - b = (sp->y + sp->shape->h + grid_size) / grid_size; + 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; @@ -325,9 +326,8 @@ hit_rocks(Sprite *s) int pixel_hit_in_bucket(struct rock *r, float x, float y) { - for(; r; r=&r->next->rock) { - if(x < r->x || y < r->y) continue; - if(pixel_collide(x - r->x, y - r->y, r->shape)) return 1; + for(; r; r=r->next) { + if(pixel_collide(SPRITE(r), x, y)) return 1; } return 0; } @@ -359,7 +359,7 @@ blast_rocks(float x, float y, float radius, int onlyslow) if(onlyslow) return; for(b=0; bnext->rock) { + for(r=rock_buckets[p][b]; r; r=r->next) { if(r->x <= 0) continue; // This makes it so your explosion from dying magically doesn't leave diff --git a/sprite.c b/sprite.c index 9a9d953..760af11 100644 --- a/sprite.c +++ b/sprite.c @@ -3,139 +3,118 @@ #include "sprite.h" void -load_sprite(Sprite *sprite, char *filename) +load_sprite(Sprite *s, char *filename) { - struct base_sprite *spr = &sprite->sprite; - spr->image = load_image(filename); - if(!spr->image) return; - if(!spr->shape) { - spr->shape = malloc(sizeof(struct shape)); - if(!spr->shape) { - fprintf(stderr, "load_sprite(): can't allocate shape structure.\n"); - exit(1); - } - get_shape(spr->image, spr->shape); - } + s->image = load_image(filename); + if(s->image) get_shape(s); } void -get_shape(SDL_Surface *img, struct shape *s) +get_shape(Sprite *s) { int x, y; uint16_t *px, transp; uint32_t bits = 0, bit, *p; - if(img->format->BytesPerPixel != 2) { + if(s->image->format->BytesPerPixel != 2) { fprintf(stderr, "get_shape(): not a 16-bit image!\n"); exit(1); } - s->area = 0; - s->w = img->w; s->h = img->h; - s->mw = ((img->w+31)>>5); - s->mask = malloc(4*s->mw*s->h); + 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); if(!s->mask) { fprintf(stderr, "get_shape(): can't allocate bitmask.\n"); exit(1); } - SDL_LockSurface(img); - px = img->pixels; - transp = img->format->colorkey; + SDL_LockSurface(s->image); + px = s->image->pixels; + transp = s->image->format->colorkey; p = s->mask; - for(y=0; yh; y++) { + for(y=0; yimage->h; y++) { bit = 0; - for(x=0; xw; x++) { + for(x=0; ximage->w; x++) { if(!bit) { bits = 0; bit = 0x80000000; } - if(*px++ != transp) { bits |= bit; s->area++; } + if(*px++ != transp) { bits |= bit; } bit >>= 1; - if(!bit || x == img->w - 1) { *(p++) = bits; } + if(!bit || x == s->image->w - 1) { *(p++) = bits; } } - px = (uint16_t *) ((uint8_t *) px + img->pitch - 2*img->w); + px = (uint16_t *) ((uint8_t *) px + s->image->pitch - 2*s->image->w); } - SDL_UnlockSurface(img); + SDL_UnlockSurface(s->image); } static int -line_collide(int xov, struct shape *r, uint32_t *rbits, struct shape *s, uint32_t *sbits) +line_collide(int xov, unsigned bit, uint32_t *amask, uint32_t *bmask) { - int lshift, n, i, ret = 0; - uint32_t lbits; - struct shape *st; - uint32_t *bt; - - - if(xov < 0) { - st = r; r = s; s = st; - bt = rbits; rbits = sbits; sbits = bt; - xov = -xov; - } - + int i, words = (xov-1) >> 5; + uint32_t abits; - lshift = (r->w - xov) & 31; - rbits += (r->w - xov) >> 5; - n = (xov + 31) >> 5; - for(i=0; i> (32 - lshift); - if(lbits & *sbits++) ret = 1; + for(i=0; i> (32-bit); + if(abits & *bmask++) return true; } - lbits = *rbits << lshift; - if(lbits & *sbits) ret = 1; + abits = *amask << bit; + if(abits & *bmask) return true; - return ret; + return false; } static int -mask_collide(int xov, int yov, struct shape *r, struct shape *s) +mask_collide(int xov, int yov, Sprite *a, Sprite *b) { - int y, ry, sy; - uint32_t *rbits, *sbits; + int y; + int xoffset = a->w - xov; + int word = xoffset >> 5, bit = xoffset & 31; + uint32_t *amask = a->mask, *bmask = b->mask; if(yov > 0) { - ry = r->h - yov; sy = 0; - rbits = r->mask + (r->h - yov) * r->mw; - sbits = s->mask; + amask = a->mask + ((a->h - yov) * a->mask_w) + word; + bmask = b->mask; } else { - ry = 0; sy = s->h + yov; - rbits = r->mask; - sbits = s->mask + (s->h + yov) * s->mw; + yov = -yov; + amask = a->mask; + bmask = b->mask + ((b->h - yov) * b->mask_w) + word; } - for(y=0; ymw; sbits += s->mw; + for(y=0; ymask_w; bmask += b->mask_w; } return 0; } int -collide(Sprite *r, Sprite *s) +collide(Sprite *a, Sprite *b) { - struct shape *rs = r->sprite.shape; - struct shape *ss = s->sprite.shape; - int dx = s->sprite.x - r->sprite.x; - int dy = s->sprite.y - r->sprite.y; - int xov, yov; + int dx, dy, xov, yov; + + if(b->x < a->x) { Sprite *tmp = a; a = b; b = tmp; } + + dx = b->x - a->x; + dy = b->y - a->y; - if(dx >= 0) xov = max(min(rs->w - dx, ss->w), 0); - else xov = -max(min(ss->w + dx, rs->w), 0); + xov = max(min(a->w - dx, b->w), 0); - if(dy >= 0) yov = max(min(rs->h - dy, ss->h), 0); - else yov = -max(min(ss->h + dy, rs->h), 0); + if(dy >= 0) yov = max(min(a->h - dy, b->h), 0); + else yov = -max(min(a->h - -dy, b->h), 0); if(xov == 0 || yov == 0) return false; - else return mask_collide(xov, yov, rs, ss); + else return mask_collide(xov, yov, a, b); } int -pixel_collide(unsigned int xoff, unsigned int yoff, struct shape *r) +pixel_collide(Sprite *s, int x, int y) { uint32_t pmask; - if(xoff >= r->w || yoff >= r->h) return 0; + if(x < s->x || y < s->y || x >= s->x + s->w || y >= s->y + s->h) return 0; - pmask = 0x80000000 >> (xoff&0x1f); - return r->mask[(yoff*r->mw) + (xoff>>5)] & pmask; + x -= s->x; y -= s->y; + pmask = 0x80000000 >> (x&0x1f); + return s->mask[(y*s->mask_w) + (x>>5)] & pmask; } diff --git a/sprite.h b/sprite.h index 939de08..7df8631 100644 --- a/sprite.h +++ b/sprite.h @@ -4,73 +4,62 @@ #include #include -typedef union sprite Sprite; +typedef struct sprite Sprite; +#define SPRITE(x) ((Sprite *) (x)) -// Shape stuff +#define BASE_SPRITE 0 +#define SHIP_SPRITE 1 +#define ROCK_SPRITE 2 -struct shape { +struct sprite { + uint8_t type; + Sprite *next; + float x, y; + float dx, dy; + SDL_Surface *image; int w, h; - int mw; // mask width (number of uint32's) + int mask_w; uint32_t *mask; - uint32_t area; }; -void get_shape(SDL_Surface *img, struct shape *s); +void get_shape(Sprite *s); int collide(Sprite *r, Sprite *s); -int pixel_collide(unsigned int xdiff, unsigned int ydiff, struct shape *r); +int pixel_collide(Sprite *s, int x, int y); -// Sprite stuff - -#define SPRITE(x) ((Sprite *) (x)) +// extended sprites -struct base_sprite { - uint8_t type; - Sprite *next; +struct ship { + // core sprite fields + uint8_t sprite_type; + struct ship *next; float x, y; float dx, dy; SDL_Surface *image; - struct shape *shape; + int w, h; + int mask_w; + uint32_t *mask; + // SHIP extras + int lives; + int jets; }; struct rock { // core sprite fields uint8_t sprite_type; - Sprite *next; + struct rock *next; float x, y; float dx, dy; SDL_Surface *image; - struct shape *shape; + int w, h; + int mask_w; + uint32_t *mask; // ROCK extras int type; }; -struct ship { - // core sprite fields - uint8_t sprite_type; - Sprite *next; - float x, y; - float dx, dy; - SDL_Surface *image; - struct shape *shape; - // SHIP extras - int lives; - int jets; -}; - -union sprite { - uint8_t type; - struct base_sprite sprite; - struct rock rock; - struct ship ship; -}; - -#define BASE_SPRITE 0 -#define SHIP_SPRITE 1 -#define ROCK_SPRITE 2 - SDL_Surface *load_image(char *filename); void load_sprite(Sprite *sprite, char *filename); -- 1.7.10.4 From 0d415d88f7ecd55273b09b619170078f7d35a910 Mon Sep 17 00:00:00 2001 From: Joshua Grams Date: Tue, 21 Mar 2006 22:18:29 +0000 Subject: [PATCH 15/16] * rocks.c (struct rock): changed generic ones to Sprite. --- rocks.c | 55 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/rocks.c b/rocks.c index a32652a..86c76e7 100644 --- a/rocks.c +++ b/rocks.c @@ -10,9 +10,10 @@ #include "mt.h" #include "rocks.h" -struct rock rocks[MAXROCKS], *free_rocks; +struct rock rocks[MAXROCKS]; +Sprite *free_rocks; -struct rock **rock_buckets[2]; +Sprite **rock_buckets[2]; int n_buckets; // we have two sets of buckets -- this variable tells which we are using. int p; @@ -34,7 +35,7 @@ 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 struct rock ** +static inline Sprite ** bucket(int x, int y, int p) { int b = (x+grid_size)/grid_size + bw*((y+grid_size)/grid_size); @@ -59,12 +60,19 @@ init_buckets(void) p = 0; } -void -transfer_rock(struct rock *r, struct rock **from, struct rock **to) +static inline void +insert_sprite(Sprite **head, Sprite *this) +{ + this->next = *head; + *head = this; +} + +static inline Sprite * +remove_sprite(Sprite **head) { - *from = r->next; - r->next = *to; - *to = r; + Sprite *this = *head; + *head = this->next; + return this; } void @@ -76,7 +84,7 @@ reset_rocks(void) rocks[0].next = NULL; for(i=1; i= 1) { rtimers[i] -= 1; if(!free_rocks) return; // sorry, we ran out of rocks! - r = free_rocks; free_rocks = r->next; + r = (struct rock *) remove_sprite(&free_rocks); type = urnd() % NROCKS; *r = prototypes[type]; r->type = type; @@ -237,8 +246,7 @@ new_rocks(void) r->dy = weighted_rnd_range(rmin[i], rmax[i]) + screendy; break; } - tmp = bucket(r->x, r->y, p); - r->next = *tmp; *tmp = r; + insert_sprite(bucket(r->x, r->y, p), SPRITE(r)); } } } @@ -247,8 +255,7 @@ void move_rocks(void) { int b; - struct rock **head; - struct rock *r; + Sprite *r, **head; // Move all the rocks for(b=0; bx + r->image->w < 0 || r->x >= XSIZE || r->y + r->image->h < 0 || r->y >= YSIZE) { - transfer_rock(r, head, &free_rocks); + insert_sprite(&free_rocks, remove_sprite(head)); r->image = NULL; - } else transfer_rock(r, head, bucket(r->x, r->y, 1-p)); + } else insert_sprite(bucket(r->x, r->y, 1-p), remove_sprite(head)); } } p = 1-p; // switch current set of buckets. @@ -286,10 +293,10 @@ draw_rocks(void) } int -hit_in_bucket(struct rock *r, Sprite *s) +hit_in_bucket(Sprite *r, Sprite *s) { for(; r; r=r->next) { - if(collide(SPRITE(r), s)) return true; + if(collide(r, s)) return true; } return false; } @@ -298,7 +305,7 @@ int hit_rocks(Sprite *s) { int l, r, t, b; - struct rock **bucket; + Sprite **bucket; l = (s->x + grid_size) / grid_size; r = (s->x + s->w + grid_size) / grid_size; @@ -324,10 +331,10 @@ hit_rocks(Sprite *s) } int -pixel_hit_in_bucket(struct rock *r, float x, float y) +pixel_hit_in_bucket(Sprite *r, float x, float y) { for(; r; r=r->next) { - if(pixel_collide(SPRITE(r), x, y)) return 1; + if(pixel_collide(r, x, y)) return 1; } return 0; } @@ -337,7 +344,7 @@ pixel_hit_rocks(float x, float y) { int ix, iy; int l, t; - struct rock **bucket; + Sprite **bucket; ix = x + grid_size; iy = y + grid_size; l = ix / grid_size; t = iy / grid_size; @@ -353,7 +360,7 @@ void blast_rocks(float x, float y, float radius, int onlyslow) { int b; - struct rock *r; + Sprite *r; float dx, dy, n; if(onlyslow) return; -- 1.7.10.4 From 5c8f059629c2127848ce4051296d2f5897bf5c0f Mon Sep 17 00:00:00 2001 From: Joshua Grams Date: Wed, 22 Mar 2006 14:02:58 +0000 Subject: [PATCH 16/16] 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