JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
moved grid stuff from rocks.c to sprite.c
authorJoshua Grams <josh@qualdan.com>
Wed, 22 Mar 2006 14:02:58 +0000 (14:02 +0000)
committerJoshua Grams <josh@qualdan.com>
Wed, 22 Mar 2006 14:02:58 +0000 (14:02 +0000)
Makefile
common.h
main.c
rocks.c
rocks.h
sprite.c
sprite.h

index 77460c4..650a98b 100644 (file)
--- 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)\"
index 59268ae..28d9ea0 100644 (file)
--- a/common.h
+++ b/common.h
@@ -4,6 +4,8 @@
 #include <stdbool.h>
 #include <stddef.h>
 
+#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 (file)
--- 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 (file)
--- 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<MAXROCKS; i++) rocks[i].image = NULL;
-
-       rocks[0].next = NULL;
-       for(i=1; i<MAXROCKS; i++) rocks[i].next = &rocks[i-1];
-       free_rocks = SPRITE(&rocks[MAXROCKS-1]);
-
-       for(i = 0; i<n_buckets; i++) {
-               rock_buckets[0][i] = NULL;
-               rock_buckets[1][i] = NULL;
-       }
-
        nrocks = I_ROCKS;
        nrocks_timer = 0;
 }
 
 #define ROCK_LEN sizeof("sprites/rockXX.png")
 
-int
-init_rocks(void)
+void
+load_rocks(void)
 {
        int i;
        char a[ROCK_LEN];
-       int maxw=0, maxh=0;
 
-       for(i = 0; i<NROCKS; i++) {
+       for(i=0; i<NROCKS; i++) {
                snprintf(a, ROCK_LEN, "sprites/rock%02d.png", i);
                load_sprite(SPRITE(&prototypes[i]), a);
-               prototypes[i].type = ROCK_SPRITE;
-               maxw = max(maxw, prototypes[i].w);
-               maxh = max(maxh, prototypes[i].h);
+               prototypes[i].sprite_type = ROCK_SPRITE;
        }
-       grid_size = max(maxw, maxh) * 3 / 2;
-       init_buckets();
+
+       memset(rocks, 0, MAXROCKS*sizeof(struct rock));
+
+       for(i=1; i<MAXROCKS; i++) rocks[i].next = &rocks[i-1];
+       free_sprites[ROCK_SPRITE] = SPRITE(&rocks[MAXROCKS-1]);
+
        reset_rocks();
-       return 0;
 }
 
 enum { LEFT, RIGHT, TOP, BOTTOM };
@@ -211,8 +150,8 @@ new_rocks(void)
        for(i=0; i<4; i++) {
                while(rtimers[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; b<n_buckets; b++) {
-               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 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; i<MAXROCKS; i++) {
-               if(!rocks[i].image) continue;
-               dest.x = rocks[i].x; dest.y = rocks[i].y;
-               SDL_BlitSurface(rocks[i].image,NULL,surf_screen,&dest);
-       }
-}
-
-int
-hit_in_bucket(Sprite *r, Sprite *s)
-{
-       for(; r; r=r->next) {
-               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; i<MAXROCKS; i++) draw_sprite(SPRITE(&rocks[i]));
 }
 
 void
-blast_rocks(float x, float y, float radius, int onlyslow)
+blast_rocks(float x, float y, float radius)
 {
-       int b;
+       int i;
        Sprite *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) {
-                       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; i<MAXROCKS; i++) {
+               if(rocks[i].sprite_type == NONE) continue;
+               r = SPRITE(&rocks[i]);
+               if(r->x <= 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 (file)
--- 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);
index 760af11..38dae30 100644 (file)
--- a/sprite.c
+++ b/sprite.c
@@ -1,15 +1,31 @@
 #include <stdlib.h>
+#include <string.h>
+#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; sq<gw*gh; sq++) {
+               head=&sprites[set][sq];
+               while(*head) {
+                       Sprite *s = remove_sprite(head);
+                       move_sprite(s); sort_sprite(s);
+               }
+       }
+       set = 1-set;  // switch to other set of sprites.
+}
+
+
 static int
 line_collide(int xov, unsigned bit, uint32_t *amask, uint32_t *bmask)
 {
@@ -108,6 +211,44 @@ collide(Sprite *a, Sprite *b)
 }
 
 int
+hit_in_square(Sprite *r, Sprite *s)
+{
+       for(; r; r=r->next) {
+               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;
+}
index 7df8631..4c0cefd 100644 (file)
--- 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 <SDL.h>
 #include <inttypes.h>
@@ -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