add complaints from HappyPenguin to todo,
some refactoring.
// initial/final counts for rocks-on-screen
#define I_ROCKS 20
// initial/final counts for rocks-on-screen
#define I_ROCKS 20
// number of rock structs to allocate
#define MAXROCKS 120
// number of rock structs to allocate
#define MAXROCKS 120
char topline[1024];
char *initerror = "";
char topline[1024];
char *initerror = "";
-struct ship ship = { SHIP, ALL_FLAGS, NULL, XSIZE/2, YSIZE/2, SCREENDXMIN, 0.0 };
+struct ship ship = { SHIP, 0, NULL, XSIZE/2, YSIZE/2, SCREENDXMIN, 0.0 };
float screendx = SCREENDXMIN, screendy = 0.0;
float xscroll, yscroll;
float screendx = SCREENDXMIN, screendy = 0.0;
float xscroll, yscroll;
+
+ 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);
+ }
+}
+
+void
+draw(void) {
+ SDL_Rect dest;
int x;
char *text;
float fadegame,fadeover;
int x;
char *text;
float fadegame,fadeover;
- // Draw a fully black background
- SDL_FillRect(surf_screen,NULL,0);
-
- // Draw the background dots
- drawdots(surf_screen);
-
- // Draw ship
- if(state == GAMEPLAY) draw_sprite(SPRITE(&ship));
-
+ SDL_FillRect(surf_screen,NULL,0); // black background
+ drawdots(surf_screen); // background dots
+ draw_sprite(SPRITE(&ship));
- // Draw the life indicators.
- if(state == GAMEPLAY || state == DEAD_PAUSE || state == GAME_OVER) {
- 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);
- }
- }
-
- // Draw the score
- snprintscore_line(topline, 50, score);
- SFont_Write(surf_screen, g_font, XSIZE-250, 0, topline);
+ show_lives();
+ show_score();
// If it's game over, show the game over graphic in the dead centre
switch (state) {
// If it's game over, show the game over graphic in the dead centre
switch (state) {
ms_frame = SDL_GetTicks() - ms_end;
ms_end += ms_frame;
ms_frame = SDL_GetTicks() - ms_end;
ms_end += ms_frame;
- if(ms_frame>200 || ms_frame<0) {
- // We won't run at all below 5 frames per second.
- // This also happens if we were paused, grr.
- t_frame = 0;
- ms_frame = 0;
- } else {
- t_frame = opt_gamespeed * ms_frame / 50;
- if(state == GAMEPLAY) score += ms_frame;
- }
+ t_frame = opt_gamespeed * ms_frame / 50;
+ if(state == GAMEPLAY) score += ms_frame;
// Update the surface
SDL_Flip(surf_screen);
}
// Update the surface
SDL_Flip(surf_screen);
}
+static inline void
+kill_ship(Sprite *ship)
+{
+ ship->flags = MOVE|DRAW;
+ SDL_SetAlpha(ship->image, SDL_SRCALPHA, 0);
+ bang = true;
+}
+
void
do_collision(Sprite *a, Sprite *b)
{
void
do_collision(Sprite *a, Sprite *b)
{
- if(a->type == SHIP) {
- a->flags = MOVE_FLAG; bang = true;
- } else if (b->type == SHIP) {
- b->flags = MOVE_FLAG; bang = true;
- } else {
- bounce(a, b);
- }
+ if(a->type == SHIP) kill_ship(a);
+ else if (b->type == SHIP) kill_ship(b);
+ else bounce(a, b);
gameloop() {
Uint8 *keystate = SDL_GetKeyState(NULL);
float tmp;
for(;;) {
gameloop() {
Uint8 *keystate = SDL_GetKeyState(NULL);
float tmp;
for(;;) {
+ SDL_PumpEvents();
+ keystate = SDL_GetKeyState(NULL);
+
if(!paused) {
// Count down the game loop timer, and change state when it gets to zero or less;
if((state_timeout -= t_frame*3) < 0) {
switch(state) {
case DEAD_PAUSE:
if(!paused) {
// Count down the game loop timer, and change state when it gets to zero or less;
if((state_timeout -= t_frame*3) < 0) {
switch(state) {
case DEAD_PAUSE:
- // Create a new ship and start all over again
- ship.flags = ALL_FLAGS;
+ // Restore the ship and continue playing
+ ship.flags = DRAW|MOVE|COLLIDE;
state = GAMEPLAY;
play_tune(TUNE_GAMEPLAY);
break;
state = GAMEPLAY;
play_tune(TUNE_GAMEPLAY);
break;
SDL_EnableUNICODE(1);
while(SDL_PollEvent(&e))
;
SDL_EnableUNICODE(1);
while(SDL_PollEvent(&e))
;
- } else if(!keystate[SDLK_SPACE]) {
state = HIGH_SCORE_DISPLAY;
state_timeout = 400;
}
state = HIGH_SCORE_DISPLAY;
state_timeout = 400;
}
}
} else {
if(state == DEAD_PAUSE) {
}
} else {
if(state == DEAD_PAUSE) {
+ float blast_radius, alpha;
if(state_timeout >= DEAD_PAUSE_LENGTH - 20.0) {
blast_radius = BLAST_RADIUS * (DEAD_PAUSE_LENGTH - state_timeout) / 20.0;
blast_rocks(bangx, bangy, blast_radius);
}
if(bangx < 60) bangx = 60;
if(state_timeout >= DEAD_PAUSE_LENGTH - 20.0) {
blast_radius = BLAST_RADIUS * (DEAD_PAUSE_LENGTH - state_timeout) / 20.0;
blast_rocks(bangx, bangy, blast_radius);
}
if(bangx < 60) bangx = 60;
+
+ alpha = 255.0 * (DEAD_PAUSE_LENGTH - state_timeout) / DEAD_PAUSE_LENGTH;
+ SDL_SetAlpha(ship.image, SDL_SRCALPHA, (uint8_t)alpha);
- // BOUNCE X
- if(ship.x<0 || ship.x>XSIZE-ship.image->w) {
- // BOUNCE from left and right wall
+ // BOUNCE off left or right edge of screen
+ if(ship.x < 0 || ship.x+ship.w > XSIZE) {
ship.x -= (ship.dx-screendx)*t_frame;
ship.dx = screendx - (ship.dx-screendx)*opt_bounciness;
}
ship.x -= (ship.dx-screendx)*t_frame;
ship.dx = screendx - (ship.dx-screendx)*opt_bounciness;
}
- // BOUNCE Y
- if(ship.y<0 || ship.y>YSIZE-ship.image->h) {
- // BOUNCE from top and bottom wall
+ // BOUNCE off top or bottom of screen
+ if(ship.y < 0 || ship.y+ship.h > YSIZE) {
ship.y -= (ship.dy-screendy)*t_frame;
ship.dy = screendy - (ship.dy-screendy)*opt_bounciness;
}
ship.y -= (ship.dy-screendy)*t_frame;
ship.dy = screendy - (ship.dy-screendy)*opt_bounciness;
}
- SDL_PumpEvents();
- keystate = SDL_GetKeyState(NULL);
-
- if(keystate[SDLK_SPACE] && (state == HIGH_SCORE_DISPLAY || state == TITLE_PAGE)) {
+ if(keystate[SDLK_SPACE]
+ && (state == HIGH_SCORE_DISPLAY
+ || state == TITLE_PAGE
+ || state == GAME_OVER)) {
reset_sprites();
reset_rocks();
ship.x = XSIZE/2.2; ship.y = YSIZE/2;
ship.dx = screendx; ship.dy = screendy;
ship.lives = 4;
reset_sprites();
reset_rocks();
ship.x = XSIZE/2.2; ship.y = YSIZE/2;
ship.dx = screendx; ship.dy = screendy;
ship.lives = 4;
- ship.flags = ALL_FLAGS;
+ ship.flags = MOVE|DRAW|COLLIDE;
+ SDL_SetAlpha(ship.image, SDL_SRCALPHA, SDL_ALPHA_OPAQUE);
add_sprite(SPRITE(&ship));
score = 0;
add_sprite(SPRITE(&ship));
score = 0;
- } else {
- SDL_PumpEvents();
- keystate = SDL_GetKeyState(NULL);
- if(state == GAMEPLAY) {
+ if(state == GAMEPLAY || state == DEAD_PAUSE) {
if(!paused) {
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(!paused) {
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(!pausedown) {
paused = !paused;
pausedown = 1;
if(!pausedown) {
paused = !paused;
pausedown = 1;
+ if(!paused) ms_end = SDL_GetTicks();
}
} else {
pausedown = 0;
}
}
} else {
pausedown = 0;
}
- } else if(state == GAME_OVER) {
- if(keystate[SDLK_SPACE]) {
- state_timeout = -1;
- }
- if(state != HIGH_SCORE_ENTRY && (keystate[SDLK_q] || keystate[SDLK_ESCAPE])) {
- return 0;
- }
+ if(state != HIGH_SCORE_ENTRY && (keystate[SDLK_q] || keystate[SDLK_ESCAPE]))
+ return;
snprintf(a, ROCK_LEN, "sprites/rock%02d.png", i);
load_sprite(SPRITE(&prototypes[i]), a);
prototypes[i].sprite_type = ROCK;
snprintf(a, ROCK_LEN, "sprites/rock%02d.png", i);
load_sprite(SPRITE(&prototypes[i]), a);
prototypes[i].sprite_type = ROCK;
- prototypes[i].flags = ALL_FLAGS;
+ prototypes[i].flags = MOVE|DRAW|COLLIDE;
}
memset(rocks, 0, MAXROCKS*sizeof(struct rock));
}
memset(rocks, 0, MAXROCKS*sizeof(struct rock));
n *= 15;
r->dx += 54.0*dx/n;
r->dy += 54.0*dy/n;
n *= 15;
r->dx += 54.0*dx/n;
r->dy += 54.0*dy/n;
- r->flags &= ~COLLIDE_FLAG;
#include "common.h"
#include "config.h"
#include "file.h"
#include "common.h"
#include "config.h"
#include "file.h"
#include "score.h"
// High score table
#include "score.h"
// High score table
-int
-snprintscore_line(char *s, size_t n, int score)
- int r = snprintf(s, n, "Time: ");
- return r + snprintscore(s+r, n-r, score);
+ char s[16];
+ int r = snprintf(s, 16, "Time: ");
+ snprintscore(s+r, 16-r, score);
+ SFont_Write(surf_screen, g_font, XSIZE-250, 0, s);
void read_high_score_table(void);
void write_high_score_table(void);
int snprintscore(char *s, size_t n, int score);
void read_high_score_table(void);
void write_high_score_table(void);
int snprintscore(char *s, size_t n, int score);
-int snprintscore_line(char *s, size_t n, int score);
void display_scores(SDL_Surface *s, uint32_t x, uint32_t y);
int new_high_score(int score);
int process_score_input(void);
void display_scores(SDL_Surface *s, uint32_t x, uint32_t y);
int new_high_score(int score);
int process_score_input(void);
void
move_sprite(Sprite *s)
{
void
move_sprite(Sprite *s)
{
- if(s->flags & DRAW_FLAG) {
- // move it.
s->x += (s->dx - screendx)*t_frame;
s->y += (s->dy - screendy)*t_frame;
}
s->x += (s->dx - screendx)*t_frame;
s->y += (s->dy - screendy)*t_frame;
}
-#define MOVE_FLAG 1
-#define DRAW_FLAG 2
-#define COLLIDE_FLAG 4
-#define ALL_FLAGS (~0)
+#define MOVE 1
+#define DRAW 2
+#define COLLIDE 4
-#define COLLIDES(sprite) ((sprite)->flags & COLLIDE_FLAG)
+#define COLLIDES(sprite) ((sprite)->flags & COLLIDE)
Sprite *free_sprites[N_TYPES]; // lists of free sprites, by type.
Sprite *free_sprites[N_TYPES]; // lists of free sprites, by type.
draw_sprite(Sprite *s)
{
SDL_Rect dest;
draw_sprite(Sprite *s)
{
SDL_Rect dest;
- if(s->flags & DRAW_FLAG) {
dest.x = s->x; dest.y = s->y;
SDL_BlitSurface(s->image, NULL, surf_screen, &dest);
}
dest.x = s->x; dest.y = s->y;
SDL_BlitSurface(s->image, NULL, surf_screen, &dest);
}
** BUG: Rocks can be created touching, often giving a high-velocity bounce.
** BUG: Rocks can be created touching, often giving a high-velocity bounce.
-*** Add a scripting language and separate game logic from the engine.
- Forth? Scheme? Lua?
+*** Move game logic into a script so we can have "variations".
+* Then an in-game menu to choose which game.
** Switch to a TTF font and all ray-traced graphics
* Then we can run at the native screen size
* Deltas on high score display?
** Switch to a TTF font and all ray-traced graphics
* Then we can run at the native screen size
* Deltas on high score display?
+
+
+Comments from HappyPenguin (and solution ideas by Josh)
+
+*** Too hard: should be able to choose difficulty from within game.
+** What do you do at game over? "Press SPACE to start a new game".
+** Multiple deaths is a problem: fade new ship in? [DONE 2006-03-24]
+** Why can't you go left? You're trying to outrun a blast wave.