basic/
basic.rs

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// ------
45
46#[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    // Use method provided by `WorldExt`.
84    w.add_resource(Tiles::new(8, 8));
85    w.register_tile_comp::<Material, TileId>();
86
87    // Initialize
88
89    {
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    // ---
104
105    d.dispatch(&mut w.res);
106}