try again or back out of challenge after final score

This commit is contained in:
Dustin Carlino 2020-01-30 13:50:46 -08:00
parent a0ec59b6c3
commit c62ca1a125
5 changed files with 87 additions and 14 deletions

View File

@ -5,7 +5,7 @@
You will first need: You will first need:
- Standard dependencies: `bash`, `curl`, `unzip`, `gunzip` - Standard dependencies: `bash`, `curl`, `unzip`, `gunzip`
- Rust, at least 1.40. https://www.rust-lang.org/tools/install - Rust, at least 1.41. https://www.rust-lang.org/tools/install
One-time setup: One-time setup:

View File

@ -81,11 +81,11 @@ impl GUI for Game {
self.states.pop().unwrap().on_destroy(ctx, &mut self.ui); self.states.pop().unwrap().on_destroy(ctx, &mut self.ui);
self.states.push(state); self.states.push(state);
} }
Transition::Clear(state) => { Transition::Clear(states) => {
while !self.states.is_empty() { while !self.states.is_empty() {
self.states.pop().unwrap().on_destroy(ctx, &mut self.ui); self.states.pop().unwrap().on_destroy(ctx, &mut self.ui);
} }
self.states.push(state); self.states.extend(states);
} }
Transition::ApplyObjectAction(action) => { Transition::ApplyObjectAction(action) => {
self.ui.per_obj.action_chosen(action); self.ui.per_obj.action_chosen(action);
@ -187,7 +187,7 @@ pub enum Transition {
Push(Box<dyn State>), Push(Box<dyn State>),
Replace(Box<dyn State>), Replace(Box<dyn State>),
PopThenReplace(Box<dyn State>), PopThenReplace(Box<dyn State>),
Clear(Box<dyn State>), Clear(Vec<Box<dyn State>>),
ApplyObjectAction(String), ApplyObjectAction(String),
PushTwice(Box<dyn State>, Box<dyn State>), PushTwice(Box<dyn State>, Box<dyn State>),
} }

View File

@ -1,8 +1,8 @@
use crate::common::Overlays; use crate::common::Overlays;
use crate::game::{msg, Transition}; use crate::game::Transition;
use crate::helpers::cmp_duration_shorter; use crate::helpers::cmp_duration_shorter;
use crate::managed::{WrappedComposite, WrappedOutcome}; use crate::managed::{WrappedComposite, WrappedOutcome};
use crate::sandbox::gameplay::{challenge_controller, GameplayMode, GameplayState}; use crate::sandbox::gameplay::{challenge_controller, FinalScore, GameplayMode, GameplayState};
use crate::ui::UI; use crate::ui::UI;
use ezgui::{EventCtx, GfxCtx, Line, ManagedWidget, Text}; use ezgui::{EventCtx, GfxCtx, Line, ManagedWidget, Text};
use geom::{Duration, Statistic, Time}; use geom::{Duration, Statistic, Time};
@ -51,8 +51,11 @@ impl GameplayState for FixTrafficSignals {
} }
if ui.primary.sim.is_done() { if ui.primary.sim.is_done() {
// TODO Stop the challenge somehow return Some(Transition::Push(FinalScore::new(
return Some(Transition::Push(msg("Final score", vec![final_score(ui)]))); ctx,
final_score(ui),
self.mode.clone(),
)));
} }
None None
@ -91,7 +94,7 @@ fn make_top_center(ctx: &mut EventCtx, ui: &UI, mode: GameplayMode) -> WrappedCo
WrappedComposite::text_button(ctx, "details", None).margin(5), WrappedComposite::text_button(ctx, "details", None).margin(5),
]) ])
.centered(), .centered(),
ManagedWidget::draw_text(ctx, Text::from(Line(format!("Goal: {}", GOAL)))), ManagedWidget::draw_text(ctx, Text::from(Line(format!("Goal: {} faster", GOAL)))),
], ],
) )
.cb( .cb(

View File

@ -7,17 +7,19 @@ mod play_scenario;
pub mod spawner; pub mod spawner;
use crate::challenges; use crate::challenges;
use crate::common::Overlays; use crate::challenges::challenges_picker;
use crate::common::{CommonState, Overlays};
use crate::edit::EditMode; use crate::edit::EditMode;
use crate::game::{msg, Transition}; use crate::game::{msg, State, Transition};
use crate::managed::WrappedComposite; use crate::managed::WrappedComposite;
use crate::pregame::main_menu;
use crate::render::{AgentColorScheme, InnerAgentColorScheme}; use crate::render::{AgentColorScheme, InnerAgentColorScheme};
use crate::sandbox::SandboxMode; use crate::sandbox::SandboxMode;
use crate::ui::UI; use crate::ui::UI;
use abstutil::Timer; use abstutil::Timer;
use ezgui::{ use ezgui::{
lctrl, Choice, Color, Composite, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, lctrl, Choice, Color, Composite, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line,
ManagedWidget, ModalMenu, Text, VerticalAlignment, Wizard, ManagedWidget, ModalMenu, Outcome, Text, VerticalAlignment, Wizard,
}; };
use geom::{Duration, Polygon}; use geom::{Duration, Polygon};
use map_model::{EditCmd, Map, MapEdits}; use map_model::{EditCmd, Map, MapEdits};
@ -320,3 +322,71 @@ fn challenge_controller(
Box::new(move |_, _| Some(Transition::Push(msg("Challenge", description.clone())))), Box::new(move |_, _| Some(Transition::Push(msg("Challenge", description.clone())))),
) )
} }
struct FinalScore {
composite: Composite,
mode: GameplayMode,
}
impl FinalScore {
fn new(ctx: &mut EventCtx, verdict: String, mode: GameplayMode) -> Box<dyn State> {
let mut txt = Text::prompt("Final score");
txt.add(Line(verdict));
Box::new(FinalScore {
composite: Composite::new(
ManagedWidget::col(vec![
ManagedWidget::draw_text(ctx, txt),
ManagedWidget::row(vec![
WrappedComposite::text_button(ctx, "try again", None),
WrappedComposite::text_button(ctx, "back to challenges", None),
])
.centered(),
])
.bg(Color::grey(0.4))
.outline(10.0, Color::WHITE)
.padding(10),
)
.aligned(HorizontalAlignment::Center, VerticalAlignment::Center)
.build(ctx),
mode,
})
}
}
impl State for FinalScore {
fn event(&mut self, ctx: &mut EventCtx, ui: &mut UI) -> Transition {
match self.composite.event(ctx) {
Some(Outcome::Clicked(x)) => match x.as_ref() {
"try again" => {
ui.primary.clear_sim();
Transition::PopThenReplace(Box::new(SandboxMode::new(
ctx,
ui,
self.mode.clone(),
)))
}
"back to challenges" => {
ui.primary.clear_sim();
Transition::Clear(vec![main_menu(ctx, ui), challenges_picker(ctx)])
}
_ => unreachable!(),
},
None => Transition::Keep,
}
}
fn draw(&self, g: &mut GfxCtx, ui: &UI) {
// Make it clear the map can't be interacted with right now.
g.fork_screenspace();
// TODO - OSD height
g.draw_polygon(
Color::BLACK.alpha(0.5),
&Polygon::rectangle(g.canvas.window_width, g.canvas.window_height),
);
g.unfork();
self.composite.draw(g);
// Still want to show hotkeys
CommonState::draw_osd(g, ui, &None);
}
}

View File

@ -153,7 +153,7 @@ impl State for SandboxMode {
ui.primary.clear_sim(); ui.primary.clear_sim();
ui.set_prebaked(None); ui.set_prebaked(None);
ctx.canvas.save_camera_state(ui.primary.map.get_name()); ctx.canvas.save_camera_state(ui.primary.map.get_name());
Some(Transition::Clear(main_menu(ctx, ui))) Some(Transition::Clear(vec![main_menu(ctx, ui)]))
} }
"quit challenge" => { "quit challenge" => {
if !ui.primary.map.get_edits().is_empty() { if !ui.primary.map.get_edits().is_empty() {
@ -166,7 +166,7 @@ impl State for SandboxMode {
ui.primary.clear_sim(); ui.primary.clear_sim();
ui.set_prebaked(None); ui.set_prebaked(None);
ctx.canvas.save_camera_state(ui.primary.map.get_name()); ctx.canvas.save_camera_state(ui.primary.map.get_name());
Some(Transition::Clear(main_menu(ctx, ui))) Some(Transition::Clear(vec![main_menu(ctx, ui)]))
} }
"keep playing" => Some(Transition::Pop), "keep playing" => Some(Transition::Pop),
_ => unreachable!(), _ => unreachable!(),