add --terrain-seed and --terrain-size arguments, plus bugfixes
authorTero Marttila <terom@fixme.fi>
Wed, 21 Jan 2009 00:21:42 +0200
changeset 409 1a03ff151abc
parent 408 e6cfc44266af
child 410 41fd46cffc52
child 421 b5b9d2aafdcb
add --terrain-seed and --terrain-size arguments, plus bugfixes
src/Application.cc
src/Application.hh
src/Engine.cc
src/Engine.hh
src/Graphics.cc
src/Graphics.hh
src/PhysicsWorld.hh
src/Player.cc
src/SinglePlayer.hh
src/Terrain.cc
src/Terrain.hh
--- a/src/Application.cc	Tue Jan 20 23:30:18 2009 +0200
+++ b/src/Application.cc	Wed Jan 21 00:21:42 2009 +0200
@@ -2,6 +2,7 @@
 #include "Application.hh"
 
 #include <stdexcept>
+#include <sstream>
 #include <cstdio>
 #include <cassert>
 
@@ -14,10 +15,22 @@
     ARG_FULLSCREEN  = 'F',
     ARG_RESOLUTION  = 'R',
 
-    ARG_LIST_MODES  = 0xff01,
-    ARG_VERSION     = 0xff02,
+    ARG_LIST_MODES      = 0xff01,
+    ARG_VERSION         = 0xff02,
+    ARG_TERRAIN_SEED    = 0xff03,
+    ARG_TERRAIN_SIZE    = 0xff04,
+
 };
 
+        
+Main::Main (void) :
+    graphics_enabled(false),
+    net_port(NETWORK_PORT_STR),
+    net_server(false),
+    net_connect("")
+{
+
+}
 
 /**
  * Set the arg_* members
@@ -48,17 +61,15 @@
     args.add_option(ARG_LIST_MODES, "list-modes", "",
             "output a list of available display modes and exit");
 
+    args.add_option(ARG_TERRAIN_SEED, "terrain-seed", "SEED",
+            "set seed for terrain random generator");
+
+    args.add_option(ARG_TERRAIN_SIZE, "terrain-size", "WIDTHxHEIGHT",
+            "set terrain size for random generator");
+
     args.add_option(ARG_VERSION, "version", "",
             "output application version and exit");
 
-    // set defaults
-    arg_graphics = false;
-    arg_port = NETWORK_PORT_STR;
-    arg_server = false;
-    arg_connect = "";
-    graphics.fullscreen = GRAPHICS_FULLSCREEN;
-    graphics.resolution = PixelCoordinate(GRAPHICS_RESOLUTION_WIDTH, GRAPHICS_RESOLUTION_HEIGHT);
-
     // extra state
     bool resolution_default = true;
     
@@ -77,19 +88,19 @@
                 return false;
 
             case ARG_PORT:
-                arg_port = args.get_argument();
+                net_port = args.get_argument();
                 break;
 
             case ARG_SERVER:
-                arg_server = true;
+                net_server = true;
                 break;
 
             case ARG_CLIENT:
-                arg_connect = args.get_argument();
+                net_connect = args.get_argument();
                 break;
 
             case ARG_GRAPHICS:
-                arg_graphics = true;
+                graphics_enabled = true;
                 break;
 
             case ARG_FULLSCREEN:
@@ -106,7 +117,7 @@
                 break;
 
             case ARG_RESOLUTION:
-                parse_arg_resolution(args.get_argument());
+                graphics.resolution = parse_arg_dimensions(args.get_argument(), "--resolution");
                 resolution_default = false;
                 break;
 
@@ -118,36 +129,55 @@
                 dump_version();
                 return false;
 
+            case ARG_TERRAIN_SEED:
+                terrain.random_seed = parse_arg_int(args.get_argument(), "--terrain-seed");
+                break;
+
+            case ARG_TERRAIN_SIZE:
+                terrain.dimensions = parse_arg_dimensions(args.get_argument(), "--terrain-size");
+                break;
+
             case CL_CommandLine::REST_ARG:
-                throw ArgumentError(args.get_argument());
+                throw ArgumentError("Trailing arguments: " + args.get_argument());
 
             default:
-                throw ArgumentError(std::string(1, (char) args.get_key()));
+                throw ArgumentError(std::string() + "Unknown argument key: " + (char) args.get_key());
 
         }
     }
 
     // check for invalid combinations of arugments
-    if (arg_server and !arg_connect.empty())
+    if (net_server and !net_connect.empty())
         throw ArgumentError("cannot be both server and client");
 
     // enable graphics by default unless server
-    if (!arg_server)
-        arg_graphics = true;
+    if (!net_server)
+        graphics_enabled = true;
     
     // continue
     return true;
 }
         
-void Main::parse_arg_resolution (const std::string &val) {
+int Main::parse_arg_int (const std::string &arg_val, const char *arg_name) {
+    int int_val;
+    
+    // read using istringstream
+    std::istringstream ss(arg_val);
+    
+    if (!(ss >> int_val))
+        throw ArgumentError(std::string() + "invalid integer arugment for " + arg_name + ": " + arg_val);
+
+    return int_val;
+}
+
+PixelCoordinate Main::parse_arg_dimensions (const std::string &arg_val, const char *arg_name) {
     unsigned int w, h;
     
     // sccanf as unsigned
-    if (sscanf(val.c_str(), "%ux%u", &w, &h) != 2)
-        throw ArgumentError("invalid format for --resolution");
+    if (sscanf(arg_val.c_str(), "%ux%u", &w, &h) != 2)
+        throw ArgumentError(std::string() + "invalid format for " + arg_name + ": " + arg_val);
     
-    // store as PixelCoordinate
-    graphics.resolution = PixelCoordinate(w, h);
+    return PixelCoordinate(w, h);
 }
         
 void Main::dump_display_modes (void) {
@@ -180,17 +210,21 @@
 
         // our engine
         Engine engine;
+
+        // setup game unless client
+        if (net_connect.empty())
+            engine.setupGame(terrain);
         
         // setup graphics
-        if (arg_graphics)
+        if (graphics_enabled)
             engine.setupGraphics(graphics);
 
         // setup either network server, client or singleplayer
-        if (arg_server) {
-            engine.setupNetworkServer(arg_port);
+        if (net_server) {
+            engine.setupNetworkServer(net_port);
 
-        } else if (!arg_connect.empty()) {
-            engine.setupNetworkClient(arg_connect, arg_port);
+        } else if (!net_connect.empty()) {
+            engine.setupNetworkClient(net_connect, net_port);
         
         } else {
             engine.setupSinglePlayer();
--- a/src/Application.hh	Tue Jan 20 23:30:18 2009 +0200
+++ b/src/Application.hh	Wed Jan 21 00:21:42 2009 +0200
@@ -23,28 +23,34 @@
         /**
          * --graphics
          */
-        bool arg_graphics;
+        bool graphics_enabled;
+
+        /**
+         * --fullscreen and --resolution
+         */
+        GraphicsConfig graphics;
+
+        /**
+         * --terrain-seed and --terrain-size
+         */
+        TerrainConfig terrain;
 
         /**
          * --port
          */
-        std::string arg_port;
+        std::string net_port;
 
         /**
          * --server
          */
-        bool arg_server;
+        bool net_server;
 
         /**
          * --connect
          */
-        std::string arg_connect;
-
-        /**
-         * --fullscreen and --resolution
-         */
-        GraphicsConfiguration graphics;
-
+        std::string net_connect;
+        
+        
         /**
          * Set the arg_* members
          *
@@ -53,9 +59,14 @@
         bool parse_args (int argc, char **argv);
 
         /**
-         * Parse and set --resolution/arg_resolution WIDTHxHEIGHT
+         * Parse signed integer argument
          */
-        void parse_arg_resolution (const std::string &val);
+        int parse_arg_int (const std::string &arg_val, const char *arg_name);
+
+        /**
+         * Parse unsigned WIDTHxHEIGHT argument
+         */
+        PixelCoordinate parse_arg_dimensions (const std::string &arg_val, const char *arg_name);
         
         /**
          * Print out a list of display modes
@@ -69,6 +80,11 @@
 
     public:
         /**
+         * Setup default values
+         */
+        Main (void);
+
+        /**
          * IT BEGAN IN AFRIKA
          */
         virtual int main (int argc, char **argv);
--- a/src/Engine.cc	Tue Jan 20 23:30:18 2009 +0200
+++ b/src/Engine.cc	Wed Jan 21 00:21:42 2009 +0200
@@ -30,12 +30,12 @@
     return *game_state;
 }
         
-GameState& Engine::setupGame (void) {
+void Engine::setupGame (const TerrainConfig &config) {
     // proxy off to setupGame(Terrain *)
-    return setupGame(new Terrain(TERRAIN_WIDTH, TERRAIN_HEIGHT, TERRAIN_RANDOM_SEED));
+    setupGame(new Terrain(config));
 }
 
-void Engine::setupGraphics (const GraphicsConfiguration &config) {
+void Engine::setupGraphics (const GraphicsConfig &config) {
     // store config
     graphics_config = &config;
     
@@ -55,9 +55,8 @@
 void Engine::setupNetworkServer (const std::string &listen_port) {
     NetworkEndpoint listen_addr(listen_port);
     
-    // setup default game
-    setupGame();
-
+    assert(terrain && game_state);
+    
     // create the server
     net_server = new NetworkServer(*game_state, listen_addr);
 }
@@ -71,8 +70,7 @@
 }
 
 void Engine::setupSinglePlayer (void) {
-    // setup default game
-    setupGame();
+    assert(terrain && game_state);
 
     // create player directly
  	LocalPlayer* lp = new SinglePlayer(*game_state);
--- a/src/Engine.hh	Tue Jan 20 23:30:18 2009 +0200
+++ b/src/Engine.hh	Wed Jan 21 00:21:42 2009 +0200
@@ -21,7 +21,7 @@
         GameState *game_state;
 
         /** Set if setupGraphics has been called */
-        const GraphicsConfiguration *graphics_config;
+        const GraphicsConfig *graphics_config;
         
         // Graphics/Input
         Graphics *graphics;
@@ -43,21 +43,34 @@
 
         /**
          * Setup game world using the given terrain, returning the new GameState
+         *
+         * XXX: fix to return void
          */
         GameState& setupGame (Terrain *terrain);
 
         /**
-         * Setup default game world using constants from Config.hh
+         * Setup game world using given terrain configuration
          */
-        GameState& setupGame (void);
+        void setupGame (const TerrainConfig &config);
 
-        // setup graphics
-        void setupGraphics (const GraphicsConfiguration &config);
+        /**
+         * Enable graphics
+         */
+        void setupGraphics (const GraphicsConfig &config);
         
-        // set up network server/client
-        // setting up both of these will lead to odd behaviour :)
+        /**
+         * Setup server, must call setupGame first
+         */
         void setupNetworkServer (const std::string &listen_port);
+
+        /**
+         * Setup client, do *not* call setupGame, configuration comes from the server
+         */
         void setupNetworkClient (const std::string &connect_host, const std::string &connect_port);
+
+        /**
+         * Setup singleplayer, must call setupGame first
+         */
 		void setupSinglePlayer (void);
         
         /**
--- a/src/Graphics.cc	Tue Jan 20 23:30:18 2009 +0200
+++ b/src/Graphics.cc	Wed Jan 21 00:21:42 2009 +0200
@@ -16,7 +16,7 @@
     );
 }
 
-Graphics::Graphics (Engine &engine, GameState &state, const GraphicsConfiguration &config) :
+Graphics::Graphics (Engine &engine, GameState &state, const GraphicsConfig &config) :
     CL_DisplayWindow(GRAPHICS_WINDOW_TITLE, config.resolution.x, config.resolution.y, config.fullscreen, true),
     engine(engine), 
     state(state), 
--- a/src/Graphics.hh	Tue Jan 20 23:30:18 2009 +0200
+++ b/src/Graphics.hh	Wed Jan 21 00:21:42 2009 +0200
@@ -3,23 +3,26 @@
 
 #include "GraphicsPointer.hh"
 #include "Types.hh"
+#include "Config.hh"
 
 /** 
  * Parameters used by Graphics
  */
-struct GraphicsConfiguration {
+struct GraphicsConfig {
     /** Initial resolution to use */
     PixelCoordinate resolution;
     
     /* Use fullscreen mode at startup */
     bool fullscreen;
+
+    /** Defaults */
+    GraphicsConfig (void) : resolution(GRAPHICS_RESOLUTION_WIDTH, GRAPHICS_RESOLUTION_HEIGHT), fullscreen(GRAPHICS_FULLSCREEN) { }
 }; 
 
 #include "GameState.hh"
 #include "Input.hh"
 #include "Timer.hh"
 #include "Engine.hh"
-#include "Config.hh"
 
 #include "GameMessageView.hh"
 
@@ -87,7 +90,7 @@
     /**
      *
      */
-    Graphics (Engine &engine, GameState &state, const GraphicsConfiguration &config);
+    Graphics (Engine &engine, GameState &state, const GraphicsConfig &config);
     
     /**
      * Returns a CL_Font that can be used for drawing text
--- a/src/PhysicsWorld.hh	Tue Jan 20 23:30:18 2009 +0200
+++ b/src/PhysicsWorld.hh	Wed Jan 21 00:21:42 2009 +0200
@@ -28,14 +28,14 @@
 public:   
     /** The world's terrain */
     Terrain &terrain;
+    
+    /** Size of simulation area */
+    Vector dimensions;
 
 protected:
     /** List of simulated objects*/
     std::list<PhysicsObject*> objects;
     
-    /** Size of simulation area */
-    Vector dimensions;
-
     /** Gravity vector */
     Vector gravity;
     
--- a/src/Player.cc	Tue Jan 20 23:30:18 2009 +0200
+++ b/src/Player.cc	Wed Jan 21 00:21:42 2009 +0200
@@ -98,9 +98,9 @@
 
 void Player::respawn (TimeMS dt) {
     (void) dt;
-
-    // XXX: ...
-    spawn(Vector(PLAYER_INITIAL_X, PLAYER_INITIAL_Y));
+    
+    // spawn in the middle of the world
+    spawn(world.dimensions / 2); 
 }
 
 void Player::handleDig (Vector pos, float radius) {
--- a/src/SinglePlayer.hh	Tue Jan 20 23:30:18 2009 +0200
+++ b/src/SinglePlayer.hh	Wed Jan 21 00:21:42 2009 +0200
@@ -9,7 +9,7 @@
 class SinglePlayer : public LocalPlayer {
     public:
         SinglePlayer (GameState &state) :
-            Player(state, Vector(PLAYER_INITIAL_X, PLAYER_INITIAL_Y), true)
+            Player(state, Vector(state.world.dimensions / 2), true)
         { 
         
         }
--- a/src/Terrain.cc	Tue Jan 20 23:30:18 2009 +0200
+++ b/src/Terrain.cc	Wed Jan 21 00:21:42 2009 +0200
@@ -18,17 +18,22 @@
     Vector(-1,-1)
 };
 
-Terrain::Terrain (void) :
-    terrain_buf(NULL), width(0), height(0)
+Terrain::Terrain (const TerrainConfig &config) :
+    terrain_buf(NULL),
+    width(config.dimensions.x), height(config.dimensions.y)
 {
-}
+    // allocate terrain_buf
+    terrain_buf = new TerrainPixel[width * height];
 
-Terrain::Terrain (PixelDimension width, PixelDimension height, int seed) :
-    terrain_buf(NULL),
-    width(width), height(height)
-{
-    // allocate+generate random terrain
-    generateTerrain(seed);
+    // fill with dirt
+    memset(terrain_buf, TERRAIN_DIRT, width * height);
+
+    // geneerate random map?
+    if (config.random_seed)
+        generateTerrain(config.random_seed);
+
+    // update pixel buffer
+    generatePixelBuffer();
 }
 
 Terrain::Terrain (PixelDimension width, PixelDimension height, TerrainPixel *terrain_buf) :
@@ -45,18 +50,9 @@
 }
 
 void Terrain::generateTerrain (int seed) {
-    // shouldn't be generated yet
-    assert(!terrain_buf);
-
     // set random number generator seed.
     srand(seed); 
 
-    // allocate terrain buffer
-    terrain_buf = new TerrainPixel[width * height];
-
-    // fill with dirt
-    memset(terrain_buf, TERRAIN_DIRT, width * height);
-
     // some constants to control random generation
     const int min_range = 25;
     const int max_range = 80;
@@ -102,9 +98,6 @@
             }
         } 
     }
-    
-    // update pixel buffer
-    generatePixelBuffer();
 }
 
 void Terrain::generatePixelBuffer (void) {
--- a/src/Terrain.hh	Tue Jan 20 23:30:18 2009 +0200
+++ b/src/Terrain.hh	Wed Jan 21 00:21:42 2009 +0200
@@ -1,8 +1,6 @@
 #ifndef TERRAIN_HH
 #define TERRAIN_HH
 
-#include <vector>
-
 #include "Vector.hh"
 #include "GraphicsPointer.hh"
 #include "Types.hh"
@@ -28,6 +26,22 @@
 typedef uint8_t TerrainPixel;
 
 /**
+ * Terrain configuration
+ */
+struct TerrainConfig {
+    /** Size of the terrain field*/
+    PixelCoordinate dimensions;
+
+    /** Set to nonzero to generate random map */
+    int random_seed;
+    
+    /** Defaults */
+    TerrainConfig (void) : dimensions(TERRAIN_WIDTH, TERRAIN_HEIGHT), random_seed(TERRAIN_RANDOM_SEED) { }
+};
+
+#include <vector>
+
+/**
  * Terrain class. Represents game terrain and contains member
  * functions to manipulate terrain and get info about it.
  * 
@@ -53,18 +67,11 @@
 
 public:    
     /**
-     * Default constructor. The width/height are set to zero and the terrain is invalid until it gets updated
+     * Construct a new terrain based on the given configuration
+     *
+     * @param config a TerrainConfig describing how to build the terrain
      */
-    Terrain (void);
-
-    /**
-     * Construct a randomly generated terrain
-     *
-     * @param width terrain width
-     * @param height terrain height
-     * @param seed random number generator seed used to generate the random terrain.
-     */
-    Terrain (PixelDimension width, PixelDimension height, int seed);
+    explicit Terrain (const TerrainConfig &config);
 
     /**
      * Construct the terrain using the provided terrain data. The given \a terrain_buf must be a linear array in the