# tinygame-core
`tinygame-core` is a minimal SDL-based runtime core for small game projects.
The crate is built around two ideas:
- a `World` that stores typed resources
- a static `Plugin` lifecycle that drives initialization and frame execution
It intentionally stays small. The goal is to provide the runtime core, not a full engine stack.
## Example
```rust
use tinygame_core::CorePlugin;
tinygame_core::app!(|world| {
world.add_plugin::<CorePlugin>();
});
```
## World
`World` is the shared runtime container.
Plugins use it to:
- insert resources during `init`
- read resources with `get<T>()` / `try_get<T>()`
- mutate resources with `get_mut<T>()` / `try_get_mut<T>()`
Resources are typed and stored once per type.
## Plugin system
Plugins are static types implementing the `Plugin` trait.
Each plugin can define:
- `get_meta()`
- `init(&mut World)`
- `pre_step(&World)`
- `step(&World)`
- `post_step(&World)`
- `exit(&World)`
### Lifecycle
Startup:
1. your setup code adds plugins to the world
2. `run_init()` calls plugin `init` hooks
Frame execution:
1. `pre_step`
2. `step`
3. `post_step`
Shutdown:
1. `exit` hooks run in reverse plugin order
All plugin hooks run on the main thread. `World` is single-threaded by design, and it checks that lifecycle methods are executed from the thread where the world was created.
### Dependencies
Plugins declare dependencies through `PluginMeta`:
```rust
PluginMeta {
name: "render",
depends_on: &["core"],
}
```
Dependencies are checked when plugins are added to the world. Missing dependencies cause a panic during setup.
## CorePlugin
`CorePlugin` is the built-in SDL integration plugin.
It is responsible for:
- initializing SDL during `init`
- inserting the `Core` resource into `World`
- collecting SDL events each frame into `Core::sdl_events`
- calling `SDL_Quit()` on shutdown
`Core` is the main runtime resource exposed by the plugin. Other plugins can read SDL events from it during frame execution.
If you need to customize SDL startup, insert `CoreSettings` before adding `CorePlugin`.
## app! macro
`app!()` generates the SDL callback entrypoints for you.
You only provide setup logic:
```rust
tinygame_core::app!(|world| {
world.add_plugin::<tinygame_core::CorePlugin>();
});
```
That setup closure is where you:
- add plugins
- insert startup configuration/resources
The generated runtime then:
- creates the `World`
- runs plugin init hooks
- dispatches frame hooks
- forwards SDL events into `Core`
## SDL bindings
`tinygame-core` publicly re-exports `sdl3_sys` so external plugins can use the same low-level SDL types.
## Features
The crate forwards a focused set of common SDL build features to `sdl3_sys`.
Default features:
- `sdl-lean-and-mean`
- `build-from-source-static`