diff options
| author | troido <troido@protonmail.com> | 2020-01-29 22:53:06 +0100 |
|---|---|---|
| committer | troido <troido@protonmail.com> | 2020-01-29 22:53:06 +0100 |
| commit | 286be37225b5de1fb438db0a4029fd391b35c13e (patch) | |
| tree | c865ca269f43d7666275d1d72096dad805135705 | |
| parent | 88f275bc427033b7981e0dc2fc5cb4b711fd5fb1 (diff) | |
players can no longer walk through walls
| -rw-r--r-- | src/assemblages.rs | 4 | ||||
| -rw-r--r-- | src/components.rs | 32 | ||||
| -rw-r--r-- | src/controls.rs | 13 | ||||
| -rw-r--r-- | src/resources.rs | 14 | ||||
| -rw-r--r-- | src/room.rs | 31 | ||||
| -rw-r--r-- | src/systems.rs | 57 | ||||
| -rw-r--r-- | src/util.rs | 8 |
7 files changed, 111 insertions, 48 deletions
diff --git a/src/assemblages.rs b/src/assemblages.rs index 2a74030..d56e0f3 100644 --- a/src/assemblages.rs +++ b/src/assemblages.rs @@ -6,7 +6,7 @@ use specs::{ EntityBuilder }; -use super::components::{Visible}; +use super::components::{Visible, Blocking}; @@ -21,7 +21,7 @@ pub struct Wall; impl Assemblage for Wall { fn build<'a>(&self, builder: EntityBuilder<'a>) -> EntityBuilder<'a>{ - builder.with(Visible{sprite: "wall".to_string(), height: 2.0}) + builder.with(Visible{sprite: "wall".to_string(), height: 2.0}).with(Blocking) } } diff --git a/src/components.rs b/src/components.rs index 07de1d5..c72ba61 100644 --- a/src/components.rs +++ b/src/components.rs @@ -1,10 +1,13 @@ +use std::ops; + use specs::{ VecStorage, Component }; use super::controls::Control; +use super::util::clamp; #[derive(Component, Debug, Hash, PartialEq, Eq, Clone, Copy)] @@ -14,6 +17,31 @@ pub struct Position { pub y: i32 } +impl ops::Add<Position> for Position { + type Output = Position; + + fn add(self, other: Position) -> Position { + Position { + x: self.x + other.x, + y: self.y + other.y + } + } +} + +impl Position { + + pub fn new(x: i32, y: i32) -> Position { + Position {x, y} + } + + pub fn clamp(self, smaller: Position, larger: Position) -> Position { + Position { + x: clamp(self.x, smaller.x, larger.x), + y: clamp(self.y, smaller.y, larger.y) + } + } +} + #[derive(Component, Debug, Clone)] #[storage(VecStorage)] pub struct Visible { @@ -24,3 +52,7 @@ pub struct Visible { #[derive(Component, Debug)] #[storage(VecStorage)] pub struct Controller(pub Control); + +#[derive(Component, Debug)] +#[storage(VecStorage)] +pub struct Blocking; diff --git a/src/controls.rs b/src/controls.rs index 58c83b0..6ba7539 100644 --- a/src/controls.rs +++ b/src/controls.rs @@ -1,6 +1,7 @@ use serde_json::Value; +use super::components::Position; #[derive(Debug)] pub enum Direction { @@ -27,13 +28,13 @@ impl Direction { } } - pub fn to_position(&self) -> (i32, i32) { + pub fn to_position(&self) -> Position { match self { - Direction::North => (0, -1), - Direction::South => (0, 1), - Direction::East => (1, 0), - Direction::West => (-1, 0), - Direction::None => (0, 0) + Direction::North => Position::new(0, -1), + Direction::South => Position::new(0, 1), + Direction::East => Position::new(1, 0), + Direction::West => Position::new(-1, 0), + Direction::None => Position::new(0, 0) } } } diff --git a/src/resources.rs b/src/resources.rs index 7c14507..3834d8f 100644 --- a/src/resources.rs +++ b/src/resources.rs @@ -1,14 +1,22 @@ use std::collections::HashMap; +use specs::Entity; use super::components::{Position, Visible}; #[derive(Default)] -pub struct Size (pub i32, pub i32); +pub struct Size { + pub width: i32, + pub height: i32 +} #[derive(Default)] pub struct TopView { - pub width: i32, - pub height: i32, pub cells: HashMap<Position, Vec<Visible>> } + + +#[derive(Default)] +pub struct Floor { + pub cells: HashMap<Position, Vec<Entity>> +} diff --git a/src/room.rs b/src/room.rs index c19af37..de179aa 100644 --- a/src/room.rs +++ b/src/room.rs @@ -10,10 +10,15 @@ use specs::{ }; use super::controls::Control; -use super::components::{Position, Visible, Controller}; +use super::components::{Position, Controller}; use super::assemblages::Assemblage; use super::resources::{Size, TopView}; -use super::systems::{Draw, Move, ClearControllers}; +use super::systems::{ + Draw, + Move, + ClearControllers, + MakeFloor +}; @@ -29,18 +34,17 @@ impl <'a, 'b>Room<'a, 'b> { pub fn new(size: (i32, i32)) -> Room<'a, 'b> { let (width, height) = size; let mut world = World::new(); - world.register::<Position>(); - world.register::<Visible>(); - world.register::<Controller>(); - world.insert(Size(width, height)); - world.insert(TopView{width: width, height: height, cells: HashMap::new()}); + world.insert(Size{width, height}); - let dispatcher = DispatcherBuilder::new() - .with(Move, "move", &[]) + let mut dispatcher = DispatcherBuilder::new() + .with(MakeFloor, "makefloor", &[]) + .with(Move, "move", &["makefloor"]) .with(Draw, "draw", &["move"]) .with(ClearControllers, "clearcontrollers", &["move"]) .build(); + dispatcher.setup(&mut world); + Room { world, dispatcher, @@ -51,8 +55,7 @@ impl <'a, 'b>Room<'a, 'b> { pub fn view(&self) -> (Vec<usize>, Vec<Vec<String>>) { let tv = &*self.world.fetch::<TopView>(); - let width = tv.width; - let height = tv.height; + let (width, height) = self.get_size(); let size = width * height; let mut values :Vec<usize> = Vec::with_capacity(size as usize); let mut mapping: Vec<Vec<String>> = Vec::new(); @@ -84,7 +87,7 @@ impl <'a, 'b>Room<'a, 'b> { } pub fn get_size(&self) -> (i32, i32) { - let Size(width, height) = *self.world.fetch::<Size>(); + let Size{width, height} = *self.world.fetch::<Size>(); (width, height) } @@ -103,10 +106,6 @@ impl <'a, 'b>Room<'a, 'b> { self.world.delete_entity(ent).expect("player in world does not have entity"); } -// pub fn clear_controls(&mut self){ -// (*self.world.fetch_mut::<Controls>()).0.clear(); -// } - pub fn control(&mut self, name: String, control: Control){ if let Some(ent) = self.players.get(&name){ let _ = self.world.write_component::<Controller>().insert(*ent, Controller(control)); diff --git a/src/systems.rs b/src/systems.rs index d00abc8..4988434 100644 --- a/src/systems.rs +++ b/src/systems.rs @@ -2,6 +2,7 @@ use specs::{ ReadStorage, WriteStorage, + Read, Write, Entities, System, @@ -11,15 +12,31 @@ use specs::{ use super::components::{ Position, Visible, - Controller + Controller, + Blocking }; use super::controls::Control; -use super::resources::TopView; +use super::resources::{ + TopView, + Size, + Floor +}; -pub struct Draw; +pub struct MakeFloor; +impl <'a> System<'a> for MakeFloor { + type SystemData = (Entities<'a>, Write<'a, Floor>, ReadStorage<'a, Position>); + fn run(&mut self, (entities, mut floor, positions): Self::SystemData) { + floor.cells.clear(); + for (ent, pos) in (&entities, &positions).join() { + floor.cells.entry(*pos).or_insert(Vec::new()).push(ent); + } + } +} + +pub struct Draw; impl <'a> System<'a> for Draw { type SystemData = (ReadStorage<'a, Position>, ReadStorage<'a, Visible>, Write<'a, TopView>); @@ -27,32 +44,30 @@ impl <'a> System<'a> for Draw { fn run(&mut self, (pos, vis, mut view): Self::SystemData) { view.cells.clear(); for (pos, vis) in (&pos, &vis).join(){ - if pos.x >= 0 && pos.y >= 0 && pos.x < view.width && pos.y < view.height { - view.cells.entry(*pos).or_insert(Vec::new()).push(vis.clone()); - view.cells.get_mut(pos).unwrap().sort_by(|a, b| b.height.partial_cmp(&a.height).unwrap()); - } + view.cells.entry(*pos).or_insert(Vec::new()).push(vis.clone()); + view.cells.get_mut(pos).unwrap().sort_by(|a, b| b.height.partial_cmp(&a.height).unwrap()); } } } -// struct Control; -// impl <'a> System <'a> for Control { -// type SystemData = WriteStorage<'a, Controller>; -// fn run (&mut self, mut controller: Self::SystemData) { -// for controller in &mut controller.join() -// } -// } - pub struct Move; impl <'a> System<'a> for Move { - type SystemData = (WriteStorage<'a, Controller>, WriteStorage<'a, Position>); - fn run(&mut self, (mut controller, mut pos): Self::SystemData) { - for (controller, pos) in (&mut controller, &mut pos).join(){ + type SystemData = (ReadStorage<'a, Controller>, WriteStorage<'a, Position>, Read<'a, Size>, ReadStorage<'a, Blocking>, Read<'a, Floor>); + fn run(&mut self, (controller, mut pos, size, blocking, floor): Self::SystemData) { + for (controller, pos) in (&controller, &mut pos).join(){ match &controller.0 { Control::Move(direction) => { - let (dx, dy) = direction.to_position(); - pos.x += dx; - pos.y += dy; + let newpos = (*pos + direction.to_position()).clamp(Position::new(0, 0), Position::new(size.width - 1, size.height - 1)); + let mut blocked = false; + for ent in floor.cells.get(&newpos).unwrap_or(&Vec::new()) { + if blocking.get(*ent).is_some(){ + blocked = true; + break; + } + } + if !blocked { + pos.clone_from(&newpos); + } } _ => {} } diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..1e7821f --- /dev/null +++ b/src/util.rs @@ -0,0 +1,8 @@ + + +use std::cmp::{min, max}; + +pub fn clamp<T: Ord>(val: T, lower: T, upper: T) -> T{ + return max(min(val, upper), lower); +} + |
