refactor emscripten loop function as lambda
took inspiration from
d9b758661f/examples/libs/emscripten/emscripten_mainloop_stub.h
This commit is contained in:
parent
2c24a938c5
commit
552d11ef86
1 changed files with 80 additions and 75 deletions
149
main.cpp
149
main.cpp
|
@ -11,7 +11,6 @@
|
|||
#include <random>
|
||||
#include <source_location>
|
||||
#include <stdexcept>
|
||||
#include <thread>
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten.h>
|
||||
|
@ -92,72 +91,14 @@ constexpr auto html2sdl_color(Uint32 rgb) {
|
|||
.a = SDL_ALPHA_OPAQUE
|
||||
};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template <typename Loopdata>
|
||||
void mainloop(void* userData) {
|
||||
constexpr SDL_Point directions[] = {
|
||||
{.x = -1, .y = 0}, {.x = 1, .y = 0}, {.x = 0, .y = -1}, {.x = 0, .y = 1}
|
||||
};
|
||||
auto& [renderer, texture, walkers, rne, dist, start_time, total_steps, next_poll_events_time, next_frame_render_time, frame_start, frame_time, continu] =
|
||||
*static_cast<Loopdata*>(userData);
|
||||
|
||||
// measure frame_time
|
||||
const auto now = clock::now();
|
||||
frame_time = now - frame_start;
|
||||
frame_start = now;
|
||||
|
||||
// possibly poll events
|
||||
if (now >= next_poll_events_time) {
|
||||
next_poll_events_time = now + std::chrono::milliseconds{20};
|
||||
poll_events(continu);
|
||||
}
|
||||
|
||||
// simulate steps for passed time //
|
||||
// roughly make a batch for every millisecond
|
||||
constexpr auto batchsize =
|
||||
std::clamp(steps_per_second / 1000 /*ms*/, 1, 1000);
|
||||
const auto total_time = now - start_time;
|
||||
const auto target_total_steps = total_time * steps_per_second /
|
||||
clock::duration{std::chrono::seconds{1}};
|
||||
for (; total_steps + batchsize <= target_total_steps;
|
||||
total_steps += batchsize) {
|
||||
sdl_check(SDL_SetRenderTarget(renderer, texture));
|
||||
sdl_check(SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND));
|
||||
for (auto& walker : walkers) {
|
||||
sdl_check(SDL_SetRenderDrawColor(
|
||||
renderer, walker.col.r, walker.col.g, walker.col.b, walker.col.a
|
||||
));
|
||||
std::array<SDL_FPoint, batchsize> point_batch;
|
||||
for (auto step = 0z; step < batchsize; ++step) {
|
||||
SDL_Point newpoint;
|
||||
do {
|
||||
newpoint = walker.pos + directions[dist(rne)];
|
||||
} while (newpoint.x < 0 or newpoint.x >= width or
|
||||
newpoint.y < 0 or newpoint.y >= height);
|
||||
walker.pos = newpoint;
|
||||
point_batch[step] = SDL_FPoint{
|
||||
static_cast<float>(newpoint.x),
|
||||
static_cast<float>(newpoint.y)
|
||||
};
|
||||
}
|
||||
sdl_check(SDL_RenderPoints(
|
||||
renderer, point_batch.data(), point_batch.size()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
///// Render screen
|
||||
sdl_check(SDL_SetRenderTarget(renderer, nullptr));
|
||||
sdl_check(
|
||||
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE)
|
||||
);
|
||||
SDL_RenderClear(renderer);
|
||||
sdl_check(SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE));
|
||||
sdl_check(SDL_RenderTexture(renderer, texture, nullptr, nullptr));
|
||||
SDL_RenderPresent(renderer);
|
||||
template <typename F>
|
||||
auto loop_fn_emscripten(void* main_loop_body_ptr) {
|
||||
(*static_cast<F*>(main_loop_body_ptr))();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main() try {
|
||||
sdl_check(SDL_Init(SDL_INIT_VIDEO));
|
||||
Defer<SDL_Quit> defer_SDL_Quit;
|
||||
|
@ -170,10 +111,8 @@ int main() try {
|
|||
sdl_check(window_.get());
|
||||
auto* renderer = sdl_check(renderer_.get());
|
||||
|
||||
{
|
||||
// dump renderer info
|
||||
std::println("Renderer name: {}", SDL_GetRendererName(renderer));
|
||||
}
|
||||
|
||||
// no clue who owns this
|
||||
auto* texture = SDL_CreateTexture(
|
||||
|
@ -213,18 +152,84 @@ int main() try {
|
|||
auto frame_start = start_time;
|
||||
auto total_steps = 0ll;
|
||||
clock::duration frame_time;
|
||||
auto loopdata = std::tie(
|
||||
renderer, texture, walkers, rne, dist, start_time, total_steps,
|
||||
next_poll_events_time, next_frame_render_time, frame_start, frame_time,
|
||||
continu
|
||||
|
||||
auto main_loop_body = [&] {
|
||||
constexpr SDL_Point directions[] = {
|
||||
{.x = -1, .y = 0},
|
||||
{.x = 1, .y = 0},
|
||||
{.x = 0, .y = -1},
|
||||
{.x = 0, .y = 1}
|
||||
};
|
||||
// measure frame_time
|
||||
const auto now = clock::now();
|
||||
frame_time = now - frame_start;
|
||||
frame_start = now;
|
||||
|
||||
// possibly poll events
|
||||
if (now >= next_poll_events_time) {
|
||||
next_poll_events_time = now + std::chrono::milliseconds{20};
|
||||
poll_events(continu);
|
||||
}
|
||||
|
||||
// simulate steps for passed time //
|
||||
// roughly make a batch for every millisecond
|
||||
constexpr auto batchsize =
|
||||
std::clamp(steps_per_second / 1000 /*ms*/, 1, 1000);
|
||||
const auto total_time = now - start_time;
|
||||
const auto target_total_steps =
|
||||
total_time * steps_per_second /
|
||||
clock::duration{std::chrono::seconds{1}};
|
||||
for (; total_steps + batchsize <= target_total_steps;
|
||||
total_steps += batchsize) {
|
||||
sdl_check(SDL_SetRenderTarget(renderer, texture));
|
||||
sdl_check(
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND)
|
||||
);
|
||||
for (auto& walker : walkers) {
|
||||
sdl_check(SDL_SetRenderDrawColor(
|
||||
renderer, walker.col.r, walker.col.g, walker.col.b,
|
||||
walker.col.a
|
||||
));
|
||||
std::array<SDL_FPoint, batchsize> point_batch;
|
||||
for (auto step = 0z; step < batchsize; ++step) {
|
||||
SDL_Point newpoint;
|
||||
do {
|
||||
newpoint = walker.pos + directions[dist(rne)];
|
||||
} while (newpoint.x < 0 or newpoint.x >= width or
|
||||
newpoint.y < 0 or newpoint.y >= height);
|
||||
walker.pos = newpoint;
|
||||
point_batch[step] = SDL_FPoint{
|
||||
static_cast<float>(newpoint.x),
|
||||
static_cast<float>(newpoint.y)
|
||||
};
|
||||
}
|
||||
sdl_check(SDL_RenderPoints(
|
||||
renderer, point_batch.data(), point_batch.size()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
///// Render screen
|
||||
sdl_check(SDL_SetRenderTarget(renderer, nullptr));
|
||||
sdl_check(
|
||||
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE)
|
||||
);
|
||||
SDL_RenderClear(renderer);
|
||||
sdl_check(SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE));
|
||||
sdl_check(SDL_RenderTexture(renderer, texture, nullptr, nullptr));
|
||||
SDL_RenderPresent(renderer);
|
||||
};
|
||||
|
||||
std::puts("initialization complete");
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
// Receives a function to call and some user data to provide it.
|
||||
emscripten_set_main_loop_arg(mainloop<decltype(loopdata)>, &loopdata, 0, 1);
|
||||
emscripten_set_main_loop_arg(
|
||||
loop_fn_emscripten<decltype(main_loop_body)>, &main_loop_body, 0, true
|
||||
);
|
||||
#else
|
||||
while (continu) {
|
||||
mainloop<decltype(loopdata)>(&loopdata);
|
||||
main_loop_body();
|
||||
std::this_thread::sleep_until(next_frame_render_time);
|
||||
next_frame_render_time += std::chrono::nanoseconds{16666666};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue