mirror of
https://github.com/a-b-street/abstreet.git
synced 2025-01-04 12:36:46 +03:00
drawing individual cars, without handling transitions yet
This commit is contained in:
parent
6aafb908b6
commit
02bc78002f
@ -1,8 +1,9 @@
|
||||
use crate::objects::{DrawCtx, ID};
|
||||
use crate::plugins::sim::new_des_model;
|
||||
use crate::plugins::{BlockingPlugin, PluginCtx};
|
||||
use crate::render::MIN_ZOOM_FOR_DETAIL;
|
||||
use ezgui::{EventLoopMode, GfxCtx, Key};
|
||||
use geom::Duration;
|
||||
use geom::{Duration, Speed};
|
||||
use map_model::{LaneID, Map, Traversable};
|
||||
use rand::seq::SliceRandom;
|
||||
use rand::SeedableRng;
|
||||
@ -69,7 +70,11 @@ impl BlockingPlugin for EvenSimplerModelController {
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, ctx: &DrawCtx) {
|
||||
self.world.draw_unzoomed(self.current_time, g, &ctx.map);
|
||||
if g.canvas.cam_zoom >= MIN_ZOOM_FOR_DETAIL {
|
||||
self.world.draw_detailed(self.current_time, g, &ctx.map);
|
||||
} else {
|
||||
self.world.draw_unzoomed(self.current_time, g, &ctx.map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,9 +108,16 @@ fn populate_world(start: LaneID, map: &Map) -> new_des_model::World {
|
||||
last_lane = t.id.dst;
|
||||
}
|
||||
|
||||
// Throw a slow vehicle in the middle
|
||||
let max_speed = if i == 4 {
|
||||
Some(Speed::miles_per_hour(10.0))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
world.spawn_car(
|
||||
CarID::tmp_new(i, VehicleType::Car),
|
||||
None,
|
||||
max_speed,
|
||||
path.clone(),
|
||||
Duration::seconds(1.0) * (i as f64),
|
||||
);
|
||||
|
@ -4,7 +4,8 @@ use map_model::{IntersectionID, LaneID, Map, Traversable, TurnID, LANE_THICKNESS
|
||||
use sim::CarID;
|
||||
use std::collections::{BTreeMap, VecDeque};
|
||||
|
||||
const VEHICLE_LENGTH: Distance = Distance::const_meters(5.0);
|
||||
const VEHICLE_LENGTH: Distance = Distance::const_meters(4.0);
|
||||
const FOLLOWING_DISTANCE: Distance = Distance::const_meters(1.0);
|
||||
const FREEFLOW: Color = Color::CYAN;
|
||||
const WAITING: Color = Color::RED;
|
||||
|
||||
@ -30,7 +31,9 @@ impl World {
|
||||
Queue {
|
||||
id: l.id,
|
||||
cars: VecDeque::new(),
|
||||
max_capacity: ((l.length() / VEHICLE_LENGTH).floor() as usize).max(1),
|
||||
max_capacity: ((l.length() / (VEHICLE_LENGTH + FOLLOWING_DISTANCE)).floor()
|
||||
as usize)
|
||||
.max(1),
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -73,7 +76,8 @@ impl World {
|
||||
}
|
||||
|
||||
let l = map.get_l(queue.id);
|
||||
let end_of_waiting_queue = l.length() - (num_waiting as f64) * VEHICLE_LENGTH;
|
||||
let end_of_waiting_queue =
|
||||
l.length() - (num_waiting as f64) * (VEHICLE_LENGTH + FOLLOWING_DISTANCE);
|
||||
|
||||
if freeflow_head.is_some() {
|
||||
// The freeflow block can range from [0, end_of_waiting_queue].
|
||||
@ -124,6 +128,74 @@ impl World {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_detailed(&self, time: Duration, g: &mut GfxCtx, map: &Map) {
|
||||
for queue in self.queues.values() {
|
||||
if queue.cars.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let l = map.get_l(queue.id);
|
||||
|
||||
let mut last_car_back: Option<Distance> = None;
|
||||
|
||||
for car in &queue.cars {
|
||||
let (front, color) = match car.state {
|
||||
CarState::Queued => {
|
||||
if last_car_back.is_none() {
|
||||
(l.length(), WAITING)
|
||||
} else {
|
||||
// TODO If the last car is still CrossingLane, then kinda weird to draw
|
||||
// us as queued
|
||||
(last_car_back.unwrap() - FOLLOWING_DISTANCE, WAITING)
|
||||
}
|
||||
}
|
||||
CarState::CrossingLane(ref i) => {
|
||||
let bound = last_car_back
|
||||
.map(|b| b - FOLLOWING_DISTANCE)
|
||||
.unwrap_or(l.length());
|
||||
(i.percent(time) * bound, FREEFLOW)
|
||||
}
|
||||
CarState::CrossingTurn(_) => unreachable!(),
|
||||
};
|
||||
let back = front - VEHICLE_LENGTH;
|
||||
if back < Distance::ZERO {
|
||||
println!("Messed up on {}", queue.id);
|
||||
break;
|
||||
} else {
|
||||
last_car_back = Some(back);
|
||||
g.draw_polygon(
|
||||
color,
|
||||
&l.lane_center_pts
|
||||
.slice(back, front)
|
||||
.unwrap()
|
||||
.0
|
||||
.make_polygons(LANE_THICKNESS),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i in self.intersections.values() {
|
||||
if let Some(ref car) = i.accepted {
|
||||
let t = map.get_t(car.path[0].as_turn());
|
||||
let percent = match car.state {
|
||||
CarState::CrossingTurn(ref int) => int.percent(time),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
// TODO The VEHICLE_LENGTH is confusing...
|
||||
let tail = percent * t.geom.length();
|
||||
g.draw_polygon(
|
||||
FREEFLOW,
|
||||
&t.geom
|
||||
.slice(tail, tail + VEHICLE_LENGTH)
|
||||
.unwrap()
|
||||
.0
|
||||
.make_polygons(LANE_THICKNESS),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn spawn_car(
|
||||
&mut self,
|
||||
id: CarID,
|
||||
|
Loading…
Reference in New Issue
Block a user