main.rs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #[macro_use]
  2. extern crate specs_derive;
  3. #[macro_use]
  4. extern crate specs_system_macro;
  5. use ggez::GameError;
  6. use rand::Rng;
  7. use specs::prelude::*;
  8. #[derive(PartialEq, Clone, Copy, Debug)]
  9. pub enum TileType {
  10. Wall,
  11. Floor,
  12. }
  13. impl TileType {
  14. fn glyph(self) -> carpet::CP437 {
  15. match self {
  16. TileType::Wall => carpet::CP437::from_char('#'),
  17. TileType::Floor => carpet::CP437::from_u8(0),
  18. }
  19. }
  20. }
  21. pub struct Map {
  22. tiles: carpet::Board<TileType>,
  23. }
  24. impl Map {
  25. fn new() -> Map {
  26. let mut rng = rand::thread_rng();
  27. let tiles = carpet::Board::new_from(80, 50, |x, y| {
  28. if x == 0 || x == 79 || y == 0 || y == 49 || rng.gen::<u8>() % 8 == 0 {
  29. TileType::Wall
  30. } else {
  31. TileType::Floor
  32. }
  33. });
  34. Map { tiles }
  35. }
  36. fn passable(&self, (x, y): (usize, usize)) -> bool {
  37. Some(&TileType::Floor) == self.tiles.get(x, y)
  38. }
  39. }
  40. #[derive(Component)]
  41. pub struct Pos {
  42. x: usize,
  43. y: usize,
  44. }
  45. #[derive(Component)]
  46. pub struct Renderable {
  47. glyph: carpet::CP437,
  48. color: carpet::Color,
  49. }
  50. #[derive(Component)]
  51. pub struct Player;
  52. impl Player {
  53. fn get_entity(world: &mut specs::World) -> Entity {
  54. let storage = (&world.read_component::<Player>(), &world.entities());
  55. storage
  56. .join()
  57. .next()
  58. .expect("No entities tagged as Player")
  59. .1
  60. }
  61. }
  62. #[derive(Component)]
  63. pub struct Motion {
  64. down: i8,
  65. right: i8,
  66. }
  67. impl Motion {
  68. fn move_player(world: &mut specs::World, down: i8, right: i8) {
  69. let player = Player::get_entity(world);
  70. world
  71. .write_component::<Motion>()
  72. .insert(player, Motion { down, right })
  73. .unwrap();
  74. }
  75. }
  76. system_impl! {
  77. Draw(
  78. resource mut game_board: carpet::GameBoard<carpet::CP437>,
  79. resource map: Map,
  80. renderable: Renderable,
  81. pos: Pos,
  82. ) {
  83. game_board.clear();
  84. for (x, y, t) in map.tiles.iter() {
  85. game_board.set([x, y], t.glyph());
  86. }
  87. for (p, r) in (&pos, &renderable).join() {
  88. game_board.set_with_color([p.x, p.y], r.glyph, r.color);
  89. }
  90. }
  91. }
  92. system! {
  93. Move (
  94. resource map: Map,
  95. mut motion: Motion,
  96. mut pos: Pos,
  97. ) {
  98. let tgt_x = (pos.x as i8 + motion.right) as usize;
  99. let tgt_y = (pos.y as i8 + motion.down) as usize;
  100. if map.passable((tgt_x, tgt_y)) {
  101. pos.x = tgt_x;
  102. pos.y = tgt_y;
  103. }
  104. } finally {
  105. motion.clear();
  106. }
  107. }
  108. fn main() -> Result<(), GameError> {
  109. let mut game: carpet::Game<carpet::CP437> = carpet::GameBuilder::new()
  110. .name("game")
  111. .author("me")
  112. .resource_path({
  113. let base = std::env::var("CARGO_MANIFEST_DIR").unwrap();
  114. let mut path = std::path::PathBuf::from(base);
  115. path.pop();
  116. path.push("resources");
  117. path
  118. })
  119. .tileset("/haberdash.gif", [12, 12])
  120. .map_size(80, 50)
  121. .build()?;
  122. game.register::<Pos>();
  123. game.register::<Renderable>();
  124. game.register::<Motion>();
  125. game.register::<Player>();
  126. game.insert(Map::new());
  127. game.create_entity()
  128. .with(Pos { x: 40, y: 25 })
  129. .with(Player)
  130. .with(Renderable {
  131. glyph: carpet::CP437::from_char('A'),
  132. color: carpet::Color::Blue,
  133. })
  134. .build();
  135. game.on_key((carpet::KeyCode::W, carpet::KeyMods::NONE), |world| {
  136. Motion::move_player(world, -1, 0);
  137. });
  138. game.on_key((carpet::KeyCode::A, carpet::KeyMods::NONE), |world| {
  139. Motion::move_player(world, 0, -1);
  140. });
  141. game.on_key((carpet::KeyCode::S, carpet::KeyMods::NONE), |world| {
  142. Motion::move_player(world, 1, 0);
  143. });
  144. game.on_key((carpet::KeyCode::D, carpet::KeyMods::NONE), |world| {
  145. Motion::move_player(world, 0, 1);
  146. });
  147. game.run_with_systems(|world| {
  148. Draw.run_now(world);
  149. Move.run_now(world);
  150. })
  151. }