|
@@ -0,0 +1,153 @@
|
|
|
+#[macro_use]
|
|
|
+extern crate specs_derive;
|
|
|
+#[macro_use]
|
|
|
+extern crate specs_system_macro;
|
|
|
+
|
|
|
+use ggez::GameError;
|
|
|
+use specs::prelude::*;
|
|
|
+
|
|
|
+#[derive(PartialEq, Clone, Copy, Debug)]
|
|
|
+enum TileType {
|
|
|
+ Wall,
|
|
|
+ Floor,
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(Component)]
|
|
|
+pub struct Pos {
|
|
|
+ x: usize,
|
|
|
+ y: usize,
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(Component)]
|
|
|
+pub struct Renderable {
|
|
|
+ glyph: carpet::CP437,
|
|
|
+ color: carpet::Color,
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(Component)]
|
|
|
+pub struct MoveLeft;
|
|
|
+
|
|
|
+#[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 board: carpet::GameBoard<carpet::CP437>,
|
|
|
+ renderable: Renderable,
|
|
|
+ pos: Pos,
|
|
|
+ ) {
|
|
|
+ board.clear();
|
|
|
+ for (p, r) in (&pos, &renderable).join() {
|
|
|
+ board.set_with_color([p.x, p.y], r.glyph, r.color);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+system! {
|
|
|
+ Leftward (
|
|
|
+ _left: MoveLeft,
|
|
|
+ mut pos: Pos,
|
|
|
+ ) {
|
|
|
+ if pos.x == 0 {
|
|
|
+ pos.x = 79;
|
|
|
+ } else {
|
|
|
+ pos.x -= 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+system! {
|
|
|
+ Move (
|
|
|
+ mut motion: Motion,
|
|
|
+ mut pos: Pos,
|
|
|
+ ) {
|
|
|
+ pos.x = (pos.x as i8 + motion.right) as usize;
|
|
|
+ pos.y = (pos.y as i8 + motion.down) as usize;
|
|
|
+ } finally {
|
|
|
+ motion.clear();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+fn main() -> Result<(), GameError> {
|
|
|
+ let mut game = 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.push("resources");
|
|
|
+ path
|
|
|
+ })
|
|
|
+ .tileset("/terminal8x8.jpg", [8, 8])
|
|
|
+ .map_size(80, 50)
|
|
|
+ .build()?;
|
|
|
+
|
|
|
+ game.register::<Pos>();
|
|
|
+ game.register::<Renderable>();
|
|
|
+ game.register::<MoveLeft>();
|
|
|
+ game.register::<Motion>();
|
|
|
+ game.register::<Player>();
|
|
|
+ game.world.print([1, 1], "Hello, world!");
|
|
|
+
|
|
|
+ game.create_entity()
|
|
|
+ .with(Pos { x: 40, y: 25 })
|
|
|
+ .with(Player)
|
|
|
+ .with(Renderable {
|
|
|
+ glyph: carpet::CP437::from_char('A'),
|
|
|
+ color: carpet::Color::Blue,
|
|
|
+ })
|
|
|
+ .build();
|
|
|
+
|
|
|
+ for i in 0..10 {
|
|
|
+ game.create_entity()
|
|
|
+ .with(Pos { x: i * 7, y: 20 })
|
|
|
+ .with(Renderable {
|
|
|
+ glyph: carpet::CP437::from_char('X'),
|
|
|
+ color: carpet::Color::Red,
|
|
|
+ })
|
|
|
+ .with(MoveLeft)
|
|
|
+ .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);
|
|
|
+ Leftward.run_now(&world);
|
|
|
+ Move.run_now(&world);
|
|
|
+ })
|
|
|
+}
|