# HG changeset patch # User Tero Marttila # Date 1232490102 -7200 # Node ID 1a03ff151abce90b05bede99902af11dcec7a6b8 # Parent e6cfc44266af2d49f9482bd9269450f6c3b83e7e add --terrain-seed and --terrain-size arguments, plus bugfixes diff -r e6cfc44266af -r 1a03ff151abc src/Application.cc --- 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 +#include #include #include @@ -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(); diff -r e6cfc44266af -r 1a03ff151abc src/Application.hh --- 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); diff -r e6cfc44266af -r 1a03ff151abc src/Engine.cc --- 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); diff -r e6cfc44266af -r 1a03ff151abc src/Engine.hh --- 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); /** diff -r e6cfc44266af -r 1a03ff151abc src/Graphics.cc --- 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), diff -r e6cfc44266af -r 1a03ff151abc src/Graphics.hh --- 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 diff -r e6cfc44266af -r 1a03ff151abc src/PhysicsWorld.hh --- 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 objects; - /** Size of simulation area */ - Vector dimensions; - /** Gravity vector */ Vector gravity; diff -r e6cfc44266af -r 1a03ff151abc src/Player.cc --- 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) { diff -r e6cfc44266af -r 1a03ff151abc src/SinglePlayer.hh --- 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) { } diff -r e6cfc44266af -r 1a03ff151abc src/Terrain.cc --- 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) { diff -r e6cfc44266af -r 1a03ff151abc src/Terrain.hh --- 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 - #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 + +/** * 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