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 ++-- 4 files changed, 35 insertions(+), 33 deletions(-) (limited to 'src/client') 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; }; -- cgit v1.2.3