// SPDX-License-Identifier: MIT // SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts® // Balls dropped onto a floor slab, in two dimensions, at a fixed step. y is // up, in metres; the slab's top is at floor.top and it is floor.thickness // thick. export module Basic.World; import std; export namespace Basic { struct Ball { std::int32_t id = 0; float x = 0; float y = 0; float vx = 0; float vy = 0; float radius = 0.1f; // Below the floor, and so out of the scene for good. bool lost = false; }; struct Physics { float gravity = -9.81f; // The share of its speed a ball keeps when it bounces. float restitution = 0.6f; // Collision checks per tick. std::int32_t substeps = 1; }; struct Floor { float top = 0; float thickness = 0.1f; }; // What `wait --event Bounce` waits for, sent for bounces faster than 1 m/s. struct BounceEvent { std::int32_t ball = 0; float speed = 0; }; class World { public: Physics physics; Floor floor; // Removes every ball and drops the scene's five, as balls 1 to 5. void Reset(); // Removes every ball; ids start again from 1. void Clear(); // Returns the new ball's id. std::int32_t Spawn(float x, float y, float vy, float radius); void Tick(float dt); const std::deque& Balls() const { return balls; } const Ball* Find(std::int32_t id) const; double Time() const { return time; } std::int32_t Lost() const; // The fastest ball's speed in the last tick, in m/s. float Fastest() const { return fastest; } private: std::deque balls; std::int32_t nextId = 1; double time = 0; float fastest = 0; }; }