#include "config.h"
#include "dust.h"
#include "file.h"
+#include "float.h"
#include "globals.h"
#include "mt.h"
#include "rocks.h"
font *g_font;
-// Structure global variables
-struct enginedots edot[MAXENGINEDOTS], *dotptr = edot;
-struct bangdots bdot[MAXBANGDOTS], *bdotptr = bdot;
+struct dot {
+ int active;
+ float x, y;
+ float dx, dy;
+ float mass; // in DOT_MASS_UNITs
+ float decay; // rate at which to reduce mass.
+ int heat; // heat multiplier (color).
+};
+
+struct dot edot[MAXENGINEDOTS], *dotptr = edot;
+struct dot bdot[MAXBANGDOTS];
// Other global variables
char topline[1024];
}
}
-void
-new_bang_dots(struct sprite *s)
-{
- int i, n, x, y;
- uint16_t *pixel, c;
- uint32_t colorkey;
- int row_inc;
- double theta, r;
- SDL_Surface *img = s->image;
-
- n = 20;
- pixel = img->pixels;
- row_inc = img->pitch/sizeof(uint16_t) - img->w;
- colorkey = img->format->colorkey;
-
- if(SDL_MUSTLOCK(img)) { SDL_LockSurface(img); }
-
- for(i=0; i<n; i++) {
- pixel = img->pixels;
- for(y=0; y<img->h; y++) {
- for(x = 0; x<img->w; x++) {
- c = *pixel++;
- if(c && c != colorkey) {
- theta = frnd()*M_PI*2;
- r = frnd(); r = 1 - r*r;
-
- bdot[bd2].dx = 45*r*cos(theta) + s->dx;
- bdot[bd2].dy = 45*r*sin(theta) + s->dy;
- bdot[bd2].x = x + s->x;
- bdot[bd2].y = y + s->y;
- //bdot[bd2].c = (i < n-3) ? 0 : c;
- bdot[bd2].life = frnd() * 99;
- bdot[bd2].decay = frnd()*3 + 1;
- bdot[bd2].active = 1;
-
- bd2 = (bd2+1) % MAXBANGDOTS;
- }
- pixel += row_inc;
- }
- }
- }
-
- if(SDL_MUSTLOCK(img)) { SDL_UnlockSurface(img); }
-}
-
-void
-move_bang_dots(float ticks)
-{
- int i;
- Sprite *hit;
-
- for(i=0; i<MAXBANGDOTS; i++) {
- if(!bdot[i].active) continue;
-
- // decrement life and maybe kill
- bdot[i].life -= bdot[i].decay * ticks/2.0;
- if(bdot[i].life < 0) { bdot[i].active = 0; continue; }
-
- // move and clip
- bdot[i].x += (bdot[i].dx - screendx)*ticks;
- bdot[i].y += (bdot[i].dy - screendy)*ticks;
- if(bdot[i].x < 0 || bdot[i].x >= (XSIZE - 0.000001) || bdot[i].y < 0 || bdot[i].y >= (YSIZE - 0.000001)) {
- bdot[i].active = 0;
- continue;
- }
-
- // check collisions
- if((hit = pixel_collides(bdot[i].x, bdot[i].y))) {
- if(hit->type != SHIP) { // they shouldn't hit the ship, but they do
- bdot[i].active = 0;
- hit->dx += ENGINE_DOT_WEIGHT * bdot[i].life * bdot[i].dx / sprite_mass(hit);
- hit->dy += ENGINE_DOT_WEIGHT * bdot[i].life * bdot[i].dy / sprite_mass(hit);
- continue;
- }
- }
- }
-}
-
-
-void
-draw_bang_dots(SDL_Surface *s)
-{
- int i;
- uint16_t *pixels, *pixel, c;
- int row_inc = s->pitch/sizeof(uint16_t);
-
- pixels = (uint16_t *) s->pixels;
-
- for(i=0; i<MAXBANGDOTS; i++) {
- if(!bdot[i].active) 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;
- }
-}
-
void
-new_engine_dots(float time_span) {
+new_engine_dots(void) {
int dir, i;
- int n = time_span * ENGINE_DOTS_PER_TIC;
+ int n = t_frame * ENGINE_DOTS_PER_TIC;
float a, r; // angle, random length
float dx, dy;
float hx, hy; // half ship width/height.
dy = r * -sin(a); // screen y is "backwards".
dotptr->active = 1;
+ dotptr->decay = 3;
+ dotptr->heat = 6;
// dot was created at a random time during the time span
- time = frnd() * time_span; // this is how long ago
+ time = frnd() * t_frame; // this is how long ago
// calculate how fast the ship was going when this engine dot was
// created (as if it had a smooth acceleration). This is used in
// the starting position (not speed) of the dot is calculated as
// though the ship were traveling at a constant speed for this
- // time_span.
+ // t_frame.
dotptr->x = (ship.x - (ship.dx - screendx) * time) + s[dir]*hx;
dotptr->y = (ship.y - (ship.dy - screendy) * time) + s[(dir+1)&3]*hy;
if(dir&1) {
dotptr->dx = past_ship_dx + 2*dx;
dotptr->dy = past_ship_dy + 20*dy;
- dotptr->life = 60 * fabs(dy);
+ dotptr->mass = 60 * fabs(dy);
} else {
dotptr->dx = past_ship_dx + 20*dx;
dotptr->dy = past_ship_dy + 2*dy;
- dotptr->life = 60 * fabs(dx);
+ dotptr->mass = 60 * fabs(dx);
}
// move the dot as though it were created in the past
}
}
+
void
-move_engine_dots(float ticks) {
- int i;
- Sprite *hit;
+new_bang_dots(struct sprite *s)
+{
+ int i, n, x, y;
+ uint16_t *pixel, c;
+ uint32_t colorkey;
+ int row_inc;
+ double theta, r;
+ SDL_Surface *img = s->image;
- for(i = 0; i<MAXENGINEDOTS; i++) {
- if(!edot[i].active) continue;
-
- edot[i].x += (edot[i].dx - screendx)*ticks;
- edot[i].y += (edot[i].dy - screendy)*ticks;
- edot[i].life -= t_frame*3;
- if(edot[i].life < 0 || edot[i].x<0 || edot[i].x >= (XSIZE - 0.000001) || edot[i].y < 0 || edot[i].y >= (YSIZE - 0.000001)) {
- edot[i].active = 0;
- continue;
+ n = 20;
+ pixel = img->pixels;
+ row_inc = img->pitch/sizeof(uint16_t) - img->w;
+ colorkey = img->format->colorkey;
+
+ if(SDL_MUSTLOCK(img)) { SDL_LockSurface(img); }
+
+ for(i=0; i<n; i++) {
+ pixel = img->pixels;
+ for(y=0; y<img->h; y++) {
+ for(x = 0; x<img->w; x++) {
+ c = *pixel++;
+ if(c && c != colorkey) {
+ theta = frnd()*M_PI*2;
+ r = frnd(); r = 1 - r*r;
+
+ bdot[bd2].dx = 45*r*cos(theta) + s->dx;
+ bdot[bd2].dy = 45*r*sin(theta) + s->dy;
+ bdot[bd2].x = x + s->x;
+ bdot[bd2].y = y + s->y;
+ bdot[bd2].mass = frnd() * 99;
+ bdot[bd2].decay = frnd()*1.5 + 0.5;
+ bdot[bd2].heat = 3;
+ bdot[bd2].active = 1;
+
+ bd2 = (bd2+1) % MAXBANGDOTS;
+ }
+ pixel += row_inc;
+ }
}
+ }
+
+ if(SDL_MUSTLOCK(img)) { SDL_UnlockSurface(img); }
+}
- // check collisions
- if((hit = pixel_collides(edot[i].x, edot[i].y))) {
- if(hit->type != SHIP) { // they shouldn't hit the ship, but they do
- edot[i].active = 0;
- hit->dx += ENGINE_DOT_WEIGHT * edot[i].life * edot[i].dx / sprite_mass(hit);
- hit->dy += ENGINE_DOT_WEIGHT * edot[i].life * edot[i].dy / sprite_mass(hit);
- continue;
+
+void
+move_dot(struct dot *d)
+{
+ Sprite *hit;
+ float mass;
+
+ if(d->active) {
+ d->x += (d->dx - screendx) * t_frame;
+ d->y += (d->dy - screendy) * t_frame;
+ d->mass -= t_frame * d->decay;
+ if(d->mass < 0 || fclip(d->x, XSIZE) || fclip(d->y, YSIZE))
+ d->active = 0;
+ else {
+ hit = pixel_collides(d->x, d->y);
+ if(hit && hit->type != SHIP) {
+ d->active = 0;
+ mass = sprite_mass(hit);
+ hit->dx += DOT_MASS_UNIT * d->mass * d->dx / mass;
+ hit->dy += DOT_MASS_UNIT * d->mass * d->dy / mass;
}
}
}
}
void
-draw_engine_dots(SDL_Surface *s) {
+move_dots(void)
+{
int i;
- uint16_t c;
- uint16_t *pixels = (uint16_t *) s->pixels;
- int row_inc = s->pitch/sizeof(uint16_t);
- int heatindex;
- for(i = 0; i<MAXENGINEDOTS; i++) {
- if(!edot[i].active) continue;
+ for(i=0; i<MAXBANGDOTS; i++) move_dot(&bdot[i]);
+ for(i=0; i<MAXENGINEDOTS; i++) move_dot(&edot[i]);
+}
+
- 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;
+void
+draw_dot(struct dot *d)
+{
+ uint16_t *pixels, *pixel;
+ int row_inc;
+
+ if(d->active) {
+ pixels = (uint16_t *) surf_screen->pixels;
+ row_inc = surf_screen->pitch / sizeof(uint16_t);
+ pixel = pixels + (int)d->y * row_inc + (int)d->x;
+ *pixel = heatcolor[min(3*W-1, (int)(d->mass * d->heat))];
}
}
void
-draw_dots(SDL_Surface *s) {
- if(SDL_MUSTLOCK(s)) { SDL_LockSurface(s); }
- draw_dust(s);
- draw_engine_dots(s);
- draw_bang_dots(s);
- if(SDL_MUSTLOCK(s)) { SDL_UnlockSurface(s); }
+draw_dots(void) {
+ int i;
+
+ if(SDL_MUSTLOCK(surf_screen)) { SDL_LockSurface(surf_screen); }
+ draw_dust();
+ for(i=0; i<MAXBANGDOTS; i++) draw_dot(&bdot[i]);
+ for(i=0; i<MAXENGINEDOTS; i++) draw_dot(&edot[i]);
+ if(SDL_MUSTLOCK(surf_screen)) { SDL_UnlockSurface(surf_screen); }
}
SDL_Surface *
draw(void)
{
SDL_FillRect(surf_screen,NULL,0); // black background
- draw_dots(surf_screen); // background dots
+ draw_dots(); // background dots
draw_sprite(SPRITE(&ship));
draw_rocks();
// and fall through to
case HIGH_SCORE_DISPLAY:
// Display de list o high scores mon.
- display_scores(surf_screen, 150,50);
+ display_scores(150,50);
break;
case GAMEPLAY:
case DEAD_PAUSE:
// Count down the state timer, and change state when it gets to zero or less;
void
-update_state(float ticks)
+update_state(void)
{
- state_timeout -= ticks*3;
+ state_timeout -= t_frame*3;
if(state_timeout > 0) return;
switch(state) {
}
if(!paused) {
- update_state(t_frame);
+ update_state();
// SCROLLING
tmp = (ship.y+ship.h/2 + ship.dy*t_frame - YSCROLLTO)/25 + (ship.dy-screendy);
dist_ahead += (screendx - BARRIER_SPEED)*t_frame;
if(MAX_DIST_AHEAD >= 0) dist_ahead = min(dist_ahead, MAX_DIST_AHEAD);
- move_sprites(t_frame); new_rocks(t_frame);
- move_engine_dots(t_frame); new_engine_dots(t_frame);
- move_bang_dots(t_frame);
- move_dust(t_frame);
+ move_sprites();
+ move_dots();
+ move_dust();
+
+ new_rocks();
+ new_engine_dots();
collisions();