main.rs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. use rltk::{GameState, Rltk, Point};
  2. use specs::prelude::*;
  3. mod components;
  4. pub use components::*;
  5. mod map;
  6. pub use map::*;
  7. mod player;
  8. use player::*;
  9. mod rect;
  10. pub use rect::Rect;
  11. mod visibility_system;
  12. use visibility_system::VisibilitySystem;
  13. mod monster_ai_system;
  14. use monster_ai_system::MonsterAI;
  15. mod map_indexing_system;
  16. use map_indexing_system::MapIndexingSystem;
  17. mod melee_combat_system;
  18. use melee_combat_system::MeleeCombatSystem;
  19. mod damage_system;
  20. use damage_system::DamageSystem;
  21. mod gui;
  22. mod gamelog;
  23. use gamelog::GameLog;
  24. mod spawner;
  25. mod inventory_system;
  26. use inventory_system::*;
  27. // ***** //
  28. // STATE //
  29. #[derive(PartialEq, Copy, Clone)]
  30. pub enum RunState {
  31. AwaitingInput,
  32. PreRun,
  33. PlayerTurn,
  34. MonsterTurn,
  35. ShowInventory,
  36. ShowDropItem,
  37. }
  38. pub struct State {
  39. pub ecs: World,
  40. }
  41. impl State {
  42. fn run_systems(&mut self) {
  43. let mut vis = VisibilitySystem{};
  44. vis.run_now(&self.ecs);
  45. let mut mob = MonsterAI{};
  46. mob.run_now(&self.ecs);
  47. let mut mapindex = MapIndexingSystem{};
  48. mapindex.run_now(&self.ecs);
  49. let mut mcs = MeleeCombatSystem{};
  50. mcs.run_now(&self.ecs);
  51. let mut dmgs = DamageSystem{};
  52. dmgs.run_now(&self.ecs);
  53. let mut pickup = ItemCollectionSystem{};
  54. pickup.run_now(&self.ecs);
  55. let mut potions = PotionUseSystem{};
  56. potions.run_now(&self.ecs);
  57. let mut drop_items = ItemDropSystem{};
  58. drop_items.run_now(&self.ecs);
  59. self.ecs.maintain();
  60. }
  61. }
  62. impl GameState for State {
  63. fn tick(&mut self, ctx : &mut Rltk) {
  64. ctx.cls();
  65. let mut newrunstate;
  66. {
  67. let runstate = self.ecs.fetch::<RunState>();
  68. newrunstate = *runstate;
  69. }
  70. match newrunstate {
  71. RunState::PreRun => {
  72. self.run_systems();
  73. self.ecs.maintain();
  74. newrunstate = RunState::AwaitingInput;
  75. }
  76. RunState::AwaitingInput => {
  77. newrunstate = player_input(self, ctx);
  78. }
  79. RunState::PlayerTurn => {
  80. self.run_systems();
  81. self.ecs.maintain();
  82. newrunstate = RunState::MonsterTurn;
  83. }
  84. RunState::MonsterTurn => {
  85. self.run_systems();
  86. self.ecs.maintain();
  87. newrunstate = RunState::AwaitingInput;
  88. }
  89. RunState::ShowInventory => {
  90. let result = gui::show_inventory(self, ctx);
  91. match result.0 {
  92. gui::ItemMenuResult::Cancel => newrunstate = RunState::AwaitingInput,
  93. gui::ItemMenuResult::NoResponse => {}
  94. gui::ItemMenuResult::Selected => {
  95. let item_entity = result.1.unwrap();
  96. let mut intent = self.ecs.write_storage::<WantsToDrinkPotion>();
  97. intent.insert(*self.ecs.fetch::<Entity>(), WantsToDrinkPotion{ potion: item_entity }).expect("Unable to insert intent");
  98. newrunstate = RunState::PlayerTurn;
  99. }
  100. }
  101. }
  102. RunState::ShowDropItem => {
  103. let result = gui::drop_item_menu(self, ctx);
  104. match result.0 {
  105. gui::ItemMenuResult::Cancel => newrunstate = RunState::AwaitingInput,
  106. gui::ItemMenuResult::NoResponse => {}
  107. gui::ItemMenuResult::Selected => {
  108. let item_entity = result.1.unwrap();
  109. let mut intent = self.ecs.write_storage::<WantsToDropItem>();
  110. intent.insert(*self.ecs.fetch::<Entity>(), WantsToDropItem{ item: item_entity }).expect("Unable to insert intent");
  111. newrunstate = RunState::PlayerTurn;
  112. }
  113. }
  114. }
  115. }
  116. {
  117. let mut runwriter = self.ecs.write_resource::<RunState>();
  118. *runwriter = newrunstate;
  119. }
  120. damage_system::delete_the_dead(&mut self.ecs);
  121. draw_map(&self.ecs, ctx);
  122. let positions = self.ecs.read_storage::<Position>();
  123. let renderables = self.ecs.read_storage::<Renderable>();
  124. let map = self.ecs.fetch::<Map>();
  125. let mut data = (&positions, &renderables).join().collect::<Vec<_>>();
  126. data.sort_by(|&a, &b| b.1.render_order.cmp(&a.1.render_order) );
  127. for (pos, render) in data.iter() {
  128. let idx = map.xy_idx(pos.x, pos.y);
  129. if map.visible_tiles[idx] { ctx.set(pos.x, pos.y, render.fg, render.bg, render.glyph) }
  130. }
  131. gui::draw_ui(&self.ecs, ctx);
  132. }
  133. }
  134. // ********
  135. // MAIN
  136. fn main() -> rltk::BError {
  137. use rltk::RltkBuilder;
  138. let context = RltkBuilder::simple80x50()
  139. .with_title("Saint Antony's Fire")
  140. .build()?;
  141. // Add scanlines
  142. //context.with_post_scanlines(true);
  143. let mut gs = State{
  144. ecs: World::new(),
  145. };
  146. gs.ecs.register::<Position>();
  147. gs.ecs.register::<Renderable>();
  148. gs.ecs.register::<Player>();
  149. gs.ecs.register::<Viewshed>();
  150. gs.ecs.register::<Monster>();
  151. gs.ecs.register::<Name>();
  152. gs.ecs.register::<BlocksTile>();
  153. gs.ecs.register::<CombatStats>();
  154. gs.ecs.register::<WantsToMelee>();
  155. gs.ecs.register::<SufferDamage>();
  156. gs.ecs.register::<Item>();
  157. gs.ecs.register::<Potion>();
  158. gs.ecs.register::<InBackpack>();
  159. gs.ecs.register::<WantsToPickupItem>();
  160. gs.ecs.register::<WantsToDrinkPotion>();
  161. gs.ecs.register::<WantsToDropItem>();
  162. let map = Map::new_map_rooms_and_corridors();
  163. let (player_x, player_y) = map.rooms[0].center();
  164. let player_entity = spawner::player(&mut gs.ecs, player_x, player_y);
  165. gs.ecs.insert(player_entity);
  166. let rng = rltk::RandomNumberGenerator::new();
  167. gs.ecs.insert(rng);
  168. for room in map.rooms.iter().skip(1) {
  169. spawner::spawn_room(&mut gs.ecs, room);
  170. }
  171. gs.ecs.insert(map);
  172. gs.ecs.insert(Point::new(player_x, player_y));
  173. gs.ecs.insert(RunState::PreRun);
  174. gs.ecs.insert(gamelog::GameLog{ entries : vec!["Saint Antony casts out...".to_string()] });
  175. rltk::main_loop(context, gs)
  176. }