main.rs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #[macro_use]
  2. extern crate itertools;
  3. #[macro_use]
  4. extern crate specs_derive;
  5. mod components;
  6. mod map;
  7. mod player;
  8. mod rect;
  9. mod systems;
  10. pub use components::*;
  11. pub use map::Map;
  12. pub use rect::Rect;
  13. use rltk::{Console, GameState, Point, Rltk, RGB};
  14. use specs::prelude::*;
  15. rltk::add_wasm_support!();
  16. #[derive(PartialEq, Copy, Clone)]
  17. pub enum RunState {
  18. AwaitingInput,
  19. PreRun,
  20. PlayerTurn,
  21. MonsterTurn,
  22. }
  23. pub struct State {
  24. pub ecs: World,
  25. }
  26. impl State {
  27. fn run_systems(&mut self) {
  28. systems::MapIndexingSystem.run_now(&self.ecs);
  29. systems::VisibilitySystem.run_now(&self.ecs);
  30. systems::MonsterAI.run_now(&self.ecs);
  31. systems::MoveFollow.run_now(&self.ecs);
  32. systems::MeleeCombatSystem.run_now(&self.ecs);
  33. systems::DamageSystem.run_now(&self.ecs);
  34. self.ecs.maintain();
  35. }
  36. }
  37. impl GameState for State {
  38. fn tick(&mut self, ctx: &mut Rltk) {
  39. ctx.cls();
  40. let mut newrunstate = *self.ecs.fetch::<RunState>();
  41. match newrunstate {
  42. RunState::PreRun => {
  43. self.run_systems();
  44. newrunstate = RunState::AwaitingInput;
  45. }
  46. RunState::AwaitingInput => {
  47. newrunstate = player::player_input(self, ctx);
  48. }
  49. RunState::PlayerTurn => {
  50. self.run_systems();
  51. newrunstate = RunState::MonsterTurn;
  52. }
  53. RunState::MonsterTurn => {
  54. self.run_systems();
  55. newrunstate = RunState::AwaitingInput;
  56. }
  57. }
  58. player::HandleInputEvent.run_now(&self.ecs);
  59. systems::HandleMoveEvent.run_now(&self.ecs);
  60. *self.ecs.write_resource() = newrunstate;
  61. systems::CleanupDead.run_now(&self.ecs);
  62. systems::DrawRenderables { ctx }.run_now(&self.ecs);
  63. }
  64. }
  65. fn main() {
  66. let context = Rltk::init_simple8x8(80, 50, "Hello Rust World", "resources");
  67. let mut gs = State { ecs: World::new() };
  68. gs.ecs.register::<Position>();
  69. gs.ecs.register::<Renderable>();
  70. gs.ecs.register::<Player>();
  71. gs.ecs.register::<Viewshed>();
  72. gs.ecs.register::<Monster>();
  73. gs.ecs.register::<Name>();
  74. gs.ecs.register::<BlocksTile>();
  75. gs.ecs.register::<CombatStats>();
  76. gs.ecs.register::<WantsToMelee>();
  77. gs.ecs.register::<SufferDamage>();
  78. gs.ecs.register::<InputEvent>();
  79. gs.ecs.register::<MoveEvent>();
  80. gs.ecs.register::<Seek>();
  81. let map: Map = Map::new_map_rooms_and_corridors();
  82. let (player_x, player_y) = map.rooms[0].center();
  83. let player_entity = gs
  84. .ecs
  85. .create_entity()
  86. .with(Position {
  87. x: player_x,
  88. y: player_y,
  89. })
  90. .with(Renderable {
  91. glyph: rltk::to_cp437('@'),
  92. fg: RGB::named(rltk::YELLOW),
  93. bg: RGB::named(rltk::BLACK),
  94. })
  95. .with(Player)
  96. .with(Viewshed {
  97. visible_tiles: Vec::new(),
  98. range: 8,
  99. dirty: true,
  100. })
  101. .with(Name {
  102. name: "Player".to_string(),
  103. })
  104. .with(CombatStats {
  105. max_hp: 30,
  106. hp: 30,
  107. defense: 2,
  108. power: 5,
  109. })
  110. .build();
  111. let mut rng = rltk::RandomNumberGenerator::new();
  112. for (i, room) in map.rooms.iter().skip(1).enumerate() {
  113. let (x, y) = room.center();
  114. let glyph: u8;
  115. let name: String;
  116. let roll = rng.roll_dice(1, 2);
  117. match roll {
  118. 1 => {
  119. glyph = rltk::to_cp437('g');
  120. name = "Goblin".to_string();
  121. }
  122. _ => {
  123. glyph = rltk::to_cp437('o');
  124. name = "Orc".to_string();
  125. }
  126. }
  127. gs.ecs
  128. .create_entity()
  129. .with(Position { x, y })
  130. .with(Renderable {
  131. glyph,
  132. fg: RGB::named(rltk::RED),
  133. bg: RGB::named(rltk::BLACK),
  134. })
  135. .with(Viewshed {
  136. visible_tiles: Vec::new(),
  137. range: 8,
  138. dirty: true,
  139. })
  140. .with(Monster)
  141. .with(Name {
  142. name: format!("{} #{}", &name, i),
  143. })
  144. .with(BlocksTile)
  145. .with(CombatStats {
  146. max_hp: 16,
  147. hp: 16,
  148. defense: 1,
  149. power: 4,
  150. })
  151. .build();
  152. }
  153. gs.ecs.insert(map);
  154. gs.ecs.insert(Point::new(player_x, player_y));
  155. gs.ecs.insert(player_entity);
  156. gs.ecs.insert(RunState::PreRun);
  157. rltk::main_loop(context, gs);
  158. }