main.rs 5.0 KB

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