1extern crate specs;
2extern crate specs_static;
3
4use specs::{
5 Component, DispatcherBuilder, ReadExpect, Read, Write, Join, System, SystemData, VecStorage, World,
6};
7use specs_static::{Id, Storage, WorldExt};
8
9pub struct Tiles {
10 width: usize,
11 height: usize,
12}
13
14impl Tiles {
15 pub fn new(width: usize, height: usize) -> Self {
16 Tiles { width, height }
17 }
18
19 pub fn id(&self, x: usize, y: usize) -> TileId {
20 TileId(y as u32 * self.width as u32 + x as u32)
21 }
22
23 pub fn iter_all(&self) -> Box<Iterator<Item = TileId>> {
24 Box::new((0..self.width as u32 * self.height as u32 - 1).map(TileId))
25 }
26}
27
28pub type TileComps<'a, C> = Read<'a, Storage<C, <C as Component>::Storage, TileId>>;
29pub type TileCompsMut<'a, C> = Write<'a, Storage<C, <C as Component>::Storage, TileId>>;
30
31#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
32pub struct TileId(u32);
33
34impl Id for TileId {
35 fn from_u32(value: u32) -> Self {
36 TileId(value)
37 }
38
39 fn id(&self) -> u32 {
40 self.0
41 }
42}
43
44#[derive(Debug)]
47enum Material {
48 Dirt,
49 Grass,
50 Water,
51}
52
53impl Component for Material {
54 type Storage = VecStorage<Self>;
55}
56
57struct Sys;
58
59impl<'a> System<'a> for Sys {
60 type SystemData = (ReadExpect<'a, Tiles>, TileComps<'a, Material>);
61
62 fn run(&mut self, (tiles, materials): Self::SystemData) {
63 if let Some(mat) = materials.get(tiles.id(3, 4)) {
64 println!("The material at (3, 4) is {:?}.", mat);
65 }
66
67 let num_water: usize = (&*materials)
68 .join()
69 .map(|mat| match *mat {
70 Material::Water => 1,
71 _ => 0,
72 })
73 .sum();
74
75 println!("There are {} tiles with water.", num_water);
76 }
77}
78
79fn main() {
80 let mut d = DispatcherBuilder::new().with(Sys, "sys", &[]).build();
81 let mut w = World::new();
82
83 w.add_resource(Tiles::new(8, 8));
85 w.register_tile_comp::<Material, TileId>();
86
87 {
90 let tiles = w.read_resource::<Tiles>();
91 let mut materials: TileCompsMut<Material> = SystemData::fetch(&w.res);
92
93 for tile_id in tiles.iter_all() {
94 materials.insert(tile_id, Material::Dirt);
95 }
96
97 materials.insert(tiles.id(1, 5), Material::Grass);
98 materials.insert(tiles.id(2, 5), Material::Grass);
99 materials.insert(tiles.id(3, 4), Material::Water);
100 materials.insert(tiles.id(3, 7), Material::Water);
101 }
102
103 d.dispatch(&mut w.res);
106}