# bevy_a5
[](https://crates.io/crates/bevy_a5)
[](https://docs.rs/bevy_a5)
[](LICENSE)
A Bevy plugin that puts the [A5](https://github.com/felixpalmer/a5)
pentagonal cell hierarchy under your game world. `bevy_a5` is to spherical
games what [`big_space`](https://docs.rs/big_space) is to deep-space games:
the same floating-origin precision pattern, but the cell space is the
surface of a planet instead of an integer Cartesian grid.
## What you get
- **Cell-anchored coordinates.** Every entity is `(GeoCell, Transform)` —
*which* A5 cell, plus a small offset within that cell. Float precision
stays tight even when the underlying world position is on the other side
of the planet.
- **Floating-origin recentre.** Walk past `recenter_threshold` and the
plugin shifts the origin to a neighbouring cell, rebasing both
translation and rotation so the world-space pose is unchanged.
Recentres are visually invisible.
- **A5 spatial queries.** `grid_disk`, `vertex_neighbors`, `spherical_cap`,
`compact`/`uncompact` — none of which a Cartesian grid can give you on a
sphere. All return uniform-resolution cell sets by design (tested
invariant).
- **Cell → entity index.** `CellEntityIndex` maintained by an observer-style
system on `Changed<GeoCell>`; `O(1)` "what entities are in cell X?"
lookup, `SmallVec`-backed buckets to avoid heap-allocation churn.
- **Display helpers.** `build_grid_line_mesh(cells, radius) -> Mesh` for
one-call wireframe grids; `DrawCellOutline` marker for ad-hoc per-entity
cell debugging via gizmos.
- **Reusable fly camera.** `FlyCam` component + `CameraPlugin` lifted from
the duplicated example boilerplate, ready to drop on a `Camera3d`.
## Install
```toml
[dependencies]
bevy = "0.18"
bevy_a5 = "0.1"
```
Bevy 0.18 is the supported version.
## Quick start
```rust
use bevy::prelude::*;
use bevy_a5::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(BevyA5Plugins) // core + camera + cell hash
.insert_resource(PlanetSettings::earth())
.add_systems(Startup, setup)
.run();
}
fn setup(mut commands: Commands) {
// Spawn the floating-origin camera at Paris.
let here = GeoCell::from_lon_lat(2.3522, 48.8566, 9).unwrap();
commands.spawn_floating_origin(here).insert((
Camera3d::default(),
FlyCam::default(),
Transform::from_xyz(0.0, 5.0, 0.0).looking_at(Vec3::ZERO, Vec3::Y),
));
// Place an entity at a neighbouring cell's centre.
let neighbour = GeoCell::from_lon_lat(2.3525, 48.8570, 9).unwrap();
commands.spawn_cell_anchor(neighbour);
}
```
## Examples
```bash
cargo run --example planet_grid # Whole-planet wireframe, fly camera
cargo run --example overhead_map # Top-down map of Paris with slippy tiles
cargo run --example flock # Spatial-query demo: brownian flock + neighbour highlighting
cargo run --example cell_origin # Live cell / heading / position HUD on the planet grid
```
`overhead_map` and `flock` cache OSM tiles under `assets/tiles/`. The first
run needs network; subsequent runs hit the cache.
## When to use it (and when not to)
`bevy_a5` makes sense if your game world is **the surface of a sphere**
(Earth, a moon, a fictional planet) and you need consistent positioning at
metre precision across the whole surface, with topologically correct
neighbour lookups (no pole singularity, no longitude-180 seam).
If your world is **flat**, use `big_space` (Cartesian high-precision) or
just plain Bevy `Transform`s — they're faster and simpler. The
[`benches/spatial_index.rs`](benches/spatial_index.rs) bench quantifies
the cost difference: on flat ground, a `(i32, i32)`-tile index is ~30–100×
faster than the A5 equivalent. You're paying for spherical correctness;
don't pay for it on a plane.
## Status
`0.1.0` — pre-release. The public API is stable enough to build against,
but expect breakage at minor versions until 1.0:
- [x] Floating-origin recentre (big-space style — origin always renders at world `(0, 0, 0)`)
- [x] Vertex-aligned cell-local frame (`-Z` toward first boundary vertex)
- [x] Spatial queries with uniform-resolution invariant
- [x] `CellEntityIndex` spatial hash
- [x] `CellTracker` temporal-coherence helper for user-driven movement
- [x] Reusable `FlyCam`
- [x] Adaptive slippy-tile zoom in the `overhead_map` example
- [x] `criterion` benchmark vs Bevy's observers-style cartesian index
- [ ] Multi-planet support (one `Planet` per root entity — currently single global `PlanetSettings`)
- [ ] Multi-`FloatingOrigin` (split-screen / networked players)
- [ ] Observer-based `CellEntityIndex` maintenance for instant reactivity
## License
MIT — see [`LICENSE`](LICENSE).