Skip to content

Commit 9978314

Browse files
committed
added GameOver screen
1 parent 01bfd04 commit 9978314

File tree

5 files changed

+91
-14
lines changed

5 files changed

+91
-14
lines changed

src/damage_system.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use crate::{
2-
components::{Name, Position, Positionable},
2+
components::{Name, Player, Position, Positionable},
33
gamelog::GameLog,
44
map::Map,
5+
RunState,
56
};
67

78
use super::{CombatStats, EventIncomingDamage};
@@ -27,23 +28,29 @@ impl<'a> System<'a> for DamageSystem {
2728
}
2829
}
2930

30-
pub fn delete_the_dead(ecs: &mut World) {
31+
pub fn delete_the_dead(ecs: &mut World) -> Option<RunState> {
3132
let mut dead: Vec<Entity> = Vec::new();
33+
let mut newrunstate_opt = None;
3234
{
3335
let entities = ecs.entities();
3436
let mut log = ecs.write_resource::<GameLog>();
3537
let combat_stats = ecs.read_storage::<CombatStats>();
3638
let names = ecs.read_storage::<Name>();
3739
let positions = ecs.read_storage::<Position>();
40+
let players = ecs.read_storage::<Player>();
3841
(&entities, &combat_stats, &positions)
3942
.join()
4043
.for_each(|(ent, stats, pos)| {
4144
if stats.hp < 1 {
42-
// TODO: add different handling for player death
4345
dead.push(ent);
4446
if let Some(victim_name) = names.get(ent) {
4547
log.entries.push(format!("{} is dead.", victim_name.name));
4648
}
49+
if let Some(_player) = players.get(ent) {
50+
{
51+
newrunstate_opt = Some(RunState::GameOver);
52+
}
53+
}
4754
let ix = {
4855
let map = ecs.fetch::<Map>();
4956
map.pos_idx(pos.from())
@@ -57,4 +64,5 @@ pub fn delete_the_dead(ecs: &mut World) {
5764
ecs.delete_entity(*victim)
5865
.unwrap_or_else(|er| panic!("Unable to delete entity with id {}: {}", victim.id(), er))
5966
});
67+
newrunstate_opt
6068
}

src/gui.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,3 +557,42 @@ pub fn main_menu(gs: &State, ctx: &mut BTerm) -> MainMenuResult {
557557
}
558558
}
559559
}
560+
561+
#[derive(PartialEq, Copy, Clone)]
562+
pub enum GameOverResult {
563+
NoSelection,
564+
QuitToMenu,
565+
}
566+
567+
pub fn game_over(ctx: &mut BTerm) -> GameOverResult {
568+
ctx.print_color_centered(
569+
15,
570+
RGB::named(YELLOW),
571+
RGB::named(BLACK),
572+
"Your journey has ended!",
573+
);
574+
ctx.print_color_centered(
575+
17,
576+
RGB::named(WHITE),
577+
RGB::named(BLACK),
578+
"One day, we'll tell you all about how you did.",
579+
);
580+
ctx.print_color_centered(
581+
18,
582+
RGB::named(WHITE),
583+
RGB::named(BLACK),
584+
"That day, sadly, is not in this chapter..",
585+
);
586+
587+
ctx.print_color_centered(
588+
20,
589+
RGB::named(MAGENTA),
590+
RGB::named(BLACK),
591+
"Press any key to return to the menu.",
592+
);
593+
594+
match ctx.key {
595+
None => GameOverResult::NoSelection,
596+
Some(_) => GameOverResult::QuitToMenu,
597+
}
598+
}

src/main.rs

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ pub enum RunState {
6868
KeyBindingsMenu,
6969
SaveGame,
7070
NextLevel,
71+
GameOver,
7172
}
7273

7374
pub struct State {
@@ -230,15 +231,25 @@ impl GameState for State {
230231
*runstate
231232
};
232233

234+
// FIXME: appears runstate is being possibly set to AwaitingInput before
235+
// going into `tick`
236+
/*
237+
tick runstate: PlayerTurn
238+
tick runstate: MonsterTurn
239+
tick runstate: AwaitingInput
240+
new runstate: GameOver
241+
tick runstate: AwaitingInput
242+
tick runstate: AwaitingInput
243+
*/
233244
ctx.cls();
234245

235-
match newrunstate {
236-
RunState::MainMenu { .. } => {}
246+
newrunstate = match newrunstate {
247+
RunState::MainMenu { .. } => newrunstate,
237248
_ => {
238249
draw_map(&self.ecs, ctx);
239250
draw_ui(&self.ecs, ctx, &self.display);
240251

241-
delete_the_dead(&mut self.ecs);
252+
let game_over_opt = delete_the_dead(&mut self.ecs);
242253

243254
{
244255
// draw renderables
@@ -254,9 +265,9 @@ impl GameState for State {
254265
ctx.set(pos.xx, pos.yy, render.fg, render.bg, render.glyph);
255266
});
256267
}
268+
game_over_opt.unwrap_or(newrunstate)
257269
}
258-
}
259-
270+
};
260271
match newrunstate {
261272
RunState::PreRun => {
262273
self.run_systems();
@@ -362,6 +373,7 @@ impl GameState for State {
362373
}
363374
gui::MainMenuStatus::Selected => match result.highlighted {
364375
gui::MainMenuSelection::NewGame => {
376+
delete_state(&mut self.ecs);
365377
(*self, _) = init_state(false, Some(ctx));
366378
newrunstate = RunState::PreRun
367379
}
@@ -404,12 +416,33 @@ impl GameState for State {
404416
self.goto_next_level();
405417
newrunstate = RunState::PreRun;
406418
}
419+
RunState::GameOver => {
420+
let result = gui::game_over(ctx);
421+
match result {
422+
gui::GameOverResult::NoSelection => {}
423+
gui::GameOverResult::QuitToMenu => {
424+
delete_state(&mut self.ecs);
425+
newrunstate = RunState::MainMenu {
426+
menu_selection: gui::MainMenuSelection::NewGame,
427+
}
428+
}
429+
}
430+
}
407431
}
408432
let mut runstate = self.ecs.fetch_mut::<RunState>();
409433
*runstate = newrunstate;
410434
}
411435
}
412436

437+
pub fn delete_state(ecs: &mut World) {
438+
// Delete everything
439+
let to_delete: Vec<Entity> = ecs.entities().join().collect();
440+
to_delete.iter().for_each(|entity| {
441+
ecs.delete_entity(*entity)
442+
.unwrap_or_else(|er| panic!("Unable to delete entity with id {}: {}", entity.id(), er))
443+
});
444+
}
445+
413446
pub fn init_state(test_ecs: bool, ctxt_opt: Option<&BTerm>) -> (State, Option<BTerm>) {
414447
let (mut gs, opt_ctxt) = if test_ecs {
415448
(

src/saveload_system.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use std::{
55

66
use specs::{prelude::*, saveload::*, World, WorldExt};
77

8-
use crate::components::*;
98
use crate::execute_with_type_list;
9+
use crate::{components::*, delete_state};
1010

1111
const SAVE_FILE: &str = "savegame.json";
1212

@@ -78,11 +78,7 @@ macro_rules! deserialize_individually {
7878

7979
pub fn load_game(ecs: &mut World) {
8080
// Delete everything
81-
let to_delete: Vec<Entity> = ecs.entities().join().collect();
82-
to_delete.iter().for_each(|entity| {
83-
ecs.delete_entity(*entity)
84-
.unwrap_or_else(|er| panic!("Unable to delete entity with id {}: {}", entity.id(), er))
85-
});
81+
delete_state(ecs);
8682
let save_file_contents = fs::read_to_string(SAVE_FILE)
8783
.unwrap_or_else(|_| panic!("Unable to read file {}", SAVE_FILE));
8884
let mut de_ser = serde_json::Deserializer::from_str(&save_file_contents);

src/util.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ fn cloneable_fn_test_fn() -> () {
6666
aa + bb
6767
}
6868
let _foo2 = foo.clone();
69+
#[allow(unused_allocation)]
6970
let _foo3 = Box::new(foo).clone_box();
7071
}
7172

0 commit comments

Comments
 (0)