bevy_pixel_map/
tile.rs

1use std::ops::Range;
2
3use bevy::prelude::{Bundle, Color, Component, IVec2, Image, Transform};
4
5use crate::TILE_SIZE;
6
7#[derive(Component)]
8pub struct DeletingTile;
9
10#[derive(Bundle)]
11pub struct TileBundle {
12    transform: Transform,
13    tile: Tile,
14}
15
16impl TileBundle {
17    pub fn new(tile: Tile, location: IVec2) -> Self {
18        Self {
19            tile,
20            transform: Transform::from_xyz(location.x as f32, location.y as f32, 0.0),
21        }
22    }
23}
24
25#[derive(Component, Debug, Clone, PartialEq)]
26pub struct Tile {
27    pub(crate) pixels: [[Color; TILE_SIZE]; TILE_SIZE],
28}
29
30impl Tile {
31    pub fn from_color(color: Color) -> Self {
32        Self {
33            pixels: [[color; TILE_SIZE]; TILE_SIZE],
34        }
35    }
36
37    pub fn from_pixels(pixels: [[Color; TILE_SIZE]; TILE_SIZE]) -> Self {
38        Self { pixels }
39    }
40
41    pub fn from_image(image: &Image, pixel_range: (Range<usize>, Range<usize>)) -> Self {
42        let mut colors = [[Color::NONE; TILE_SIZE]; TILE_SIZE];
43
44        assert_eq!(pixel_range.0.len(), TILE_SIZE);
45        assert_eq!(pixel_range.1.len(), TILE_SIZE);
46
47        for x in pixel_range.0.clone() {
48            for y in pixel_range.1.clone() {
49                let pixel_index = y * image.size().x as usize * 4 + x * 4;
50
51                colors[y - pixel_range.1.start][x - pixel_range.0.start] = Color::rgba_u8(
52                    image.data[pixel_index],
53                    image.data[pixel_index + 1],
54                    image.data[pixel_index + 2],
55                    image.data[pixel_index + 3],
56                );
57            }
58        }
59
60        Self { pixels: colors }
61    }
62
63    pub fn set_pixel(&mut self, loc: IVec2, color: Color) {
64        if !verify_pixel_loc(loc) {
65            return;
66        }
67
68        self.pixels[loc.y as usize][loc.x as usize] = color
69    }
70
71    pub fn get_pixel(&self, loc: IVec2) -> Option<Color> {
72        if !verify_pixel_loc(loc) {
73            return None;
74        }
75
76        Some(self.pixels[loc.y as usize][loc.x as usize])
77    }
78
79    pub fn pixel_count(&self) -> usize {
80        let mut pixel_count = 0;
81        for x in 0..TILE_SIZE {
82            for y in 0..TILE_SIZE {
83                if self.pixels[y][x].a() > 0.0 {
84                    pixel_count += 1;
85                }
86            }
87        }
88
89        pixel_count
90    }
91}
92
93fn verify_pixel_loc(loc: IVec2) -> bool {
94    if loc.x < 0 || loc.x >= TILE_SIZE as i32 || loc.y < 0 || loc.y >= TILE_SIZE as i32 {
95        return false;
96    }
97    true
98}