summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/assemblages.rs4
-rw-r--r--src/components.rs32
-rw-r--r--src/controls.rs13
-rw-r--r--src/resources.rs14
-rw-r--r--src/room.rs31
-rw-r--r--src/systems.rs57
-rw-r--r--src/util.rs8
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);
+}
+