File size: 2,705 Bytes
3ce1a40 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | #pragma once
#include <cstdint>
#include <string>
#include "../render/render.h"
#include "../audio/audio.h"
#include "../input/input.h"
namespace unify {
struct EngineConfig {
std::string title = "UNIFY";
int width = 640, height = 360;
uint32_t tick_rate = 60;
uint64_t seed = 1;
std::string asset_root = "assets";
std::string boot_scene = "title";
size_t lua_memory_limit = 64u << 20;
int lua_gc_budget_kb = 32;
int max_ticks_per_frame = 8; // beyond this the sim drops time instead of spiralling
};
/// Platform backend. UNIFY talks to the platform only through this interface; gameplay
/// never sees it. Implementations: Headless (engine), SDL2 (backends/sdl), Unreal
/// (backends/unreal). A backend supplies a render device, an audio device, input events
/// stamped on its clock, and presentation of finished frames.
class Backend {
public:
virtual ~Backend() = default;
virtual const char* name() const = 0;
virtual bool init(const EngineConfig& config, std::string& error) = 0;
virtual RenderDevice& render_device() = 0;
virtual AudioDevice& audio_device() = 0;
/// Pushes pending OS events into `input`, timestamped with now_ns(). Sets quit on close.
virtual void poll(InputSystem& input, bool& quit) = 0;
virtual void present(const RenderTarget& frame) = 0;
/// Monotonic platform clock (the input clock). Nondeterministic; never visible to gameplay.
virtual uint64_t now_ns() = 0;
virtual void shutdown() = 0;
};
/// Offscreen backend: software rendering, null audio device, programmatic input and a
/// controllable clock. Used for tests, CI, replays and servers.
class HeadlessBackend : public Backend {
public:
const char* name() const override { return "headless"; }
bool init(const EngineConfig&, std::string&) override { return true; }
RenderDevice& render_device() override { return device_; }
AudioDevice& audio_device() override { return audio_; }
void poll(InputSystem&, bool& quit) override { quit = quit_; }
void present(const RenderTarget& frame) override { last_frame_ = frame.color; presented_++; }
uint64_t now_ns() override { return clock_ns_; }
void shutdown() override { audio_.stop(); }
void advance_clock(uint64_t ns) { clock_ns_ += ns; }
void set_clock(uint64_t ns) { clock_ns_ = ns; }
void request_quit() { quit_ = true; }
const Image& last_frame() const { return last_frame_; }
uint64_t presented() const { return presented_; }
private:
SoftwareRenderDevice device_;
NullAudioDevice audio_;
uint64_t clock_ns_ = 0;
bool quit_ = false;
Image last_frame_;
uint64_t presented_ = 0;
};
} // namespace unify
|