main.rs 4.6 KB

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