mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-24 23:15:24 +03:00
Add a 'blog' gameplay mode, which disables going back to the title screen, switching maps, etc. cyipt/actdev#66
This commit is contained in:
parent
7c0bac236a
commit
b38b7da8bb
@ -109,6 +109,7 @@ pub fn main() {
|
||||
};
|
||||
flags.sim_flags.load = name.path();
|
||||
flags.study_area = Some(site);
|
||||
mode = Some(sandbox::GameplayMode::Blog(name));
|
||||
}
|
||||
|
||||
args.done();
|
||||
@ -143,7 +144,11 @@ fn setup_app(
|
||||
// usually time is midnight, so save some effort and start with the correct color scheme. If
|
||||
// we're loading a savestate and it's actually daytime, we'll pay a small penalty to switch
|
||||
// colors.
|
||||
if maybe_mode.is_some() {
|
||||
if let Some(GameplayMode::PlayScenario(_, _, _))
|
||||
| Some(GameplayMode::FixTrafficSignals)
|
||||
| Some(GameplayMode::OptimizeCommute(_, _))
|
||||
| Some(GameplayMode::Tutorial(_)) = maybe_mode
|
||||
{
|
||||
opts.color_scheme = map_gui::colors::ColorSchemeChoice::NightMode;
|
||||
}
|
||||
let cs = map_gui::colors::ColorScheme::new(ctx, opts.color_scheme);
|
||||
@ -273,10 +278,23 @@ fn finish_app_setup(
|
||||
crate::sandbox::gameplay::Tutorial::initialize(ctx, app);
|
||||
}
|
||||
|
||||
let start_daytime = Box::new(|ctx: &mut EventCtx, app: &mut App| {
|
||||
ctx.loading_screen("start in the daytime", |_, mut timer| {
|
||||
app.primary
|
||||
.sim
|
||||
.timed_step(&app.primary.map, Duration::hours(6), &mut None, &mut timer);
|
||||
});
|
||||
vec![Transition::Keep]
|
||||
});
|
||||
|
||||
let states: Vec<Box<dyn State<App>>> = if title {
|
||||
vec![Box::new(TitleScreen::new(ctx, app))]
|
||||
} else if let Some(mode) = maybe_mode {
|
||||
vec![SandboxMode::simple_new(ctx, app, mode)]
|
||||
if let GameplayMode::Blog(_) = mode {
|
||||
vec![SandboxMode::async_new(ctx, app, mode, start_daytime)]
|
||||
} else {
|
||||
vec![SandboxMode::simple_new(ctx, app, mode)]
|
||||
}
|
||||
} else {
|
||||
// We got here by just passing --dev and a map as flags; we're just looking at an empty
|
||||
// map. Start in the daytime.
|
||||
@ -284,17 +302,7 @@ fn finish_app_setup(
|
||||
ctx,
|
||||
app,
|
||||
GameplayMode::Freeform(app.primary.map.get_name().clone()),
|
||||
Box::new(|ctx, app| {
|
||||
ctx.loading_screen("start in the daytime", |_, mut timer| {
|
||||
app.primary.sim.timed_step(
|
||||
&app.primary.map,
|
||||
Duration::hours(6),
|
||||
&mut None,
|
||||
&mut timer,
|
||||
);
|
||||
});
|
||||
vec![Transition::Keep]
|
||||
}),
|
||||
start_daytime,
|
||||
)]
|
||||
};
|
||||
if let Some(ss) = savestate {
|
||||
|
78
game/src/sandbox/gameplay/blog.rs
Normal file
78
game/src/sandbox/gameplay/blog.rs
Normal file
@ -0,0 +1,78 @@
|
||||
use map_gui::tools::nice_map_name;
|
||||
use widgetry::{
|
||||
lctrl, EventCtx, GfxCtx, HorizontalAlignment, Key, Line, Outcome, Panel, StyledButtons,
|
||||
VerticalAlignment, Widget,
|
||||
};
|
||||
|
||||
use crate::app::{App, Transition};
|
||||
use crate::edit::EditMode;
|
||||
use crate::sandbox::gameplay::freeform::ChangeScenario;
|
||||
use crate::sandbox::gameplay::{GameplayMode, GameplayState};
|
||||
use crate::sandbox::{Actions, SandboxControls};
|
||||
|
||||
pub struct Blog {
|
||||
top_center: Panel,
|
||||
}
|
||||
|
||||
impl Blog {
|
||||
pub fn new(ctx: &mut EventCtx) -> Box<dyn GameplayState> {
|
||||
Box::new(Blog {
|
||||
top_center: Panel::empty(ctx),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl GameplayState for Blog {
|
||||
fn event(
|
||||
&mut self,
|
||||
ctx: &mut EventCtx,
|
||||
app: &mut App,
|
||||
_: &mut SandboxControls,
|
||||
_: &mut Actions,
|
||||
) -> Option<Transition> {
|
||||
match self.top_center.event(ctx) {
|
||||
Outcome::Clicked(x) => match x.as_ref() {
|
||||
// TODO This'll bring us out of this GameplayMode.
|
||||
"change scenario" => Some(Transition::Push(ChangeScenario::new(ctx, app, "none"))),
|
||||
"edit map" => Some(Transition::Push(EditMode::new(
|
||||
ctx,
|
||||
app,
|
||||
GameplayMode::Freeform(app.primary.map.get_name().clone()),
|
||||
))),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _: &App) {
|
||||
self.top_center.draw(g);
|
||||
}
|
||||
|
||||
fn recreate_panels(&mut self, ctx: &mut EventCtx, app: &App) {
|
||||
let row = Widget::row(vec![
|
||||
Line(nice_map_name(app.primary.map.get_name()))
|
||||
.small_heading()
|
||||
.draw(ctx),
|
||||
Widget::vert_separator(ctx, 50.0),
|
||||
ctx.style()
|
||||
.btn_light_popup_icon_text("system/assets/tools/calendar.svg", "none")
|
||||
.hotkey(Key::S)
|
||||
.build_widget(ctx, "change scenario"),
|
||||
ctx.style()
|
||||
.btn_outline_light_icon_text("system/assets/tools/pencil.svg", "Edit map")
|
||||
.hotkey(lctrl(Key::E))
|
||||
.build_widget(ctx, "edit map"),
|
||||
])
|
||||
.centered();
|
||||
|
||||
self.top_center = Panel::new(row)
|
||||
.aligned(HorizontalAlignment::Center, VerticalAlignment::Top)
|
||||
.build(ctx);
|
||||
}
|
||||
|
||||
fn has_tool_panel(&self) -> bool {
|
||||
// Get rid of the home button, which would allow escaping to the title screen
|
||||
false
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ use crate::pregame::MainMenu;
|
||||
use crate::sandbox::{Actions, SandboxControls, SandboxMode};
|
||||
|
||||
// TODO pub so challenges can grab cutscenes and SandboxMode can dispatch to actions. Weird?
|
||||
mod blog;
|
||||
pub mod commute;
|
||||
pub mod fix_traffic_signals;
|
||||
pub mod freeform;
|
||||
@ -38,6 +39,7 @@ pub enum GameplayMode {
|
||||
PlayScenario(MapName, String, Vec<ScenarioModifier>),
|
||||
FixTrafficSignals,
|
||||
OptimizeCommute(OrigPersonID, Duration),
|
||||
Blog(MapName),
|
||||
|
||||
// current
|
||||
Tutorial(TutorialPointer),
|
||||
@ -102,13 +104,15 @@ impl GameplayMode {
|
||||
GameplayMode::FixTrafficSignals => MapName::seattle("downtown"),
|
||||
GameplayMode::OptimizeCommute(_, _) => MapName::seattle("montlake"),
|
||||
GameplayMode::Tutorial(_) => MapName::seattle("montlake"),
|
||||
GameplayMode::Blog(ref name) => name.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scenario(&self, app: &App, mut rng: XorShiftRng, timer: &mut Timer) -> LoadScenario {
|
||||
let map = &app.primary.map;
|
||||
let name = match self {
|
||||
GameplayMode::Freeform(_) => {
|
||||
// TODO Start with a scenario in blog mode, once all the actdev scenarios are imported.
|
||||
GameplayMode::Freeform(_) | GameplayMode::Blog(_) => {
|
||||
let mut s = Scenario::empty(map, "empty");
|
||||
s.only_seed_buses = None;
|
||||
return LoadScenario::Scenario(s);
|
||||
@ -214,6 +218,7 @@ impl GameplayMode {
|
||||
commute::OptimizeCommute::new(ctx, app, *p, *goal)
|
||||
}
|
||||
GameplayMode::Tutorial(current) => Tutorial::make_gameplay(ctx, app, *current),
|
||||
GameplayMode::Blog(_) => blog::Blog::new(ctx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user