9 releases (5 breaking)
| 0.6.0 | Feb 25, 2026 |
|---|---|
| 0.5.0 | Feb 3, 2026 |
| 0.4.0 | Jan 26, 2026 |
| 0.3.1 | Jan 20, 2026 |
| 0.1.6 | Dec 31, 2025 |
#2163 in Game dev
Used in 2 crates
400KB
7.5K
SLoC
bevy_map_runtime
Runtime map loading and rendering for Bevy 0.18 using bevy_ecs_tilemap.
Part of bevy_map_editor.
Features
- Efficient tilemap rendering via bevy_ecs_tilemap 0.18
- Asset-based map loading with hot reload support
- Custom entity spawning with
#[derive(MapEntity)] - Autoloading for animations and dialogues
- Collision integration with Avian2D physics (optional
physicsfeature) - Runtime tile modification
Quick Start
use bevy::prelude::*;
use bevy_map::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(MapRuntimePlugin)
.add_systems(Startup, load_map)
.run();
}
fn load_map(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2d);
commands.spawn(MapHandle(asset_server.load("maps/level.map.json")));
}
Custom Entities
Register entity types to spawn game objects from map data:
use bevy::prelude::*;
use bevy_map::prelude::*;
#[derive(Component, MapEntity)]
#[map_entity(type_name = "Chest")]
pub struct Chest {
#[map_prop]
pub loot_table: String,
#[map_prop(default = false)]
pub locked: bool,
}
// Register in your app builder
App::new()
.add_plugins(MapRuntimePlugin)
.register_map_entity::<Chest>()
// ... other setup
Auto-Loading Animations
Use AnimatedSpriteHandle to autoload sprite animations from a map project:
use bevy::prelude::*;
use bevy_map::prelude::*;
use bevy_map::runtime::AnimatedSpriteHandle;
fn spawn_player(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn((
AnimatedSpriteHandle::new(
asset_server.load("maps/game.map.json"),
"player_sprite",
"idle", // animation name defined in editor
),
Transform::default(),
));
}
Autoloading Dialogues
Use DialogueTreeHandle to auto-load dialogues:
use bevy::prelude::*;
use bevy_map::prelude::*;
use bevy_map::runtime::DialogueTreeHandle;
fn spawn_npc(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(DialogueTreeHandle::new(
asset_server.load("maps/game.map.json"),
"merchant_greeting", // dialogue name defined in editor
));
}
Manual Animation Control
For direct control over sprites, use #[map_sprite]:
#[derive(Component, MapEntity)]
#[map_entity(type_name = "Player")]
pub struct Player {
#[map_prop]
pub speed: f32,
#[map_sprite("player_sprite")]
pub sprite: Option<Handle<Image>>,
}
Collision Integration (Avian2D)
Enable the physics feature to automatically spawn colliders from tile collision data:
bevy_map = { version = "0.1", features = ["physics"] }
use bevy::prelude::*;
use bevy_map::prelude::*;
use bevy_map::runtime::MapCollisionPlugin;
use avian2d::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(MapRuntimePlugin)
.add_plugins(MapCollisionPlugin) // Auto-spawns Avian2D colliders!
.add_plugins(PhysicsPlugins::default())
.add_systems(Startup, load_map)
.run();
}
fn load_map(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2d);
// Collisions are spawned automatically from tile properties!
commands.spawn(MapHandle(asset_server.load("maps/level.map.json")));
}
The MapCollisionPlugin reads collision shapes defined in the tileset editor and spawns corresponding Avian2D Collider components. Query MapCollider to access original collision data.
Entity Type Components (Zero-Code Physics & Input)
Configure physics, input, and sprites at the entity type level in the editor - no Rust code needed!
Automatic Physics
With MapEntityPhysicsPlugin, entities spawn with physics components based on their type configuration:
use bevy::prelude::*;
use bevy_map::prelude::*;
use bevy_map::runtime::{MapEntityPhysicsPlugin, MapCollisionPlugin};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(MapRuntimePlugin)
.add_plugins(MapCollisionPlugin) // Tile colliders
.add_plugins(MapEntityPhysicsPlugin) // Entity physics from type config!
.add_systems(Startup, load_map)
.run();
}
In the Schema Editor, go to the "Components" tab and configure:
- Body Type: Dynamic, Kinematic, or Static
- Collider: Box, Capsule, or Circle with custom dimensions
- Physics properties: Gravity scale, friction, restitution, etc.
Automatic Input
With MapEntityInputPlugin, entities respond to input based on their type configuration:
use bevy::prelude::*;
use bevy_map::prelude::*;
use bevy_map::runtime::{MapEntityInputPlugin, MapEntityPhysicsPlugin};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(MapRuntimePlugin)
.add_plugins(MapEntityPhysicsPlugin) // Physics for movement
.add_plugins(MapEntityInputPlugin) // Input from type config!
.add_systems(Startup, load_map)
.run();
}
Built-in input profiles:
- Platformer: A/D movement, Space to jump
- Top-Down: WASD 8-directional movement
- Twin-Stick: WASD move, mouse aim (marker only)
- Custom: Add your own systems that query the marker component
Automatic Sprites
With MapEntitySpritePlugin, entities spawn with sprites from type configuration:
use bevy::prelude::*;
use bevy_map::prelude::*;
use bevy_map::runtime::MapEntitySpritePlugin;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(MapRuntimePlugin)
.add_plugins(MapEntitySpritePlugin) // Sprites from type config!
.add_systems(Startup, load_map)
.run();
}
In the Schema Editor Components tab, select a sprite sheet and default animation.
Full Zero-Code Setup
For a complete platformer with no entity code:
use bevy::prelude::*;
use bevy_map::prelude::*;
use bevy_map::runtime::{MapCollisionPlugin, MapEntityPhysicsPlugin, MapEntityInputPlugin, MapEntitySpritePlugin};
use avian2d::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(MapRuntimePlugin)
.add_plugins(MapCollisionPlugin) // Tile colliders
.add_plugins(MapEntityPhysicsPlugin) // Entity physics
.add_plugins(MapEntityInputPlugin) // Entity input
.add_plugins(MapEntitySpritePlugin) // Entity sprites
.insert_resource(Gravity(Vec2::new(0.0, -800.0)))
.add_systems(Startup, load_map)
.run();
}
fn load_map(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2d);
commands.spawn(MapHandle(asset_server.load("maps/level.map.json")));
// Player, NPCs, crates - all configured in editor, no code needed!
}
Re-exported Types
For convenience, use bevy_map::prelude::* which includes all commonly used types:
use bevy_map::prelude::*;
// Includes: MapRuntimePlugin, MapHandle, MapEntity, AnimatedSprite,
// DialogueRunner, DialogueTree, and more
License
MIT OR Apache-2.0
Dependencies
~58–98MB
~1.5M SLoC