bones_render/
tilemap.rs

1//! Tile map rendering components.
2
3use crate::prelude::*;
4
5/// A tilemap layer component.
6#[derive(Clone, Debug, TypeUlid)]
7#[ulid = "01GNF7SRDRN4K8HPW32JAHKMX1"]
8pub struct TileLayer {
9    /// The vector of tile slots in this layer.
10    pub tiles: Vec<Option<Entity>>,
11    /// The size of the layer in tiles.
12    pub grid_size: UVec2,
13    /// The size of each tile in the layer.
14    pub tile_size: Vec2,
15    /// The texture atlas to use for the layer
16    pub atlas: Handle<Atlas>,
17}
18
19/// A tilemap tile component.
20#[derive(Clone, Debug, TypeUlid, Default)]
21#[ulid = "01GNZHDZV61TFPEE4GDJY4SRAM"]
22pub struct Tile {
23    /// The tile index in the tilemap texture.
24    pub idx: usize,
25    /// Whether or not to flip the tile horizontally.
26    pub flip_x: bool,
27    /// Whether or not to flip tile vertically.
28    pub flip_y: bool,
29}
30
31impl TileLayer {
32    /// Create a new tile layer
33    pub fn new(grid_size: UVec2, tile_size: Vec2, atlas: Handle<Atlas>) -> Self {
34        let tile_count = (grid_size.x * grid_size.y) as usize;
35        let mut tiles = Vec::with_capacity(tile_count);
36        for _ in 0..tile_count {
37            tiles.push(None);
38        }
39        Self {
40            tiles,
41            grid_size,
42            tile_size,
43            atlas,
44        }
45    }
46
47    #[inline]
48    fn idx(&self, pos: UVec2) -> Option<usize> {
49        let idx = self.grid_size.x as i32 * pos.y as i32 + pos.x as i32;
50        idx.try_into().ok()
51    }
52
53    /// Get's the tile at the given position in the layer, indexed with the bottom-left of the layer
54    /// being (0, 0).
55    pub fn get(&self, pos: UVec2) -> Option<Entity> {
56        self.idx(pos)
57            .and_then(|idx| self.tiles.get(idx).cloned().flatten())
58    }
59
60    /// Set the tile at the given position, to a certain entity.
61    pub fn set(&mut self, pos: UVec2, entity: Option<Entity>) {
62        let idx = self.idx(pos).expect("Tile pos out of bounds");
63        *self.tiles.get_mut(idx).unwrap_or_else(|| {
64            panic!(
65                "Tile pos out of range of tile size: pos {:?} size {:?}",
66                pos, self.grid_size
67            )
68        }) = entity;
69    }
70}