Add main menu

This commit is contained in:
Timothy Warren 2021-11-08 10:22:11 -05:00
parent 7d0200b262
commit 84934128d5
2 changed files with 176 additions and 26 deletions

View File

@ -1,9 +1,21 @@
use crate::{
game_log::GameLog, CombatStats, InBackpack, Map, Name, Player, Position, State, Viewshed,
};
use crate::components::{CombatStats, InBackpack, Name, Player, Position, Viewshed};
use crate::{game_log::GameLog, Map, RunState, State};
use rltk::{Point, Rltk, VirtualKeyCode, RGB};
use specs::prelude::*;
#[derive(PartialEq, Copy, Clone)]
pub enum MainMenuSelection {
NewGame,
LoadGame,
Quit,
}
#[derive(PartialEq, Copy, Clone)]
pub enum MainMenuResult {
NoSelection { selected: MainMenuSelection },
Selected { selected: MainMenuSelection },
}
pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
ctx.draw_box(
0,
@ -395,3 +407,113 @@ pub fn ranged_target(
(ItemMenuResult::NoResponse, None)
}
pub fn main_menu(gs: &mut State, ctx: &mut Rltk) -> MainMenuResult {
let runstate = gs.ecs.fetch::<RunState>();
ctx.print_color_centered(
15,
RGB::named(rltk::YELLOW),
RGB::named(rltk::BLACK),
"Rust Roguelike Tutorial",
);
if let RunState::MainMenu {
menu_selection: selection,
} = *runstate
{
if selection == MainMenuSelection::NewGame {
ctx.print_color_centered(
24,
RGB::named(rltk::MAGENTA),
RGB::named(rltk::BLACK),
"Begin New Game",
);
} else {
ctx.print_color_centered(
24,
RGB::named(rltk::WHITE),
RGB::named(rltk::BLACK),
"Begin New Game",
);
}
if selection == MainMenuSelection::LoadGame {
ctx.print_color_centered(
25,
RGB::named(rltk::MAGENTA),
RGB::named(rltk::BLACK),
"Load Game",
);
} else {
ctx.print_color_centered(
25,
RGB::named(rltk::WHITE),
RGB::named(rltk::BLACK),
"Load Game",
);
}
if selection == MainMenuSelection::Quit {
ctx.print_color_centered(
26,
RGB::named(rltk::MAGENTA),
RGB::named(rltk::BLACK),
"Quit",
);
} else {
ctx.print_color_centered(26, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), "Quit");
}
match ctx.key {
None => {
return MainMenuResult::NoSelection {
selected: selection,
}
}
Some(key) => match key {
VirtualKeyCode::Escape => {
return MainMenuResult::NoSelection {
selected: selection,
}
}
VirtualKeyCode::Up => {
let newselection;
match selection {
MainMenuSelection::NewGame => newselection = MainMenuSelection::Quit,
MainMenuSelection::LoadGame => newselection = MainMenuSelection::NewGame,
MainMenuSelection::Quit => newselection = MainMenuSelection::LoadGame,
}
return MainMenuResult::NoSelection {
selected: newselection,
};
}
VirtualKeyCode::Down => {
let newselection;
match selection {
MainMenuSelection::NewGame => newselection = MainMenuSelection::LoadGame,
MainMenuSelection::LoadGame => newselection = MainMenuSelection::Quit,
MainMenuSelection::Quit => newselection = MainMenuSelection::NewGame,
}
return MainMenuResult::NoSelection {
selected: newselection,
};
}
VirtualKeyCode::Return => {
return MainMenuResult::Selected {
selected: selection,
}
}
_ => {
return MainMenuResult::NoSelection {
selected: selection,
}
}
},
}
}
MainMenuResult::NoSelection {
selected: MainMenuSelection::NewGame,
}
}

View File

@ -48,7 +48,13 @@ pub enum RunState {
MonsterTurn,
ShowInventory,
ShowDropItem,
ShowTargeting { range: i32, item: Entity },
ShowTargeting {
range: i32,
item: Entity,
},
MainMenu {
menu_selection: gui::MainMenuSelection,
},
}
pub struct State {
@ -91,34 +97,39 @@ impl State {
impl GameState for State {
fn tick(&mut self, ctx: &mut Rltk) {
ctx.cls();
// Draw the UI
draw_map(&self.ecs, ctx);
{
let positions = self.ecs.read_storage::<Position>();
let renderables = self.ecs.read_storage::<Renderable>();
let map = self.ecs.fetch::<Map>();
let mut data: Vec<_> = (&positions, &renderables).join().collect();
data.sort_by(|&a, &b| b.1.render_order.cmp(&a.1.render_order));
for (pos, render) in data.iter() {
let idx = map.xy_idx(pos.x, pos.y);
if map.visible_tiles[idx] {
ctx.set(pos.x, pos.y, render.fg, render.bg, render.glyph)
}
}
gui::draw_ui(&self.ecs, ctx);
}
let mut newrunstate;
{
let runstate = self.ecs.fetch::<RunState>();
newrunstate = *runstate;
}
ctx.cls();
match newrunstate {
RunState::MainMenu { .. } => {}
_ => {
// Draw the UI
draw_map(&self.ecs, ctx);
{
let positions = self.ecs.read_storage::<Position>();
let renderables = self.ecs.read_storage::<Renderable>();
let map = self.ecs.fetch::<Map>();
let mut data: Vec<_> = (&positions, &renderables).join().collect();
data.sort_by(|&a, &b| b.1.render_order.cmp(&a.1.render_order));
for (pos, render) in data.iter() {
let idx = map.xy_idx(pos.x, pos.y);
if map.visible_tiles[idx] {
ctx.set(pos.x, pos.y, render.fg, render.bg, render.glyph)
}
}
gui::draw_ui(&self.ecs, ctx);
}
}
}
match newrunstate {
RunState::PreRun => {
self.run_systems();
@ -212,6 +223,23 @@ impl GameState for State {
}
}
}
RunState::MainMenu { .. } => {
let result = gui::main_menu(self, ctx);
match result {
gui::MainMenuResult::NoSelection { selected } => {
newrunstate = RunState::MainMenu {
menu_selection: selected,
}
}
gui::MainMenuResult::Selected { selected } => match selected {
gui::MainMenuSelection::NewGame => newrunstate = RunState::PreRun,
gui::MainMenuSelection::LoadGame => newrunstate = RunState::PreRun,
gui::MainMenuSelection::Quit => {
::std::process::exit(0);
}
},
}
}
}
{