* sound.h: moved #defines out to here, used them in main.c.
* dust.c: moved space dust functions out to here.
DATA_PREFIX := /usr/share/vor
PROGRAM_PREFIX := /usr/games/bin
+CFLAGS := -Wall
+LDFLAGS :=
+
debug := $(if $(DEBUG),-DDEBUG=1)
paths := -DDATA_PREFIX=\"$(DATA_PREFIX)\"
sdl-cflags := $(shell sdl-config --cflags)
sdl-ldflags := $(shell sdl-config --libs)
-ldflags := $(sdl-ldflags) -lSDL_image -lSDL_mixer
+ldflags := $(sdl-ldflags) -lSDL_image -lSDL_mixer $(LDFLAGS)
cflags := $(sdl-cflags) $(debug) $(paths) $(CFLAGS)
-my_objects := args.o file.o rocks.o score.o shape.o sound.o
+my_objects := args.o dust.o file.o mt.o rocks.o score.o shape.o sound.o
my_objects += $(if $(DEBUG),debug.o) main.o
libs := SFont.o
objects := $(libs) $(my_objects)
break;
case 'm': opt_music = 1; break;
case 's': opt_sound = 0; opt_music = 0; break;
- case ARGP_KEY_END:
- break;
- default:
- return ARGP_ERR_UNKNOWN;
+ default: return ARGP_ERR_UNKNOWN;
}
return 0;
}
#define MAXENGINEDOTS 5000
#define MAXBANGDOTS 50000
-#define MAXSPACEDOTS 2000
-#define MAXDUSTDEPTH 2
#define W 100
#define M 255
--- /dev/null
+#include <SDL.h>
+#include <math.h>
+
+#include "config.h"
+#include "globals.h"
+#include "dust.h"
+#include "mt.h"
+
+struct dust_mote {
+ float x,y,z;
+ Uint16 color;
+};
+
+struct dust_mote motes[N_DUST_MOTES];
+
+void
+init_dust(void)
+{
+ int i, b;
+ for(i=0; i<N_DUST_MOTES; i++) {
+ motes[i].x = frnd()*(XSIZE-5);
+ motes[i].y = frnd()*(YSIZE-5);
+ motes[i].z = MAX_DUST_DEPTH*sqrt(frnd());
+ b = (MAX_DUST_DEPTH - motes[i].z) * 255.0 / MAX_DUST_DEPTH;
+ motes[i].color = SDL_MapRGB(surf_screen->format, b, b, b);
+ }
+}
+
+void
+move_dust(void)
+{
+ int i;
+ for(i=0; i<N_DUST_MOTES; i++) {
+ motes[i].x -= xscroll / (1.3 + motes[i].z);
+ motes[i].y -= yscroll / (1.3 + motes[i].z);
+ if(motes[i].y >= XSIZE) motes[i].x -= XSIZE;
+ else if(motes[i].x < 0) motes[i].x += XSIZE;
+ if(motes[i].y > YSIZE) motes[i].y -= YSIZE;
+ else if(motes[i].y < 0) motes[i].y += YSIZE;
+ }
+}
+
+void
+draw_dust(SDL_Surface *s)
+{
+ int i;
+ uint16_t *pixels = s->pixels;
+ for(i=0; i<N_DUST_MOTES; i++) {
+ pixels[s->pitch/2*(int)motes[i].y + (int)motes[i].x] = motes[i].color;
+ }
+}
--- /dev/null
+#ifndef VOR_DUST_H
+#define VOR_DUST_H
+
+#include <stdint.h>
+
+/*
+ * Dust motes are harmless background items. They are created when the
+ * program is initialized, and are simply wrapped whenever they hit the
+ * edge of the screen.
+ */
+
+#define N_DUST_MOTES 2000
+#define MAX_DUST_DEPTH 2
+
+void init_dust(void);
+void move_dust(void);
+void draw_dust(SDL_Surface *);
+
+#endif // VOR_DUST_H
+gfx-deps := gfx.mk povimg.sh
-data/sprites/ship.png: ship.pov gfx.mk
+data/sprites/ship.png: ship.pov $(gfx-deps)
./povimg.sh +W32 +H32 $< > $@
-data/indicators/life.png: ship.pov gfx.mk
+data/indicators/life.png: ship.pov $(gfx-deps)
./povimg.sh +W17 +H17 $< > $@
-data/sprites/rock%.png: rocks.pov gfx.mk
+data/sprites/rock%.png: rocks.pov $(gfx-deps)
./povimg.sh +H52 +W52 +K$* $< > $@
// is a number starting at between 0 and 50 and counting backward.
float life; // When reduced to 0, set active = 0
};
-struct spacedot {
- // Space dots are harmless background items
- // All are active. When one falls off the edge, another is created at the start.
- float x,y,z;
- Uint16 color;
-};
// ************************************* VARS
// SDL_Surface global variables
// Structure global variables
extern struct enginedots edot[MAXENGINEDOTS], *dotptr;
extern struct bangdots bdot[MAXBANGDOTS], *bdotptr;
-extern struct spacedot sdot[MAXSPACEDOTS];
// Other global variables
extern char topline[1024];
#include "args.h"
#include "common.h"
#include "config.h"
+#include "dust.h"
#include "file.h"
#include "globals.h"
+#include "mt.h"
#include "rocks.h"
#include "score.h"
#include "shape.h"
// Structure global variables
struct enginedots edot[MAXENGINEDOTS], *dotptr = edot;
struct bangdots bdot[MAXBANGDOTS], *bdotptr = bdot;
-struct spacedot sdot[MAXSPACEDOTS];
// Other global variables
char topline[1024];
// ************************************* FUNCS
-float
-rnd() {
- return (float)random()/(float)RAND_MAX;
-}
-
void
init_engine_dots() {
int i;
}
void
-init_space_dots() {
- int i,b;
- for(i = 0; i<MAXSPACEDOTS; i++) {
- sdot[i].x = rnd()*(XSIZE-5);
- sdot[i].y = rnd()*(YSIZE-5);
- sdot[i].z = MAXDUSTDEPTH*sqrt(rnd());
- b = (MAXDUSTDEPTH - sdot[i].z) * 255.0 / MAXDUSTDEPTH;
- sdot[i].color = SDL_MapRGB(surf_screen->format, b, b, b);
- }
-}
-
-void
-make_bang_dots(int xbang, int ybang, int dx, int dy, SDL_Surface *s, int power) {
-
- // TODO - stop generating dots after a certain amount of time has passed, to cope with slower CPUs.
- // TODO - generate and display dots in a circular buffer
-
+new_bang_dots(int xbang, int ybang, int dx, int dy, SDL_Surface *s, int power)
+{
int x,y,endcount;
Uint16 *rawpixel,c;
double theta,r;
c = rawpixel[s->pitch/2*y + x];
if(c && c != s->format->colorkey) {
- theta = rnd()*M_PI*2;
+ theta = frnd()*M_PI*2;
- r = 1-(rnd()*rnd());
+ r = 1-(frnd()*frnd());
bdot[bd2].dx = (power/50.0)*45.0*cos(theta)*r + dx;
bdot[bd2].dy = (power/50.0)*45.0*sin(theta)*r + dy;
// Replace the last few bang dots with the pixels from the exploding object
bdot[bd2].c = (endcount>0)?c:0;
bdot[bd2].life = 100;
- bdot[bd2].decay = rnd()*3 + 1;
+ bdot[bd2].decay = frnd()*3 + 1;
bdot[bd2].active = 1;
bd2++;
void
-draw_space_dots(SDL_Surface *s) {
- int i;
- Uint16 *rawpixel;
- rawpixel = (Uint16 *) s->pixels;
-
- for(i = 0; i<MAXSPACEDOTS; i++) {
- if(sdot[i].y<0) {
- sdot[i].y = 0;
- }
- rawpixel[(int)(s->pitch/2*(int)sdot[i].y) + (int)(sdot[i].x)] = sdot[i].color;
- sdot[i].x -= xscroll / (1.3 + sdot[i].z);
- sdot[i].y -= yscroll / (1.3 + sdot[i].z);
- if(sdot[i].y >= XSIZE) sdot[i].x -= XSIZE;
- else if(sdot[i].x < 0) sdot[i].x = XSIZE-1;
- if(sdot[i].y > YSIZE) sdot[i].y -= YSIZE;
- else if(sdot[i].y < 0) sdot[i].y += YSIZE-1;
- }
-}
-
-void
draw_engine_dots(SDL_Surface *s) {
int i;
Uint16 *rawpixel;
for(i = 0; i<n; i++) {
if(dotptr->active == 0) {
- a = rnd()*M_PI + (dir-1)*M_PI_2;
- r = sin(rnd()*M_PI);
+ a = frnd()*M_PI + (dir-1)*M_PI_2;
+ r = sin(frnd()*M_PI);
dx = r * cos(a);
dy = r * -sin(a); // screen y is "backwards".
dotptr->active = 1;
- dotptr->x = shipx + s[dir]*hx + (rnd()-0.5)*3;
- dotptr->y = shipy + s[(dir+1)&3]*hy + (rnd()-0.5)*3;
+ dotptr->x = shipx + s[dir]*hx + (frnd()-0.5)*3;
+ dotptr->y = shipy + s[(dir+1)&3]*hy + (frnd()-0.5)*3;
if(dir&1) {
dotptr->dx = shipdx + 2*dx;
dotptr->dy = shipdy + 20*dy;
}
}
+ move_dust();
+
SDL_LockSurface(s);
- draw_space_dots(s);
+ draw_dust(s);
draw_engine_dots(s);
draw_bang_dots(s);
SDL_UnlockSurface(s);
atexit(SDL_Quit);
}
- play_tune(0);
+ play_tune(TUNE_TITLE_PAGE);
// Attempt to get the required video size
flag = SDL_DOUBLEBUF | SDL_HWSURFACE;
NULLERROR(surf_life = SDL_DisplayFormat(temp));
init_engine_dots();
- init_space_dots();
+ init_dust();
init_rocks();
break;
case HIGH_SCORE_ENTRY:
- play_tune(2);
+ play_tune(TUNE_HIGH_SCORE_ENTRY);
if(!process_score_input()) { // done inputting name
// Change state to briefly show high scores page
// Write the high score table to the file
write_high_score_table();
- // Play the title page tune
- play_tune(0);
+ play_tune(TUNE_TITLE_PAGE);
}
// FALL THROUGH TO
case HIGH_SCORE_DISPLAY:
case DEAD_PAUSE:
// Create a new ship and start all over again
state = GAMEPLAY;
- play_tune(1);
+ play_tune(TUNE_GAMEPLAY);
break;
case GAME_OVER:
if(new_high_score(score)) {
state_timeout = 500.0;
break;
case HIGH_SCORE_ENTRY:
- // state = TITLE_PAGE;
- // play_tune(1);
- // state_timeout = 100.0;
break;
case TITLE_PAGE:
state = HIGH_SCORE_DISPLAY;
if(draw() && state == GAMEPLAY) {
// Died
- play_sound(0); // Play the explosion sound
+ play_sound(SOUND_BANG); // Play the explosion sound
bangx = shipx; bangy = shipy; bangdx = shipdx; bangdy = shipdy;
- make_bang_dots(shipx,shipy,shipdx,shipdy,surf_ship,30);
+ new_bang_dots(shipx,shipy,shipdx,shipdy,surf_ship,30);
shipdx *= 0.5; shipdy *= 0.5;
if(shipdx < SCREENDXMIN) shipdx = SCREENDXMIN;
if(--nships <= 0) {
score = 0;
state = GAMEPLAY;
- play_tune(1);
+ play_tune(TUNE_GAMEPLAY);
gameover = 0;
shipx = XSIZE/2.2; shipy = YSIZE/2;
--- /dev/null
+/* mt.c - A C program for MT199937, with initialization improved 2002-02-10.
+
+ -----
+ 2003-07-01 - Stripped out stuff I didn't need, converted to
+ stdint.h types, changed source formatting a bit. --Josh
+ -----
+
+ A C-program for MT19937, with initialization improved 2002-02-10.
+ Coded by Takuji Nishimura and Makoto Matsumoto.
+ This is a faster version by taking Shawn Cokus's optimization,
+ Matthe Bellew's simplification, Isaku Wada's real version.
+
+ Before using, initialize the state by using init_genrand(seed)
+ or init_by_array(init_key, key_length).
+
+ Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. The names of its contributors may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+ Any feedback is very welcome.
+ http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
+ email: m-mat@math.sci.hiroshima-u.ac.jp
+*/
+
+#include "mt.h"
+
+/* Period parameters */
+#define N 624
+#define M 397
+#define MATRIX_A 0x9908b0dfUL /* constant vector a */
+#define UMASK 0x80000000UL /* most significant w-r bits */
+#define LMASK 0x7fffffffUL /* least significant r bits */
+#define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
+#define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL))
+
+static uint32_t state[N]; /* The array for the state vector */
+static int left = 1;
+static int initf = 0;
+static uint32_t *next;
+
+/* Initializes state[N] with a seed. */
+void
+init_mt(uint32_t s)
+{
+ int j;
+ state[0]= s & 0xffffffffUL;
+ for (j=1; j<N; j++) {
+ state[j] = (1812433253UL * (state[j-1] ^ (state[j-1] >> 30)) + j);
+ /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
+ /* In the previous versions, MSBs of the seed affect */
+ /* only MSBs of the array state[]. */
+ /* 2002/01/09 modified by Makoto Matsumoto */
+ state[j] &= 0xffffffffUL; /* for >32 bit machines */
+ }
+ left = 1; initf = 1;
+}
+
+static void
+next_state(void)
+{
+ uint32_t *p=state;
+ int j;
+
+ /* If mt_init() has not been called,
+ a default initial seed is used. */
+ if (initf==0) init_mt(5489UL);
+
+ left = N;
+ next = state;
+
+ for (j=N-M+1; --j; p++)
+ *p = p[M] ^ TWIST(p[0], p[1]);
+
+ for (j=M; --j; p++)
+ *p = p[M-N] ^ TWIST(p[0], p[1]);
+
+ *p = p[M-N] ^ TWIST(p[0], state[0]);
+}
+
+/* Generates a random number in [0,0xffffffff] */
+uint32_t
+urnd(void)
+{
+ uint32_t y;
+
+ if (--left == 0) next_state();
+ y = *next++;
+
+ /* Tempering */
+ y ^= (y >> 11);
+ y ^= (y << 7) & 0x9d2c5680UL;
+ y ^= (y << 15) & 0xefc60000UL;
+ y ^= (y >> 18);
+
+ return y;
+}
+
+float
+frnd(void)
+{
+ return urnd()/(float)0x100000000UL;
+}
+
+float
+crnd(void)
+{
+ return (urnd()-0x80000000)/(float)0x100000000UL;
+}
--- /dev/null
+#ifndef VOR_MT_H
+#define VOR_MT_H
+
+#include <stdint.h>
+
+void init_mt(uint32_t s);
+uint32_t irnd(void); // [0, 0xfffffff]
+float frnd(void); // [0, 1)
+float crnd(void); // [-0.5, 0.5)
+
+#endif // VOR_MT_H
#!/bin/sh
-povray -D +A -O- +FP $* 2>/dev/null | pnmcrop | pnmtopng -transparent =black
+povray -D +A -O- +FP $* 2>/dev/null | pnmcrop | pnmtopng -transparent =black 2>/dev/null
#include "config.h"
#include "file.h"
#include "globals.h"
+#include "mt.h"
#include "rocks.h"
#include "shape.h"
#define RDX 2.5 // range for rock dx values (+/-)
#define RDY 2.5 // range for rock dy values (+/-)
-float rnd(void);
-
-#define crnd() (2*(rnd()-0.5))
-
-
int
init_rocks(void)
{
float
weighted_rnd_range(float min, float max) {
- return sqrt(min * min + rnd() * (max * max - min * min));
+ return sqrt(min * min + frnd() * (max * max - min * min));
}
void
switch(i) {
case RIGHT:
rockptr->x = XSIZE;
- rockptr->y = rnd()*(YSIZE + rockptr->image->h);
+ 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 = rnd()*(YSIZE + rockptr->image->h);
+ 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 = rnd()*(XSIZE + rockptr->image->w);
+ 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 = rnd()*(XSIZE + rockptr->image->w);
+ rockptr->x = frnd()*(XSIZE + rockptr->image->w);
rockptr->y = -rockptr->image->h;
rockptr->dx = RDX*crnd();
#include "config.h"
#include "sound.h"
-#define TUNE_TITLE_PAGE 0
-#define TUNE_GAMEPLAY 1
-#define TUNE_HIGH_SCORE_ENTRY 2
-#define NUM_TUNES 3
-
-#define SOUND_BANG 0
-#define NUM_SOUNDS 4
static Mix_Music *music[NUM_TUNES];
static int music_volume[NUM_TUNES] = {128,128,128};
void play_sound(int i);
void play_tune(int i);
+#define TUNE_TITLE_PAGE 0
+#define TUNE_GAMEPLAY 1
+#define TUNE_HIGH_SCORE_ENTRY 2
+#define NUM_TUNES 3
+
+#define SOUND_BANG 0
+#define NUM_SOUNDS 4
+
#endif // VOR_SOUND_H