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;
////////////////////////////////////////////////////////////
/// \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
///
/// This function puts the time counter back to zero.
/// It also returns the time elapsed since the clock was started.
/// This function puts the time counter back to zero, returns
/// the elapsed time, and leaves the clock in a running state.
///
/// \return Time elapsed
///
/// \see reset
///
////////////////////////////////////////////////////////////
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:
////////////////////////////////////////////////////////////
// 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
@ -130,7 +170,7 @@ private:
///
/// 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).
/// It also ensures monotonicity, which means that the returned
/// time can never go backward, even if the system time is
@ -143,6 +183,8 @@ private:
/// Time time1 = clock.getElapsedTime();
/// ...
/// Time time2 = clock.restart();
/// ...
/// Time time3 = clock.reset();
/// \endcode
///
/// The sf::Time value returned by the clock can then be

View File

@ -34,17 +34,54 @@ namespace sf
////////////////////////////////////////////////////////////
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()
{
const auto now = priv::ClockImpl::now();
const auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(now - m_startTime);
m_startTime = now;
const Time elapsed = getElapsedTime();
m_refPoint = priv::ClockImpl::now();
m_stopPoint = {};
return elapsed;
}
////////////////////////////////////////////////////////////
Time Clock::reset()
{
const Time elapsed = getElapsedTime();
m_refPoint = priv::ClockImpl::now();
m_stopPoint = m_refPoint;
return elapsed;
}

View File

@ -9,6 +9,8 @@
TEST_CASE("[System] sf::Clock")
{
using namespace std::chrono_literals;
SECTION("Type traits")
{
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>);
}
SECTION("Construction")
{
const sf::Clock clock;
CHECK(clock.isRunning());
CHECK(clock.getElapsedTime() >= sf::microseconds(0));
}
SECTION("getElapsedTime()")
{
const sf::Clock clock;
CHECK(clock.getElapsedTime() >= sf::microseconds(0));
const auto elapsed = clock.getElapsedTime();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
std::this_thread::sleep_for(1ms);
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()")
{
sf::Clock clock;
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();
CHECK(clock.restart() < elapsed);
}
SECTION("reset()")
{
sf::Clock clock;
CHECK(clock.reset() >= sf::microseconds(0));
CHECK(!clock.isRunning());
}
}