chunk-flow-field 0.1.0

Library for make flow field in grid map. using box-shaped chunk.
Documentation
use crate::{
    map::Map,
    types::{Cell, OrthogonalLine, Pos, Side},
};

#[derive(Debug)]
pub struct Block {
    pub x: usize,
    pub y: usize,
    pub width: usize,
    pub height: usize,
}

impl Block {
    pub fn expand(&mut self, map: &Map) -> Option<()> {
        let mut expand_y_up = true;
        let mut expand_y_down = true;
        for x in self.x..self.x + self.width {
            if self.y == 0 || matches!(map.get_cell(x, self.y - 1), Cell::Wall | Cell::Block(_)) {
                expand_y_up = false;
            }
            if (self.y + self.height == map.height)
                || matches!(
                    map.get_cell(x, self.y + self.height),
                    Cell::Wall | Cell::Block(_)
                )
            {
                expand_y_down = false;
            }
        }
        let mut expand_x_left = true;
        let mut expand_x_right = true;
        for y in self.y..self.y + self.height {
            if self.x == 0 || matches!(map.get_cell(self.x - 1, y), Cell::Wall | Cell::Block(_)) {
                expand_x_left = false;
            }
            if (self.x + self.width == map.width)
                || matches!(
                    map.get_cell(self.x + self.width, y),
                    Cell::Wall | Cell::Block(_)
                )
            {
                expand_x_right = false;
            }
        }

        if self.width >= self.height {
            if expand_y_up || expand_y_down {
                if expand_y_up {
                    self.y -= 1;
                    self.height += 1;
                }
                if expand_y_down {
                    self.height += 1;
                }
                return Some(());
            } else if expand_x_left || expand_x_right {
                if expand_x_left {
                    self.x -= 1;
                    self.width += 1;
                }
                if expand_x_right {
                    self.width += 1;
                }
                return Some(());
            }
            return None;
        } else {
            if expand_x_left || expand_x_right {
                if expand_x_left {
                    self.x -= 1;
                    self.width += 1;
                }
                if expand_x_right {
                    self.width += 1;
                }
                return Some(());
            } else if expand_y_up || expand_y_down {
                if expand_y_up {
                    self.y -= 1;
                    self.height += 1;
                }
                if expand_y_down {
                    self.height += 1;
                }
                return Some(());
            }
            return None;
        }
    }

    pub fn center(&self) -> Pos {
        Pos {
            x: self.x + self.width / 2,
            y: self.y + self.height / 2,
        }
    }

    pub fn side_line(&self, side: Side) -> OrthogonalLine {
        match side {
            Side::Top => OrthogonalLine {
                is_vertical: false,
                fixed: self.y,
                from: self.x,
                to: self.x + self.width,
            },
            Side::Bottom => OrthogonalLine {
                is_vertical: false,
                fixed: self.y + self.height - 1,
                from: self.x,
                to: self.x + self.width,
            },
            Side::Left => OrthogonalLine {
                is_vertical: true,
                fixed: self.x,
                from: self.y,
                to: self.y + self.height,
            },
            Side::Right => OrthogonalLine {
                is_vertical: true,
                fixed: self.x + self.width - 1,
                from: self.y,
                to: self.y + self.height,
            },
        }
    }
}