Skip to content

Commit

Permalink
Make cars and pathfinding deal (in a simple way) with changed roads #17
Browse files Browse the repository at this point in the history
  • Loading branch information
aeplay committed Dec 17, 2016
1 parent 2b1d130 commit 84d362b
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 12 deletions.
2 changes: 1 addition & 1 deletion src/game/lanes_and_cars/lane_rendering.rs
Expand Up @@ -203,7 +203,7 @@ impl Recipient<RenderToScene> for Lane {
let weaker_random_color = [(random_color[0] + 1.0) / 2.0, (random_color[1] + 1.0) / 2.0, (random_color[2] + 1.0) / 2.0];
(weaker_random_color, as_destination.is_landmark())
} else {
([0.0, 0.0, 0.0], false)
([1.0, 1.0, 1.0], false)
};

renderer_id << UpdateThing{
Expand Down
32 changes: 21 additions & 11 deletions src/game/lanes_and_cars/mod.rs
Expand Up @@ -103,37 +103,44 @@ use self::pathfinding::RoutingInfo;
impl Recipient<AddCar> for Lane {
fn receive(&mut self, msg: &AddCar) -> Fate {match *msg{
AddCar{car, ..} => {
// TODO: horrible hack to encode it like this
let car_forcibly_spawned = *car.as_obstacle.position < 0.0;

let maybe_next_hop_interaction = self.pathfinding_info.routes.get(car.destination)
.or(self.pathfinding_info.routes.get(car.destination.landmark_destination()))
.map(|&RoutingInfo{outgoing_idx, ..}| {
.or_else(|| {
println!("NO ROUTE!");
if car_forcibly_spawned || self.pathfinding_info.routes.is_empty() {
None
} else {
// pseudorandom, lol
self.pathfinding_info.routes.values().nth((car.velocity * 10000.0) as usize % self.pathfinding_info.routes.len())
}
}).map(|&RoutingInfo{outgoing_idx, ..}| {
outgoing_idx as usize
});

if let Some(next_hop_interaction) = maybe_next_hop_interaction {
let routed_car = LaneCar{
next_hop_interaction: next_hop_interaction as u8,
as_obstacle: if *car.as_obstacle.position < 0.0 {
as_obstacle: if car_forcibly_spawned {
car.as_obstacle.offset_by(-*car.as_obstacle.position).offset_by(
self.cars.get(0).map(|last_car| *last_car.position).unwrap_or(self.length / 2.0) - 6.0
)
} else {car.as_obstacle},
.. car
};

if *routed_car.position < 0.0 {
// TODO: cancel trip
return Fate::Live;
}

// TODO: optimize using BinaryHeap?
let maybe_next_car_position = self.cars.iter().position(|other_car| other_car.as_obstacle.position > car.as_obstacle.position);
match maybe_next_car_position {
Some(next_car_position) => self.cars.insert(next_car_position, routed_car),
None => self.cars.push(routed_car)
}
} else {
println!("NO ROUTE!");
// TODO: cancel trip
}

Fate::Live
}
}}
Expand Down Expand Up @@ -200,10 +207,13 @@ impl Recipient<Tick> for Lane {
Tick{dt, current_tick} => {
self.in_construction += dt * 400.0;

let do_traffic = current_tick % TRAFFIC_LOGIC_THROTTLING == self.id().instance_id as usize % TRAFFIC_LOGIC_THROTTLING;

let old_green = self.green;
self.green = if self.timings.is_empty() {true} else {self.timings[(current_tick / 25) % self.timings.len()]};

if old_green != self.green {
// TODO: this is just a hacky way to update new lanes about existing lane's green
if old_green != self.green || do_traffic {
for interaction in &self.interactions {
if let Interaction{kind: InteractionKind::Previous{..}, partner_lane, ..} = *interaction {
partner_lane << SignalChanged{from: self.id(), green: self.green}
Expand All @@ -215,8 +225,6 @@ impl Recipient<Tick> for Lane {
self::pathfinding::tick(self);
}

let do_traffic = current_tick % TRAFFIC_LOGIC_THROTTLING == self.id().instance_id as usize % TRAFFIC_LOGIC_THROTTLING;

if do_traffic {
// TODO: optimize using BinaryHeap?
self.obstacles.sort_by_key(|&(ref obstacle, _id)| obstacle.position);
Expand Down Expand Up @@ -779,9 +787,11 @@ impl Recipient<Disconnect> for Lane {
).collect::<Vec<_>>();
// TODO: Cancel trip
self.cars.retain(|car| !interaction_indices_to_remove.contains(&(car.next_hop_interaction as usize)));
self.obstacles.retain(|&(_obstacle, from_id)| from_id != other_id);
for idx in interaction_indices_to_remove.into_iter().rev() {
self.interactions.remove(idx);
}
pathfinding::on_disconnect(self, other_id);
other_id << ConfirmDisconnect;
Fate::Live
}
Expand Down
16 changes: 16 additions & 0 deletions src/game/lanes_and_cars/pathfinding/mod.rs
Expand Up @@ -52,6 +52,17 @@ pub fn on_connect(lane: &mut Lane) {
lane.pathfinding_info.routing_timeout = ROUTING_TIMEOUT_AFTER_CHANGE;
}

pub fn on_disconnect(lane: &mut Lane, disconnected_id: ID) {
let new_routes = lane.pathfinding_info.routes.pairs().filter_map(|(destination, route)|
if route.learned_from == disconnected_id {
None
} else {Some((*destination, *route))}
).collect();
lane.pathfinding_info.routes = new_routes;
lane.pathfinding_info.routes_changed = true;
lane.pathfinding_info.query_routes_next_tick = true;
}

const MIN_LANDMARK_INCOMING : usize = 3;
const ROUTING_TIMEOUT_AFTER_CHANGE : u16 = 15;

Expand Down Expand Up @@ -311,6 +322,11 @@ impl Recipient<ForgetRoutes> for Lane {
} else {false};
if forget {
self.pathfinding_info.routes.remove(*destination_to_forget);
if destination_to_forget.is_landmark() {
self.cars.retain(|car| car.destination.landmark != destination_to_forget.landmark)
} else {
self.cars.retain(|car| &car.destination != destination_to_forget)
}
forgotten.push(*destination_to_forget);
}
}
Expand Down

0 comments on commit 84d362b

Please sign in to comment.