tilemap/
tilemap.rs

1use bevy::{prelude::*, render::camera::ScalingMode, utils::HashMap, window::PrimaryWindow};
2use bevy_pixel_map::prelude::*;
3
4use bevy_pixel_map::multi_tile::MultiTile;
5
6#[derive(Default, Resource)]
7pub struct TileResource {
8    image_handles: HashMap<String, Handle<Image>>,
9}
10
11#[derive(Default, Resource)]
12pub struct MousePosResource {
13    pub mouse_pos: Vec2,
14}
15
16pub fn mouse_pos_system(
17    windows: Query<&Window, With<PrimaryWindow>>,
18    cameras: Query<(&Camera, &GlobalTransform)>,
19    mut mouse_pos_resource: ResMut<MousePosResource>,
20) {
21    if let Some(mouse_pos) = windows.single().cursor_position() {
22        let (camera, trans) = cameras.single();
23        let mouse_location = camera.viewport_to_world_2d(trans, mouse_pos).unwrap();
24        mouse_pos_resource.mouse_pos = mouse_location;
25    }
26}
27
28pub fn main() {
29    App::new()
30        .add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest()))
31        .add_plugins(PixelPlugin)
32        .add_systems(Startup, setup_system)
33        .add_systems(Update, (mouse_pos_system, placement_system).chain())
34        .insert_resource(TileResource::default())
35        .insert_resource(MousePosResource::default())
36        .run()
37}
38
39pub fn setup_system(
40    mut commands: Commands,
41    asset_server: Res<AssetServer>,
42    mut tile_resource: ResMut<TileResource>,
43) {
44    let mut camera_bundle = Camera2dBundle::default();
45    camera_bundle.projection.viewport_origin = Vec2::new(0.5, 0.5);
46    camera_bundle.projection.scaling_mode = ScalingMode::WindowSize(25.6);
47    commands.spawn(camera_bundle);
48
49    commands.spawn(TilemapBundle::default());
50
51    let image_resoure = asset_server.load("lightslate.png");
52    tile_resource
53        .image_handles
54        .insert("Lightslate".to_string(), image_resoure);
55}
56
57fn placement_system(
58    mut commands: Commands,
59    mut tilemaps: Query<&mut Tilemap>,
60    input: Res<Input<MouseButton>>,
61    keys: Res<Input<KeyCode>>,
62    mouse_pos_resource: Res<MousePosResource>,
63
64    images: Res<Assets<Image>>,
65    tile_resource: Res<TileResource>,
66) {
67    // Now convert to tile coords.
68    let (tile_coord, pixel_coord) = world_unit_to_pixel(mouse_pos_resource.mouse_pos);
69
70    if input.pressed(MouseButton::Left) {
71        let image = images
72            .get(tile_resource.image_handles.get("Lightslate").unwrap())
73            .unwrap();
74        // Set the tile at that location
75        tilemaps.single_mut().set_tile(
76            &mut commands,
77            tile_coord,
78            Tile::from_image(image, (16..24, 16..24)),
79            (),
80        );
81    }
82
83    if input.pressed(MouseButton::Right) {
84        tilemaps.single_mut().delete_tile(tile_coord);
85    }
86
87    if keys.pressed(KeyCode::P) {
88        // Set the tile's pixel to red
89        tilemaps
90            .single_mut()
91            .set_pixel(tile_coord, pixel_coord, Color::RED);
92    }
93
94    if keys.pressed(KeyCode::M) {
95        // Remove the tile at that location
96        let image = images
97            .get(tile_resource.image_handles.get("Lightslate").unwrap())
98            .unwrap();
99
100        let tile = MultiTile::from_image(image);
101        tile.place(tile_coord, &mut tilemaps.single_mut(), &mut commands);
102    }
103}