Crafter.Debug/examples/Basic/implementations/main.cpp

58 lines
2 KiB
C++
Raw Permalink Normal View History

// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
// A headless simulation at 60 ticks a second. The plain build simulates ten
// seconds as fast as it can and prints what happened; the debug build runs in
// real time, serving Crafter.Debug, until an agent says quit.
import std;
import Basic.DebugShim;
import Basic.World;
#ifdef BASIC_DEBUG_API
import Crafter.Thread;
import Basic.DebugCommands;
#endif
namespace Debug = Crafter::Debug;
using Clock = std::chrono::steady_clock;
namespace {
constexpr float dt = 1.0f / 60.0f;
#ifdef BASIC_DEBUG_API
constexpr bool realTime = true;
#else
constexpr bool realTime = false;
#endif
}
int main() {
Basic::World world;
world.Reset();
#ifdef BASIC_DEBUG_API
// The session's transport runs on Crafter.Thread's pool. An app that
// already uses the pool starts it as usual; this one only needs it here.
Crafter::ThreadPool::Start();
Debug::Session debug({ .name = "basic" });
Basic::RegisterDebug(world);
std::println("basic: running; drive it with ./build/crafter-debug, stop it with ./build/crafter-debug quit");
#endif
const auto tick = std::chrono::duration_cast<Clock::duration>(std::chrono::duration<float>(dt));
Clock::time_point next = Clock::now();
while (!Debug::QuitRequested() && (realTime || world.Time() < 10.0)) {
Debug::Pump();
if (Debug::Advance()) world.Tick(dt);
if constexpr (realTime) {
next += tick;
// After a stop in a debugger, carry on from now instead of
// racing to catch up.
if (Clock::now() - next > std::chrono::seconds(1)) next = Clock::now();
std::this_thread::sleep_until(next);
}
}
std::println("basic: {:.1f} s simulated; {} balls, {} below the floor", world.Time(), world.Balls().size(), world.Lost());
for (const Basic::Ball& ball : world.Balls()) {
if (ball.lost) std::println(" ball {} fell through the floor", ball.id);
}
}