/* * main.c * * Where it all begins * * (c) 2008 Thomas White * * thrust3d - a silly game * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include "types.h" #include "model.h" #include "game.h" #include "render.h" #include "physics.h" #include "utils.h" typedef enum { RES_640, RES_800, RES_1280, RES_1330, RES_1440, RES_1600 } ScreenResolution; static void main_version() { printf("Thrust3D version "PACKAGE_VERSION", (c) 2008 Thomas White \n"); } int main(int argc, char *argv[]) { SDL_Event event; int finished; SDL_Surface *screen; int width, height; int c; Uint32 video_flags; ScreenResolution res; Uint32 t; res = RES_800; width = 800; height = 600; video_flags = SDL_OPENGL; while ((c = getopt(argc, argv, "hvr:f")) != -1) { switch ( c ) { case 'r' : { if ( strcasecmp(optarg, "640") == 0 ) res = RES_640; if ( strcasecmp(optarg, "800") == 0 ) res = RES_800; if ( strcasecmp(optarg, "1280") == 0 ) res = RES_1280; if ( strcasecmp(optarg, "1330") == 0 ) res = RES_1330; if ( strcasecmp(optarg, "1440") == 0 ) res = RES_1440; if ( strcasecmp(optarg, "1600") == 0 ) res = RES_1600; break; } case 'f' : { video_flags = video_flags | SDL_FULLSCREEN; break; } case 'v' : { main_version(); return 0; } case 'h' : { printf("Syntax: %s [-h] [-r ] [-f]\n\n", argv[0]); printf("Post-apocalyptic Jet Set Willy, set in a 3D nuclear power station.\n\n"); printf(" -h Display this help message and exit.\n"); printf(" -v Display version number and exit.\n"); printf(" -r Set display resolution. See below for possible values for .\n"); printf(" -f Use the full screen.\n\n"); printf("Allowable values for are as follows:\n\n"); printf(" Width Height\n"); printf(" 640 - 640 x 480\n"); printf(" 800 - 800 x 600 (this is the default)\n"); printf(" 1280 - 1280 x 1024\n"); printf(" 1330 - 1330 x 900 (widescreen)\n"); printf(" 1440 - 1440 x 900 (widescreen)\n"); printf(" 1600 - 1600 x 1050 (widescreen)\n"); printf("\n"); main_version(); return 0; } default : { return 1; } } } /* SDL initial setup */ if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) { fprintf(stderr, "Couldn't initialise SDL: %s\n", SDL_GetError()); return 1; } atexit(SDL_Quit); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); switch ( res ) { case RES_640 : { width = 640; height = 480; break; } case RES_800 : { width = 800; height = 600; break; } case RES_1280 : { width = 1280; height = 1024; break; } case RES_1330 : { width = 1330; height = 900; break; } case RES_1440 : { width = 1440; height = 900; break; } case RES_1600 : { width = 1680; height = 1050; break; } default : { assert(this_point_not_reached); break; } } screen = SDL_SetVideoMode(width, height, 16, video_flags); if ( screen == NULL ) { fprintf(stderr, "Couldn't set video mode: %s\n", SDL_GetError()); SDL_Quit(); return 1; } SDL_WM_SetCaption("Thrust3D", "Thrust3D"); SDL_ShowCursor(SDL_DISABLE); /* World setup */ Game *game; game = game_new(width, height); /* Main loop */ finished = 0; t = SDL_GetTicks(); while ( !finished ) { /* Timer advances only when game is not paused */ t = SDL_GetTicks(); if ( game->paused ) { game->tlast = t; } SDL_PollEvent(&event); switch ( event.type ) { case SDL_KEYDOWN : if ( !game->paused ) { if ( event.key.keysym.sym == SDLK_SPACE ) game->thrusting = 1; if ( event.key.keysym.sym == SDLK_LEFT ) game->turn_left = 1; if ( event.key.keysym.sym == SDLK_RIGHT ) game->turn_right = 1; if ( event.key.keysym.sym == SDLK_UP ) game->forward = 1; if ( event.key.keysym.sym == SDLK_DOWN ) game->reverse = 1; } if ( event.key.keysym.sym == SDLK_p ) game_pause(game); if ( event.key.keysym.sym == SDLK_q ) finished = 1; break; case SDL_KEYUP : /* Process key releases even when paused */ if ( event.key.keysym.sym == SDLK_SPACE ) game->thrusting = 0; if ( event.key.keysym.sym == SDLK_LEFT ) game->turn_left = 0; if ( event.key.keysym.sym == SDLK_RIGHT ) game->turn_right = 0; if ( event.key.keysym.sym == SDLK_UP ) game->forward = 0; if ( event.key.keysym.sym == SDLK_DOWN ) game->reverse = 0; if ( event.key.keysym.sym == SDLK_p ) game->pause_rel = 1; break; case SDL_VIDEOEXPOSE : /* Don't bother redrawing if not paused - not long to wait! */ if ( game->paused ) render_draw(game, t); break; case SDL_QUIT : finished = 1; break; } if ( !game->paused ) { physics_step(game, t); render_draw(game, t); } printf("%+7.4f %+7.4f %+7.4f %+5.1f deg %+7.5f %+7.5f %+7.5f %2i %2i %2i %3i fps\r", game->lander->x, game->lander->y, game->lander->z, rad2deg(game->lander->yaw), game->lander->vx, game->lander->vy, game->lander->vz, game->cur_room_x, game->cur_room_y, game->cur_room_z, game->fps); fflush(stdout); /* Calculate FPS every half a second */ game->frames++; if ( t - game->t_fps > 500 ) { game->fps = (500*game->frames) / (t - game->t_fps); game->t_fps = t; game->frames = 0; game->frame_delay_fiddled = 0; } /* Attempt to hold output FPS close to some target value */ if ( (!game->frame_delay_fiddled) && (game->fps < 30) ) { game->frame_delay -= game->frame_delay/20; game->frame_delay_fiddled = 1; } if ( (!game->frame_delay_fiddled) && (game->fps > 50) ) { game->frame_delay += game->frame_delay/20; game->frame_delay_fiddled = 1; } /* Sleep for a bit to avoid hogging the CPU. */ usleep(game->frame_delay); } render_shutdown(game->render); SDL_CloseAudio(); SDL_Quit(); printf("\n"); return 0; }