mirror of
https://github.com/NoelFB/blah.git
synced 2024-11-25 16:18:57 +08:00
more precise timing
renamed Time::elapsed -> Time::seconds, change type to double updated game to store ticks (microseconds) instead of milliseconds for better update precision
This commit is contained in:
parent
2c2d668927
commit
ac58379de8
|
@ -5,14 +5,20 @@ namespace Blah
|
|||
{
|
||||
struct Time
|
||||
{
|
||||
// uptime, in milliseconds
|
||||
static uint64_t milliseconds;
|
||||
// ticks per second (microseconds, in this case)
|
||||
static constexpr uint64_t ticks_per_second = 1000000;
|
||||
|
||||
// uptime, in ticks
|
||||
static uint64_t ticks;
|
||||
|
||||
// uptime, in seconds
|
||||
static float elapsed;
|
||||
static double seconds;
|
||||
|
||||
// previous frame uptime, in ticks
|
||||
static uint64_t previous_ticks;
|
||||
|
||||
// previous frame uptime, in seconds
|
||||
static float previous_elapsed;
|
||||
static double previous_seconds;
|
||||
|
||||
// delta time from last frame
|
||||
static float delta;
|
||||
|
@ -21,10 +27,10 @@ namespace Blah
|
|||
static float pause_timer;
|
||||
|
||||
// pauses the entire application for the given time
|
||||
static void pause_for(float time);
|
||||
static void pause_for(float duration);
|
||||
|
||||
// returns true on the given time interval
|
||||
static bool on_interval(float time, float delta, float interval, float offset);
|
||||
static bool on_interval(double time, float delta, float interval, float offset);
|
||||
|
||||
// returns true on the given time interval
|
||||
static bool on_interval(float delta, float interval, float offset);
|
||||
|
@ -33,10 +39,10 @@ namespace Blah
|
|||
static bool on_interval(float interval, float offset = 0);
|
||||
|
||||
// returns true when the given timestamp is passed
|
||||
static bool on_time(float time, float timestamp);
|
||||
static bool on_time(double time, double timestamp);
|
||||
|
||||
// returns true between time intervals
|
||||
static bool between_interval(float time, float interval, float offset);
|
||||
static bool between_interval(double time, float interval, float offset);
|
||||
|
||||
// returns true between time intervals
|
||||
static bool between_interval(float interval, float offset = 0);
|
||||
|
|
|
@ -61,9 +61,9 @@ namespace Blah
|
|||
int m_last_value_i = 0;
|
||||
bool m_pressed = false;
|
||||
bool m_released = false;
|
||||
float m_last_press_time = -1;
|
||||
float m_last_release_time = -1;
|
||||
float m_repeat_press_time = -1;
|
||||
double m_last_press_time = -1;
|
||||
double m_last_release_time = -1;
|
||||
double m_repeat_press_time = -1;
|
||||
|
||||
public:
|
||||
VirtualAxis& add_keys(Key negative, Key positive);
|
||||
|
|
|
@ -61,9 +61,9 @@ namespace Blah
|
|||
bool m_down = false;
|
||||
bool m_pressed = false;
|
||||
bool m_released = false;
|
||||
float m_last_press_time = -1;
|
||||
float m_last_release_time = -1;
|
||||
float m_repeat_press_time = -1;
|
||||
double m_last_press_time = -1;
|
||||
double m_last_release_time = -1;
|
||||
double m_repeat_press_time = -1;
|
||||
|
||||
public:
|
||||
VirtualButton& add_key(Key key);
|
||||
|
|
|
@ -70,9 +70,9 @@ namespace Blah
|
|||
bool m_released = false;
|
||||
|
||||
float m_i_deadzone;
|
||||
float m_last_press_time = -1;
|
||||
float m_last_release_time = -1;
|
||||
float m_repeat_press_time = -1;
|
||||
double m_last_press_time = -1;
|
||||
double m_last_release_time = -1;
|
||||
double m_repeat_press_time = -1;
|
||||
|
||||
public:
|
||||
VirtualStick();
|
||||
|
|
|
@ -6,13 +6,6 @@
|
|||
|
||||
using namespace Blah;
|
||||
|
||||
const uint16_t UTF8_LEAD_SURROGATE_MIN = 0xd800u;
|
||||
const uint16_t UTF8_LEAD_SURROGATE_MAX = 0xdbffu;
|
||||
const uint16_t UTF8_TRAIL_SURROGATE_MIN = 0xdc00u;
|
||||
const uint16_t UTF8_TRAIL_SURROGATE_MAX = 0xdfffu;
|
||||
const uint16_t UTF8_LEAD_OFFSET = UTF8_LEAD_SURROGATE_MIN - (0x10000 >> 10);
|
||||
const uint32_t UTF8_SURROGATE_OFFSET = 0x10000u - (UTF8_LEAD_SURROGATE_MIN << 10) - UTF8_TRAIL_SURROGATE_MIN;
|
||||
|
||||
char Str::empty_buffer[1] = { '\0' };
|
||||
|
||||
bool Str::operator==(const Str& rhs) const
|
||||
|
@ -217,24 +210,30 @@ Str& Str::append_fmt(const char* fmt, ...)
|
|||
return *this;
|
||||
}
|
||||
|
||||
Str& Str::append_utf16(const uint16_t* start, const uint16_t* end, bool swapEndian)
|
||||
Str& Str::append_utf16(const uint16_t* start, const uint16_t* end, bool swap_endian)
|
||||
{
|
||||
// converts utf16 into utf8
|
||||
// more info: https://en.wikipedia.org/wiki/UTF-16#Description
|
||||
|
||||
const uint16_t surrogate_min = 0xd800u;
|
||||
const uint16_t surrogate_max = 0xdbffu;
|
||||
|
||||
while (start != end)
|
||||
{
|
||||
uint16_t next = (*start++);
|
||||
if (swapEndian)
|
||||
if (swap_endian)
|
||||
next = ((next & 0xff) << 8 | ((next & 0xff00) >> 8));
|
||||
|
||||
uint32_t cp = 0xffff & next;
|
||||
|
||||
if ((cp >= UTF8_LEAD_SURROGATE_MIN && cp <= UTF8_LEAD_SURROGATE_MAX))
|
||||
if ((cp >= surrogate_min && cp <= surrogate_max))
|
||||
{
|
||||
next = (*start++);
|
||||
if (swapEndian)
|
||||
if (swap_endian)
|
||||
next = ((next & 0xff) << 8 | ((next & 0xff00) >> 8));
|
||||
|
||||
uint32_t trail = 0xffff & next;
|
||||
cp = (cp << 10) + trail + UTF8_SURROGATE_OFFSET;
|
||||
cp = (cp << 10) + trail + 0x10000u - (surrogate_min << 10) - 0xdc00u;
|
||||
}
|
||||
|
||||
append(cp);
|
||||
|
|
|
@ -48,8 +48,8 @@ namespace
|
|||
// update at a fixed timerate
|
||||
// TODO: allow a non-fixed step update?
|
||||
{
|
||||
uint64_t time_target = (uint64_t)((1.0f / app_config.target_framerate) * 1000);
|
||||
uint64_t time_curr = PlatformBackend::time();
|
||||
uint64_t time_target = (uint64_t)((1.0 / app_config.target_framerate) * Time::ticks_per_second);
|
||||
uint64_t time_curr = PlatformBackend::ticks();
|
||||
uint64_t time_diff = time_curr - time_last;
|
||||
time_last = time_curr;
|
||||
time_accumulator += time_diff;
|
||||
|
@ -57,9 +57,10 @@ namespace
|
|||
// do not let us run too fast
|
||||
while (time_accumulator < time_target)
|
||||
{
|
||||
PlatformBackend::sleep((int)(time_target - time_accumulator));
|
||||
int milliseconds = (int)(time_target - time_accumulator) / (Time::ticks_per_second / 1000);
|
||||
PlatformBackend::sleep(milliseconds);
|
||||
|
||||
time_curr = PlatformBackend::time();
|
||||
time_curr = PlatformBackend::ticks();
|
||||
time_diff = time_curr - time_last;
|
||||
time_last = time_curr;
|
||||
time_accumulator += time_diff;
|
||||
|
@ -81,15 +82,16 @@ namespace
|
|||
if (Time::pause_timer > 0)
|
||||
{
|
||||
Time::pause_timer -= Time::delta;
|
||||
if (Time::pause_timer <= -0.0001f)
|
||||
if (Time::pause_timer <= -0.0001)
|
||||
Time::delta = -Time::pause_timer;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
Time::milliseconds += time_target;
|
||||
Time::previous_elapsed = Time::elapsed;
|
||||
Time::elapsed += Time::delta;
|
||||
Time::previous_ticks = Time::ticks;
|
||||
Time::ticks += time_target;
|
||||
Time::previous_seconds = Time::seconds;
|
||||
Time::seconds += Time::delta;
|
||||
|
||||
InputBackend::frame();
|
||||
GraphicsBackend::frame();
|
||||
|
@ -147,7 +149,7 @@ bool App::run(const Config* c)
|
|||
if (app_config.on_startup != nullptr)
|
||||
app_config.on_startup();
|
||||
|
||||
time_last = PlatformBackend::time();
|
||||
time_last = PlatformBackend::ticks();
|
||||
time_accumulator = 0;
|
||||
|
||||
// display window
|
||||
|
@ -173,8 +175,11 @@ bool App::run(const Config* c)
|
|||
// clear static state
|
||||
app_is_running = false;
|
||||
app_is_exiting = false;
|
||||
Time::milliseconds = 0;
|
||||
Time::elapsed = 0;
|
||||
|
||||
Time::ticks = 0;
|
||||
Time::seconds = 0;
|
||||
Time::previous_ticks = 0;
|
||||
Time::previous_seconds = 0;
|
||||
Time::delta = 0;
|
||||
|
||||
return true;
|
||||
|
|
|
@ -5,50 +5,51 @@ using namespace Blah;
|
|||
|
||||
namespace
|
||||
{
|
||||
float modf(float x, float m)
|
||||
double modf(double x, double m)
|
||||
{
|
||||
return x - (int)(x / m) * m;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t Time::milliseconds = 0;
|
||||
float Time::elapsed = 0;
|
||||
uint64_t Time::ticks = 0;
|
||||
uint64_t Time::previous_ticks = 0;
|
||||
double Time::seconds = 0;
|
||||
double Time::previous_seconds = 0;
|
||||
float Time::delta = 0;
|
||||
float Time::previous_elapsed = 0;
|
||||
float Time::pause_timer = 0;
|
||||
|
||||
void Time::pause_for(float time)
|
||||
void Time::pause_for(float duration)
|
||||
{
|
||||
if (time >= pause_timer)
|
||||
pause_timer = time;
|
||||
if (duration >= pause_timer)
|
||||
pause_timer = duration;
|
||||
}
|
||||
|
||||
bool Time::on_interval(float time, float delta, float interval, float offset)
|
||||
bool Time::on_interval(double time, float delta, float interval, float offset)
|
||||
{
|
||||
return floor((time - offset - delta) / interval) < floor((time - offset) / interval);
|
||||
}
|
||||
|
||||
bool Time::on_interval(float delta, float interval, float offset)
|
||||
{
|
||||
return Time::on_interval(Time::elapsed, delta, interval, offset);
|
||||
return Time::on_interval(Time::seconds, delta, interval, offset);
|
||||
}
|
||||
|
||||
bool Time::on_interval(float interval, float offset)
|
||||
{
|
||||
return Time::on_interval(Time::elapsed, Time::delta, interval, offset);
|
||||
return Time::on_interval(Time::seconds, Time::delta, interval, offset);
|
||||
}
|
||||
|
||||
bool Time::on_time(float time, float timestamp)
|
||||
bool Time::on_time(double time, double timestamp)
|
||||
{
|
||||
return time >= timestamp && time - Time::delta < timestamp;
|
||||
}
|
||||
|
||||
bool Time::between_interval(float time, float interval, float offset)
|
||||
bool Time::between_interval(double time, float interval, float offset)
|
||||
{
|
||||
return modf(time - offset, interval * 2) >= interval;
|
||||
}
|
||||
|
||||
bool Time::between_interval(float interval, float offset)
|
||||
{
|
||||
return between_interval(Time::elapsed, interval, offset);
|
||||
return between_interval(Time::seconds, interval, offset);
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ void InputBackend::on_mouse_down(MouseButton button)
|
|||
{
|
||||
g_next_state.mouse.down[i] = true;
|
||||
g_next_state.mouse.pressed[i] = true;
|
||||
g_next_state.mouse.timestamp[i] = Time::milliseconds;
|
||||
g_next_state.mouse.timestamp[i] = Time::ticks;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,7 @@ void InputBackend::on_key_down(Key key)
|
|||
{
|
||||
g_next_state.keyboard.down[i] = true;
|
||||
g_next_state.keyboard.pressed[i] = true;
|
||||
g_next_state.keyboard.timestamp[i] = Time::milliseconds;
|
||||
g_next_state.keyboard.timestamp[i] = Time::ticks;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,7 +170,7 @@ void InputBackend::on_button_down(int index, int button)
|
|||
{
|
||||
g_next_state.controllers[index].down[button] = 1;
|
||||
g_next_state.controllers[index].pressed[button] = 1;
|
||||
g_next_state.controllers[index].button_timestamp[button] = Time::milliseconds;
|
||||
g_next_state.controllers[index].button_timestamp[button] = Time::ticks;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,7 +194,7 @@ void InputBackend::on_axis_move(int index, int axis, float value)
|
|||
axis < g_next_state.controllers[index].axis_count)
|
||||
{
|
||||
g_next_state.controllers[index].axis[axis] = value;
|
||||
g_next_state.controllers[index].axis_timestamp[axis] = Time::milliseconds;
|
||||
g_next_state.controllers[index].axis_timestamp[axis] = Time::ticks;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -102,16 +102,16 @@ void VirtualAxis::update()
|
|||
if (m_value_i != 0 && m_last_value_i != m_value_i)
|
||||
{
|
||||
m_pressed = true;
|
||||
m_last_press_time = m_repeat_press_time = Time::elapsed;
|
||||
m_last_press_time = m_repeat_press_time = Time::seconds;
|
||||
}
|
||||
else if (m_value_i == m_last_value_i && m_value_i != 0)
|
||||
{
|
||||
if (Time::elapsed - m_last_press_time <= m_press_buffer)
|
||||
if (Time::seconds - m_last_press_time <= m_press_buffer)
|
||||
m_pressed = true;
|
||||
else if (m_repeat_interval > 0 && Time::elapsed >= m_repeat_press_time + m_repeat_delay)
|
||||
else if (m_repeat_interval > 0 && Time::seconds >= m_repeat_press_time + m_repeat_delay)
|
||||
{
|
||||
int prev = (int)((Time::previous_elapsed - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
|
||||
int cur = (int)((Time::elapsed - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
|
||||
int prev = (int)((Time::previous_seconds - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
|
||||
int cur = (int)((Time::seconds - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
|
||||
m_pressed = prev < cur;
|
||||
}
|
||||
}
|
||||
|
@ -120,9 +120,9 @@ void VirtualAxis::update()
|
|||
if (m_last_value_i != 0 && m_value_i != m_last_value_i)
|
||||
{
|
||||
m_released = true;
|
||||
m_last_release_time = Time::elapsed;
|
||||
m_last_release_time = Time::seconds;
|
||||
}
|
||||
else if (Time::elapsed - m_last_release_time <= m_release_buffer)
|
||||
else if (Time::seconds - m_last_release_time <= m_release_buffer)
|
||||
m_released = true;
|
||||
else
|
||||
m_released = false;
|
||||
|
|
|
@ -68,7 +68,7 @@ void VirtualButton::update()
|
|||
m_pressed = false;
|
||||
m_released = false;
|
||||
|
||||
//Keys
|
||||
// Keys
|
||||
for (int i = 0; i < m_keys_len; i++)
|
||||
{
|
||||
m_keys[i].update();
|
||||
|
@ -78,7 +78,7 @@ void VirtualButton::update()
|
|||
m_released = m_released || m_keys[i].released;
|
||||
}
|
||||
|
||||
//Buttons
|
||||
// Buttons
|
||||
for (int i = 0; i < m_buttons_len; i++)
|
||||
{
|
||||
m_buttons[i].update();
|
||||
|
@ -88,7 +88,7 @@ void VirtualButton::update()
|
|||
m_released = m_released || m_buttons[i].released;
|
||||
}
|
||||
|
||||
//Axes
|
||||
// Axes
|
||||
for (int i = 0; i < m_axes_len; i++)
|
||||
{
|
||||
m_axes[i].update();
|
||||
|
@ -98,27 +98,27 @@ void VirtualButton::update()
|
|||
m_released = m_released || m_axes[i].released;
|
||||
}
|
||||
|
||||
//pressed?
|
||||
// pressed?
|
||||
if (m_pressed)
|
||||
{
|
||||
m_repeat_press_time = m_last_press_time = Time::elapsed;
|
||||
m_repeat_press_time = m_last_press_time = Time::seconds;
|
||||
}
|
||||
else if (Time::elapsed - m_last_press_time <= m_press_buffer)
|
||||
else if (Time::seconds - m_last_press_time <= m_press_buffer)
|
||||
{
|
||||
m_pressed = true;
|
||||
}
|
||||
else if (m_down && m_repeat_interval > 0 && Time::elapsed >= m_repeat_press_time + m_repeat_delay)
|
||||
else if (m_down && m_repeat_interval > 0 && Time::seconds >= m_repeat_press_time + m_repeat_delay)
|
||||
{
|
||||
int prev = (int)((Time::previous_elapsed - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
|
||||
int cur = (int)((Time::elapsed - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
|
||||
int prev = (int)((Time::previous_seconds - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
|
||||
int cur = (int)((Time::seconds - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
|
||||
m_pressed = prev < cur;
|
||||
}
|
||||
|
||||
//released?
|
||||
// released?
|
||||
if (m_released)
|
||||
m_last_release_time = Time::elapsed;
|
||||
m_last_release_time = Time::seconds;
|
||||
else
|
||||
m_released = Time::elapsed - m_last_release_time <= m_release_buffer;
|
||||
m_released = Time::seconds - m_last_release_time <= m_release_buffer;
|
||||
}
|
||||
|
||||
void VirtualButton::KeyNode::init(Key key)
|
||||
|
|
|
@ -118,16 +118,16 @@ void VirtualStick::update()
|
|||
if (m_value_i != Point::zero && m_last_value_i != m_value_i)
|
||||
{
|
||||
m_pressed = true;
|
||||
m_last_press_time = m_repeat_press_time = Time::elapsed;
|
||||
m_last_press_time = m_repeat_press_time = Time::seconds;
|
||||
}
|
||||
else if (m_value_i == m_last_value_i && m_value_i != Point::zero)
|
||||
{
|
||||
if (Time::elapsed - m_last_press_time <= m_press_buffer)
|
||||
if (Time::seconds - m_last_press_time <= m_press_buffer)
|
||||
m_pressed = true;
|
||||
else if (m_repeat_interval > 0 && Time::elapsed >= m_repeat_press_time + m_repeat_delay)
|
||||
else if (m_repeat_interval > 0 && Time::seconds >= m_repeat_press_time + m_repeat_delay)
|
||||
{
|
||||
int prev = (int)((Time::previous_elapsed - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
|
||||
int cur = (int)((Time::elapsed - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
|
||||
int prev = (int)((Time::previous_seconds - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
|
||||
int cur = (int)((Time::seconds - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
|
||||
m_pressed = prev < cur;
|
||||
}
|
||||
}
|
||||
|
@ -136,9 +136,9 @@ void VirtualStick::update()
|
|||
if (m_last_value_i != Point::zero && m_value_i != m_last_value_i)
|
||||
{
|
||||
m_released = true;
|
||||
m_last_release_time = Time::elapsed;
|
||||
m_last_release_time = Time::seconds;
|
||||
}
|
||||
else if (Time::elapsed - m_last_release_time <= m_release_buffer)
|
||||
else if (Time::seconds - m_last_release_time <= m_release_buffer)
|
||||
m_released = true;
|
||||
else
|
||||
m_released = false;
|
||||
|
|
|
@ -21,8 +21,8 @@ namespace Blah
|
|||
// Called during shutdown
|
||||
void shutdown();
|
||||
|
||||
// The time, in milliseconds, since the Application was started
|
||||
uint64_t time();
|
||||
// The time, in ticks (microseconds) since the Application was started
|
||||
uint64_t ticks();
|
||||
|
||||
// Called every frame
|
||||
void frame();
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <blah/core/app.h>
|
||||
#include <blah/core/filesystem.h>
|
||||
#include <blah/core/log.h>
|
||||
#include <blah/core/time.h>
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL_vulkan.h>
|
||||
|
@ -170,9 +171,11 @@ void PlatformBackend::shutdown()
|
|||
SDL_Quit();
|
||||
}
|
||||
|
||||
uint64_t PlatformBackend::time()
|
||||
uint64_t PlatformBackend::ticks()
|
||||
{
|
||||
return (uint64_t)SDL_GetTicks();
|
||||
auto counter = SDL_GetPerformanceCounter();
|
||||
auto per_second = (double)SDL_GetPerformanceFrequency();
|
||||
return (uint64_t)(counter * (Time::ticks_per_second / per_second));
|
||||
}
|
||||
|
||||
// Macro defined by X11 conflicts with MouseButton enum
|
||||
|
|
Loading…
Reference in New Issue
Block a user