use super::{Bounds, Contacts, Velocity};
use crate::{BitFlags, Body, SpriteFlag, SpriteId};
#[doc(hidden)]
pub trait Kinetic {
fn body(&self) -> &Body;
fn body_mut(&mut self) -> &mut Body;
fn velocity_mut(&mut self) -> &mut Velocity;
fn contacts(&self) -> &Contacts;
fn contacts_mut(&mut self) -> &mut Contacts;
fn bounds(&self) -> Bounds;
fn solid(&self) -> Option<BitFlags<SpriteFlag>> {
None
}
fn heeds(&self) -> BitFlags<SpriteFlag> {
BitFlags::all()
}
fn sprite(&self) -> Option<SpriteId> {
None
}
fn confines(&self) -> Option<Bounds> {
None
}
fn prop(&self) -> bool {
false
}
}
#[cfg(test)]
mod tests {
use super::{super::Contact, *};
#[test]
fn a_member_says_nothing_about_itself_unless_it_wants_to() {
struct Pebble {
body: Body,
velocity: Velocity,
contacts: Contacts,
}
impl Kinetic for Pebble {
fn body(&self) -> &Body {
&self.body
}
fn body_mut(&mut self) -> &mut Body {
&mut self.body
}
fn velocity_mut(&mut self) -> &mut Velocity {
&mut self.velocity
}
fn contacts(&self) -> &Contacts {
&self.contacts
}
fn contacts_mut(&mut self) -> &mut Contacts {
&mut self.contacts
}
fn bounds(&self) -> Bounds {
Bounds::of(&self.body, 1, 1)
}
}
let pebble = Pebble {
body: Body::new(0.0, 0.0),
velocity: Velocity::new(1.0, 0.5),
contacts: Contacts::default(),
};
assert!(pebble.solid().is_none());
assert_eq!(pebble.sprite(), None);
assert_eq!(pebble.confines(), None);
assert_eq!(pebble.heeds(), BitFlags::all());
assert!(!pebble.prop());
assert_eq!(*pebble.contacts(), Contacts::empty());
}
#[test]
fn the_contacts_slot_is_where_a_step_leaves_its_answer() {
let mut walker = Walker::at(0.0, 0.0);
assert_eq!(*walker.contacts(), Contacts::empty());
*walker.contacts_mut() = Contact::Below.into();
assert!(walker.contacts().below());
assert!(!walker.contacts().above());
}
#[test]
fn a_member_covers_the_rectangle_it_says_it_does() {
let walker = Walker::at(16.0, 16.0);
let bounds = walker.bounds();
assert_eq!((bounds.x(), bounds.y()), (16, 16));
assert_eq!((bounds.width(), bounds.height()), (8, 8));
let member: &dyn Kinetic = &walker;
assert_eq!(member.bounds(), Bounds::new(16, 16, 8, 8));
}
struct Walker {
body: Body,
velocity: Velocity,
contacts: Contacts,
}
impl Walker {
fn at(x: f32, y: f32) -> Self {
Self {
body: Body::new(x, y),
velocity: Velocity::default(),
contacts: Contacts::default(),
}
}
}
impl Kinetic for Walker {
fn body(&self) -> &Body {
&self.body
}
fn body_mut(&mut self) -> &mut Body {
&mut self.body
}
fn velocity_mut(&mut self) -> &mut Velocity {
&mut self.velocity
}
fn contacts(&self) -> &Contacts {
&self.contacts
}
fn contacts_mut(&mut self) -> &mut Contacts {
&mut self.contacts
}
fn bounds(&self) -> Bounds {
Bounds::of(&self.body, 8, 8)
}
fn solid(&self) -> Option<BitFlags<SpriteFlag>> {
Some(SOLID.into())
}
fn sprite(&self) -> Option<SpriteId> {
Some(WALKER_SPRITE)
}
}
const SOLID: SpriteFlag = SpriteFlag::Flag0;
const WALKER_SPRITE: SpriteId = SpriteId(9);
}