gemini_engine/containers/
collision_container.rs

1use crate::{
2    containers::PixelContainer,
3    core::{CanDraw, Vec2D},
4};
5
6/// Must be implemented to be used by the [`CollisionContainer`]
7pub trait CanCollide {
8    /// Returns `true` if the collider intersects the passed position
9    #[must_use]
10    fn collides_with_pos(&self, pos: Vec2D) -> bool;
11}
12
13/// Container for references to collider objects
14#[derive(Clone)]
15pub struct CollisionContainer<'e> {
16    /// The elements used to define the collision hitbox. This can be anything that implements [`CanCollide`]
17    pub elements: Vec<&'e dyn CanCollide>,
18}
19
20impl Default for CollisionContainer<'_> {
21    fn default() -> Self {
22        Self::new()
23    }
24}
25
26impl<'e> CollisionContainer<'e> {
27    /// Create a new `CollisionContainer`
28    #[must_use]
29    pub const fn new() -> Self {
30        Self { elements: vec![] }
31    }
32
33    /// Add an element to the container
34    pub fn push(&mut self, element: &'e impl CanCollide) {
35        self.elements.push(element);
36    }
37
38    /// Returns true if the given element implementing [`CanDraw`] is overlapping the `CollisionContainer`
39    pub fn overlaps_element(&self, element: &impl CanDraw) -> bool {
40        self.will_overlap_element(element, Vec2D::ZERO)
41    }
42
43    /// Returns true if the given element implementing [`CanDraw`] will be overlapping the `CollisionContainer` when moved by `offset`
44    pub fn will_overlap_element(&self, element: &impl CanDraw, offset: Vec2D) -> bool {
45        PixelContainer::from(element)
46            .pixels
47            .into_iter()
48            .any(|p| self.collides_with_pos(p.pos + offset))
49    }
50}
51
52impl CanCollide for CollisionContainer<'_> {
53    /// Returns true if any of the elements in the `CollisionContainer` intersect the passed position
54    fn collides_with_pos(&self, pos: Vec2D) -> bool {
55        self.elements.iter().any(|e| e.collides_with_pos(pos))
56    }
57}
58
59impl<'e> From<&'e dyn CanCollide> for CollisionContainer<'e> {
60    fn from(element: &'e dyn CanCollide) -> Self {
61        Self {
62            elements: vec![element],
63        }
64    }
65}