Lets try something different
in the collisions.rs
- create a
PointIterthat has aVec<(f64, f64)>andidx - create a convenient method to take Vec<(f64, f64)> and convert it
intoPointIter - implement
IteratorforPointIter - create a
Pointstrait that has one method,points, that returns anPointIter - create a
Containstrait that has one method,contains_point, that returnsboolif the point is contained within the geometry - all of this in
src/shapes/collisions.rs
Complete Code
pub struct PointIter {
points: Vec<(f64, f64)>,
idx: usize,
}
impl From<Vec<(f64, f64)>> for PointIter {
fn from(value: Vec<(f64, f64)>) -> Self {
return PointIter {
points: value,
idx: 0,
};
}
}
impl Iterator for PointIter {
type Item = (f64, f64);
fn next(&mut self) -> Option<Self::Item> {
if self.idx >= self.points.len() {
return None;
}
let point = self.points[self.idx];
self.idx += 1;
return Some(point);
}
}
pub trait Points {
fn points(&self) -> PointIter;
}
pub trait Contains {
fn contains_point(&self, point: (f64, f64)) -> bool;
}
So why did we do this?
Lets relook at our Collidable implementation. We can now do a "blanket"
implementation. This allows us to define a generic implemenation over generic
trait combinations!!!
You> "i know all these words individually, but when you put them together like that..."
Me> "Just watch (and program to get the most out of it)"
Complete Code
impl<T> Collidable<T> for T where T: Contains + Points {
fn collide(&self, other: &T) -> bool {
for point in other.points() {
if self.contains_point(point) {
return true;
}
}
return false;
}
}