sshattrick 0.1.1

Hockey in your terminal over SSH.
Documentation
use crate::types::Palette;
use glam::{U16Vec2, Vec2};
use image::RgbaImage;
use ratatui::layout::Rect;
use std::{
    collections::{hash_map::Iter, HashMap},
    fmt::Debug,
};

#[derive(Debug, Default, Clone)]
pub struct HitBox {
    inner: HashMap<U16Vec2, ColliderType>,
    size: U16Vec2,
}

impl From<HashMap<U16Vec2, ColliderType>> for HitBox {
    fn from(value: HashMap<U16Vec2, ColliderType>) -> Self {
        let size = value
            .keys()
            .fold(U16Vec2::ZERO, |acc, p| acc.max(*p + U16Vec2::ONE));
        Self { inner: value, size }
    }
}

impl From<(Rect, ColliderType)> for HitBox {
    fn from(value: (Rect, ColliderType)) -> Self {
        let (rect, collider_type) = value;
        let size = U16Vec2::new(rect.width, rect.height);

        let mut inner = HashMap::new();
        for x in 0..rect.width {
            for y in 0..rect.height {
                inner.insert(U16Vec2::new(x, y), collider_type);
            }
        }
        Self { inner, size }
    }
}

impl HitBox {
    pub fn iter(&self) -> Iter<'_, U16Vec2, ColliderType> {
        self.inner.iter()
    }

    pub fn get(&self, k: &U16Vec2) -> Option<&ColliderType> {
        self.inner.get(k)
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ColliderType {
    Goalie,
    GoalieAreaVerticalSize,
    GoalieAreaHorizontalSide,
    Player,
    Puck,
    Stick,
    Catcher,
}

pub trait Body: Sprite {
    fn mass(&self) -> f32;
    fn previous_rect(&self) -> Rect {
        Rect {
            x: self.previous_position().x,
            y: self.previous_position().y,
            width: self.hit_box().size.x,
            height: self.hit_box().size.y,
        }
    }

    fn rect(&self) -> Rect {
        Rect {
            x: self.position().x,
            y: self.position().y,
            width: self.hit_box().size.x,
            height: self.hit_box().size.y,
        }
    }

    fn previous_position(&self) -> U16Vec2;

    fn position(&self) -> U16Vec2;

    fn set_position(&mut self, position: U16Vec2);

    fn velocity(&self) -> Vec2;

    fn set_velocity(&mut self, velocity: Vec2);

    fn update_body(&mut self, _: f32) {}
}

pub trait Sprite {
    fn image(&self, palette: Palette) -> &RgbaImage;

    fn hit_box(&self) -> &HitBox;

    fn size(&self) -> U16Vec2 {
        self.hit_box().size
    }

    fn update_sprite(&mut self, _: f32) {}
}

pub trait Entity: Body + Debug + Send + Sync {
    fn update(&mut self, deltatime: f32) {
        self.update_body(deltatime);
        self.update_sprite(deltatime);
    }
}