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 <random>
|
||||||
#include <source_location>
|
#include <source_location>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
#include <emscripten.h>
|
#include <emscripten.h>
|
||||||
|
@ -92,72 +91,14 @@ constexpr auto html2sdl_color(Uint32 rgb) {
|
||||||
.a = SDL_ALPHA_OPAQUE
|
.a = SDL_ALPHA_OPAQUE
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} // namespace
|
|
||||||
|
|
||||||
template <typename Loopdata>
|
template <typename F>
|
||||||
void mainloop(void* userData) {
|
auto loop_fn_emscripten(void* main_loop_body_ptr) {
|
||||||
constexpr SDL_Point directions[] = {
|
(*static_cast<F*>(main_loop_body_ptr))();
|
||||||
{.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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
int main() try {
|
int main() try {
|
||||||
sdl_check(SDL_Init(SDL_INIT_VIDEO));
|
sdl_check(SDL_Init(SDL_INIT_VIDEO));
|
||||||
Defer<SDL_Quit> defer_SDL_Quit;
|
Defer<SDL_Quit> defer_SDL_Quit;
|
||||||
|
@ -170,10 +111,8 @@ int main() try {
|
||||||
sdl_check(window_.get());
|
sdl_check(window_.get());
|
||||||
auto* renderer = sdl_check(renderer_.get());
|
auto* renderer = sdl_check(renderer_.get());
|
||||||
|
|
||||||
{
|
|
||||||
// dump renderer info
|
// dump renderer info
|
||||||
std::println("Renderer name: {}", SDL_GetRendererName(renderer));
|
std::println("Renderer name: {}", SDL_GetRendererName(renderer));
|
||||||
}
|
|
||||||
|
|
||||||
// no clue who owns this
|
// no clue who owns this
|
||||||
auto* texture = SDL_CreateTexture(
|
auto* texture = SDL_CreateTexture(
|
||||||
|
@ -213,18 +152,84 @@ int main() try {
|
||||||
auto frame_start = start_time;
|
auto frame_start = start_time;
|
||||||
auto total_steps = 0ll;
|
auto total_steps = 0ll;
|
||||||
clock::duration frame_time;
|
clock::duration frame_time;
|
||||||
auto loopdata = std::tie(
|
|
||||||
renderer, texture, walkers, rne, dist, start_time, total_steps,
|
auto main_loop_body = [&] {
|
||||||
next_poll_events_time, next_frame_render_time, frame_start, frame_time,
|
constexpr SDL_Point directions[] = {
|
||||||
continu
|
{.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");
|
std::puts("initialization complete");
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
// Receives a function to call and some user data to provide it.
|
// 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
|
#else
|
||||||
while (continu) {
|
while (continu) {
|
||||||
mainloop<decltype(loopdata)>(&loopdata);
|
main_loop_body();
|
||||||
std::this_thread::sleep_until(next_frame_render_time);
|
std::this_thread::sleep_until(next_frame_render_time);
|
||||||
next_frame_render_time += std::chrono::nanoseconds{16666666};
|
next_frame_render_time += std::chrono::nanoseconds{16666666};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue