Make sf::Clock pausable

This commit is contained in:
MetGang 2022-07-20 14:40:45 +02:00 committed by Chris Thrasher
parent b39be46db0
commit 8835f42589
3 changed files with 120 additions and 10 deletions

View File

@ -103,22 +103,62 @@ public:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Time getElapsedTime() const; Time getElapsedTime() const;
////////////////////////////////////////////////////////////
/// \brief Check whether the clock is running
///
/// \return True if the clock is running, false otherwise
///
////////////////////////////////////////////////////////////
bool isRunning() const;
////////////////////////////////////////////////////////////
/// \brief Start the clock
///
/// \see stop
///
////////////////////////////////////////////////////////////
void start();
////////////////////////////////////////////////////////////
/// \brief Stop the clock
///
/// \see start
///
////////////////////////////////////////////////////////////
void stop();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Restart the clock /// \brief Restart the clock
/// ///
/// This function puts the time counter back to zero. /// This function puts the time counter back to zero, returns
/// It also returns the time elapsed since the clock was started. /// the elapsed time, and leaves the clock in a running state.
/// ///
/// \return Time elapsed /// \return Time elapsed
/// ///
/// \see reset
///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Time restart(); Time restart();
////////////////////////////////////////////////////////////
/// \brief Reset the clock
///
/// This function puts the time counter back to zero, returns
/// the elapsed time, and leaves the clock in a paused state.
///
/// \return Time elapsed
///
/// \see restart
///
////////////////////////////////////////////////////////////
Time reset();
private: private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
priv::ClockImpl::time_point m_startTime{priv::ClockImpl::now()}; //!< Time of last reset priv::ClockImpl::time_point m_refPoint{priv::ClockImpl::now()}; //!< Time of last reset
priv::ClockImpl::time_point m_stopPoint; //!< Time of last stop
}; };
} // namespace sf } // namespace sf
@ -130,7 +170,7 @@ private:
/// ///
/// sf::Clock is a lightweight class for measuring time. /// sf::Clock is a lightweight class for measuring time.
/// ///
/// Its provides the most precise time that the underlying /// It provides the most precise time that the underlying
/// OS can achieve (generally microseconds or nanoseconds). /// OS can achieve (generally microseconds or nanoseconds).
/// It also ensures monotonicity, which means that the returned /// It also ensures monotonicity, which means that the returned
/// time can never go backward, even if the system time is /// time can never go backward, even if the system time is
@ -143,6 +183,8 @@ private:
/// Time time1 = clock.getElapsedTime(); /// Time time1 = clock.getElapsedTime();
/// ... /// ...
/// Time time2 = clock.restart(); /// Time time2 = clock.restart();
/// ...
/// Time time3 = clock.reset();
/// \endcode /// \endcode
/// ///
/// The sf::Time value returned by the clock can then be /// The sf::Time value returned by the clock can then be

View File

@ -34,17 +34,54 @@ namespace sf
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Time Clock::getElapsedTime() const Time Clock::getElapsedTime() const
{ {
return std::chrono::duration_cast<std::chrono::microseconds>(priv::ClockImpl::now() - m_startTime); if (isRunning())
return std::chrono::duration_cast<std::chrono::microseconds>(priv::ClockImpl::now() - m_refPoint);
return std::chrono::duration_cast<std::chrono::microseconds>(m_stopPoint - m_refPoint);
}
////////////////////////////////////////////////////////////
bool Clock::isRunning() const
{
return m_stopPoint == priv::ClockImpl::time_point();
}
////////////////////////////////////////////////////////////
void Clock::start()
{
if (!isRunning())
{
m_refPoint += priv::ClockImpl::now() - m_stopPoint;
m_stopPoint = {};
}
}
////////////////////////////////////////////////////////////
void Clock::stop()
{
if (isRunning())
m_stopPoint = priv::ClockImpl::now();
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Time Clock::restart() Time Clock::restart()
{ {
const auto now = priv::ClockImpl::now(); const Time elapsed = getElapsedTime();
const auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(now - m_startTime); m_refPoint = priv::ClockImpl::now();
m_startTime = now; m_stopPoint = {};
return elapsed;
}
////////////////////////////////////////////////////////////
Time Clock::reset()
{
const Time elapsed = getElapsedTime();
m_refPoint = priv::ClockImpl::now();
m_stopPoint = m_refPoint;
return elapsed; return elapsed;
} }

View File

@ -9,6 +9,8 @@
TEST_CASE("[System] sf::Clock") TEST_CASE("[System] sf::Clock")
{ {
using namespace std::chrono_literals;
SECTION("Type traits") SECTION("Type traits")
{ {
STATIC_CHECK(std::is_copy_constructible_v<sf::Clock>); STATIC_CHECK(std::is_copy_constructible_v<sf::Clock>);
@ -17,21 +19,50 @@ TEST_CASE("[System] sf::Clock")
STATIC_CHECK(std::is_nothrow_move_assignable_v<sf::Clock>); STATIC_CHECK(std::is_nothrow_move_assignable_v<sf::Clock>);
} }
SECTION("Construction")
{
const sf::Clock clock;
CHECK(clock.isRunning());
CHECK(clock.getElapsedTime() >= sf::microseconds(0));
}
SECTION("getElapsedTime()") SECTION("getElapsedTime()")
{ {
const sf::Clock clock; const sf::Clock clock;
CHECK(clock.getElapsedTime() >= sf::microseconds(0)); CHECK(clock.getElapsedTime() >= sf::microseconds(0));
const auto elapsed = clock.getElapsedTime(); const auto elapsed = clock.getElapsedTime();
std::this_thread::sleep_for(std::chrono::milliseconds(1)); std::this_thread::sleep_for(1ms);
CHECK(clock.getElapsedTime() > elapsed); CHECK(clock.getElapsedTime() > elapsed);
} }
SECTION("start/stop")
{
sf::Clock clock;
clock.stop();
CHECK(!clock.isRunning());
const auto elapsed = clock.getElapsedTime();
std::this_thread::sleep_for(1ms);
CHECK(elapsed == clock.getElapsedTime());
clock.start();
CHECK(clock.isRunning());
CHECK(clock.getElapsedTime() >= elapsed);
}
SECTION("restart()") SECTION("restart()")
{ {
sf::Clock clock; sf::Clock clock;
CHECK(clock.restart() >= sf::microseconds(0)); CHECK(clock.restart() >= sf::microseconds(0));
std::this_thread::sleep_for(std::chrono::milliseconds(1)); CHECK(clock.isRunning());
std::this_thread::sleep_for(1ms);
const auto elapsed = clock.restart(); const auto elapsed = clock.restart();
CHECK(clock.restart() < elapsed); CHECK(clock.restart() < elapsed);
} }
SECTION("reset()")
{
sf::Clock clock;
CHECK(clock.reset() >= sf::microseconds(0));
CHECK(!clock.isRunning());
}
} }