framerate independent walker speed

This commit is contained in:
Jakob Hördt 2024-08-07 23:22:26 +02:00
parent 47bca440d3
commit 9c58521ec6
2 changed files with 51 additions and 50 deletions

View file

@ -1,2 +1,2 @@
#!/bin/bash #!/bin/bash
/usr/lib/emscripten/em++ -std=c++26 --use-port=sdl2 -O2 --emrun --shell-file emscripten_shell.html -sASSERTIONS -o index.html main.cpp /usr/lib/emscripten/em++ -std=c++26 --use-port=sdl2 -O2 --shell-file emscripten_shell.html -sASSERTIONS -o index.html main.cpp

View file

@ -2,6 +2,7 @@
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <array>
#include <chrono> #include <chrono>
#include <format> #include <format>
#include <memory> #include <memory>
@ -59,11 +60,11 @@ auto operator+(SDL_Point a, SDL_Point b) {
return SDL_Point{.x = a.x + b.x, .y = a.y + b.y}; return SDL_Point{.x = a.x + b.x, .y = a.y + b.y};
} }
using clock = std::chrono::steady_clock;
constexpr int width = 1000; constexpr int width = 1000;
constexpr int height = 500; constexpr int height = 500;
constexpr auto steps_per_second = 3;
// constexpr int width = 3440;
// constexpr int height = 1440;
template <auto EF> template <auto EF>
struct [[nodiscard("give this a name so SDL_Quit is called at the end" struct [[nodiscard("give this a name so SDL_Quit is called at the end"
@ -77,8 +78,6 @@ struct [[nodiscard("give this a name so SDL_Quit is called at the end"
~Defer() { EF(); } ~Defer() { EF(); }
}; };
using clock = std::chrono::steady_clock;
auto poll_events(bool& continu) { auto poll_events(bool& continu) {
for (SDL_Event e; SDL_PollEvent(&e);) { for (SDL_Event e; SDL_PollEvent(&e);) {
if (e.type == SDL_QUIT) { continu = false; } if (e.type == SDL_QUIT) { continu = false; }
@ -91,8 +90,8 @@ void mainloop(void* userData) {
constexpr SDL_Point directions[] = { constexpr SDL_Point directions[] = {
{.x = -1, .y = 0}, {.x = 1, .y = 0}, {.x = 0, .y = -1}, {.x = 0, .y = 1} {.x = -1, .y = 0}, {.x = 1, .y = 0}, {.x = 0, .y = -1}, {.x = 0, .y = 1}
}; };
constexpr auto batchsize = 1000; constexpr auto batchsize = 1;
auto& [renderer, texture, pos, pos1, rne, dist, start_time, next_poll_events_time, next_frame_render_time, frame_start, frame_time, continu] = auto& [renderer, texture, pos, pos1, rne, dist, start_time, total_steps, next_poll_events_time, next_frame_render_time, frame_start, frame_time, continu] =
*static_cast<Loopdata*>(userData); *static_cast<Loopdata*>(userData);
// measure frame_time // measure frame_time
@ -100,53 +99,55 @@ void mainloop(void* userData) {
frame_time = now - frame_start; frame_time = now - frame_start;
frame_start = now; frame_start = now;
// possibly poll events
if (now >= next_poll_events_time) { if (now >= next_poll_events_time) {
next_poll_events_time = now + std::chrono::milliseconds{200}; next_poll_events_time = now + std::chrono::milliseconds{200};
poll_events(continu); poll_events(continu);
std::println("last frame_time={} batchsize={}", frame_time, batchsize);
} }
std::array<SDL_Point, batchsize> point_batch; // simulate steps for passed time
for (auto step = 0z; step < batchsize; ++step) { const auto total_time = now - start_time;
SDL_Point newpoint; const auto target_total_steps = total_time * steps_per_second /
do { clock::duration{std::chrono::seconds{1}};
newpoint = pos + directions[dist(rne)]; std::print(
} while (newpoint.x < 0 or newpoint.x >= width or newpoint.y < 0 or "total_time={} total_steps={} target={}\r", total_time, total_steps,
newpoint.y >= height); target_total_steps
pos = newpoint; );
point_batch[step] = newpoint;
}
///// Render image for (; total_steps + batchsize <= target_total_steps;
sdl_check(SDL_SetRenderTarget(renderer, texture)); total_steps += batchsize) {
sdl_check(SDL_SetRenderDrawBlendMode( std::array<SDL_Point, batchsize> point_batch;
renderer, for (auto step = 0z; step < batchsize; ++step) {
SDL_ComposeCustomBlendMode( SDL_Point newpoint;
SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, do {
SDL_BLENDOPERATION_ADD, SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE, newpoint = pos + directions[dist(rne)];
SDL_BLENDOPERATION_ADD } while (newpoint.x < 0 or newpoint.x >= width or newpoint.y < 0 or
) newpoint.y >= height);
)); pos = newpoint;
sdl_check(SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 32)); point_batch[step] = newpoint;
sdl_check( }
SDL_RenderDrawPoints(renderer, point_batch.data(), point_batch.size())
); ///// Render image
for (auto step = 0z; step < batchsize; ++step) { sdl_check(SDL_SetRenderTarget(renderer, texture));
SDL_Point newpoint; sdl_check(SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND));
do { sdl_check(SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xff));
newpoint = pos1 + directions[dist(rne)]; sdl_check(SDL_RenderDrawPoints(
} while (newpoint.x < 0 or newpoint.x >= width or newpoint.y < 0 or renderer, point_batch.data(), point_batch.size()
newpoint.y >= height); ));
pos1 = newpoint; for (auto step = 0z; step < batchsize; ++step) {
point_batch[step] = newpoint; SDL_Point newpoint;
do {
newpoint = pos1 + directions[dist(rne)];
} while (newpoint.x < 0 or newpoint.x >= width or newpoint.y < 0 or
newpoint.y >= height);
pos1 = newpoint;
point_batch[step] = newpoint;
}
sdl_check(SDL_SetRenderDrawColor(renderer, 0xff, 0xff, 0xff, 0xff));
sdl_check(SDL_RenderDrawPoints(
renderer, point_batch.data(), point_batch.size()
));
} }
sdl_check(SDL_SetRenderDrawColor(renderer, 0xff, 0xff, 0xff, 32));
sdl_check(
SDL_RenderDrawPoints(renderer, point_batch.data(), point_batch.size())
);
// sdl_check(SDL_SetRenderDrawColor(renderer, 0xff, 0xff, 0xff,
// 32)); sdl_check(SDL_RenderFillRect(renderer, nullptr));
// SDL_RenderCopy(renderer, fade_texture, nullptr, nullptr);
///// Render screen ///// Render screen
sdl_check(SDL_SetRenderTarget(renderer, nullptr)); sdl_check(SDL_SetRenderTarget(renderer, nullptr));
@ -155,7 +156,6 @@ void mainloop(void* userData) {
); );
SDL_RenderClear(renderer); SDL_RenderClear(renderer);
sdl_check(SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE)); sdl_check(SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE));
// sdl_check(SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_NONE));
sdl_check(SDL_RenderCopy(renderer, texture, nullptr, nullptr)); sdl_check(SDL_RenderCopy(renderer, texture, nullptr, nullptr));
SDL_RenderPresent(renderer); SDL_RenderPresent(renderer);
} }
@ -204,9 +204,10 @@ int main() try {
auto next_poll_events_time = start_time; auto next_poll_events_time = start_time;
auto next_frame_render_time = start_time; auto next_frame_render_time = start_time;
auto frame_start = start_time; auto frame_start = start_time;
auto total_steps = 0ll;
clock::duration frame_time; clock::duration frame_time;
auto loopdata = std::tie( auto loopdata = std::tie(
renderer, texture, pos, pos1, rne, dist, start_time, renderer, texture, pos, pos1, rne, dist, start_time, total_steps,
next_poll_events_time, next_frame_render_time, frame_start, frame_time, next_poll_events_time, next_frame_render_time, frame_start, frame_time,
continu continu
); );