From 1c63cbf204b1d2c667ce9f821ccb197d0ffb0ac3 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Wed, 11 May 2011 14:48:17 +0000 Subject: Review of the main loop timer, converted timers from float to unsigned long, corrected a number of timing bugs, improved client framerate stability. --- src/client/client.cc | 45 ++++++++++++----------- src/client/client.h | 2 +- src/client/infowidget.cc | 17 +++++---- src/client/infowidget.h | 4 +-- src/core/Makefile.am | 2 -- src/core/application.cc | 7 ++-- src/core/application.h | 21 ++++++----- src/core/entity.cc | 10 +++--- src/core/entity.h | 11 +++--- src/core/gameinterface.h | 17 +++++---- src/core/gameserver.cc | 83 +++++++++++++++++++++++++++++++------------ src/core/gameserver.h | 15 ++++---- src/core/netserver.cc | 14 ++++++-- src/core/netserver.h | 3 ++ src/core/physics.cc | 14 ++------ src/core/physics.h | 5 +-- src/core/timer.cc | 50 -------------------------- src/core/timer.h | 50 -------------------------- src/dedicated/console.cc | 1 - src/dedicated/dedicated.cc | 6 +--- src/game/base/jumppoint.cc | 14 ++++---- src/game/base/jumppoint.h | 4 +-- src/game/base/ship.cc | 4 +-- src/game/base/ship.h | 4 +-- src/game/example/spectator.cc | 15 +++++--- src/game/example/spectator.h | 2 +- src/game/intro/convoy.cc | 6 ++-- src/game/intro/convoy.h | 4 +-- src/model/mapfile.cc | 5 +-- src/sys/Makefile.am | 4 +-- src/sys/timer.cc | 46 ++++++++++++++++++++++++ src/sys/timer.h | 50 ++++++++++++++++++++++++++ 32 files changed, 289 insertions(+), 246 deletions(-) delete mode 100644 src/core/timer.cc delete mode 100644 src/core/timer.h create mode 100644 src/sys/timer.cc create mode 100644 src/sys/timer.h diff --git a/src/client/client.cc b/src/client/client.cc index d761e6e..b514e57 100644 --- a/src/client/client.cc +++ b/src/client/client.cc @@ -179,14 +179,12 @@ void Client::run() srand(seed); // default framerate 125fps, 8 milliseconds - Uint32 client_frame_lenght = 8; - - Uint32 client_current_timestamp = 0; - Uint32 client_previous_timestamp = 0; + unsigned long client_frame_lenght = 8; + unsigned long client_current_timestamp = 0; while (true) { // current time in microseconds - client_current_timestamp = SDL_GetTicks(); + client_current_timestamp = timestamp(); // calculate the desired frame length if (cl_framerate->value() < 0) { @@ -196,32 +194,33 @@ void Client::run() } if (cl_framerate->value()) { - client_frame_lenght = (Uint32) floorf(1000.0f / cl_framerate->value()); + client_frame_lenght = (unsigned long) floorf(1000.0f / cl_framerate->value()); + if (client_frame_lenght < 1) + client_frame_lenght = 1; } else { - client_frame_lenght = 0; + client_frame_lenght = 1; } - // only advance per microsecond frame - const Uint32 d = client_current_timestamp - client_previous_timestamp; - if ((d > 0)) { - if (d >= client_frame_lenght) { - frame(client_current_timestamp); - client_previous_timestamp = client_current_timestamp; - } else { - SDL_Delay(client_frame_lenght - d); - } - } else { - SDL_Delay(1); + frame(); + + // sleep for the remainder of the frame + const unsigned long elapsed = timestamp() - client_current_timestamp; + if (elapsed < client_frame_lenght - 1) { + sys::sleep (client_frame_lenght - elapsed -1); + } + + while (timestamp() < client_current_timestamp + client_frame_lenght) { + // busy waiting for the last microsecond } } } -void Client::frame(unsigned long timestamp) +void Client::frame() { input::frame(); - core::Application::frame(timestamp); + core::Application::frame(); if (!connected()) { const std::string module_label(core::Loader::label()); @@ -264,9 +263,9 @@ void Client::frame(unsigned long timestamp) } } - video::frame((float)(timestamp - previous_timestamp) / 1000.0f); - - previous_timestamp = timestamp; + const float now = timestamp(); + video::frame((float)(now - previous_timestamp) / 1000.0f); + previous_timestamp = now; } void Client::shutdown() diff --git a/src/client/client.h b/src/client/client.h index a5ce297..85562a1 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -75,7 +75,7 @@ public: protected: /// run a client frame - virtual void frame(unsigned long timestamp); + virtual void frame(); private: diff --git a/src/client/infowidget.cc b/src/client/infowidget.cc index 52af5ef..752c09b 100644 --- a/src/client/infowidget.cc +++ b/src/client/infowidget.cc @@ -104,16 +104,19 @@ StatsInfoWidget::StatsInfoWidget(ui::Widget *parent) : ui::Widget(parent) void StatsInfoWidget::draw() { // average fps - fps_counter_time[fps_counter_index] = core::application()->time(); + unsigned long fps = 0.0f; + const unsigned long now = core::application()->timestamp(); + fps_counter_time[fps_counter_index] = now; fps_counter_index = (fps_counter_index + 1) % fps_counter_size; - float min_time = core::application()->time(); + + unsigned long min_time = now; for (size_t i = 0; i < fps_counter_size; i++) if (fps_counter_time[i] < min_time) min_time = fps_counter_time[i]; - float fps = 0.0f; - float t = (core::application()->time() - min_time); + + const unsigned long t = now - min_time; if (t > 0) { - fps = roundf(((float) fps_counter_size ) / t); + fps = (fps_counter_size - 1) * 1000 / t; } std::ostringstream textstream; @@ -133,13 +136,13 @@ void StatsInfoWidget::draw() if (core::Stats::network_bytes_sent + core::Stats::network_bytes_received) { net_counter_traffic[net_counter_index] = core::Stats::network_bytes_sent + core::Stats::network_bytes_received; - net_counter_time[net_counter_index] = core::application()->time(); + net_counter_time[net_counter_index] = core::application()->timestamp(); size_t index_max = net_counter_index; net_counter_index = (net_counter_index + 1) % net_counter_size; size_t index_min = net_counter_index; - float d = net_counter_time[index_max] - net_counter_time[index_min]; + float d = float (net_counter_time[index_max] - net_counter_time[index_min]) / 1000.0f; if (d > 0) { float traffic = net_counter_traffic[index_max] - net_counter_traffic[index_min]; textstream << "^Nnet ^B" << std::setw(6) << roundf((float) traffic / d) << "\n"; diff --git a/src/client/infowidget.h b/src/client/infowidget.h index e773ef4..d2936e4 100644 --- a/src/client/infowidget.h +++ b/src/client/infowidget.h @@ -40,10 +40,10 @@ protected: virtual void draw(); private: - float fps_counter_time[fps_counter_size]; + unsigned long fps_counter_time[fps_counter_size]; size_t fps_counter_index; - float net_counter_time[net_counter_size]; + unsigned long net_counter_time[net_counter_size]; size_t net_counter_traffic[net_counter_size]; size_t net_counter_index; }; diff --git a/src/core/Makefile.am b/src/core/Makefile.am index e6b98e5..c1f4632 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -33,7 +33,6 @@ noinst_HEADERS = \ range.h \ signals.h \ stats.h \ - timer.h \ zone.h libcore_la_SOURCES = \ @@ -63,7 +62,6 @@ libcore_la_SOURCES = \ player.cc \ signals.cc \ stats.cc \ - timer.cc \ zone.cc libcore_la_DEPENDENCIES = \ diff --git a/src/core/application.cc b/src/core/application.cc index ec7e89c..38c39a1 100644 --- a/src/core/application.cc +++ b/src/core/application.cc @@ -72,7 +72,6 @@ Application::Application() } application_instance = this; - application_timestamp = 0; application_game = 0; #ifndef _WIN32 @@ -321,10 +320,8 @@ void Application::disconnect() } } -void Application::frame(unsigned long timestamp) +void Application::frame() { - application_timestamp = timestamp; - // execute commands in the buffer CommandBuffer::exec(); @@ -332,7 +329,7 @@ void Application::frame(unsigned long timestamp) return; // run a game interface frame - application_game->frame(timestamp); + application_game->frame(application_timer.timestamp()); if (!application_game->running()) disconnect(); diff --git a/src/core/application.h b/src/core/application.h index 37b70c2..cdaef67 100644 --- a/src/core/application.h +++ b/src/core/application.h @@ -8,6 +8,7 @@ #define __INCLUDED_CORE_APPLICATION_H__ #include "sys/sys.h" +#include "sys/timer.h" #include "core/commandbuffer.h" #include "core/cvar.h" @@ -30,14 +31,16 @@ public: /*----- inspectors ----------------------------------------------- */ - /// the current application time, in microseconds + /// the current application time, in milliseconds inline unsigned long timestamp() const { - return application_timestamp; + return application_timer.timestamp(); } - - /// the current application time, in seconds - float time() const { - return ((float)(timestamp()) / 1000.0f); + + /** + * @brief return the current application time, in seconds. + * */ + inline float time() const { + return (float) application_timer.timestamp() / 1000.0f; } /// true if the core is connected to a running game interface @@ -99,7 +102,7 @@ public: protected: /// run a core frame - virtual void frame(unsigned long timestamp); + virtual void frame(); /// load cvar config void load_config(); @@ -114,8 +117,8 @@ protected: void load_commandline(int count, char **argments); private: - /// time the core has been running - unsigned long application_timestamp; + /// main loop timer + sys::Timer application_timer; GameInterface *application_game; diff --git a/src/core/entity.cc b/src/core/entity.cc index 915dafe..6ce94a7 100644 --- a/src/core/entity.cc +++ b/src/core/entity.cc @@ -488,7 +488,7 @@ void Entity::remove_menu(std::string const &label) } -void Entity::frame(float seconds) +void Entity::frame(const unsigned long elapsed) { if (entity_collision_child_shapes.size() > 0) { btCompoundShape *compoundshape = static_cast (entity_collision_shape); @@ -782,9 +782,9 @@ void EntityDynamic::reset() set_dirty(); } -void EntityDynamic::frame(float seconds) +void EntityDynamic::frame(const unsigned long elapsed) { - Entity::frame(seconds); + Entity::frame(elapsed); if (entity_state == Docked) { return; @@ -1251,9 +1251,9 @@ void EntityControlable::action(btScalar seconds) } // osirion game frame (runs at osirion server framerate) -void EntityControlable::frame(float seconds) +void EntityControlable::frame(const unsigned long elapsed) { - EntityDynamic::frame(seconds); + EntityDynamic::frame(elapsed); // update zone keepalive bounding box if (owner() && (owner()->control() == this) && zone()) { diff --git a/src/core/entity.h b/src/core/entity.h index 230ce1b..164f746 100644 --- a/src/core/entity.h +++ b/src/core/entity.h @@ -263,8 +263,9 @@ public: /** * @brief runs one game frame for the entity * The default implementation does nothing + * @param elapsed elepased time since previous frame, in milliseconds */ - virtual void frame(float seconds); + virtual void frame(const unsigned long elapsed); /** * @brief runs one upkeep frame for the entity @@ -588,12 +589,13 @@ public: /// set event state virtual void set_state(int state); - /// runs one game frame for the entity /** + * @brief runs one game frame for the entity * The default implementation will update the position() of the entity, * determined by its speed() and axis() + * @param elapsed elepased time since previous frame, in milliseconds */ - virtual void frame(float seconds); + virtual void frame(const unsigned long elapsed); /** * @brief reset the physics state @@ -743,8 +745,9 @@ public: * @brief runs one game frame for the entity * The default implementation will set direction() and thrust() to the desired targets * and calls its parent frame() funcion. + * @param elapsed elepased time since previous frame, in milliseconds */ - virtual void frame(float seconds); + virtual void frame(const unsigned long elapsed); /// current thrust float entity_thrust; diff --git a/src/core/gameinterface.h b/src/core/gameinterface.h index 369b828..d99903f 100644 --- a/src/core/gameinterface.h +++ b/src/core/gameinterface.h @@ -67,11 +67,13 @@ public: return game_interactive; } - /// return the current game time, in seconds + /** + * @brief return the current game time, in seconds. + * */ inline float time() const { - return ((float)(game_timestamp) / 1000.0f); + return (float) game_timestamp / 1000.0f; } - + /** * @brief return the current game time, in milliseconds. * 1000 milliseconds equals one second. @@ -99,7 +101,7 @@ public: /// run one game time frame /// @param timestamp current application time - virtual void frame(unsigned long timestamp) = 0; + virtual void frame(const unsigned long timestamp) = 0; protected: /// the local player @@ -108,16 +110,17 @@ protected: /// all the players Players game_players; - model::VertexArray *game_vertexarray; - /// timestamp of the time the playerlist was last changed unsigned long game_playerlist_timestamp; - void set_timestamp(unsigned long timestamp); + /// set the current game time + void set_timestamp(const unsigned long timestamp); void set_running(const bool running); void set_interactive(const bool interactive); + + model::VertexArray *game_vertexarray; private: bool game_running; diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc index 85a956d..58367e5 100644 --- a/src/core/gameserver.cc +++ b/src/core/gameserver.cc @@ -39,17 +39,42 @@ void func_who(std::string const &args) void func_time(std::string const &args) { - using namespace std; + using namespace std; - // FIXME unify with dedicated server clock - int minutes = (int) floorf(server()->time() / 60.0f); - int seconds = (int) floorf(server()->time() - (float) minutes * 60.0f); - - int syshours, sysminutes, sysseconds; - sys::get_localtime(syshours, sysminutes, sysseconds); - - con_print << "Uptime " << minutes << ":" << setfill('0') << setw(2) << seconds << - " Local time " << setfill(' ') << setw(2) << syshours << ":" << setfill('0') << setw(2) << sysminutes << ":" << setw(2) << sysseconds << setfill(' ') << std::endl; + // system time + int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0, milliseconds = 0; + sys::get_localtime(year, month, day, hour, min, sec, milliseconds); + + con_print << "Local time: " + << std::setw(4) << std::setfill('0') << year << "-" + << std::setw(2) << std::setfill('0') << month << "-" + << std::setw(2) << std::setfill('0') << day << " " + << std::setw(2) << hour << ":" + << std::setw(2) << min << ":" + << std::setw(2) << sec << " " + << std::setw(2) << " "; + + // uptime + float uptime = core::game()->time(); + + const int uptime_days = (int) floorf(uptime / (24.0f * 3600.0f)); + uptime -= uptime_days * 24.0f * 3600.0f; + + const int uptime_hours = (int) floorf(uptime / 3600.0f); + uptime -= uptime_hours * 3600.0f; + + const int uptime_minutes = (int) floorf(uptime / 60.0f); + uptime -= uptime_minutes * 60.0f; + + const int uptime_seconds = (int) floorf(uptime); + + con_print << " Uptime: "; + if (uptime_days > 0) { + con_print << uptime_days << " " << aux::plural("day", uptime_days); + } + con_print << std::setfill('0') << std::setw(2) << uptime_hours << ":" + << std::setfill('0') << std::setw(2) << uptime_minutes << ":" + << std::setfill('0') << std::setw(2) << uptime_seconds << std::endl; } void func_mute(std::string const &args) @@ -126,7 +151,6 @@ GameServer::GameServer() : GameInterface() server_network = 0; server_previoustime = 0; server_maxplayerid = 1; - server_startup = application()->timestamp(); // create the default infotype for entities Entity::set_infotype(new InfoType("entity")); @@ -196,7 +220,10 @@ GameServer::GameServer() : GameInterface() if (!Cvar::sv_dedicated->value()) { player_connect(localplayer()); } - + + set_timestamp(server_timer.timestamp()); + server_previoustime = timestamp(); + set_running(true); } @@ -471,7 +498,7 @@ void GameServer::player_connect(Player *player) // manage player list game_players.push_back(player); - set_playerlist_timestamp(timestamp()); + set_playerlist_timestamp(server_timer.timestamp()); } void GameServer::player_disconnect(Player *player) @@ -489,16 +516,16 @@ void GameServer::player_disconnect(Player *player) // manage player list std::list:: iterator it = game_players.begin(); - while (((*it)->id() != player->id()) && (it != game_players.end())) { + while ((it != game_players.end()) && ((*it)->id() != player->id())) { it++; } if (it != game_players.end()) { game_players.erase(it); } - set_playerlist_timestamp(timestamp()); + set_playerlist_timestamp(server_timer.timestamp()); } -void GameServer::frame(unsigned long timestamp) +void GameServer::frame(const unsigned long timestamp) { if (error()) return; @@ -519,24 +546,36 @@ void GameServer::frame(unsigned long timestamp) /*if (!Cvar::sv_dedicated->value()) { update_clientstate(); }*/ - - Physics::frame(timestamp); if ((Cvar::sv_dedicated->value() || Cvar::sv_private->value())) { if (core::Cvar::sv_framerate->value()) { - float fps = ::floorf(1000.0f / core::Cvar::sv_framerate->value()); - if (server_startup + this->timestamp() + (unsigned long) fps > timestamp) { + + const unsigned long server_framelength = (unsigned long) ::floorf(1000.0f / core::Cvar::sv_framerate->value()); + + if (server_timer.timestamp() < server_previoustime + server_framelength) { return; } } } server_previoustime = this->timestamp(); - set_timestamp(timestamp - server_startup); + set_timestamp(server_timer.timestamp()); + + if (server_network) { + server_network->transmit(); + + if (server_network->error()) { + abort(); + return; + } + } - const float elapsed = (float)(this->timestamp() - server_previoustime) / 1000.0f; + const unsigned long elapsed = (this->timestamp() - server_previoustime); const unsigned long keepalive_timeout = (Cvar::sv_keepalive ? 1000 * (unsigned long) Cvar::sv_keepalive->value() : (unsigned long) 0 ); + // run a physics frame + Physics::frame(elapsed); + // reset zone keepalive state for (Zone::Registry::iterator zit = Zone::registry().begin(); zit != Zone::registry().end(); zit++) { Zone *zone= (*zit).second; diff --git a/src/core/gameserver.h b/src/core/gameserver.h index ab2bf92..2e1aa2a 100644 --- a/src/core/gameserver.h +++ b/src/core/gameserver.h @@ -7,6 +7,7 @@ #ifndef __INCLUDED_CORE_GAMESERVER_H__ #define __INCLUDED_CORE_GAMESERVER_H__ +#include "sys/timer.h" #include "core/gameinterface.h" #include "core/message.h" #include "core/module.h" @@ -41,7 +42,12 @@ public: void player_disconnect(Player *player); /// run a game server time frame - void frame(unsigned long timestamp); + virtual void frame(const unsigned long timestamp); + + /// server timer + inline const sys::Timer & timer() { + return server_timer; + } /// a player sends a chat message to the global chat channel void shout(Player *player, std::string const &args); @@ -70,11 +76,6 @@ public: /// a player sends a command to the game server void exec(Player *player, std::string const &cmdline); - /// time the server was started - inline const unsigned long startup() const { - return server_startup; - } - /// request info record with id virtual Info *request_info(const unsigned int id); @@ -99,7 +100,7 @@ private: unsigned int server_maxplayerid; unsigned long server_previoustime; - unsigned long server_startup; + sys::Timer server_timer; }; inline GameServer *server() diff --git a/src/core/netserver.cc b/src/core/netserver.cc index 0bd6350..d9a5bed 100644 --- a/src/core/netserver.cc +++ b/src/core/netserver.cc @@ -359,7 +359,7 @@ void NetServer::client_frame(NetClient *client, unsigned long timestamp) } else { // send a server frame marker - send_frame_marker(client, timestamp); + send_frame_marker(client, server()->timer().timestamp()); // send updates for entities in the zone for (Entity::Registry::iterator it = Entity::registry().begin(); it != Entity::registry().end(); it++) { @@ -411,6 +411,16 @@ void NetServer::client_frame(NetClient *client, unsigned long timestamp) } } +// transmit pending packets to all clients +void NetServer::transmit() +{ + // send updates to each client + for (Clients::iterator it = clients.begin(); it != clients.end(); it++) { + NetClient *client = *it; + client->transmit(); + } +} + // run a network server frame, send updates to clients void NetServer::frame(unsigned long timestamp) { @@ -730,7 +740,7 @@ void NetServer::parse_incoming_message(NetClient *client, const std::string & me } else if (command.compare("ping") == 0) { unsigned long timestamp; if (msgstream >> timestamp) { - client->player()->set_ping(application()->timestamp() - server()->startup() - timestamp); + client->player()->set_ping(server()->timer().timestamp() - timestamp); } return; } diff --git a/src/core/netserver.h b/src/core/netserver.h index 6eeb49b..d8635e4 100644 --- a/src/core/netserver.h +++ b/src/core/netserver.h @@ -57,6 +57,9 @@ public: /// run a network server frame void frame(unsigned long timestamp); + + /// transmit pending packets to all clients + void transmit(); /// receive data from clients void receive(); diff --git a/src/core/physics.cc b/src/core/physics.cc index 90fb184..9ffe13c 100644 --- a/src/core/physics.cc +++ b/src/core/physics.cc @@ -15,7 +15,6 @@ namespace core { btDefaultCollisionConfiguration *Physics::physics_configuration = 0; btCollisionDispatcher *Physics::physics_dispatcher = 0; btSequentialImpulseConstraintSolver *Physics::physics_solver = 0; -unsigned long Physics::physics_timestamp = 0; void Physics::init() { @@ -27,8 +26,6 @@ void Physics::init() physics_dispatcher = new btCollisionDispatcher(physics_configuration); btGImpactCollisionAlgorithm::registerAlgorithm(physics_dispatcher); physics_solver = new btSequentialImpulseConstraintSolver; - - physics_timestamp = 0; } void Physics::done() @@ -46,18 +43,13 @@ void Physics::done() physics_solver = 0; } -void Physics::frame(const unsigned long timestamp) +void Physics::frame(const unsigned long elapsed) { - if (!timestamp) - return; - - const float seconds = (float) (timestamp - physics_timestamp) / 1000.0f; + const float seconds = (float) elapsed / 1000.0f; for (core::Zone::Registry::iterator it = core::Zone::registry().begin(); it != core::Zone::registry().end(); it++) { - (*it).second->physics()->stepSimulation(seconds); + (*it).second->physics()->stepSimulation(seconds, 8); } - - physics_timestamp = timestamp; } } // namespace core diff --git a/src/core/physics.h b/src/core/physics.h index 3237c3a..1989410 100644 --- a/src/core/physics.h +++ b/src/core/physics.h @@ -28,7 +28,7 @@ public: static void done(); - static void frame(const unsigned long timestamp); + static void frame(const unsigned long elapsed); inline static btDefaultCollisionConfiguration *configuration() { return physics_configuration; @@ -46,9 +46,6 @@ private: static btDefaultCollisionConfiguration *physics_configuration; static btCollisionDispatcher *physics_dispatcher; static btSequentialImpulseConstraintSolver *physics_solver; - - static unsigned long physics_timestamp; - }; } // namespace core diff --git a/src/core/timer.cc b/src/core/timer.cc deleted file mode 100644 index 6f2e914..0000000 --- a/src/core/timer.cc +++ /dev/null @@ -1,50 +0,0 @@ -/* - core/timer.cc - This file is part of the Osirion project and is distributed under - the terms and conditions of the GNU General Public License version 2 -*/ - -#include "core/timer.h" - -#include -#include -#include - -namespace core -{ - -Timer::Timer() -{ - gettimeofday(&this->timer_tick, &this->timer_tz); - this->timer_elapsed = 0; -} - -Timer::~Timer() -{ -} - -void Timer::mark() -{ - gettimeofday(&timer_tick, &timer_tz); -} - -unsigned long Timer::timestamp() -{ - struct timeval tick; - struct timezone tick_tz; - - gettimeofday(&tick, &tick_tz); - - // calculate elapsed time in 10^-6 seconds - unsigned long delta = 0; - delta = tick.tv_sec * 1000 + tick.tv_usec / 1000; - delta -= timer_tick.tv_sec * 1000 + timer_tick.tv_usec / 1000; - return delta; -} - -float Timer::elapsed() -{ - return ((float) timestamp() / 1000.0f); -} - -} diff --git a/src/core/timer.h b/src/core/timer.h deleted file mode 100644 index 5157811..0000000 --- a/src/core/timer.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - core/timer.h - This file is part of the Osirion project and is distributed under - the terms and conditions of the GNU General Public License version 2 -*/ - -#ifndef __INCLUDED_CORE_TIMER_H__ -#define __INCLUDED_CORE_TIMER_H__ - -#include - -namespace core -{ - -/// a timer measures intervals in seconds -/*! A timer class measures the time elapsed -* between the last two calls to its mark() function. -*/ -class Timer -{ -public: - /// Constructor - Timer(); - /// Destructor - ~Timer(); - - /// mark the current time as zero - /*! Reset the timer, all subsequent calls too elapsed() will - * use the current timestamp as reference - */ - void mark(); - - /*! return the time elapsed since the last mark, in seconds - * @see mark() - */ - float elapsed(); - - /// return timestamp since last mark, in microseconds - unsigned long timestamp(); - -private: - float timer_elapsed; - struct timezone timer_tz; - struct timeval timer_tick; -}; // class Timer - -} // namespace core - -#endif // __INCLUDED_CORE_TIMER_H__ - diff --git a/src/dedicated/console.cc b/src/dedicated/console.cc index fd61ffe..10fe261 100644 --- a/src/dedicated/console.cc +++ b/src/dedicated/console.cc @@ -222,7 +222,6 @@ void Console::draw_status() << std::setw(2) << " "; // uptime - // FIXME this is plain wrong, but the timing routines need to be refactored first float uptime = core::game()->time(); const int uptime_days = (int) floorf(uptime / (24.0f * 3600.0f)); diff --git a/src/dedicated/dedicated.cc b/src/dedicated/dedicated.cc index 3d763f4..f93b5fa 100644 --- a/src/dedicated/dedicated.cc +++ b/src/dedicated/dedicated.cc @@ -10,7 +10,6 @@ #include "core/core.h" #include "core/cvar.h" #include "core/stats.h" -#include "core/timer.h" #include "dedicated/console.h" #include "dedicated/dedicated.h" @@ -52,11 +51,8 @@ void Dedicated::init(int count, char **arguments) void Dedicated::run() { - core::Timer timer; - timer.mark(); - while (connected()) { - frame(timer.timestamp()); + frame(); #ifdef HAVE_CURSES console()->frame(); #endif diff --git a/src/game/base/jumppoint.cc b/src/game/base/jumppoint.cc index 80c99ef..3d9fd01 100644 --- a/src/game/base/jumppoint.cc +++ b/src/game/base/jumppoint.cc @@ -179,19 +179,17 @@ void JumpGate::func_dock(Ship *ship) void JumpGate::activate() { - jumpgate_timer = jump_timer_delay; + jumpgate_timer = jump_timer_delay * 1000; set_state(core::Entity::Normal); } -void JumpGate::frame(float elapsed) +void JumpGate::frame(const unsigned long elapsed) { - if (jumpgate_timer > 0) { + if (jumpgate_timer > elapsed) { jumpgate_timer -= elapsed; - - if (jumpgate_timer < 0) { - set_state(core::Entity::NoPower); - jumpgate_timer = 0; - } + } else if (state() != core::Entity::NoPower) { + set_state(core::Entity::NoPower); + jumpgate_timer = 0; } } diff --git a/src/game/base/jumppoint.h b/src/game/base/jumppoint.h index 40f9e5d..33a9f9f 100644 --- a/src/game/base/jumppoint.h +++ b/src/game/base/jumppoint.h @@ -75,14 +75,14 @@ public: void activate(); - virtual void frame(float elapsed); + virtual void frame(const unsigned long elapsed); static inline void set_template (const Template *entitytemplate) { jumpgate_template = entitytemplate; } private: - float jumpgate_timer; + unsigned long jumpgate_timer; static const Template *jumpgate_template; }; diff --git a/src/game/base/ship.cc b/src/game/base/ship.cc index 0fa44fb..7a499c3 100644 --- a/src/game/base/ship.cc +++ b/src/game/base/ship.cc @@ -365,7 +365,7 @@ void Ship::action (btScalar seconds) } } -void Ship::frame(float seconds) +void Ship::frame(const unsigned long elapsed) { //const float direction_reaction = 2.0f; // directional control reaction time //const float thrust_reaction = 0.5f; // thrust control reaction time @@ -646,7 +646,7 @@ void Ship::frame(float seconds) } */ - EntityControlable::frame(seconds); + EntityControlable::frame(elapsed); } diff --git a/src/game/base/ship.h b/src/game/base/ship.h index b0256aa..37dae0d 100644 --- a/src/game/base/ship.h +++ b/src/game/base/ship.h @@ -53,11 +53,11 @@ public: return ship_roll_force; } - /// physices frame + /// physics frame virtual void action (btScalar seconds); /// game frame - virtual void frame(float seconds); + virtual void frame(const unsigned long elapsed); /// move the ship to a different zone virtual void set_zone(core::Zone *zone); diff --git a/src/game/example/spectator.cc b/src/game/example/spectator.cc index 5fc7fc6..9ca9497 100644 --- a/src/game/example/spectator.cc +++ b/src/game/example/spectator.cc @@ -33,7 +33,7 @@ Spectator::~Spectator() { } -void Spectator::frame(float elapsed) +void Spectator::frame(const unsigned long elapsed) { // only update if necessary if (!entity_speed && ! target_thrust && !target_direction && !target_pitch && !target_roll && !target_strafe && !target_afterburner) @@ -41,9 +41,11 @@ void Spectator::frame(float elapsed) // assign thrust value from input entity_thrust = target_thrust; + + const float seconds = (float) elapsed / 1000.0f; // rotate according to input - float rotation = g_spectatorrotation->value() * elapsed; + float rotation = g_spectatorrotation->value() * seconds; get_axis().change_direction(target_direction * rotation); get_axis().change_pitch(target_pitch * rotation); get_axis().change_roll(target_roll * rotation); @@ -54,14 +56,17 @@ void Spectator::frame(float elapsed) // assign new location if (entity_speed) - get_location() += axis().forward() * entity_speed * elapsed; + get_location() += axis().forward() * entity_speed * seconds; if (target_afterburner) - get_location() += axis().forward() * maxspeed * target_afterburner * elapsed; + get_location() += axis().forward() * maxspeed * target_afterburner * seconds; if (target_strafe) - get_location() += axis().left() * maxspeed * target_strafe * elapsed; + get_location() += axis().left() * maxspeed * target_strafe * seconds; + if (target_vstrafe) + get_location() += axis().up() * maxspeed * target_vstrafe * seconds; + // set dirty flag set_dirty(); } diff --git a/src/game/example/spectator.h b/src/game/example/spectator.h index 57f223b..bd141b2 100644 --- a/src/game/example/spectator.h +++ b/src/game/example/spectator.h @@ -21,7 +21,7 @@ public: ~Spectator(); /// update the ship state - virtual void frame(float elapsed); + virtual void frame(const unsigned long elapsed); static core::Cvar *g_spectatorspeed; static core::Cvar *g_spectatorrotation; diff --git a/src/game/intro/convoy.cc b/src/game/intro/convoy.cc index 118bdee..8a436bb 100644 --- a/src/game/intro/convoy.cc +++ b/src/game/intro/convoy.cc @@ -30,9 +30,9 @@ Member::~Member() { } -void Member::frame(float seconds) +void Member::frame(const unsigned long elapsed) { - get_location() += axis().forward() * speed() * thrust() * seconds; + get_location() += axis().forward() * speed() * thrust() * ((float) elapsed / 1000.0f); } /* ---- class Convoy ----------------------------------------------- */ @@ -82,7 +82,7 @@ void Convoy::add(const std::string &modelname) member->get_axis().assign(axis()); } -void Convoy::frame(float seconds) +void Convoy::frame(const unsigned long elapsed) { for (Members::iterator it = convoy_members.begin(); it != convoy_members.end();) { Member *member = (*it); diff --git a/src/game/intro/convoy.h b/src/game/intro/convoy.h index 22e3f7c..127db5e 100644 --- a/src/game/intro/convoy.h +++ b/src/game/intro/convoy.h @@ -23,7 +23,7 @@ public: Member(std::string const &modelname); ~Member(); - void frame(float seconds); + void frame(const unsigned long elapsed); }; /* ---- class Convoy ----------------------------------------------- */ @@ -37,7 +37,7 @@ public: void add(const char *modelname); void add(const std::string &modelname); - virtual void frame(float seconds); + virtual void frame(const unsigned long elapsed); private: typedef std::list Members; diff --git a/src/model/mapfile.cc b/src/model/mapfile.cc index 8dc9d0e..b0f5bea 100644 --- a/src/model/mapfile.cc +++ b/src/model/mapfile.cc @@ -530,6 +530,7 @@ bool MapFile::read_patchdef() mesh[i+1][j] * SCALE); map_collisiontriangles.add(*triangle); } + } else { // not clip, convert to quads Quad *quad = new Quad( @@ -1875,11 +1876,11 @@ Model * MapFile::load(std::string const &name) switch (fragmentdst->type()) { case Fragment::Triangles: - model->model_tris_count += (fragmentdst->structural_size() + fragmentdst->detail_size()) / 3; + model->model_tris_count += (fragmentdst->structural_size() + fragmentdst->detail_size()) / 3; model->model_tris_detail_count += fragmentdst->detail_size() / 3; break; case Fragment::Quads: - model->model_quad_count += (fragmentdst->structural_size() + fragmentdst->detail_size()) / 4; + model->model_quad_count += (fragmentdst->structural_size() + fragmentdst->detail_size()) / 4; model->model_quad_detail_count += fragmentdst->detail_size() / 4; break; } diff --git a/src/sys/Makefile.am b/src/sys/Makefile.am index be1c636..ff1fbe0 100644 --- a/src/sys/Makefile.am +++ b/src/sys/Makefile.am @@ -2,5 +2,5 @@ INCLUDES = -I$(top_srcdir)/src METASOURCES = AUTO libsys_la_LDFLAGS = -avoid-version -no-undefined noinst_LTLIBRARIES = libsys.la -libsys_la_SOURCES = consoleinterface.cc sys.cc -noinst_HEADERS = consoleinterface.h sys.h +libsys_la_SOURCES = consoleinterface.cc sys.cc timer.cc +noinst_HEADERS = consoleinterface.h sys.h timer.h diff --git a/src/sys/timer.cc b/src/sys/timer.cc new file mode 100644 index 0000000..c46ece2 --- /dev/null +++ b/src/sys/timer.cc @@ -0,0 +1,46 @@ +/* + sys/timer.cc + This file is part of the Osirion project and is distributed under + the terms and conditions of the GNU General Public License version 2 +*/ + +#include "sys/timer.h" + +#include + +#include +#include + +namespace sys +{ + +Timer::Timer() +{ + reset(); +} + +Timer::~Timer() +{ +} + +void Timer::reset() +{ + struct timeval tick; + struct timezone tick_tz; + + gettimeofday(&tick, &tick_tz); + timer_start = tick.tv_sec * 1000 + tick.tv_usec / 1000; +} + +unsigned long Timer::timestamp() const +{ + struct timeval tick; + struct timezone tick_tz; + + gettimeofday(&tick, &tick_tz); + unsigned long delta = (tick.tv_sec * 1000 + tick.tv_usec / 1000) - timer_start; + + return delta; +} + +} diff --git a/src/sys/timer.h b/src/sys/timer.h new file mode 100644 index 0000000..125363d --- /dev/null +++ b/src/sys/timer.h @@ -0,0 +1,50 @@ +/* + sys/timer.h + This file is part of the Osirion project and is distributed under + the terms and conditions of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_SYS_TIMER_H__ +#define __INCLUDED_SYS_TIMER_H__ + +namespace sys +{ + +/// a timer measures intervals in seconds +/*! A timer class measures the time elapsed +* between the last two calls to its mark() function. +*/ +class Timer +{ +public: + /** + * @brief constructor + * The constructor autmaticly calls reset() + * */ + Timer(); + + /** + * @brief destructor + * */ + ~Timer(); + + /** + * @brief reset the timer to 0 + */ + void reset(); + + /** + * @brief return the time elapsed since the last reset() call, in milliseconds + * + * */ + unsigned long timestamp() const; + +private: + unsigned long timer_start; + +}; // class Timer + +} // namespace sys + +#endif // __INCLUDED_SYS_TIMER_H__ + -- cgit v1.2.3