spawner.rs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. extern crate rltk;
  2. use rltk::{ RGB, RandomNumberGenerator };
  3. extern crate specs;
  4. use specs::prelude::*;
  5. use super::{CombatStats, Player, Renderable, Name, Position, Viewshed, Monster, BlocksTile, Rect, Item, Potion, map::MAPWIDTH};
  6. /// Spawns the player and returns his/her entity object.
  7. pub fn player(ecs : &mut World, player_x : i32, player_y : i32) -> Entity {
  8. ecs
  9. .create_entity()
  10. .with(Position { x: player_x, y: player_y })
  11. .with(Renderable {
  12. glyph: rltk::to_cp437('@'),
  13. fg: RGB::named(rltk::YELLOW),
  14. bg: RGB::named(rltk::BLACK),
  15. render_order: 0
  16. })
  17. .with(Player{})
  18. .with(Viewshed{ visible_tiles : Vec::new(), range: 8, dirty: true })
  19. .with(Name{name: "Player".to_string() })
  20. .with(CombatStats{ max_hp: 30, hp: 30, defense: 2, power: 5 })
  21. .build()
  22. }
  23. const MAX_MONSTERS : i32 = 4;
  24. const MAX_ITEMS : i32 = 2;
  25. /// Fills a room with stuff!
  26. pub fn spawn_room(ecs: &mut World, room : &Rect) {
  27. let mut monster_spawn_points : Vec<usize> = Vec::new();
  28. let mut item_spawn_points : Vec<usize> = Vec::new();
  29. // Scope to keep the borrow checker happy
  30. {
  31. let mut rng = ecs.write_resource::<RandomNumberGenerator>();
  32. let num_monsters = rng.roll_dice(1, MAX_MONSTERS + 2) - 3;
  33. let num_items = rng.roll_dice(1, MAX_ITEMS + 2) - 3;
  34. for _i in 0 .. num_monsters {
  35. let mut added = false;
  36. while !added {
  37. let x = (room.x1 + rng.roll_dice(1, i32::abs(room.x2 - room.x1))) as usize;
  38. let y = (room.y1 + rng.roll_dice(1, i32::abs(room.y2 - room.y1))) as usize;
  39. let idx = (y * MAPWIDTH) + x;
  40. if !monster_spawn_points.contains(&idx) {
  41. monster_spawn_points.push(idx);
  42. added = true;
  43. }
  44. }
  45. }
  46. for _i in 0 .. num_items {
  47. let mut added = false;
  48. while !added {
  49. let x = (room.x1 + rng.roll_dice(1, i32::abs(room.x2 - room.x1))) as usize;
  50. let y = (room.y1 + rng.roll_dice(1, i32::abs(room.y2 - room.y1))) as usize;
  51. let idx = (y * MAPWIDTH) + x;
  52. if !item_spawn_points.contains(&idx) {
  53. item_spawn_points.push(idx);
  54. added = true;
  55. }
  56. }
  57. }
  58. }
  59. // Actually spawn the monsters
  60. for idx in monster_spawn_points.iter() {
  61. let x = *idx % MAPWIDTH;
  62. let y = *idx / MAPWIDTH;
  63. random_monster(ecs, x as i32, y as i32);
  64. }
  65. // Actually spawn the potions
  66. for idx in item_spawn_points.iter() {
  67. let x = *idx % MAPWIDTH;
  68. let y = *idx / MAPWIDTH;
  69. health_potion(ecs, x as i32, y as i32);
  70. }
  71. }
  72. fn random_monster(ecs: &mut World, x: i32, y: i32) {
  73. let roll :i32;
  74. {
  75. let mut rng = ecs.write_resource::<RandomNumberGenerator>();
  76. roll = rng.roll_dice(1, 2);
  77. }
  78. match roll {
  79. 1 => { orc(ecs, x, y) }
  80. _ => { goblin(ecs, x, y) }
  81. }
  82. }
  83. fn orc(ecs: &mut World, x: i32, y: i32) { monster(ecs, x, y, rltk::to_cp437('o'), "Orc"); }
  84. fn goblin(ecs: &mut World, x: i32, y: i32) { monster(ecs, x, y, rltk::to_cp437('g'), "Goblin"); }
  85. fn monster<S : ToString>(ecs: &mut World, x: i32, y: i32, glyph : u8, name : S) {
  86. ecs.create_entity()
  87. .with(Position{ x, y })
  88. .with(Renderable{
  89. glyph,
  90. fg: RGB::named(rltk::RED),
  91. bg: RGB::named(rltk::BLACK),
  92. render_order: 1
  93. })
  94. .with(Viewshed{ visible_tiles : Vec::new(), range: 8, dirty: true })
  95. .with(Monster{})
  96. .with(Name{ name : name.to_string() })
  97. .with(BlocksTile{})
  98. .with(CombatStats{ max_hp: 16, hp: 16, defense: 1, power: 4 })
  99. .build();
  100. }
  101. fn health_potion(ecs: &mut World, x: i32, y: i32) {
  102. ecs.create_entity()
  103. .with(Position{ x, y })
  104. .with(Renderable{
  105. glyph: rltk::to_cp437('¡'),
  106. fg: RGB::named(rltk::MAGENTA),
  107. bg: RGB::named(rltk::BLACK),
  108. render_order: 2
  109. })
  110. .with(Name{ name : "Health Potion".to_string() })
  111. .with(Item{})
  112. .with(Potion{ heal_amount: 8 })
  113. .build();
  114. }