use specs::world::WorldExt; use specs::{Component, NullStorage, VecStorage}; pub type World = ncollide2d::world::CollisionWorld; /// Register all the components with the world. pub fn register(world: &mut specs::World) { world.register::(); world.register::(); world.register::(); world.register::(); world.register::(); world.register::(); world.register::(); world.register::(); world.register::(); } /// The `Position` component represents (in world coordinates) a thing /// that has a position in the world, measured from the top-left of /// the thing. #[derive(Component, Debug, Clone)] #[storage(VecStorage)] pub struct Position { pub x: f32, pub y: f32, } impl Position { /// Convert a `Position` to a screen point pub fn to_point(&self) -> mint::Point2 { mint::Point2 { x: self.x * 3.0, y: self.y * 3.0, } } pub fn to_grid(&self) -> (i32, i32) { ((self.x / 24.0) as i32, (self.y / 24.0) as i32) } pub fn moved(&self, vel: &Velocity) -> Position { Position { x: self.x + vel.dx, y: self.y + vel.dy, } } } /// The `Velocity` componenent is present on any entity that moves /// through the world, and represents its rate of change per /// time-unit. #[derive(Component, Debug)] #[storage(VecStorage)] pub struct Velocity { pub dx: f32, pub dy: f32, } /// The `Sprite` components represents the current display location of /// a sprite in the spritesheet. #[derive(Component, Debug)] #[storage(VecStorage)] pub struct Sprite { pub u: u8, pub v: u8, } impl Sprite { /// Convert a `Sprite` into the rectangle that specifies the /// sprite location on the spritesheet pub fn to_rect(&self) -> ggez::graphics::Rect { ggez::graphics::Rect { x: (1.0 / 32.0) * self.u as f32, y: (1.0 / 32.0) * self.v as f32, w: 1.0 / 32.0, h: 1.0 / 32.0, } } } /// A drawing-phase component: represents tiles that appear in the /// background of everything. #[derive(Component, Default, Debug)] #[storage(NullStorage)] pub struct Background; /// A drawing-phase component: represents tiles which appear in the /// foreground, possibly entities. #[derive(Component, Default, Debug)] #[storage(NullStorage)] pub struct Foreground; /// A drawing-phase component: represents tiles which appear on top of /// everything else, such as the tops of trees or roofs of houses. #[derive(Component, Default, Debug)] #[storage(NullStorage)] pub struct Decoration; /// A component that represents entities which are controlled by the /// keyboard. #[derive(Component, Default, Debug)] #[storage(NullStorage)] pub struct Controlled; /// A component that represents entities which can collide with other /// things. #[derive(Component, Debug)] #[storage(VecStorage)] pub struct Collision { pub has_collision: bool, } /// A component which represents things which have a collision shape /// in the world #[derive(Component)] #[storage(VecStorage)] pub struct Blocking { pub handle: ncollide2d::pipeline::CollisionObjectSlabHandle, } impl Blocking { /// create a `Blocking` component for an entity given a specified shape pub fn new_shape(e: specs::Entity, w: &mut World, volume: S) -> Blocking where S: ncollide2d::shape::Shape, { let (handle, _) = w.add( nalgebra::geometry::Isometry::identity(), ncollide2d::shape::ShapeHandle::new(volume), ncollide2d::pipeline::CollisionGroups::new(), ncollide2d::pipeline::object::GeometricQueryType::Proximity(0.0), e, ); Blocking { handle } } /// create an 11pxx11px box for an entity pub fn new_box(e: specs::Entity, w: &mut World) -> Blocking { Blocking::new_shape( e, w, ncollide2d::shape::Cuboid::new(nalgebra::Vector2::new(11.0, 11.0)), ) } /// create a 11px ball for an entity pub fn new_ball(e: specs::Entity, w: &mut World) -> Blocking { Blocking::new_shape(e, w, ncollide2d::shape::Ball::new(11.0)) } }