Browse Source

Add as-yet-untouched ch4

Getty Ritter 5 years ago
parent
commit
ab3e8044b4
4 changed files with 199 additions and 1 deletions
  1. 12 0
      Cargo.lock
  2. 2 1
      Cargo.toml
  3. 15 0
      ch4/Cargo.toml
  4. 170 0
      ch4/src/main.rs

+ 12 - 0
Cargo.lock

@@ -288,6 +288,18 @@ dependencies = [
  "specs-system-macro 0.1.0 (git+https://git.infinitenegativeutility.com/getty/specs-system-macro.git)",
 ]
 
+[[package]]
+name = "ch4"
+version = "0.1.0"
+dependencies = [
+ "carpet 0.1.0",
+ "ggez 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "specs 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "specs-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "specs-system-macro 0.1.0 (git+https://git.infinitenegativeutility.com/getty/specs-system-macro.git)",
+]
+
 [[package]]
 name = "clang-sys"
 version = "0.28.1"

+ 2 - 1
Cargo.toml

@@ -5,4 +5,5 @@ members = [
   "ch1",
   "ch2",
   "ch3",
-]
+  "ch4",
+]

+ 15 - 0
ch4/Cargo.toml

@@ -0,0 +1,15 @@
+[package]
+name = "ch4"
+version = "0.1.0"
+authors = ["Getty Ritter <gettylefou@gmail.com>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+ggez = "*"
+carpet = { path = "../carpet" }
+specs = "*"
+specs-derive = "*"
+specs-system-macro = { git = "https://git.infinitenegativeutility.com/getty/specs-system-macro.git" }
+rand = "*"

+ 170 - 0
ch4/src/main.rs

@@ -0,0 +1,170 @@
+#[macro_use]
+extern crate specs_derive;
+#[macro_use]
+extern crate specs_system_macro;
+
+use ggez::GameError;
+use specs::prelude::*;
+use rand::Rng;
+
+#[derive(PartialEq, Clone, Copy, Debug)]
+pub enum TileType {
+    Wall,
+    Floor,
+}
+
+impl TileType {
+    fn glyph(&self) -> carpet::CP437 {
+        match self {
+            TileType::Wall => carpet::CP437::from_char('#'),
+            TileType::Floor => carpet::CP437::from_u8(0),
+        }
+    }
+}
+
+pub struct Map {
+    tiles: carpet::Board<TileType>,
+}
+
+impl Map {
+    fn new() -> Map {
+        let mut rng = rand::thread_rng();
+        let tiles = carpet::Board::new_from(80, 50, |x, y| {
+            if x == 0 || x == 79 || y == 0 || y == 49 {
+                TileType::Wall
+            } else if rng.gen::<u8>() % 8 == 0 {
+                TileType::Wall
+            } else {
+                TileType::Floor
+            }
+        });
+        Map { tiles }
+    }
+
+    fn passable(&self, (x, y): (usize, usize)) -> bool {
+        Some(&TileType::Floor) == self.tiles.get(x, y)
+    }
+}
+
+#[derive(Component)]
+pub struct Pos {
+    x: usize,
+    y: usize,
+}
+
+#[derive(Component)]
+pub struct Renderable {
+    glyph: carpet::CP437,
+    color: carpet::Color,
+}
+
+#[derive(Component)]
+pub struct Player;
+
+impl Player {
+    fn get_entity(world: &mut specs::World) -> Entity {
+        let storage = (&world.read_component::<Player>(), &world.entities());
+        storage.join().next().expect("No entities tagged as Player").1
+    }
+}
+
+#[derive(Component)]
+pub struct Motion {
+    down: i8,
+    right: i8,
+}
+
+impl Motion {
+    fn move_player(world: &mut specs::World, down: i8, right: i8) {
+        let player = Player::get_entity(world);
+        world.write_component::<Motion>().insert(player, Motion { down, right }).unwrap();
+    }
+}
+
+system_impl! {
+    Draw(
+        resource mut game_board: carpet::GameBoard<carpet::CP437>,
+        resource map: Map,
+        renderable: Renderable,
+        pos: Pos,
+    ) {
+        game_board.clear();
+        for (x, y, t) in map.tiles.iter() {
+            game_board.set([x, y], t.glyph());
+        }
+        for (p, r) in (&pos, &renderable).join() {
+            game_board.set_with_color([p.x, p.y], r.glyph, r.color);
+        }
+    }
+}
+
+system! {
+    Move (
+        resource map: Map,
+        mut motion: Motion,
+        mut pos: Pos,
+    ) {
+        let tgt_x = (pos.x as i8 + motion.right) as usize;
+        let tgt_y = (pos.y as i8 + motion.down) as usize;
+        if map.passable((tgt_x, tgt_y)) {
+            pos.x = tgt_x;
+            pos.y = tgt_y;
+        }
+    } finally {
+        motion.clear();
+    }
+}
+
+fn main() -> Result<(), GameError> {
+    let mut game: carpet::Game<carpet::CP437> =
+        carpet::GameBuilder::new()
+        .name("game")
+        .author("me")
+        .resource_path({
+            let base = std::env::var("CARGO_MANIFEST_DIR").unwrap();
+            let mut path = std::path::PathBuf::from(base);
+            path.pop();
+            path.push("resources");
+            path
+        })
+        .tileset("/haberdash.gif", [12, 12])
+        .map_size(80, 50)
+        .build()?;
+
+    game.register::<Pos>();
+    game.register::<Renderable>();
+    game.register::<Motion>();
+    game.register::<Player>();
+
+    game.insert(Map::new());
+
+    game.create_entity()
+        .with(Pos { x: 40, y: 25 })
+        .with(Player)
+        .with(Renderable {
+            glyph: carpet::CP437::from_char('A'),
+            color: carpet::Color::Blue,
+        })
+        .build();
+
+    game.on_key((carpet::VirtualKeyCode::W, carpet::KeyMods::NONE), |world| {
+        Motion::move_player(world, -1, 0);
+    });
+
+    game.on_key((carpet::VirtualKeyCode::A, carpet::KeyMods::NONE), |world| {
+        Motion::move_player(world, 0, -1);
+    });
+
+    game.on_key((carpet::VirtualKeyCode::S, carpet::KeyMods::NONE), |world| {
+        Motion::move_player(world, 1, 0);
+    });
+
+    game.on_key((carpet::VirtualKeyCode::D, carpet::KeyMods::NONE), |world| {
+        Motion::move_player(world, 0, 1);
+    });
+
+    game.run_with_systems(|world| {
+        Draw.run_now(&world);
+        Move.run_now(&world);
+    })
+}