From 27d14ac97dee2922419edfe056d30e46cca6bd4b Mon Sep 17 00:00:00 2001 From: Llywelwyn Date: Tue, 11 Jul 2023 08:17:18 +0100 Subject: [PATCH] gameover --- src/damage_system.rs | 6 ++--- src/gui.rs | 31 ++++++++++++++++++++++++ src/main.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 3 deletions(-) diff --git a/src/damage_system.rs b/src/damage_system.rs index eb5df75..8330e13 100644 --- a/src/damage_system.rs +++ b/src/damage_system.rs @@ -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::GameOver; } } } diff --git a/src/gui.rs b/src/gui.rs index 460c641..4758a54 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -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, + }, + } +} diff --git a/src/main.rs b/src/main.rs index 63783b2..c10fc7f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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::(); + let mut rng = self.ecs.write_resource::(); + *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::(); + *player_position = Point::new(player_x, player_y); + let mut position_components = self.ecs.write_storage::(); + let mut player_entity_writer = self.ecs.write_resource::(); + *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::(); + 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;