diff --git a/main.cpp b/main.cpp index 8f7beb9..740098c 100644 --- a/main.cpp +++ b/main.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #ifdef __EMSCRIPTEN__ #include @@ -92,72 +91,14 @@ constexpr auto html2sdl_color(Uint32 rgb) { .a = SDL_ALPHA_OPAQUE }; } -} // namespace -template -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(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 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(newpoint.x), - static_cast(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 +auto loop_fn_emscripten(void* main_loop_body_ptr) { + (*static_cast(main_loop_body_ptr))(); } +} // namespace + int main() try { sdl_check(SDL_Init(SDL_INIT_VIDEO)); Defer 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)); - } + // 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 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(newpoint.x), + static_cast(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, &loopdata, 0, 1); + emscripten_set_main_loop_arg( + loop_fn_emscripten, &main_loop_body, 0, true + ); #else while (continu) { - mainloop(&loopdata); + main_loop_body(); std::this_thread::sleep_until(next_frame_render_time); next_frame_render_time += std::chrono::nanoseconds{16666666}; }