#include #include #include /// At time/frame 0: /// 1. An initial render is always triggered. /// 2. No update is triggered (not enough time passed). TEST_CASE(simloop_initial_render) { Timer timer = {}; Simloop simloop = simloop_make( &(SimloopArgs){.update_fps = 10, .max_render_fps = 0, .timer = &timer}); SimloopOut simout; simloop_update(&simloop, &simout); TEST_TRUE(simout.should_render); TEST_TRUE(!simout.should_update); TEST_EQUAL(simout.frame, 0); } /// The initial render is not re-triggered if there is a render frame rate cap /// and time does not advance. TEST_CASE(simloop_initial_render_not_retriggered) { Timer timer = {}; Simloop simloop = simloop_make( &(SimloopArgs){.update_fps = 10, .max_render_fps = 10, .timer = &timer}); SimloopOut simout; simloop_update(&simloop, &simout); TEST_TRUE(simout.should_render); TEST_TRUE(!simout.should_update); TEST_EQUAL(simout.frame, 0); for (int i = 0; i < 10; i++) { // Note that time does not advance. simloop_update(&simloop, &simout); TEST_TRUE(!simout.should_render); TEST_TRUE(!simout.should_update); TEST_EQUAL(simout.frame, 0); } } /// A simulation loop with no render frame cap: /// 1. Updates based on the desired update frame rate. /// 2. Renders at every loop. TEST_CASE(simloop_no_render_frame_cap) { constexpr int UPDATE_FPS = 10; const time_delta EXPECT_UPDATE = sec_to_time_delta(1.0 / (double)UPDATE_FPS); const time_delta STEP = sec_to_time_delta(1); const time_delta SIM_TIME_SEC = sec_to_time_delta(30); Timer timer = {}; Simloop simloop = simloop_make(&(SimloopArgs){ .update_fps = UPDATE_FPS, .max_render_fps = 0, .timer = &timer}); SimloopOut simout; for (time_delta t = 0; t < SIM_TIME_SEC; t += STEP) { timer_advance(&timer, t); simloop_update(&simloop, &simout); TEST_TRUE(simout.should_render); TEST_EQUAL((t > 0) && ((t % EXPECT_UPDATE) == 0), simout.should_update); } } /// A simulation loop with a render frame cap: /// 1. Updates based on the desired update frame rate. /// 2. Renders based on the desired render frame rate. TEST_CASE(simloop_with_render_frame_cap) { constexpr int UPDATE_FPS = 10; constexpr int RENDER_FPS = 5; const time_delta EXPECT_UPDATE = sec_to_time_delta(1.0 / (double)UPDATE_FPS); const time_delta EXPECT_RENDER = sec_to_time_delta(1.0 / (double)RENDER_FPS); const time_delta STEP = sec_to_time_delta(0.1); const time_delta SIM_TIME_SEC = sec_to_time_delta(30); Timer timer = {}; Simloop simloop = simloop_make(&(SimloopArgs){ .update_fps = UPDATE_FPS, .max_render_fps = RENDER_FPS, .timer = &timer}); SimloopOut simout; for (time_delta t = 0; t < SIM_TIME_SEC; t += STEP) { timer_advance(&timer, t); simloop_update(&simloop, &simout); // Also expecting initial render at t=0. TEST_EQUAL((t % EXPECT_RENDER) == 0, simout.should_render); TEST_EQUAL((t > 0) && ((t % EXPECT_UPDATE) == 0), simout.should_update); } } int main() { return 0; }