From 0c92fe510799dde8568e4d787908704c35a0864c Mon Sep 17 00:00:00 2001 From: Jason Woofenden Date: Tue, 8 May 2007 02:38:56 -0400 Subject: [PATCH] fixed crashes, autopilot working 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 | 2 + Makefile | 4 +- args.c | 8 +++- args.h | 2 + autopilot.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ autopilot.h | 23 ++++++++++++ float.h | 31 ++++++++++++++++ main.c | 35 ++++++++++++++---- 8 files changed, 210 insertions(+), 12 deletions(-) create mode 100644 autopilot.c create mode 100644 autopilot.h diff --git a/.gitignore b/.gitignore index 3f49269..fbac7cf 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ data/icon.png data/ship.png data/life.png data/font.png +tags +log diff --git a/Makefile b/Makefile index 92401ad..840adfe 100644 --- 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 --- 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 --- 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 index 0000000..789aff5 --- /dev/null +++ b/autopilot.c @@ -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 +#include +#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 index 0000000..7038ff1 --- /dev/null +++ b/autopilot.h @@ -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 --- 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 --- 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 -- 1.7.10.4