This commit is contained in:
Llywelwyn 2023-07-11 08:17:18 +01:00
parent 8d04c40389
commit 27d14ac97d
3 changed files with 91 additions and 3 deletions

View file

@ -1,4 +1,4 @@
use super::{gamelog, CombatStats, Entities, Item, Map, Name, Player, Position, SufferDamage};
use super::{gamelog, CombatStats, Entities, Item, Map, Name, Player, Position, RunState, SufferDamage};
use specs::prelude::*;
pub struct DamageSystem {}
@ -64,8 +64,8 @@ pub fn delete_the_dead(ecs: &mut World) {
dead.push(entity)
}
Some(_) => {
// This is where the GameOver state will go eventully. But currently
// it's easier to just keep the game going for the sake of testing.
let mut runstate = ecs.write_resource::<RunState>();
*runstate = RunState::GameOver;
}
}
}

View file

@ -389,3 +389,34 @@ pub fn main_menu(gs: &mut State, ctx: &mut Rltk) -> MainMenuResult {
}
MainMenuResult::NoSelection { selected: MainMenuSelection::NewGame }
}
#[derive(PartialEq, Copy, Clone)]
pub enum GameOverResult {
NoSelection,
QuitToMenu,
}
pub fn game_over(ctx: &mut Rltk) -> GameOverResult {
ctx.print_color_centered(15, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "Your journey has ended!");
ctx.print_color_centered(
17,
RGB::named(rltk::WHITE),
RGB::named(rltk::BLACK),
format!("You died after {} turns.", crate::gamelog::get_event_count("Turn")),
);
ctx.print_color_centered(
19,
RGB::named(rltk::MAGENTA),
RGB::named(rltk::BLACK),
"Press Escape to return to the menu.",
);
match ctx.key {
None => GameOverResult::NoSelection,
Some(key) => match key {
VirtualKeyCode::Escape => GameOverResult::QuitToMenu,
_ => GameOverResult::NoSelection,
},
}
}

View file

@ -52,6 +52,7 @@ pub enum RunState {
ShowTargeting { range: i32, item: Entity, aoe: i32 },
MainMenu { menu_selection: gui::MainMenuSelection },
SaveGame,
GameOver,
NextLevel,
MagicMapReveal { row: i32, cursed: bool },
}
@ -174,6 +175,52 @@ impl State {
player_health.hp = i32::max(player_health.hp, player_health.max_hp / 2);
}
}
fn game_over_cleanup(&mut self) {
// Delete everything
let mut to_delete = Vec::new();
for e in self.ecs.entities().join() {
to_delete.push(e);
}
for del in to_delete.iter() {
self.ecs.delete_entity(*del).expect("Deletion failed");
}
// Build a new map and place the player
let worldmap;
{
let mut worldmap_resource = self.ecs.write_resource::<Map>();
let mut rng = self.ecs.write_resource::<RandomNumberGenerator>();
*worldmap_resource = Map::new_map_rooms_and_corridors(&mut rng, 1);
worldmap = worldmap_resource.clone();
}
// Spawn bad guys
for room in worldmap.rooms.iter().skip(1) {
spawner::spawn_room(&mut self.ecs, room, 1);
}
// Place the player and update resources
let (player_x, player_y) = worldmap.rooms[0].centre();
let player_entity = spawner::player(&mut self.ecs, player_x, player_y, "Player".to_string());
let mut player_position = self.ecs.write_resource::<Point>();
*player_position = Point::new(player_x, player_y);
let mut position_components = self.ecs.write_storage::<Position>();
let mut player_entity_writer = self.ecs.write_resource::<Entity>();
*player_entity_writer = player_entity;
let player_pos_comp = position_components.get_mut(player_entity);
if let Some(player_pos_comp) = player_pos_comp {
player_pos_comp.x = player_x;
player_pos_comp.y = player_y;
}
// Mark the player's visibility as dirty
let mut viewshed_components = self.ecs.write_storage::<Viewshed>();
let vs = viewshed_components.get_mut(player_entity);
if let Some(vs) = vs {
vs.dirty = true;
}
}
}
impl GameState for State {
@ -342,6 +389,16 @@ impl GameState for State {
saveload_system::save_game(&mut self.ecs);
new_runstate = RunState::MainMenu { menu_selection: gui::MainMenuSelection::LoadGame };
}
RunState::GameOver => {
let result = gui::game_over(ctx);
match result {
gui::GameOverResult::NoSelection => {}
gui::GameOverResult::QuitToMenu => {
self.game_over_cleanup();
new_runstate = RunState::MainMenu { menu_selection: gui::MainMenuSelection::NewGame };
}
}
}
RunState::NextLevel => {
self.goto_next_level();
new_runstate = RunState::PreRun;