JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
fixed crashes, autopilot working
authorJason Woofenden <jason183@herkamire.com>
Tue, 8 May 2007 06:38:56 +0000 (02:38 -0400)
committerJason Woofenden <jason183@herkamire.com>
Tue, 8 May 2007 06:38:56 +0000 (02:38 -0400)
new engine dots are checked to be on the screen
ship bouncing always gets the ship back on the screen
ship is bounced onto screen before exploading (so bang dots always start on the screen)
ship now has (unreasonably high) maximum speed
Autopilot works (hits random keys) and has commandline options -a --autopilot

.gitignore
Makefile
args.c
args.h
autopilot.c [new file with mode: 0644]
autopilot.h [new file with mode: 0644]
float.h
main.c

index 3f49269..fbac7cf 100644 (file)
@@ -7,3 +7,5 @@ data/icon.png
 data/ship.png
 data/life.png
 data/font.png
+tags
+log
index 92401ad..840adfe 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -28,7 +28,7 @@ sdl-ldflags := $(shell sdl-config --libs)
 ldflags := $(sdl-ldflags) -lSDL_image -lSDL_mixer $(LDFLAGS)
 cflags := $(sdl-cflags) $(paths) $(CFLAGS)
 
-my_objects := args.o dust.o file.o mt.o rocks.o score.o sprite.o sound.o
+my_objects := args.o dust.o file.o mt.o rocks.o score.o sprite.o sound.o autopilot.o
 my_objects += main.o
 libs := font.o
 objects := $(libs) $(my_objects)
@@ -71,7 +71,7 @@ dust.o: globals.h dust.h float.h mt.h
 
 file.o: file.h common.h
 
-main.o: args.h common.h dust.h file.h float.h globals.h mt.h rocks.h score.h sprite.h sound.h
+main.o: args.h common.h dust.h file.h float.h globals.h mt.h rocks.h score.h sprite.h sound.h autopilot.h
 
 mt.o: mt.h
 
diff --git a/args.c b/args.c
index f194690..f747033 100644 (file)
--- a/args.c
+++ b/args.c
@@ -8,6 +8,8 @@
 int opt_fullscreen;
 int opt_sound;
 
+int opt_autopilot;
+
 static void
 show_help(void)
 {
@@ -35,6 +37,7 @@ short_opt(char c, char *arg)
                                  exit(0);
                case '?':
                case 'h': return 0;
+               case 'a': opt_autopilot = 1; break;
                default: 
                                  fprintf(stderr, "unknown option -%c\n\n", c);
                                  return 0;
@@ -49,9 +52,9 @@ parse_short_opts(const char *s, char *arg)
        return short_opt(*s, arg);
 }
 
-static char *long_opts[] = { "full-screen", "silent", "version", "help" };
+static char *long_opts[] = { "full-screen", "silent", "version", "help", "autopilot" };
 
-static char short_opts[] = { 'f', 's', 'V', 'h' };
+static char short_opts[] = { 'f', 's', 'V', 'h', 'a' };
 
 int
 parse_long_opt(const char *s, char *arg)
@@ -70,6 +73,7 @@ init_opts(void)
 {
        opt_fullscreen = 0;
        opt_sound = 1;
+       opt_autopilot = 0;
 }
 
 int
diff --git a/args.h b/args.h
index 4b1569e..4b2cd13 100644 (file)
--- a/args.h
+++ b/args.h
@@ -5,6 +5,8 @@
 extern int opt_fullscreen;
 extern int opt_sound;
 
+extern int opt_autopilot;
+
 int parse_opts(int argc, char *argv[]);
 
 #endif // VOR_ARGS_H
diff --git a/autopilot.c b/autopilot.c
new file mode 100644 (file)
index 0000000..789aff5
--- /dev/null
@@ -0,0 +1,117 @@
+//  Copyright (C) 2007 Jason Woofenden
+//
+//  This file is part of VoR.
+//
+//  VoR is free software; you can redistribute it and/or modify it
+//  under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2, or (at your option)
+//  any later version.
+//
+//  VoR is distributed in the hope that it will be useful, but
+//  WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with VoR; see the file COPYING.  If not, write to the
+//  Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+//  MA 02111-1307, USA.
+
+
+// This file has code to generate SDL keypress events
+
+#include <stdlib.h>
+#include <SDL.h>
+#include "mt.h"
+
+// SETTINGS
+//
+// auto pilot waits a random amount of time between zero and this many 1/20ths of a second
+#define AUTOPILOT_MAX_DELAY 20.0
+
+#define NUM_KEYS 5
+SDLKey keysyms[NUM_KEYS] = { SDLK_SPACE, SDLK_LEFT, SDLK_RIGHT, SDLK_UP, SDLK_DOWN};
+int states[NUM_KEYS] =     { 0,          0,         0,          0,       0,       };
+
+float next_time;
+float delay;
+
+void
+autopilot_set_timer() {
+       delay = 0;
+       next_time = frnd() * AUTOPILOT_MAX_DELAY;
+}
+
+void
+autopilot_init() {
+       autopilot_set_timer();
+}
+       
+void
+autopilot_fix_keystates(Uint8* table) {
+       int i;
+       for(i = 0; i < NUM_KEYS; ++i) {
+               table[keysyms[i]] = states[i];
+       }
+}
+
+int
+autopilot_num_down() {
+       int i, num;
+       for(num = 0, i = 0; i < NUM_KEYS; ++i) {
+               if(states[i]) {
+                       num++;
+               }
+       }
+
+       return num;
+}
+
+void
+autopilot_send_event() {
+       int down = autopilot_num_down();
+       int nth, i;
+       //SDL_Event event;
+
+       if(down && frnd() < 0.25 + (down / 4.0)) {
+               //event.type = SDL_KEYUP;
+               //event.key.state = 0;
+               nth = (urnd() % down) + 1;
+               for(i = 0; ; ++i) {
+                       if(states[i]) {
+                               --nth;
+                       }
+                       if(nth == 0) {
+                               //event.key.keysym.sym = keysyms[i];
+                               states[i] = 0;
+                               break;
+                       }
+               }
+       } else {
+               //event.type = SDL_KEYDOWN;
+               //event.key.state = 1;
+               nth = (urnd() % (NUM_KEYS - down)) + 1;
+               for(i = 0; ; ++i) {
+                       if(!states[i]) {
+                               --nth;
+                       }
+                       if(nth == 0) {
+                               //event.key.keysym.sym = keysyms[i];
+                               states[i] = 1;
+                               break;
+                       }
+               }
+       }
+
+       //fprintf(stderr, "push event: %i %i\n", event.key.keysym.sym, event.type);
+       //SDL_PushEvent(&event);
+}
+
+void
+autopilot(float ticks) {
+       delay += ticks;
+       if(delay > next_time) {
+               autopilot_set_timer();
+               autopilot_send_event();
+       }
+}
diff --git a/autopilot.h b/autopilot.h
new file mode 100644 (file)
index 0000000..7038ff1
--- /dev/null
@@ -0,0 +1,23 @@
+//  Copyright (C) 2007 Jason Woofenden
+//
+//  This file is part of VoR.
+//
+//  VoR is free software; you can redistribute it and/or modify it
+//  under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2, or (at your option)
+//  any later version.
+//
+//  VoR is distributed in the hope that it will be useful, but
+//  WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with VoR; see the file COPYING.  If not, write to the
+//  Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+//  MA 02111-1307, USA.
+
+
+void autopilot_init();
+int autopilot(float ticks);
+void autopilot_fix_keystates(Uint8* table);
diff --git a/float.h b/float.h
index 83e0a90..1f07d6c 100644 (file)
--- a/float.h
+++ b/float.h
@@ -12,6 +12,37 @@ fclip(float f, float max)
        return f < SMIDGE || f >= (max - SMIDGE);
 }
 
+static inline float
+fconstrain(float f, float max)
+{
+       max -= SMIDGE;
+
+       if(f > max) {
+               return max;
+       }
+       if(f < SMIDGE) {
+               return SMIDGE;
+       }
+
+       return f;
+}
+
+static inline float
+fconstrain2(float f, float min, float max)
+{
+       min += SMIDGE;
+       max -= SMIDGE;
+
+       if(f > max) {
+               return max;
+       }
+       if(f < min) {
+               return min;
+       }
+
+       return f;
+}
+
 // wrap f so it's within the range [SMIDGE..(max-SMIDGE)]
 // assumes f is not outside this range by more than (max - (2 * SMIDGE))
 static inline float
diff --git a/main.c b/main.c
index 276cf3a..91556ad 100644 (file)
--- a/main.c
+++ b/main.c
@@ -41,6 +41,7 @@
 #include "score.h"
 #include "sprite.h"
 #include "sound.h"
+#include "autopilot.h"
 
 // ************************************* VARS
 // SDL_Surface global variables
@@ -165,7 +166,6 @@ new_engine_dots(void) {
                                dx = r * cos(a);
                                dy = r * -sin(a);  // screen y is "backwards".
 
-                               dotptr->active = 1;
                                dotptr->decay = 3;
                                dotptr->heat = 6;
 
@@ -202,8 +202,14 @@ new_engine_dots(void) {
                                dotptr->x += (dotptr->dx - screendx) * time;
                                dotptr->y += (dotptr->dy - screendy) * time;
 
-                               if(dotptr - edot < MAXENGINEDOTS-1) dotptr++;
-                               else dotptr = edot;
+                               if(!fclip(dotptr->x, XSIZE) && !fclip(dotptr->y, YSIZE)) {
+                                       dotptr->active = 1;
+                                       if(dotptr - edot < MAXENGINEDOTS-1) {
+                                               dotptr++;
+                                       } else {
+                                               dotptr = edot;
+                                       }
+                               }
                        }
                }
        }
@@ -619,12 +625,16 @@ gameloop() {
        for(;;) {
                ms_frame = SDL_GetTicks() - ms_end;
                ms_end += ms_frame;
-               if(ms_frame > 100) {
-                       ms_frame = 100;
+               if(ms_frame > 50) {
+                       ms_frame = 50;
                }
                t_frame = gamespeed * ms_frame / 50;
                frames++;
 
+               if(opt_autopilot) {
+                       autopilot(t_frame);
+               }
+
                while(SDL_PollEvent(&e)) {
                        switch(e.type) {
                                case SDL_QUIT: return;
@@ -649,6 +659,7 @@ gameloop() {
                        }
                }
                keystate = SDL_GetKeyState(NULL);
+               autopilot_fix_keystates(keystate);
 
                if(state == GAMEPLAY) {
                        if(!paused) {
@@ -658,6 +669,10 @@ gameloop() {
                                if(keystate[SDLK_DOWN]  || keystate[SDLK_t]) { ship.dy += THRUSTER_STRENGTH*t_frame; ship.jets |= 1<<1;}
                                if(keystate[SDLK_RIGHT] || keystate[SDLK_n]) { ship.dx += THRUSTER_STRENGTH*t_frame; ship.jets |= 1<<2;}
                                if(keystate[SDLK_UP]    || keystate[SDLK_c]) { ship.dy -= THRUSTER_STRENGTH*t_frame; ship.jets |= 1<<3;}
+                               if(ship.jets) {
+                                       ship.dx = fconstrain2(ship.dx, -50, 50);
+                                       ship.dy = fconstrain2(ship.dy, -50, 50);
+                               }
                                if(keystate[SDLK_3])            { SDL_SaveBMP(surf_screen, "snapshot.bmp"); }
                        }
 
@@ -692,22 +707,26 @@ gameloop() {
                        move_dust();
 
                        new_rocks();
-                       new_engine_dots();
-
-                       collisions();
 
                        // 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)*BOUNCINESS;
+                               ship.x = fconstrain(ship.x, XSIZE - ship.w);
                        }
 
                        // 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)*BOUNCINESS;
+                               ship.y = fconstrain(ship.y, YSIZE - ship.h);
                        }
 
+                       new_engine_dots();
+
+                       collisions(); // must happen after ship bouncing because it puts pixels where the ship is (thus the ship must be on the screen)
+
+
                        draw();
 
                        // new game