JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
refactoring towards sprites, updated todo
authorJoshua Grams <josh@qualdan.com>
Tue, 21 Mar 2006 12:43:36 +0000 (12:43 +0000)
committerJoshua Grams <josh@qualdan.com>
Tue, 21 Mar 2006 12:43:36 +0000 (12:43 +0000)
main.c
rocks.c
shape.h

diff --git a/main.c b/main.c
index fb2b755..3f66ce0 100644 (file)
--- 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; i<n; i++) {
                if(dotptr->active == 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<<m) { // 'jets' is a bit field
+               if(ship.jets & 1<<m) { // 'jets' is a bit field
                        new_engine_dots(80,m);
                }
        }
@@ -371,8 +368,13 @@ init(void) {
        NULLERROR(surf_b_over = load_image("banners/over.png"));
 
        // Load the spaceship graphic.
-       NULLERROR(surf_ship = load_image("sprites/ship.png"));
-       get_shape(surf_ship, &shipshape);
+       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 the life indicator (small ship) graphic.
        NULLERROR(surf_life = load_image("indicators/life.png"));
@@ -416,16 +418,16 @@ draw() {
 
        // Draw ship
        if(state == GAMEPLAY ) {
-               dest.x = shipx;
-               dest.y = shipy;
-               SDL_BlitSurface(surf_ship,NULL,surf_screen,&dest);
+               dest.x = ship.x;
+               dest.y = ship.y;
+               SDL_BlitSurface(ship.image,NULL,surf_screen,&dest);
        }
 
        draw_rocks();
 
        // Draw the life indicators.
        if(state == GAMEPLAY || state == DEAD_PAUSE || state == GAME_OVER) {
-               for(i = 0; i<nships-1; i++) {
+               for(i = 0; i<ship.lives-1; i++) {
                        dest.x = (i + 1)*(surf_life->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 (file)
--- a/rocks.c
+++ b/rocks.c
 
 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; i<MAXROCKS; i++) rocks[i].image = NULL;
        rocks[0].next = NULL; free_rocks = &rocks[MAXROCKS-1];
-       for(i = 1; i<MAXROCKS; i++) rocks[i].next = &rocks[i-1];
+       for(i = 1; i<MAXROCKS; i++) rocks[i].next = SPRITE(&rocks[i-1]);
        for(i = 0; i<n_buckets; i++) {
                rock_buckets[0][i] = NULL;
                rock_buckets[1][i] = NULL;
@@ -190,7 +182,7 @@ void
 new_rocks(void)
 {
        int i;
-       struct rock_struct *r;
+       struct rock *r;
        float ti[4];
        float rmin[4];
        float rmax[4];
@@ -214,9 +206,9 @@ new_rocks(void)
                        rtimers[i] -= 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];
+                       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; b<n_buckets; b++) {
@@ -295,9 +287,9 @@ draw_rocks(void)
 }
 
 int
-hit_in_bucket(struct rock_struct *r, float x, float y, struct shape *shape)
+hit_in_bucket(struct rock *r, float x, float y, struct shape *shape)
 {
-       for(; r; r=r->next) {
+       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; b<n_buckets; b++) {
-               for(r=rock_buckets[p][b]; r; r=r->next) {
+               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 (file)
--- a/shape.h
+++ b/shape.h
@@ -2,7 +2,10 @@
 #define VOR_SHAPE_H
 
 #include <SDL/SDL.h>
-#include <stdint.h>
+#include <inttypes.h>
+
+
+// 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