Draw traffic signals changing over time in the experiment

This commit is contained in:
Dustin Carlino 2020-12-08 09:05:06 -08:00
parent c8a37a27a0
commit 3d361074ab
4 changed files with 47 additions and 41 deletions

View File

@ -31,7 +31,6 @@ pub struct Game {
animator: Animator,
snow: SnowEffect,
time: Time,
state: GameState,
player: Player,
}
@ -45,6 +44,7 @@ impl Game {
upzones: HashSet<BuildingID>,
) -> Box<dyn State<App>> {
app.session.current_vehicle = vehicle.name.clone();
app.time = Time::START_OF_DAY;
let title_panel = Panel::new(Widget::row(vec![
Btn::svg_def("system/assets/tools/home.svg")
@ -108,7 +108,6 @@ impl Game {
animator: Animator::new(ctx),
snow: SnowEffect::new(ctx),
time: Time::START_OF_DAY,
state,
player,
};
@ -121,7 +120,7 @@ impl Game {
fn update_panels(&mut self, ctx: &mut EventCtx, app: &App) {
let time = format!(
"{}",
self.state.level.time_limit - (self.time - Time::START_OF_DAY)
self.state.level.time_limit - (app.time - Time::START_OF_DAY)
)
.draw_text(ctx);
self.time_panel.replace(ctx, "time", time);
@ -159,9 +158,9 @@ impl Game {
impl State<App> for Game {
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition {
if let Some(dt) = ctx.input.nonblocking_is_update_event() {
self.time += dt;
app.time += dt;
if self.time - Time::START_OF_DAY >= self.state.level.time_limit {
if app.time - Time::START_OF_DAY >= self.state.level.time_limit {
return Transition::Replace(Results::new(
ctx,
app,
@ -192,7 +191,7 @@ impl State<App> for Game {
if let Some(increase) = self.state.present_dropped(ctx, app, b) {
let path_speed = Duration::seconds(0.2);
self.animator.add(
self.time,
app.time,
path_speed,
Effect::FollowPath {
color: app.session.colors.score,
@ -201,7 +200,7 @@ impl State<App> for Game {
},
);
self.animator.add(
self.time + path_speed,
app.time + path_speed,
Duration::seconds(0.5),
Effect::Scale {
lerp_scale: (1.0, 4.0),
@ -220,7 +219,7 @@ impl State<App> for Game {
self.state.energy += refill;
let path_speed = Duration::seconds(0.2);
self.animator.add(
self.time,
app.time,
path_speed,
Effect::FollowPath {
color: app.session.colors.energy,
@ -229,7 +228,7 @@ impl State<App> for Game {
},
);
self.animator.add(
self.time + path_speed,
app.time + path_speed,
Duration::seconds(0.5),
Effect::Scale {
lerp_scale: (1.0, 4.0),
@ -258,19 +257,18 @@ impl State<App> for Game {
if let Some(t) = self.minimap.event(ctx, app) {
return t;
}
self.animator.event(ctx, self.time);
self.snow.event(ctx, self.time);
self.animator.event(ctx, app.time);
self.snow.event(ctx, app.time);
if self.state.has_energy() {
self.state.energyless_arrow = None;
} else {
if self.state.energyless_arrow.is_none() {
self.state.energyless_arrow = Some(EnergylessArrow::new(ctx, self.time));
self.state.energyless_arrow = Some(EnergylessArrow::new(ctx, app.time));
}
let stores = self.state.bldgs.all_stores();
self.state.energyless_arrow.as_mut().unwrap().update(
ctx,
app,
self.time,
self.player.get_pos(),
stores,
);
@ -330,7 +328,7 @@ impl State<App> for Game {
if true {
self.state
.vehicle
.animate(g, self.time)
.animate(g, app.time)
.centered_on(self.player.get_pos())
.rotate_around_batch_center(self.player.get_angle())
.draw(g);
@ -440,18 +438,11 @@ impl EnergylessArrow {
}
}
fn update(
&mut self,
ctx: &mut EventCtx,
app: &App,
time: Time,
sleigh: Pt2D,
all_stores: Vec<BuildingID>,
) {
if self.last_update == time {
fn update(&mut self, ctx: &mut EventCtx, app: &App, sleigh: Pt2D, all_stores: Vec<BuildingID>) {
if self.last_update == app.time {
return;
}
self.last_update = time;
self.last_update = app.time;
// Find the closest store as the crow -- or Santa -- flies
// TODO Or pathfind and show them that?
let store = app.map.get_b(
@ -463,7 +454,7 @@ impl EnergylessArrow {
// Vibrate in size slightly
let period = Duration::seconds(0.5);
let pct = ((time - self.started) % period) / period;
let pct = ((app.time - self.started) % period) / period;
// -1 to 1
let shift = (pct * std::f64::consts::PI).sin();
let thickness = Distance::meters(5.0 + shift);

View File

@ -1,7 +1,7 @@
use std::collections::{BTreeSet, VecDeque};
use abstutil::Timer;
use geom::{Distance, Duration, Line, Polygon, Pt2D};
use geom::{Distance, Line, Polygon, Pt2D};
use map_gui::options::TrafficSignalStyle;
use map_gui::render::{traffic_signal, DrawMovement, DrawOptions};
use map_gui::tools::PopupMsg;
@ -600,14 +600,14 @@ fn make_side_panel(
let mut col = vec![txt.draw(ctx)];
col.push(Widget::horiz_separator(ctx, 0.2));
{
let mut total = Duration::ZERO;
for s in &canonical_signal.stages {
total += s.phase_type.simple_duration();
}
// TODO Say "normally" to account for adaptive stages?
col.push(format!("One full cycle lasts {}", total).draw_text(ctx));
}
col.push(
format!(
"One full cycle lasts {}",
canonical_signal.simple_cycle_duration()
)
.draw_text(ctx),
);
if members.len() == 1 {
col.push(Btn::text_bg2("Edit entire signal").build_def(ctx, Key::E));

View File

@ -19,6 +19,8 @@ pub struct SimpleApp<T> {
pub current_selection: Option<ID>,
/// Custom per-app state can be stored here
pub session: T,
/// If desired, this can be advanced to render traffic signals changing.
pub time: Time,
}
impl<T> SimpleApp<T> {
@ -50,6 +52,7 @@ impl<T> SimpleApp<T> {
opts,
current_selection: None,
session,
time: Time::START_OF_DAY,
}
})
}
@ -259,16 +262,19 @@ impl<T> AppLike for SimpleApp<T> {
}
fn sim_time(&self) -> Time {
Time::START_OF_DAY
self.time
}
fn current_stage_and_remaining_time(&self, id: IntersectionID) -> (usize, Duration) {
(
0,
self.map.get_traffic_signal(id).stages[0]
.phase_type
.simple_duration(),
)
let signal = self.map.get_traffic_signal(id);
let mut time_left = (self.time - Time::START_OF_DAY) % signal.simple_cycle_duration();
for (idx, stage) in signal.stages.iter().enumerate() {
if time_left < stage.phase_type.simple_duration() {
return (idx, time_left);
}
time_left -= stage.phase_type.simple_duration();
}
unreachable!()
}
}

View File

@ -234,6 +234,15 @@ impl ControlTrafficSignal {
turn, self.id
)
}
/// How long a full cycle of the signal lasts, assuming no actuated timings.
pub fn simple_cycle_duration(&self) -> Duration {
let mut total = Duration::ZERO;
for s in &self.stages {
total += s.phase_type.simple_duration();
}
total
}
}
impl Stage {